Fix a bug in instcombine for fmul in fast math mode.
authorQuentin Colombet <qcolombet@apple.com>
Thu, 28 Feb 2013 21:12:40 +0000 (21:12 +0000)
committerQuentin Colombet <qcolombet@apple.com>
Thu, 28 Feb 2013 21:12:40 +0000 (21:12 +0000)
The instcombine recognized pattern looks like:
a = b * c
d = a +/- Cst
or
a = b * c
d = Cst +/- a

When creating the new operands for fadd or fsub instruction following the related fmul, the first operand was created with the second original operand (M0 was created with C1) and the second with the first (M1 with Opnd0).

The fix consists in creating the new operands with the appropriate original operand, i.e., M0 with Opnd0 and M1 with C1.

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

lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
test/Transforms/InstCombine/fast-math.ll

index 8e4267f898634e2fda2e1a53930a948a6919d5e6..173f2bf6330469c638dbaa4a8e07b755fb089f82 100644 (file)
@@ -402,7 +402,7 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
           return ReplaceInstUsesWith(I, V);
       }
 
-      // (MDC +/- C1) * C2 => (MDC * C2) +/- (C1 * C2)
+      // (MDC +/- C1) * C => (MDC * C) +/- (C1 * C)
       Instruction *FAddSub = dyn_cast<Instruction>(Op0);
       if (FAddSub &&
           (FAddSub->getOpcode() == Instruction::FAdd ||
@@ -420,8 +420,8 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
 
         if (C1 && C1->getValueAPF().isNormal() &&
             isFMulOrFDivWithConstant(Opnd0)) {
-          Value *M0 = ConstantExpr::getFMul(C1, C);
-          Value *M1 = isNormalFp(cast<ConstantFP>(M0)) ? 
+          Value *M1 = ConstantExpr::getFMul(C1, C);
+          Value *M0 = isNormalFp(cast<ConstantFP>(M1)) ? 
                       foldFMulConst(cast<Instruction>(Opnd0), C, &I) :
                       0;
           if (M0 && M1) {
index c97bd28222b8a63864239a5000b5c4fc5c06f377..3e32a2e4dd48052a30bc624eeb65509ce8f6a28a 100644 (file)
@@ -172,6 +172,17 @@ define double @fmul_distribute3(double %f1) {
 ; CHECK: fmul fast double %t2, 0x10000000000000
 }
 
+; ((X*C1) + C2) * C3 => (X * (C1*C3)) + (C2*C3) (i.e. distribution)
+define float @fmul_distribute4(float %f1) {
+  %t1 = fmul float %f1, 6.0e+3
+  %t2 = fsub float 2.0e+3, %t1
+  %t3 = fmul fast float %t2, 5.0e+3
+  ret float %t3
+; CHECK: @fmul_distribute4
+; CHECK: %1 = fmul fast float %f1, 3.000000e+07
+; CHECK: %t3 = fsub fast float 1.000000e+07, %1
+}
+
 ; C1/X * C2 => (C1*C2) / X
 define float @fmul2(float %f1) {
   %t1 = fdiv float 2.0e+3, %f1