diff options
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 15 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/intrinsics.ll | 13 | 
2 files changed, 28 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index ff745641581..658178d5914 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -421,6 +421,21 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {          return InsertValueInst::Create(Struct, II->getArgOperand(0), 0);        }      } + +    // We can strength reduce reduce this signed add into a regular add if we +    // can prove that it will never overflow. +    if (II->getIntrinsicID() == Intrinsic::sadd_with_overflow) { +      Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1); +      if (WillNotOverflowSignedAdd(LHS, RHS)) { +        Value *Add = Builder->CreateNSWAdd(LHS, RHS); +        Add->takeName(&CI); +        Constant *V[] = {UndefValue::get(Add->getType()), Builder->getFalse()}; +        StructType *ST = cast<StructType>(II->getType()); +        Constant *Struct = ConstantStruct::get(ST, V); +        return InsertValueInst::Create(Struct, Add, 0); +      } +    } +      break;    case Intrinsic::usub_with_overflow:    case Intrinsic::ssub_with_overflow: diff --git a/llvm/test/Transforms/InstCombine/intrinsics.ll b/llvm/test/Transforms/InstCombine/intrinsics.ll index 91c44704ce7..9b58d9386f5 100644 --- a/llvm/test/Transforms/InstCombine/intrinsics.ll +++ b/llvm/test/Transforms/InstCombine/intrinsics.ll @@ -3,6 +3,7 @@  %overflow.result = type {i8, i1}  declare %overflow.result @llvm.uadd.with.overflow.i8(i8, i8) +declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)  declare %overflow.result @llvm.umul.with.overflow.i8(i8, i8)  declare double @llvm.powi.f64(double, i32) nounwind readonly  declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone @@ -89,6 +90,18 @@ define i8 @uaddtest7(i8 %A, i8 %B) {  ; CHECK-NEXT: ret i8 %z  } +; PR20194 +define { i32, i1 } @saddtest1(i8 %a, i8 %b) { +  %A = sext i8 %a to i32 +  %B = sext i8 %b to i32 +  %x = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %A, i32 %B) +  ret { i32, i1 } %x +; CHECK-LABEL: @saddtest1 +; CHECK: %x = add nsw i32 %A, %B +; CHECK-NEXT: %1 = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 %x, 0 +; CHECK-NEXT:  ret { i32, i1 } %1 +} +  define i8 @umultest1(i8 %A, i1* %overflowPtr) {    %x = call %overflow.result @llvm.umul.with.overflow.i8(i8 0, i8 %A)  | 

