[InstSimplify] Add SimplifyFPBinOp function.
authorMichael Zolotukhin <mzolotukhin@apple.com>
Fri, 6 Feb 2015 20:02:51 +0000 (20:02 +0000)
committerMichael Zolotukhin <mzolotukhin@apple.com>
Fri, 6 Feb 2015 20:02:51 +0000 (20:02 +0000)
It is a variation of SimplifyBinOp, but it takes into account
FastMathFlags.

It is needed in inliner and loop-unroller to accurately predict the
transformation's outcome (previously we dropped the flags and were too
conservative in some cases).

Example:
float foo(float *a, float b) {
 float r;
 if (a[1] * b)
   r = /* a lot of expensive computations */;
 else
   r = 1;
 return r;
}
float boo(float *a) {
 return foo(a, 0.0);
}

Without this patch, we don't inline 'foo' into 'boo'.

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

include/llvm/Analysis/InstructionSimplify.h
lib/Analysis/IPA/InlineCost.cpp
lib/Analysis/InstructionSimplify.cpp
lib/Transforms/Scalar/LoopUnrollPass.cpp

index b88e0899f19a80bfc2357e15a15bd640a0c21e0e..cc734b3cb2ca4318ad962f3a803e23b4607568d3 100644 (file)
@@ -277,6 +277,17 @@ namespace llvm {
                        const DominatorTree *DT = nullptr,
                        AssumptionCache *AC = nullptr,
                        const Instruction *CxtI = nullptr);
+  /// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can
+  /// fold the result.  If not, this returns null.
+  /// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the
+  /// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp.
+  Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
+                         const FastMathFlags &FMF,
+                         const DataLayout *TD = nullptr,
+                         const TargetLibraryInfo *TLI = nullptr,
+                         const DominatorTree *DT = nullptr,
+                         AssumptionCache *AC = nullptr,
+                         const Instruction *CxtI = nullptr);
 
   /// \brief Given a function and iterators over arguments, see if we can fold
   /// the result.
index c180f36b9234264d8eba0e42999c25884585a9cf..64f78f408fdad504ba730e7600018f6d72b36d46 100644 (file)
@@ -601,7 +601,13 @@ bool CallAnalyzer::visitBinaryOperator(BinaryOperator &I) {
   if (!isa<Constant>(RHS))
     if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS))
       RHS = SimpleRHS;
-  Value *SimpleV = SimplifyBinOp(I.getOpcode(), LHS, RHS, DL);
+  Value *SimpleV = nullptr;
+  if (auto FI = dyn_cast<FPMathOperator>(&I))
+    SimpleV =
+        SimplifyFPBinOp(I.getOpcode(), LHS, RHS, FI->getFastMathFlags(), DL);
+  else
+    SimpleV = SimplifyBinOp(I.getOpcode(), LHS, RHS, DL);
+
   if (Constant *C = dyn_cast_or_null<Constant>(SimpleV)) {
     SimplifiedValues[&I] = C;
     return true;
index 588d625910f7f8dbfc9a596122c22af9f8af4a86..d02bb2b8f525bd66e4a23df66464e359bd828350 100644 (file)
@@ -61,6 +61,8 @@ struct Query {
 static Value *SimplifyAndInst(Value *, Value *, const Query &, unsigned);
 static Value *SimplifyBinOp(unsigned, Value *, Value *, const Query &,
                             unsigned);
+static Value *SimplifyFPBinOp(unsigned, Value *, Value *, const FastMathFlags &,
+                              const Query &, unsigned);
 static Value *SimplifyCmpInst(unsigned, Value *, Value *, const Query &,
                               unsigned);
 static Value *SimplifyOrInst(Value *, Value *, const Query &, unsigned);
@@ -3465,6 +3467,25 @@ static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
   }
 }
 
+/// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can
+/// fold the result.  If not, this returns null.
+/// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the
+/// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp.
+static Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
+                              const FastMathFlags &FMF, const Query &Q,
+                              unsigned MaxRecurse) {
+  switch (Opcode) {
+  case Instruction::FAdd:
+    return SimplifyFAddInst(LHS, RHS, FMF, Q, MaxRecurse);
+  case Instruction::FSub:
+    return SimplifyFSubInst(LHS, RHS, FMF, Q, MaxRecurse);
+  case Instruction::FMul:
+    return SimplifyFMulInst(LHS, RHS, FMF, Q, MaxRecurse);
+  default:
+    return SimplifyBinOp(Opcode, LHS, RHS, Q, MaxRecurse);
+  }
+}
+
 Value *llvm::SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
                            const DataLayout *DL, const TargetLibraryInfo *TLI,
                            const DominatorTree *DT, AssumptionCache *AC,
@@ -3473,6 +3494,15 @@ Value *llvm::SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
                          RecursionLimit);
 }
 
+Value *llvm::SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
+                             const FastMathFlags &FMF, const DataLayout *DL,
+                             const TargetLibraryInfo *TLI,
+                             const DominatorTree *DT, AssumptionCache *AC,
+                             const Instruction *CxtI) {
+  return ::SimplifyFPBinOp(Opcode, LHS, RHS, FMF, Query(DL, TLI, DT, AC, CxtI),
+                           RecursionLimit);
+}
+
 /// SimplifyCmpInst - Given operands for a CmpInst, see if we can
 /// fold the result.
 static Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
index bd9da14f66931e4835c0f18a9c84a5fb3ed9b68a..87237c62299bf89f94aeac5b5f0e126f95b8b4eb 100644 (file)
@@ -311,7 +311,12 @@ class UnrollAnalyzer : public InstVisitor<UnrollAnalyzer, bool> {
     if (!isa<Constant>(RHS))
       if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS))
         RHS = SimpleRHS;
-    Value *SimpleV = SimplifyBinOp(I.getOpcode(), LHS, RHS);
+    Value *SimpleV = nullptr;
+    if (auto FI = dyn_cast<FPMathOperator>(&I))
+      SimpleV =
+          SimplifyFPBinOp(I.getOpcode(), LHS, RHS, FI->getFastMathFlags());
+    else
+      SimpleV = SimplifyBinOp(I.getOpcode(), LHS, RHS);
 
     if (SimpleV && CountedInsns.insert(&I).second)
       NumberOfOptimizedInstructions += TTI.getUserCost(&I);