forked from OSchip/llvm-project
[InstSimplify] Add SimplifyFPBinOp function.
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'. llvm-svn: 228432
This commit is contained in:
parent
8c89a82c88
commit
4e8598eee3
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue