InstCombine: Turn mul.with.overflow(X, 2) into the cheaper add.with.overflow(X, X)
authorBenjamin Kramer <benny.kra@googlemail.com>
Sat, 21 May 2011 09:22:06 +0000 (09:22 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sat, 21 May 2011 09:22:06 +0000 (09:22 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131789 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineCalls.cpp
test/Transforms/InstCombine/intrinsics.ll

index 243937705aceaa4f4a0bedc959523415f27dd1d2..ea0ffd9c34035b24a07b4a6c6522300e7a52b84f 100644 (file)
@@ -535,6 +535,20 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
         Constant *Struct = ConstantStruct::get(II->getContext(), V, 2, false);
         return InsertValueInst::Create(Struct, II->getArgOperand(0), 0);
       }
+
+      // [su]mul.with.overflow(X, 2) -> [su]add.with.overflow(X, X)
+      if (RHSI->equalsInt(2)) {
+        Intrinsic::ID Add =
+          II->getIntrinsicID() == Intrinsic::smul_with_overflow ?
+          Intrinsic::sadd_with_overflow : Intrinsic::uadd_with_overflow;
+
+        Module *M = II->getParent()->getParent()->getParent();
+        const Type *Ty = RHSI->getType();
+        Function *F = Intrinsic::getDeclaration(M, Add, &Ty, 1);
+
+        Value *Ops[] = { II->getArgOperand(0), II->getArgOperand(0) };
+        return CallInst::Create(F, Ops, Ops+2);
+      }
     }
     break;
   case Intrinsic::ppc_altivec_lvx:
index 107f313b019379a0cf8d3ee7e72fbda0c5016244..3a0b312a2a228acced0f3f90a3f006c310581e58 100644 (file)
@@ -114,6 +114,7 @@ define i8 @umultest2(i8 %A, i1* %overflowPtr) {
 
 %ov.result.32 = type { i32, i1 }
 declare %ov.result.32 @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
+declare %ov.result.32 @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
 
 define i32 @umultest3(i32 %n) nounwind {
   %shr = lshr i32 %n, 2
@@ -139,6 +140,26 @@ define i32 @umultest4(i32 %n) nounwind {
 ; CHECK: umul.with.overflow
 }
 
+define i32 @umultest5(i32 %n) nounwind {
+  %mul = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %n, i32 2)
+  %ov = extractvalue %ov.result.32 %mul, 1
+  %res = extractvalue %ov.result.32 %mul, 0
+  %ret = select i1 %ov, i32 -1, i32 %res
+  ret i32 %ret
+; CHECK: @umultest5
+; CHECK: llvm.uadd.with.overflow.i32(i32 %n, i32 %n)
+}
+
+define i32 @smultest1(i32 %n) nounwind {
+  %mul = call %ov.result.32 @llvm.smul.with.overflow.i32(i32 %n, i32 2)
+  %ov = extractvalue %ov.result.32 %mul, 1
+  %res = extractvalue %ov.result.32 %mul, 0
+  %ret = select i1 %ov, i32 -1, i32 %res
+  ret i32 %ret
+; CHECK: @smultest1
+; CHECK: llvm.sadd.with.overflow.i32(i32 %n, i32 %n)
+}
+
 define void @powi(double %V, double *%P) {
 entry:
   %A = tail call double @llvm.powi.f64(double %V, i32 -1) nounwind