26 #define DEBUG_TYPE "spec-phis" 28 STATISTIC(NumPHIsSpeculated,
"Number of PHI nodes we speculated around");
30 "Number of critical edges which were split for speculation");
32 "Number of instructions we speculated around the PHI nodes");
34 "Number of new, redundant instructions inserted");
59 auto *UI = cast<Instruction>(U.getUser());
66 if (UI->getParent() != PhiBB) {
67 LLVM_DEBUG(
dbgs() <<
" Unsafe: use in a different BB: " << *UI <<
"\n");
78 LLVM_DEBUG(
dbgs() <<
" Unsafe: can't speculate use: " << *UI <<
"\n");
86 DFSStack.
push_back({UI, UI->value_op_begin()});
91 while (OpIt != UI->value_op_end()) {
110 if (ParentBB == PhiBB) {
111 if (isa<PHINode>(OpI)) {
115 }
else if (DT.
dominates(ParentBB, PhiBB)) {
122 if (PotentialSpecSet.
count(OpI))
127 if (UnsafeSet.
count(OpI) || ParentBB != PhiBB ||
134 for (
auto &StackPair : DFSStack) {
142 if (!Visited.
insert(OpI).second)
149 OpIt = OpI->value_op_begin();
154 PotentialSpecSet.
insert(UI);
157 }
while (!DFSStack.
empty());
163 for (
auto *
I : Visited)
165 "Failed to mark a visited instruction as safe!");
203 bool NonFreeMat =
false;
204 struct CostsAndCount {
220 auto InsertResult = CostsAndCounts.
insert({IncomingC, {}});
222 ++InsertResult.first->second.Count;
224 if (!InsertResult.second)
227 int &MatCost = InsertResult.first->second.MatCost;
228 MatCost = TTI.
getIntImmCost(IncomingC->getValue(), IncomingC->getType());
229 NonFreeMat |= MatCost != TTI.
TCC_Free;
247 auto *UserI = cast<Instruction>(U.getUser());
250 unsigned Idx = U.getOperandNo();
265 if (UserI->isBinaryOp() && UserI->isCommutative() && Idx != 1)
271 if (
auto *UserII = dyn_cast<IntrinsicInst>(UserI))
272 IID = UserII->getIntrinsicID();
274 for (
auto &IncomingConstantAndCostsAndCount : CostsAndCounts) {
275 ConstantInt *IncomingC = IncomingConstantAndCostsAndCount.first;
276 int MatCost = IncomingConstantAndCostsAndCount.second.MatCost;
277 int &FoldedCost = IncomingConstantAndCostsAndCount.second.FoldedCost;
290 if (FoldedCost > MatCost) {
291 LLVM_DEBUG(
dbgs() <<
" Not profitable to fold imm: " << *IncomingC
293 " Materializing cost: " 296 " Accumulated folded cost: " 297 << FoldedCost <<
"\n");
305 for (
auto IncomingConstantAndCostsAndCount : CostsAndCounts) {
306 int MatCost = IncomingConstantAndCostsAndCount.second.MatCost;
307 int FoldedCost = IncomingConstantAndCostsAndCount.second.FoldedCost;
308 int Count = IncomingConstantAndCostsAndCount.second.Count;
310 TotalMatCost += MatCost * Count;
311 TotalFoldedCost += FoldedCost * Count;
313 assert(TotalFoldedCost <= TotalMatCost &&
"If each constant's folded cost is " 314 "less that its materialized cost, " 315 "the sum must be as well.");
317 LLVM_DEBUG(
dbgs() <<
" Cost savings " << (TotalMatCost - TotalFoldedCost)
318 <<
": " << PN <<
"\n");
319 CostSavingsMap[&PN] = TotalMatCost - TotalFoldedCost;
335 template <
typename IsVisitedT,
typename VisitT>
337 IsVisitedT IsVisited,
342 auto *UI = cast<Instruction>(U.getUser());
349 DFSStack.
push_back({UI, UI->value_op_begin()});
353 while (OpIt != UI->value_op_end()) {
361 if (!OpI || IsVisited(OpI))
368 OpIt = OpI->value_op_begin();
372 assert(!IsVisited(UI) &&
"Should not have already visited a node!");
374 }
while (!DFSStack.
empty());
426 for (
auto *PN : PNs) {
427 assert(UserSet.
empty() &&
"Must start with an empty user set!");
429 UserSet.
insert(cast<Instruction>(U.getUser()));
430 PNUserCountMap[PN] = UserSet.
size();
431 for (
auto *UI : UserSet)
432 UserToPNMap.
insert({UI, {}}).
first->second.push_back(PN);
448 return !PotentialSpecSet.
count(I) || SpecCostMap.
count(I);
456 if (
auto *OpI = dyn_cast<Instruction>(OpV)) {
457 auto CostMapIt = SpecCostMap.
find(OpI);
458 if (CostMapIt != SpecCostMap.
end())
459 Cost += CostMapIt->second;
464 assert(Inserted &&
"Must not re-insert a cost during the DFS!");
468 auto UserPNsIt = UserToPNMap.
find(I);
469 if (UserPNsIt == UserToPNMap.
end())
471 auto &UserPNs = UserPNsIt->second;
472 auto UserPNsSplitIt = std::stable_partition(
473 UserPNs.begin(), UserPNs.end(), [&](
PHINode *UserPN) {
474 int &PNUserCount = PNUserCountMap.
find(UserPN)->second;
477 "Should never re-visit a PN after its user count hits zero!");
479 return PNUserCount != 0;
489 SpecCostMap.
find(cast<Instruction>(U.getUser()))->second;
490 SpecCost *= (NumPreds - 1);
494 int CostSavings = CostSavingsMap.
find(PN)->second;
495 if (SpecCost > CostSavings) {
501 " Speculation cost: " 502 << SpecCost <<
"\n");
510 auto *UI = cast<Instruction>(U.getUser());
511 auto CostMapIt = SpecCostMap.
find(UI);
512 if (CostMapIt->second == 0)
515 CostMapIt->second = 0;
516 SpecWorklist.push_back(UI);
522 while (!SpecWorklist.empty()) {
524 assert(SpecCostMap.
find(SpecI)->second == 0 &&
525 "Didn't zero out a cost!");
532 auto CostMapIt = SpecCostMap.
find(OpI);
533 if (CostMapIt == SpecCostMap.
end() || CostMapIt->second == 0)
535 CostMapIt->second = 0;
536 SpecWorklist.push_back(OpI);
557 NumPHIsSpeculated += SpecPNs.
size();
560 auto *ParentBB = SpecPNs[0]->getParent();
563 for (
auto *PredBB : PredSet) {
569 LLVM_DEBUG(
dbgs() <<
" Split critical edge from: " << PredBB->getName()
573 assert(PredBB->getSingleSuccessor() == ParentBB &&
574 "We need a non-critical predecessor to speculate into.");
575 assert(!isa<InvokeInst>(PredBB->getTerminator()) &&
576 "Cannot have a non-critical invoke!");
591 return !PotentialSpecSet.
count(I) ||
602 int NumSpecInsts = SpecList.
size() * SpecPreds.
size();
603 int NumRedundantInsts = NumSpecInsts - SpecList.
size();
605 <<
" speculated instructions, " << NumRedundantInsts
606 <<
" redundancies\n");
607 NumSpeculatedInstructions += NumSpecInsts;
608 NumNewRedundantInstructions += NumRedundantInsts;
619 for (
auto *OrigI : SpecList)
620 for (
auto *OpV : OrigI->operand_values()) {
622 if (!OpPN || OpPN->getParent() != ParentBB)
625 auto InsertResult = SpeculatedValueMap.
insert({OpPN, {}});
626 if (!InsertResult.second)
629 auto &SpeculatedVals = InsertResult.first->second;
637 for (
int i : llvm::seq<int>(0, OpPN->getNumIncomingValues()))
638 IncomingValueMap[OpPN->getIncomingBlock(i)] = OpPN->getIncomingValue(i);
640 for (
auto *PredBB : SpecPreds)
641 SpeculatedVals.push_back(IncomingValueMap.
find(PredBB)->second);
645 for (
int PredIdx : llvm::seq<int>(0, SpecPreds.
size())) {
646 auto *PredBB = SpecPreds[PredIdx];
647 assert(PredBB->getSingleSuccessor() == ParentBB &&
648 "We need a non-critical predecessor to speculate into.");
650 for (
auto *OrigI : SpecList) {
651 auto *NewI = OrigI->clone();
652 NewI->setName(
Twine(OrigI->getName()) +
"." +
Twine(PredIdx));
653 NewI->insertBefore(PredBB->getTerminator());
658 for (
Use &U : NewI->operands()) {
662 auto MapIt = SpeculatedValueMap.
find(OpI);
663 if (MapIt == SpeculatedValueMap.
end())
665 const auto &SpeculatedVals = MapIt->second;
666 assert(SpeculatedVals[PredIdx] &&
667 "Must have a speculated value for this predecessor!");
668 assert(SpeculatedVals[PredIdx]->
getType() == OpI->getType() &&
669 "Speculated value has the wrong type!");
672 U.set(SpeculatedVals[PredIdx]);
677 if (NewI->isBinaryOp() && NewI->isCommutative() &&
678 isa<Constant>(NewI->getOperand(0)) &&
679 !isa<Constant>(NewI->getOperand(1)))
680 NewI->getOperandUse(0).swap(NewI->getOperandUse(1));
682 SpeculatedValueMap[OrigI].push_back(NewI);
683 assert(SpeculatedValueMap[OrigI][PredIdx] == NewI &&
684 "Mismatched speculated instruction index!");
696 if (!OrigI->use_empty()) {
697 auto *SpecIPN = IRB.
CreatePHI(OrigI->getType(), SpecPreds.
size(),
698 Twine(OrigI->getName()) +
".phi");
700 auto &SpeculatedVals = SpeculatedValueMap.
find(OrigI)->second;
701 for (
int PredIdx : llvm::seq<int>(0, SpecPreds.
size()))
702 SpecIPN->addIncoming(SpeculatedVals[PredIdx], SpecPreds[PredIdx]);
705 OrigI->replaceAllUsesWith(SpecIPN);
710 OrigI->eraseFromParent();
715 for (
auto *SpecPN : SpecPNs) {
716 assert(SpecPN->use_empty() &&
"All users should have been speculated!");
717 SpecPN->eraseFromParent();
751 *PN, CostSavingsMap, PotentialSpecSet,
764 for (
auto *PredBB : PNs[0]->blocks()) {
765 if (!PredSet.
insert(PredBB))
773 if (isa<IndirectBrInst>(PredBB->getTerminator()) ||
774 isa<InvokeInst>(PredBB->getTerminator())) {
776 << PredBB->getName() <<
"\n");
780 if (PredSet.
size() < 2) {
781 LLVM_DEBUG(
dbgs() <<
" Unimportant: phi with only one predecessor\n");
786 PNs, CostSavingsMap, PotentialSpecSet, PredSet.
size(), DT, TTI);
800 bool Changed =
false;
803 auto BBI = BB->
begin();
804 while (
auto *PN = dyn_cast<PHINode>(&*BBI)) {
IntegerType * getType() const
getType - Specialize the getType() method to always return an IntegerType, which reduces the amount o...
This routine provides some synthesis utilities to produce sequences of values.
iterator_range< use_iterator > uses()
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents lattice values for constants.
size_type size() const
Determine the number of elements in the SetVector.
void push_back(const T &Elt)
Analysis pass providing the TargetTransformInfo.
STATISTIC(NumFunctions, "Total number of functions")
Analysis pass which computes a DominatorTree.
void reserve(size_type N)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Option class for critical edge splitting.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
A Use represents the edge between a Value definition and its users.
static bool isSafeToSpeculatePHIUsers(PHINode &PN, DominatorTree &DT, SmallPtrSetImpl< Instruction *> &PotentialSpecSet, SmallPtrSetImpl< Instruction *> &UnsafeSet)
Check whether speculating the users of a PHI node around the PHI will be safe.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
bool insert(const value_type &X)
Insert a new element into the SetVector.
DenseMap< BasicBlock *, Value * > IncomingValueMap
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
const APInt & getValue() const
Return the constant as an APInt value reference.
BasicBlock * SplitCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions())
If this edge is a critical edge, insert a new node to split the critical edge.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
iterator find(const_arg_type_t< KeyT > Val)
A set of analyses that are preserved following a run of a transformation pass.
size_t size() const
size - Get the array size.
static SmallVector< PHINode *, 16 > findProfitablePHIs(ArrayRef< PHINode *> PNs, const SmallDenseMap< PHINode *, int, 16 > &CostSavingsMap, const SmallPtrSetImpl< Instruction *> &PotentialSpecSet, int NumPreds, DominatorTree &DT, TargetTransformInfo &TTI)
Find profitable PHIs to speculate.
LLVM_NODISCARD bool empty() const
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
static bool tryToSpeculatePHIs(SmallVectorImpl< PHINode *> &PNs, DominatorTree &DT, TargetTransformInfo &TTI)
Try to speculate around a series of PHIs from a single basic block.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly...
static void visitPHIUsersAndDepsInPostOrder(ArrayRef< PHINode *> PNs, IsVisitedT IsVisited, VisitT Visit)
Simple helper to walk all the users of a list of phis depth first, and call a visit function on each ...
iterator erase(const_iterator CI)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static wasm::ValType getType(const TargetRegisterClass *RC)
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Iterator for directly iterating over the operand Values.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
A SetVector that performs no allocations if smaller than a certain size.
This is the shared class of boolean and integer constants.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_NODISCARD T pop_back_val()
unsigned getNumIncomingValues() const
Return the number of incoming edges.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
bool mayBeMemoryDependent(const Instruction &I)
Returns true if the result or effects of the given instructions I depend on or influence global memor...
LLVM_NODISCARD bool empty() const
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
iterator_range< value_op_iterator > operand_values()
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
static bool isSafeAndProfitableToSpeculateAroundPHI(PHINode &PN, SmallDenseMap< PHINode *, int, 16 > &CostSavingsMap, SmallPtrSetImpl< Instruction *> &PotentialSpecSet, SmallPtrSetImpl< Instruction *> &UnsafeSet, DominatorTree &DT, TargetTransformInfo &TTI)
Check whether, in isolation, a given PHI node is both safe and profitable to speculate users around...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
static void speculatePHIs(ArrayRef< PHINode *> SpecPNs, SmallPtrSetImpl< Instruction *> &PotentialSpecSet, SmallSetVector< BasicBlock *, 16 > &PredSet, DominatorTree &DT)
Speculate users around a set of PHI nodes.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
A container for analyses that lazily runs them and caches their results.
const BasicBlock * getParent() const