Index: llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -18,6 +18,7 @@ #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" @@ -381,6 +382,59 @@ 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 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; @@ -436,6 +490,9 @@ case Instruction::SDiv: BBChanged |= processSDiv(cast(II), LVI); break; + case Instruction::Add: + BBChanged |= processAdd(cast(II), LVI); + break; } } Index: llvm/trunk/test/Transforms/CorrelatedValuePropagation/add.ll =================================================================== --- llvm/trunk/test/Transforms/CorrelatedValuePropagation/add.ll +++ llvm/trunk/test/Transforms/CorrelatedValuePropagation/add.ll @@ -0,0 +1,91 @@ +; 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 +}