mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-19 18:24:00 +00:00
Teach the SLP Vectorizer that keeping some values live over a callsite can have a cost.
Some types, such as 128-bit vector types on AArch64, don't have any callee-saved registers. So if a value needs to stay live over a callsite, it must be spilled and refilled. This cost is now taken into account. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214859 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -361,6 +361,10 @@ public:
|
||||
/// Returns the vectorized root.
|
||||
Value *vectorizeTree();
|
||||
|
||||
/// \returns the cost incurred by unwanted spills and fills, caused by
|
||||
/// holding live values over call sites.
|
||||
int getSpillCost();
|
||||
|
||||
/// \returns the vectorization cost of the subtree that starts at \p VL.
|
||||
/// A negative number means that this is profitable.
|
||||
int getTreeCost();
|
||||
@ -1543,6 +1547,68 @@ bool BoUpSLP::isFullyVectorizableTinyTree() {
|
||||
return true;
|
||||
}
|
||||
|
||||
int BoUpSLP::getSpillCost() {
|
||||
// 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,
|
||||
// query TTI to see if there is a cost to keeping values live over it
|
||||
// (for example, if spills and fills are required).
|
||||
unsigned BundleWidth = VectorizableTree.front().Scalars.size();
|
||||
int Cost = 0;
|
||||
|
||||
SmallPtrSet<Instruction*, 4> LiveValues;
|
||||
Instruction *PrevInst = nullptr;
|
||||
|
||||
for (unsigned N = 0; N < VectorizableTree.size(); ++N) {
|
||||
Instruction *Inst = dyn_cast<Instruction>(VectorizableTree[N].Scalars[0]);
|
||||
if (!Inst)
|
||||
continue;
|
||||
|
||||
if (!PrevInst) {
|
||||
PrevInst = Inst;
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(
|
||||
dbgs() << "SLP: #LV: " << LiveValues.size();
|
||||
for (auto *X : LiveValues)
|
||||
dbgs() << " " << X->getName();
|
||||
dbgs() << ", Looking at ";
|
||||
Inst->dump();
|
||||
);
|
||||
|
||||
// Update LiveValues.
|
||||
LiveValues.erase(PrevInst);
|
||||
for (auto &J : PrevInst->operands()) {
|
||||
if (isa<Instruction>(&*J) && ScalarToTreeEntry.count(&*J))
|
||||
LiveValues.insert(cast<Instruction>(&*J));
|
||||
}
|
||||
|
||||
// Now find the sequence of instructions between PrevInst and Inst.
|
||||
BasicBlock::reverse_iterator InstIt(Inst), PrevInstIt(PrevInst);
|
||||
--PrevInstIt;
|
||||
while (InstIt != PrevInstIt) {
|
||||
if (PrevInstIt == PrevInst->getParent()->rend()) {
|
||||
PrevInstIt = Inst->getParent()->rbegin();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isa<CallInst>(&*PrevInstIt) && &*PrevInstIt != PrevInst) {
|
||||
SmallVector<Type*, 4> V;
|
||||
for (auto *II : LiveValues)
|
||||
V.push_back(VectorType::get(II->getType(), BundleWidth));
|
||||
Cost += TTI->getCostOfKeepingLiveOverCall(V);
|
||||
}
|
||||
|
||||
++PrevInstIt;
|
||||
}
|
||||
|
||||
PrevInst = Inst;
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "SLP: SpillCost=" << Cost << "\n");
|
||||
return Cost;
|
||||
}
|
||||
|
||||
int BoUpSLP::getTreeCost() {
|
||||
int Cost = 0;
|
||||
DEBUG(dbgs() << "SLP: Calculating cost for tree of size " <<
|
||||
@ -1578,6 +1644,8 @@ int BoUpSLP::getTreeCost() {
|
||||
I->Lane);
|
||||
}
|
||||
|
||||
Cost += getSpillCost();
|
||||
|
||||
DEBUG(dbgs() << "SLP: Total Cost " << Cost + ExtractCost<< ".\n");
|
||||
return Cost + ExtractCost;
|
||||
}
|
||||
|
Reference in New Issue
Block a user