[llvm] r325187 - [InstCombine] clean up fold for X / C -> X * (1.0/C); NFCI

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 14 15:04:17 PST 2018


Author: spatel
Date: Wed Feb 14 15:04:17 2018
New Revision: 325187

URL: http://llvm.org/viewvc/llvm-project?rev=325187&view=rev
Log:
[InstCombine] clean up fold for X / C -> X * (1.0/C); NFCI

This should work with vector constants too, but it's currently limited to scalar.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=325187&r1=325186&r2=325187&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Wed Feb 14 15:04:17 2018
@@ -1317,33 +1317,34 @@ Instruction *InstCombiner::visitSDiv(Bin
   return nullptr;
 }
 
-/// CvtFDivConstToReciprocal tries to convert X/C into X*1/C if C not a special
-/// FP value and:
-///    1) 1/C is exact, or
-///    2) reciprocal is allowed.
-/// If the conversion was successful, the simplified expression "X * 1/C" is
-/// returned; otherwise, nullptr is returned.
-static Instruction *CvtFDivConstToReciprocal(Value *Dividend, Constant *Divisor,
-                                             bool AllowReciprocal) {
-  if (!isa<ConstantFP>(Divisor)) // TODO: handle vectors.
+/// Try to convert X/C into X * (1/C).
+static Instruction *foldFDivConstantDivisor(BinaryOperator &FDiv) {
+  // TODO: Handle vector constants.
+  ConstantFP *CFP;
+  if (!match(FDiv.getOperand(1), m_ConstantFP(CFP)))
     return nullptr;
 
-  const APFloat &FpVal = cast<ConstantFP>(Divisor)->getValueAPF();
+  const APFloat &FpVal = CFP->getValueAPF();
   APFloat Reciprocal(FpVal.getSemantics());
-  bool Cvt = FpVal.getExactInverse(&Reciprocal);
 
-  if (!Cvt && AllowReciprocal && FpVal.isFiniteNonZero()) {
+  // This returns false if the inverse would be a denormal.
+  bool HasRecip = FpVal.getExactInverse(&Reciprocal);
+  // If the inverse is not exact, we may still be able to convert if we are
+  // not operating with strict math.
+  if (!HasRecip && FDiv.hasAllowReciprocal() && FpVal.isFiniteNonZero()) {
     Reciprocal = APFloat(FpVal.getSemantics(), 1.0f);
-    (void)Reciprocal.divide(FpVal, APFloat::rmNearestTiesToEven);
-    Cvt = !Reciprocal.isDenormal();
+    Reciprocal.divide(FpVal, APFloat::rmNearestTiesToEven);
+    // Disallow denormal constants because we don't know what would happen
+    // on all targets.
+    // TODO: Function attributes can tell us that denorms are flushed?
+    HasRecip = !Reciprocal.isDenormal();
   }
 
-  if (!Cvt)
+  if (!HasRecip)
     return nullptr;
 
-  ConstantFP *R;
-  R = ConstantFP::get(Dividend->getType()->getContext(), Reciprocal);
-  return BinaryOperator::CreateFMul(Dividend, R);
+  auto *RecipCFP = ConstantFP::get(FDiv.getContext(), Reciprocal);
+  return BinaryOperator::CreateFMul(FDiv.getOperand(0), RecipCFP);
 }
 
 Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
@@ -1356,14 +1357,17 @@ Instruction *InstCombiner::visitFDiv(Bin
                                   SQ.getWithInstruction(&I)))
     return replaceInstUsesWith(I, V);
 
+  if (Instruction *FMul = foldFDivConstantDivisor(I)) {
+    FMul->copyFastMathFlags(&I);
+    return FMul;
+  }
+
   if (isa<Constant>(Op0))
     if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
       if (Instruction *R = FoldOpIntoSelect(I, SI))
         return R;
 
   bool AllowReassociate = I.isFast();
-  bool AllowReciprocal = I.hasAllowReciprocal();
-
   if (Constant *Op1C = dyn_cast<Constant>(Op1)) {
     if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
       if (Instruction *R = FoldOpIntoSelect(I, SI))
@@ -1377,18 +1381,14 @@ Instruction *InstCombiner::visitFDiv(Bin
 
       if (match(Op0, m_FMul(m_Value(X), m_Constant(C1)))) {
         // (X*C1)/C2 => X * (C1/C2)
-        //
         Constant *C = ConstantExpr::getFDiv(C1, C2);
         if (isNormalFp(C))
           Res = BinaryOperator::CreateFMul(X, C);
       } else if (match(Op0, m_FDiv(m_Value(X), m_Constant(C1)))) {
-        // (X/C1)/C2 => X /(C2*C1) [=> X * 1/(C2*C1) if reciprocal is allowed]
+        // (X/C1)/C2 => X /(C2*C1)
         Constant *C = ConstantExpr::getFMul(C1, C2);
-        if (isNormalFp(C)) {
-          Res = CvtFDivConstToReciprocal(X, C, AllowReciprocal);
-          if (!Res)
-            Res = BinaryOperator::CreateFDiv(X, C);
-        }
+        if (isNormalFp(C))
+          Res = BinaryOperator::CreateFDiv(X, C);
       }
 
       if (Res) {
@@ -1396,13 +1396,6 @@ Instruction *InstCombiner::visitFDiv(Bin
         return Res;
       }
     }
-
-    // X / C => X * 1/C
-    if (Instruction *T = CvtFDivConstToReciprocal(Op0, Op1C, AllowReciprocal)) {
-      T->copyFastMathFlags(&I);
-      return T;
-    }
-
     return nullptr;
   }
 




More information about the llvm-commits mailing list