InstCombine: If the divisor of an fdiv has an exact inverse, turn it into an fmul.
authorBenjamin Kramer <benny.kra@googlemail.com>
Wed, 30 Mar 2011 15:42:35 +0000 (15:42 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Wed, 30 Mar 2011 15:42:35 +0000 (15:42 +0000)
Fixes PR9587.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128546 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
test/Transforms/InstCombine/fdiv.ll [new file with mode: 0644]

index d1a1fd6ddfacabaea1633438fd085c2c9801ff54..665138748151b069953cedf3540b5a7a4e29f28b 100644 (file)
@@ -452,6 +452,18 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
   if (Value *V = SimplifyFDivInst(Op0, Op1, TD))
     return ReplaceInstUsesWith(I, V);
 
+  if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1)) {
+    const APFloat &Op1F = Op1C->getValueAPF();
+
+    // If the divisor has an exact multiplicative inverse we can turn the fdiv
+    // into a cheaper fmul.
+    APFloat Reciprocal(Op1F.getSemantics());
+    if (Op1F.getExactInverse(&Reciprocal)) {
+      ConstantFP *RFP = ConstantFP::get(Builder->getContext(), Reciprocal);
+      return BinaryOperator::CreateFMul(Op0, RFP);
+    }
+  }
+
   return 0;
 }
 
diff --git a/test/Transforms/InstCombine/fdiv.ll b/test/Transforms/InstCombine/fdiv.ll
new file mode 100644 (file)
index 0000000..f4e0b48
--- /dev/null
@@ -0,0 +1,25 @@
+; RUN: opt -S -instcombine < %s | FileCheck %s
+
+define float @test1(float %x) nounwind readnone ssp {
+  %div = fdiv float %x, 0x3810000000000000
+  ret float %div
+
+; CHECK: @test1
+; CHECK-NEXT: fmul float %x, 0x47D0000000000000
+}
+
+define float @test2(float %x) nounwind readnone ssp {
+  %div = fdiv float %x, 0x47E0000000000000
+  ret float %div
+
+; CHECK: @test2
+; CHECK-NEXT: fmul float %x, 0x3800000000000000
+}
+
+define float @test3(float %x) nounwind readnone ssp {
+  %div = fdiv float %x, 0x36A0000000000000
+  ret float %div
+
+; CHECK: @test3
+; CHECK-NEXT: fdiv float %x, 0x36A0000000000000
+}