[llvm] r326608 - [InstCombine] partly fix FMF for fmul+log2 fold

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 2 12:32:46 PST 2018


Author: spatel
Date: Fri Mar  2 12:32:46 2018
New Revision: 326608

URL: http://llvm.org/viewvc/llvm-project?rev=326608&view=rev
Log:
[InstCombine] partly fix FMF for fmul+log2 fold

The code was checking that all of the instructions in the 
sequence are 'fast', but that's not necessary. The final 
multiply is all that we need to check (tests adjusted). 
The fmul doesn't need to be fully 'fast' either, but that 
can be another patch.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/trunk/test/Transforms/InstCombine/fmul.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=326608&r1=326607&r2=326608&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Fri Mar  2 12:32:46 2018
@@ -447,35 +447,6 @@ Instruction *InstCombiner::visitMul(Bina
   return Changed ? &I : nullptr;
 }
 
-/// Detect pattern log2(Y * 0.5) with corresponding fast math flags.
-static void detectLog2OfHalf(Value *&Op, Value *&Y, IntrinsicInst *&Log2) {
-  if (!Op->hasOneUse())
-    return;
-
-  IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op);
-  if (!II)
-    return;
-  if (II->getIntrinsicID() != Intrinsic::log2 || !II->isFast())
-    return;
-  Log2 = II;
-
-  Value *OpLog2Of = II->getArgOperand(0);
-  if (!OpLog2Of->hasOneUse())
-    return;
-
-  Instruction *I = dyn_cast<Instruction>(OpLog2Of);
-  if (!I)
-    return;
-
-  if (I->getOpcode() != Instruction::FMul || !I->isFast())
-    return;
-
-  if (match(I->getOperand(0), m_SpecificFP(0.5)))
-    Y = I->getOperand(1);
-  else if (match(I->getOperand(1), m_SpecificFP(0.5)))
-    Y = I->getOperand(0);
-}
-
 /// Helper function of InstCombiner::visitFMul(). Return true iff the given
 /// value is FMul or FDiv with one and only one operand being a finite-non-zero
 /// constant (i.e. not Zero/NaN/Infinity).
@@ -617,30 +588,24 @@ Instruction *InstCombiner::visitFMul(Bin
   if (Op0 == Op1 && match(Op0, m_Intrinsic<Intrinsic::fabs>(m_Value(X))))
     return BinaryOperator::CreateFMulFMF(X, X, &I);
 
-  // Under unsafe algebra do:
-  // X * log2(0.5*Y) = X*log2(Y) - X
-  if (AllowReassociate) {
-    Value *OpX = nullptr;
-    Value *OpY = nullptr;
-    IntrinsicInst *Log2;
-    detectLog2OfHalf(Op0, OpY, Log2);
-    if (OpY) {
-      OpX = Op1;
-    } else {
-      detectLog2OfHalf(Op1, OpY, Log2);
-      if (OpY) {
-        OpX = Op0;
-      }
+  // log2(X * 0.5) * Y = log2(X) * Y - Y
+  if (I.isFast()) {
+    IntrinsicInst *Log2 = nullptr;
+    if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::log2>(
+            m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
+      Log2 = cast<IntrinsicInst>(Op0);
+      Y = Op1;
+    }
+    if (match(Op1, m_OneUse(m_Intrinsic<Intrinsic::log2>(
+            m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
+      Log2 = cast<IntrinsicInst>(Op1);
+      Y = Op0;
     }
-    // if pattern detected emit alternate sequence
-    if (OpX && OpY) {
-      BuilderTy::FastMathFlagGuard Guard(Builder);
-      Builder.setFastMathFlags(Log2->getFastMathFlags());
-      Log2->setArgOperand(0, OpY);
-      Value *FMulVal = Builder.CreateFMul(OpX, Log2);
-      Value *FSub = Builder.CreateFSub(FMulVal, OpX);
-      FSub->takeName(&I);
-      return replaceInstUsesWith(I, FSub);
+    if (Log2) {
+      Log2->setArgOperand(0, X);
+      Log2->copyFastMathFlags(&I);
+      Value *LogXTimesY = Builder.CreateFMulFMF(Log2, Y, &I);
+      return BinaryOperator::CreateFSubFMF(LogXTimesY, Y, &I);
     }
   }
 

Modified: llvm/trunk/test/Transforms/InstCombine/fmul.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fmul.ll?rev=326608&r1=326607&r2=326608&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fmul.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fmul.ll Fri Mar  2 12:32:46 2018
@@ -302,7 +302,7 @@ define float @reassoc_common_operand_mul
 
 declare float @llvm.log2.f32(float)
 
-; X * log2(Y * 0.5) = X * log2(Y) - X
+; log2(Y * 0.5) * X = log2(Y) * X - X
 
 define float @log2half(float %x, float %y) {
 ; CHECK-LABEL: @log2half(
@@ -311,8 +311,8 @@ define float @log2half(float %x, float %
 ; CHECK-NEXT:    [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
-  %halfy = fmul fast float %y, 0.5
-  %log2 = call fast float @llvm.log2.f32(float %halfy)
+  %halfy = fmul float %y, 0.5
+  %log2 = call float @llvm.log2.f32(float %halfy)
   %mul = fmul fast float %log2, %x
   ret float %mul
 }
@@ -321,13 +321,13 @@ define float @log2half_commute(float %x1
 ; CHECK-LABEL: @log2half_commute(
 ; CHECK-NEXT:    [[X:%.*]] = fdiv float [[X1:%.*]], 7.000000e+00
 ; CHECK-NEXT:    [[LOG2:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]])
-; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X]], [[LOG2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X]]
 ; CHECK-NEXT:    [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %x = fdiv float %x1, 7.0 ; thwart complexity-based canonicalization
-  %halfy = fmul fast float %y, 0.5
-  %log2 = call fast float @llvm.log2.f32(float %halfy)
+  %halfy = fmul float %y, 0.5
+  %log2 = call float @llvm.log2.f32(float %halfy)
   %mul = fmul fast float %x, %log2
   ret float %mul
 }




More information about the llvm-commits mailing list