LLVM 23.0.0git
CodeMoverUtils.cpp
Go to the documentation of this file.
1//===- CodeMoverUtils.cpp - CodeMover Utilities ----------------------------==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This family of functions perform movements on basic blocks, and instructions
10// contained within a function.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/Statistic.h"
19#include "llvm/IR/Dominators.h"
20
21using namespace llvm;
22
23#define DEBUG_TYPE "codemover-utils"
24
25STATISTIC(HasDependences,
26 "Cannot move across instructions that has memory dependences");
27STATISTIC(MayThrowException, "Cannot move across instructions that may throw");
28STATISTIC(NotMovedPHINode, "Movement of PHINodes are not supported");
29STATISTIC(NotMovedTerminator, "Movement of Terminator are not supported");
30
31static bool domTreeLevelBefore(DominatorTree *DT, const Instruction *InstA,
32 const Instruction *InstB) {
33 // Use ordered basic block in case the 2 instructions are in the same
34 // block.
35 if (InstA->getParent() == InstB->getParent())
36 return InstA->comesBefore(InstB);
37
38 DomTreeNode *DA = DT->getNode(InstA->getParent());
39 DomTreeNode *DB = DT->getNode(InstB->getParent());
40 return DA->getLevel() < DB->getLevel();
41}
42
44 llvm::Statistic &Stat) {
45 ++Stat;
46 LLVM_DEBUG(dbgs() << "Unable to move instruction: " << I << ". "
47 << Stat.getDesc());
48 return false;
49}
50
51/// Collect all instructions in between \p StartInst and \p EndInst, and store
52/// them in \p InBetweenInsts.
53static void
55 SmallPtrSetImpl<Instruction *> &InBetweenInsts) {
56 assert(InBetweenInsts.empty() && "Expecting InBetweenInsts to be empty");
57
58 /// Get the next instructions of \p I, and push them to \p WorkList.
59 auto getNextInsts = [](Instruction &I,
61 if (Instruction *NextInst = I.getNextNode())
62 WorkList.insert(NextInst);
63 else {
64 assert(I.isTerminator() && "Expecting a terminator instruction");
65 for (BasicBlock *Succ : successors(&I))
66 WorkList.insert(&Succ->front());
67 }
68 };
69
71 getNextInsts(StartInst, WorkList);
72 while (!WorkList.empty()) {
73 Instruction *CurInst = *WorkList.begin();
74 WorkList.erase(CurInst);
75
76 if (CurInst == &EndInst)
77 continue;
78
79 if (!InBetweenInsts.insert(CurInst).second)
80 continue;
81
82 getNextInsts(*CurInst, WorkList);
83 }
84}
85
87 DominatorTree &DT, const PostDominatorTree *PDT,
88 DependenceInfo *DI, bool CheckForEntireBlock) {
89 // Skip tests when we don't have PDT or DI
90 if (!PDT || !DI)
91 return false;
92
93 // Cannot move itself before itself.
94 if (&I == &InsertPoint)
95 return false;
96
97 // Not moved.
98 if (I.getNextNode() == &InsertPoint)
99 return true;
100
102 return reportInvalidCandidate(I, NotMovedPHINode);
103
104 if (I.isTerminator())
105 return reportInvalidCandidate(I, NotMovedTerminator);
106
107 if (isReachedBefore(&I, &InsertPoint, &DT, PDT))
108 for (const Use &U : I.uses())
109 if (auto *UserInst = dyn_cast<Instruction>(U.getUser())) {
110 // If InsertPoint is in a BB that comes after I, then we cannot move if
111 // I is used in the terminator of the current BB.
112 if (I.getParent() == InsertPoint.getParent() &&
113 UserInst == I.getParent()->getTerminator())
114 return false;
115 if (UserInst != &InsertPoint && !DT.dominates(&InsertPoint, U)) {
116 // If UserInst is an instruction that appears later in the same BB as
117 // I, then it is okay to move since I will still be available when
118 // UserInst is executed.
119 if (CheckForEntireBlock && I.getParent() == UserInst->getParent() &&
120 DT.dominates(&I, UserInst))
121 continue;
122 return false;
123 }
124 }
125 if (isReachedBefore(&InsertPoint, &I, &DT, PDT))
126 for (const Value *Op : I.operands())
127 if (auto *OpInst = dyn_cast<Instruction>(Op)) {
128 if (&InsertPoint == OpInst)
129 return false;
130 // If OpInst is an instruction that appears earlier in the same BB as
131 // I, then it is okay to move since OpInst will still be available.
132 if (CheckForEntireBlock && I.getParent() == OpInst->getParent() &&
133 DT.dominates(OpInst, &I))
134 continue;
135 if (!DT.dominates(OpInst, &InsertPoint))
136 return false;
137 }
138
139 DT.updateDFSNumbers();
140 const bool MoveForward = domTreeLevelBefore(&DT, &I, &InsertPoint);
141 Instruction &StartInst = (MoveForward ? I : InsertPoint);
142 Instruction &EndInst = (MoveForward ? InsertPoint : I);
144 collectInstructionsInBetween(StartInst, EndInst, InstsToCheck);
145 if (!MoveForward)
146 InstsToCheck.insert(&InsertPoint);
147
148 // Check if there exists instructions which may throw, may synchonize, or may
149 // never return, from I to InsertPoint.
151 if (llvm::any_of(InstsToCheck, [](Instruction *I) {
152 if (I->mayThrow())
153 return true;
154
155 const CallBase *CB = dyn_cast<CallBase>(I);
156 if (!CB)
157 return false;
158 if (!CB->hasFnAttr(Attribute::WillReturn))
159 return true;
160 if (!CB->hasFnAttr(Attribute::NoSync))
161 return true;
162
163 return false;
164 })) {
165 return reportInvalidCandidate(I, MayThrowException);
166 }
167
168 // Check if I has any output/flow/anti dependences with instructions from \p
169 // StartInst to \p EndInst.
170 if (llvm::any_of(InstsToCheck, [&DI, &I](Instruction *CurInst) {
171 auto DepResult = DI->depends(&I, CurInst);
172 if (DepResult && (DepResult->isOutput() || DepResult->isFlow() ||
173 DepResult->isAnti()))
174 return true;
175 return false;
176 }))
177 return reportInvalidCandidate(I, HasDependences);
178
179 return true;
180}
181
183 DominatorTree &DT, const PostDominatorTree *PDT,
184 DependenceInfo *DI) {
185 return llvm::all_of(BB, [&](Instruction &I) {
186 if (BB.getTerminator() == &I)
187 return true;
188
189 return isSafeToMoveBefore(I, InsertPoint, DT, PDT, DI,
190 /*CheckForEntireBlock=*/true);
191 });
192}
193
195 DominatorTree &DT,
196 const PostDominatorTree &PDT,
197 DependenceInfo &DI) {
198 for (Instruction &I :
201
202 if (isSafeToMoveBefore(I, *MovePos, DT, &PDT, &DI))
203 I.moveBeforePreserving(MovePos);
204 }
205}
206
208 DominatorTree &DT,
209 const PostDominatorTree &PDT,
210 DependenceInfo &DI) {
211 Instruction *MovePos = ToBB.getTerminator();
212 while (FromBB.size() > 1) {
213 Instruction &I = FromBB.front();
214 if (isSafeToMoveBefore(I, *MovePos, DT, &PDT, &DI))
215 I.moveBeforePreserving(MovePos->getIterator());
216 }
217}
218
220 const BasicBlock *OtherBlock,
221 const DominatorTree *DT,
222 const PostDominatorTree *PDT) {
223 const BasicBlock *CommonDominator =
224 DT->findNearestCommonDominator(ThisBlock, OtherBlock);
225 if (CommonDominator == nullptr)
226 return false;
227
228 /// Recursively check the predecessors of \p ThisBlock up to
229 /// their common dominator, and see if any of them post-dominates
230 /// \p OtherBlock.
233 WorkList.push_back(ThisBlock);
234 while (!WorkList.empty()) {
235 const BasicBlock *CurBlock = WorkList.pop_back_val();
236 Visited.insert(CurBlock);
237 if (PDT->dominates(CurBlock, OtherBlock))
238 return true;
239
240 for (const auto *Pred : predecessors(CurBlock)) {
241 if (Pred == CommonDominator || Visited.count(Pred))
242 continue;
243 WorkList.push_back(Pred);
244 }
245 }
246 return false;
247}
248
250 const DominatorTree *DT,
251 const PostDominatorTree *PDT) {
252 const BasicBlock *BB0 = I0->getParent();
253 const BasicBlock *BB1 = I1->getParent();
254 if (BB0 == BB1)
255 return DT->dominates(I0, I1);
256
257 return nonStrictlyPostDominate(BB1, BB0, DT, PDT);
258}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool reportInvalidCandidate(const Instruction &I, llvm::Statistic &Stat)
static bool domTreeLevelBefore(DominatorTree *DT, const Instruction *InstA, const Instruction *InstB)
static void collectInstructionsInBetween(Instruction &StartInst, const Instruction &EndInst, SmallPtrSetImpl< Instruction * > &InBetweenInsts)
Collect all instructions in between StartInst and EndInst, and store them in InBetweenInsts.
#define I(x, y, z)
Definition MD5.cpp:57
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:114
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
const Instruction & front() const
Definition BasicBlock.h:493
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
size_t size() const
Definition BasicBlock.h:491
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition BasicBlock.h:233
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
DependenceInfo - This class is the main dependence-analysis driver.
LLVM_ABI std::unique_ptr< Dependence > depends(Instruction *Src, Instruction *Dst, bool UnderRuntimeAssumptions=false)
depends - Tests for a dependence between the Src and Dst instructions.
void updateDFSNumbers() const
updateDFSNumbers - Assign In and Out numbers to the nodes while walking dominator tree in dfs order.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:164
LLVM_ABI Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
LLVM_ABI bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
iterator begin() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1737
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto successors(const MachineBasicBlock *BB)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:632
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
LLVM_ABI void moveInstructionsToTheEnd(BasicBlock &FromBB, BasicBlock &ToBB, DominatorTree &DT, const PostDominatorTree &PDT, DependenceInfo &DI)
Move instructions, in an order-preserving manner, from FromBB to the end of ToBB when proven safe.
LLVM_ABI bool isReachedBefore(const Instruction *I0, const Instruction *I1, const DominatorTree *DT, const PostDominatorTree *PDT)
DomTreeNodeBase< BasicBlock > DomTreeNode
Definition Dominators.h:94
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1744
NoopStatistic Statistic
Definition Statistic.h:162
auto reverse(ContainerTy &&C)
Definition STLExtras.h:406
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
LLVM_ABI bool nonStrictlyPostDominate(const BasicBlock *ThisBlock, const BasicBlock *OtherBlock, const DominatorTree *DT, const PostDominatorTree *PDT)
In case that two BBs ThisBlock and OtherBlock are control flow equivalent but they do not strictly do...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI void moveInstructionsToTheBeginning(BasicBlock &FromBB, BasicBlock &ToBB, DominatorTree &DT, const PostDominatorTree &PDT, DependenceInfo &DI)
Move instructions, in an order-preserving manner, from FromBB to the beginning of ToBB when proven sa...
DWARFExpression::Operation Op
auto predecessors(const MachineBasicBlock *BB)
LLVM_ABI bool isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, DominatorTree &DT, const PostDominatorTree *PDT=nullptr, DependenceInfo *DI=nullptr, bool CheckForEntireBlock=false)
Return true if I can be safely moved before InsertPoint.