diff options
author | Nikita Popov <npopov@redhat.com> | 2024-09-19 09:39:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-19 09:39:35 +0200 |
commit | 4ec4ac15ed47ccb52d79e01c038865817d0cedf6 (patch) | |
tree | bc6dea85a60fb75dedc47f021d8c051f153a63f1 /llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp | |
parent | c18be32185ca10e55bdef0f2d43629ccfb7e89eb (diff) | |
download | llvm-4ec4ac15ed47ccb52d79e01c038865817d0cedf6.zip llvm-4ec4ac15ed47ccb52d79e01c038865817d0cedf6.tar.gz llvm-4ec4ac15ed47ccb52d79e01c038865817d0cedf6.tar.bz2 |
[SCEVExpander] Fix addrec cost model (#106704)
The current isHighCostExpansion cost model for addrecs computes the cost
for some kind of polynomial expansion that does not appear to have any
relation to addrec expansion whatsoever.
A literal expansion of an affine addrec is a phi and add (plus the
expansion of start and step). For a non-affine addrec, we get another
phi+add for each additional addrec nested in the step recurrence.
This partially `fixes` https://github.com/llvm/llvm-project/issues/53205
(the runtime unroll test case in this PR).
Diffstat (limited to 'llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp | 48 |
1 files changed, 11 insertions, 37 deletions
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp index c7d758a..0927a301 100644 --- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp @@ -1911,43 +1911,17 @@ template<typename T> static InstructionCost costAndCollectOperands( break; } case scAddRecExpr: { - // In this polynominal, we may have some zero operands, and we shouldn't - // really charge for those. So how many non-zero coefficients are there? - int NumTerms = llvm::count_if(S->operands(), [](const SCEV *Op) { - return !Op->isZero(); - }); - - assert(NumTerms >= 1 && "Polynominal should have at least one term."); - assert(!(*std::prev(S->operands().end()))->isZero() && - "Last operand should not be zero"); - - // Ignoring constant term (operand 0), how many of the coefficients are u> 1? - int NumNonZeroDegreeNonOneTerms = - llvm::count_if(S->operands(), [](const SCEV *Op) { - auto *SConst = dyn_cast<SCEVConstant>(Op); - return !SConst || SConst->getAPInt().ugt(1); - }); - - // Much like with normal add expr, the polynominal will require - // one less addition than the number of it's terms. - InstructionCost AddCost = ArithCost(Instruction::Add, NumTerms - 1, - /*MinIdx*/ 1, /*MaxIdx*/ 1); - // Here, *each* one of those will require a multiplication. - InstructionCost MulCost = - ArithCost(Instruction::Mul, NumNonZeroDegreeNonOneTerms); - Cost = AddCost + MulCost; - - // What is the degree of this polynominal? - int PolyDegree = S->getNumOperands() - 1; - assert(PolyDegree >= 1 && "Should be at least affine."); - - // The final term will be: - // Op_{PolyDegree} * x ^ {PolyDegree} - // Where x ^ {PolyDegree} will again require PolyDegree-1 mul operations. - // Note that x ^ {PolyDegree} = x * x ^ {PolyDegree-1} so charging for - // x ^ {PolyDegree} will give us x ^ {2} .. x ^ {PolyDegree-1} for free. - // FIXME: this is conservatively correct, but might be overly pessimistic. - Cost += MulCost * (PolyDegree - 1); + // Addrec expands to a phi and add per recurrence. + unsigned NumRecurrences = S->getNumOperands() - 1; + Cost += TTI.getCFInstrCost(Instruction::PHI, CostKind) * NumRecurrences; + Cost += + TTI.getArithmeticInstrCost(Instruction::Add, S->getType(), CostKind) * + NumRecurrences; + // AR start is used in phi. + Worklist.emplace_back(Instruction::PHI, 0, S->getOperand(0)); + // Other operands are used in add. + for (const SCEV *Op : S->operands().drop_front()) + Worklist.emplace_back(Instruction::Add, 1, Op); break; } } |