#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LazyValueInfo.h"
#include "llvm/IR/CFG.h"
-#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
return true;
}
-static bool processAdd(BinaryOperator *AddOp, LazyValueInfo *LVI) {
- typedef OverflowingBinaryOperator OBO;
-
- if (AddOp->getType()->isVectorTy() || hasLocalDefs(AddOp))
- return false;
-
- bool NSW = AddOp->hasNoSignedWrap();
- bool NUW = AddOp->hasNoUnsignedWrap();
- if (NSW && NUW)
- return false;
-
- BasicBlock *BB = AddOp->getParent();
-
- Value *LHS = AddOp->getOperand(0);
- Value *RHS = AddOp->getOperand(1);
-
- ConstantRange LRange = LVI->getConstantRange(LHS, BB, AddOp);
-
- // Initialize RRange only if we need it. If we know that guaranteed no wrap
- // range for the given LHS range is empty don't spend time calculating the
- // range for the RHS.
- Optional<ConstantRange> RRange;
- auto LazyRRange = [&] () {
- if (!RRange)
- RRange = LVI->getConstantRange(RHS, BB, AddOp);
- return RRange.getValue();
- };
-
- bool Changed = false;
- if (!NUW) {
- ConstantRange NUWRange =
- LRange.makeGuaranteedNoWrapRegion(BinaryOperator::Add, LRange,
- OBO::NoUnsignedWrap);
- if (!NUWRange.isEmptySet()) {
- bool NewNUW = NUWRange.contains(LazyRRange());
- AddOp->setHasNoUnsignedWrap(NewNUW);
- Changed |= NewNUW;
- }
- }
- if (!NSW) {
- ConstantRange NSWRange =
- LRange.makeGuaranteedNoWrapRegion(BinaryOperator::Add, LRange,
- OBO::NoSignedWrap);
- if (!NSWRange.isEmptySet()) {
- bool NewNSW = NSWRange.contains(LazyRRange());
- AddOp->setHasNoSignedWrap(NewNSW);
- Changed |= NewNSW;
- }
- }
-
- return Changed;
-}
-
static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
if (Constant *C = LVI->getConstant(V, At->getParent(), At))
return C;
case Instruction::SDiv:
BBChanged |= processSDiv(cast<BinaryOperator>(II), LVI);
break;
- case Instruction::Add:
- BBChanged |= processAdd(cast<BinaryOperator>(II), LVI);
- break;
}
}
+++ /dev/null
-; RUN: opt < %s -correlated-propagation -S | FileCheck %s
-
-; CHECK-LABEL: @test0(
-define void @test0(i32 %a) {
-entry:
- %cmp = icmp slt i32 %a, 100
- br i1 %cmp, label %bb, label %exit
-
-bb:
-; CHECK: %add = add nsw i32 %a, 1
- %add = add i32 %a, 1
- br label %exit
-
-exit:
- ret void
-}
-
-; CHECK-LABEL: @test1(
-define void @test1(i32 %a) {
-entry:
- %cmp = icmp ult i32 %a, 100
- br i1 %cmp, label %bb, label %exit
-
-bb:
-; CHECK: %add = add nuw nsw i32 %a, 1
- %add = add i32 %a, 1
- br label %exit
-
-exit:
- ret void
-}
-
-; CHECK-LABEL: @test2(
-define void @test2(i32 %a) {
-entry:
- %cmp = icmp ult i32 %a, -1
- br i1 %cmp, label %bb, label %exit
-
-bb:
-; CHECK: %add = add nuw i32 %a, 1
- %add = add i32 %a, 1
- br label %exit
-
-exit:
- ret void
-}
-
-; CHECK-LABEL: @test3(
-define void @test3(i32 %a) {
-entry:
- %cmp = icmp ule i32 %a, -1
- br i1 %cmp, label %bb, label %exit
-
-bb:
-; CHECK: %add = add i32 %a, 1
- %add = add i32 %a, 1
- br label %exit
-
-exit:
- ret void
-}
-
-; CHECK-LABEL: @test4(
-define void @test4(i32 %a) {
-entry:
- %cmp = icmp slt i32 %a, 2147483647
- br i1 %cmp, label %bb, label %exit
-
-bb:
-; CHECK: %add = add nsw i32 %a, 1
- %add = add i32 %a, 1
- br label %exit
-
-exit:
- ret void
-}
-
-; CHECK-LABEL: @test5(
-define void @test5(i32 %a) {
-entry:
- %cmp = icmp sle i32 %a, 2147483647
- br i1 %cmp, label %bb, label %exit
-
-bb:
-; CHECK: %add = add i32 %a, 1
- %add = add i32 %a, 1
- br label %exit
-
-exit:
- ret void
-}