[CostModel]Migrate getTreeCost() to use InstructionCost

This patch changes the type of cost variables (for instance: Cost, ExtractCost,
SpillCost) to use InstructionCost.
This patch also changes the type of cost variables to InstructionCost in other
functions that use the result of getTreeCost()
This patch is part of a series of patches to use InstructionCost instead of
unsigned/int for the cost model functions.

See this thread for context:
http://lists.llvm.org/pipermail/llvm-dev/2020-November/146408.html

Depends on D91174

Differential Revision: https://reviews.llvm.org/D93049
This commit is contained in:
Caroline Concatto 2020-12-10 13:52:35 +00:00
parent 60e4698b9a
commit 07217e0a1b
1 changed files with 24 additions and 19 deletions

View File

@ -587,11 +587,11 @@ public:
/// \returns the cost incurred by unwanted spills and fills, caused by /// \returns the cost incurred by unwanted spills and fills, caused by
/// holding live values over call sites. /// holding live values over call sites.
int getSpillCost() const; InstructionCost getSpillCost() const;
/// \returns the vectorization cost of the subtree that starts at \p VL. /// \returns the vectorization cost of the subtree that starts at \p VL.
/// A negative number means that this is profitable. /// A negative number means that this is profitable.
int getTreeCost(); InstructionCost getTreeCost();
/// Construct a vectorizable tree that starts at \p Roots, ignoring users for /// Construct a vectorizable tree that starts at \p Roots, ignoring users for
/// the purpose of scheduling and extraction in the \p UserIgnoreLst. /// the purpose of scheduling and extraction in the \p UserIgnoreLst.
@ -3949,13 +3949,13 @@ bool BoUpSLP::isTreeTinyAndNotFullyVectorizable() const {
return true; return true;
} }
int BoUpSLP::getSpillCost() const { InstructionCost BoUpSLP::getSpillCost() const {
// Walk from the bottom of the tree to the top, tracking which values are // Walk from the bottom of the tree to the top, tracking which values are
// live. When we see a call instruction that is not part of our tree, // live. When we see a call instruction that is not part of our tree,
// query TTI to see if there is a cost to keeping values live over it // query TTI to see if there is a cost to keeping values live over it
// (for example, if spills and fills are required). // (for example, if spills and fills are required).
unsigned BundleWidth = VectorizableTree.front()->Scalars.size(); unsigned BundleWidth = VectorizableTree.front()->Scalars.size();
int Cost = 0; InstructionCost Cost = 0;
SmallPtrSet<Instruction*, 4> LiveValues; SmallPtrSet<Instruction*, 4> LiveValues;
Instruction *PrevInst = nullptr; Instruction *PrevInst = nullptr;
@ -4031,8 +4031,8 @@ int BoUpSLP::getSpillCost() const {
return Cost; return Cost;
} }
int BoUpSLP::getTreeCost() { InstructionCost BoUpSLP::getTreeCost() {
int Cost = 0; InstructionCost Cost = 0;
LLVM_DEBUG(dbgs() << "SLP: Calculating cost for tree of size " LLVM_DEBUG(dbgs() << "SLP: Calculating cost for tree of size "
<< VectorizableTree.size() << ".\n"); << VectorizableTree.size() << ".\n");
@ -4062,7 +4062,7 @@ int BoUpSLP::getTreeCost() {
})) }))
continue; continue;
int C = getEntryCost(&TE); InstructionCost C = getEntryCost(&TE);
Cost += C; Cost += C;
LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C
<< " for bundle that starts with " << *TE.Scalars[0] << " for bundle that starts with " << *TE.Scalars[0]
@ -4071,7 +4071,7 @@ int BoUpSLP::getTreeCost() {
} }
SmallPtrSet<Value *, 16> ExtractCostCalculated; SmallPtrSet<Value *, 16> ExtractCostCalculated;
int ExtractCost = 0; InstructionCost ExtractCost = 0;
for (ExternalUser &EU : ExternalUses) { for (ExternalUser &EU : ExternalUses) {
// We only add extract cost once for the same scalar. // We only add extract cost once for the same scalar.
if (!ExtractCostCalculated.insert(EU.Scalar).second) if (!ExtractCostCalculated.insert(EU.Scalar).second)
@ -4101,7 +4101,7 @@ int BoUpSLP::getTreeCost() {
} }
} }
int SpillCost = getSpillCost(); InstructionCost SpillCost = getSpillCost();
Cost += SpillCost + ExtractCost; Cost += SpillCost + ExtractCost;
#ifndef NDEBUG #ifndef NDEBUG
@ -6009,10 +6009,10 @@ bool SLPVectorizerPass::vectorizeStoreChain(ArrayRef<Value *> Chain, BoUpSLP &R,
R.computeMinimumValueSizes(); R.computeMinimumValueSizes();
int Cost = R.getTreeCost(); InstructionCost Cost = R.getTreeCost();
LLVM_DEBUG(dbgs() << "SLP: Found cost = " << Cost << " for VF =" << VF << "\n"); LLVM_DEBUG(dbgs() << "SLP: Found cost = " << Cost << " for VF =" << VF << "\n");
if (Cost < -SLPCostThreshold) { if (Cost.isValid() && Cost < -SLPCostThreshold) {
LLVM_DEBUG(dbgs() << "SLP: Decided to vectorize cost = " << Cost << "\n"); LLVM_DEBUG(dbgs() << "SLP: Decided to vectorize cost = " << Cost << "\n");
using namespace ore; using namespace ore;
@ -6213,7 +6213,7 @@ bool SLPVectorizerPass::tryToVectorizeList(ArrayRef<Value *> VL, BoUpSLP &R,
bool Changed = false; bool Changed = false;
bool CandidateFound = false; bool CandidateFound = false;
int MinCost = SLPCostThreshold; InstructionCost MinCost = SLPCostThreshold.getValue();
bool CompensateUseCost = bool CompensateUseCost =
!InsertUses.empty() && llvm::all_of(InsertUses, [](const Value *V) { !InsertUses.empty() && llvm::all_of(InsertUses, [](const Value *V) {
@ -6269,7 +6269,7 @@ bool SLPVectorizerPass::tryToVectorizeList(ArrayRef<Value *> VL, BoUpSLP &R,
continue; continue;
R.computeMinimumValueSizes(); R.computeMinimumValueSizes();
int Cost = R.getTreeCost(); InstructionCost Cost = R.getTreeCost();
CandidateFound = true; CandidateFound = true;
if (CompensateUseCost) { if (CompensateUseCost) {
// TODO: Use TTI's getScalarizationOverhead for sequence of inserts // TODO: Use TTI's getScalarizationOverhead for sequence of inserts
@ -6299,7 +6299,7 @@ bool SLPVectorizerPass::tryToVectorizeList(ArrayRef<Value *> VL, BoUpSLP &R,
// Switching to the TTI interface might help a bit. // Switching to the TTI interface might help a bit.
// Alternative solution could be pattern-match to detect a no-op or // Alternative solution could be pattern-match to detect a no-op or
// shuffle. // shuffle.
unsigned UserCost = 0; InstructionCost UserCost = 0;
for (unsigned Lane = 0; Lane < OpsWidth; Lane++) { for (unsigned Lane = 0; Lane < OpsWidth; Lane++) {
auto *IE = cast<InsertElementInst>(InsertUses[I + Lane]); auto *IE = cast<InsertElementInst>(InsertUses[I + Lane]);
if (auto *CI = dyn_cast<ConstantInt>(IE->getOperand(2))) if (auto *CI = dyn_cast<ConstantInt>(IE->getOperand(2)))
@ -6311,9 +6311,9 @@ bool SLPVectorizerPass::tryToVectorizeList(ArrayRef<Value *> VL, BoUpSLP &R,
Cost -= UserCost; Cost -= UserCost;
} }
MinCost = std::min(MinCost, Cost); MinCost = InstructionCost::min(MinCost, Cost);
if (Cost < -SLPCostThreshold) { if (Cost.isValid() && Cost < -SLPCostThreshold) {
LLVM_DEBUG(dbgs() << "SLP: Vectorizing list at cost:" << Cost << ".\n"); LLVM_DEBUG(dbgs() << "SLP: Vectorizing list at cost:" << Cost << ".\n");
R.getORE()->emit(OptimizationRemark(SV_NAME, "VectorizedList", R.getORE()->emit(OptimizationRemark(SV_NAME, "VectorizedList",
cast<Instruction>(Ops[0])) cast<Instruction>(Ops[0]))
@ -7088,9 +7088,14 @@ public:
V.computeMinimumValueSizes(); V.computeMinimumValueSizes();
// Estimate cost. // Estimate cost.
int TreeCost = V.getTreeCost(); InstructionCost TreeCost = V.getTreeCost();
int ReductionCost = getReductionCost(TTI, ReducedVals[i], ReduxWidth); InstructionCost ReductionCost =
int Cost = TreeCost + ReductionCost; getReductionCost(TTI, ReducedVals[i], ReduxWidth);
InstructionCost Cost = TreeCost + ReductionCost;
if (!Cost.isValid()) {
LLVM_DEBUG(dbgs() << "Encountered invalid baseline cost.\n");
return false;
}
if (Cost >= -SLPCostThreshold) { if (Cost >= -SLPCostThreshold) {
V.getORE()->emit([&]() { V.getORE()->emit([&]() {
return OptimizationRemarkMissed(SV_NAME, "HorSLPNotBeneficial", return OptimizationRemarkMissed(SV_NAME, "HorSLPNotBeneficial",