94 #define DEBUG_TYPE "mldst-motion"
108 const int MagicCompileTimeControl = 250;
122 bool isLoadHoistBarrierInRange(
const Instruction &Start,
124 bool SafeToLoadUnconditionally);
134 bool isStoreSinkBarrierInRange(
const Instruction &Start,
144 void MergedLoadStoreMotion::removeInstruction(
Instruction *Inst) {
147 MD->removeInstruction(Inst);
148 if (
auto *LI = dyn_cast<LoadInst>(Inst))
149 MD->invalidateCachedPointerInfo(LI->getPointerOperand());
151 MD->invalidateCachedPointerInfo(Inst);
161 assert(isDiamondHead(BB) &&
"Basic block is not head of a diamond");
168 bool MergedLoadStoreMotion::isDiamondHead(
BasicBlock *BB) {
172 if (!BI || !BI->isConditional())
186 if (!Succ0Succ || !Succ1Succ || Succ0Succ != Succ1Succ)
198 bool MergedLoadStoreMotion::isLoadHoistBarrierInRange(
200 bool SafeToLoadUnconditionally) {
201 if (!SafeToLoadUnconditionally)
207 return AA->canInstructionRangeModRef(Start, End, Loc,
MRI_Mod);
237 !isLoadHoistBarrierInRange(BB1->
front(), *Load1, Load1,
238 SafeToLoadUnconditionally) &&
239 !isLoadHoistBarrierInRange(BB0->
front(), *Load0, Load0,
240 SafeToLoadUnconditionally)) {
253 void MergedLoadStoreMotion::hoistInstruction(
BasicBlock *BB,
257 dbgs() <<
"Instruction Left\n"; HoistCand->
dump();
dbgs() <<
"\n";
258 dbgs() <<
"Instruction Right\n"; ElseInst->
dump();
dbgs() <<
"\n");
276 removeInstruction(HoistCand);
279 removeInstruction(ElseInst);
285 bool MergedLoadStoreMotion::isSafeToHoist(
Instruction *
I)
const {
288 if (
auto *Instr = dyn_cast<Instruction>(&U))
289 if (Instr->getParent() == Parent)
302 if (A0 && A1 && A0->isIdenticalTo(A1) && isSafeToHoist(A0) &&
303 A0->hasOneUse() && (A0->getParent() == L0->
getParent()) &&
304 A1->hasOneUse() && (A1->getParent() == L1->
getParent()) &&
305 isa<GetElementPtrInst>(A0)) {
307 dbgs() <<
"Instruction Left\n"; L0->
dump();
dbgs() <<
"\n";
308 dbgs() <<
"Instruction Right\n"; L1->
dump();
dbgs() <<
"\n");
309 hoistInstruction(BB, A0, A1);
310 hoistInstruction(BB, L0, L1);
322 bool MergedLoadStoreMotion::mergeLoads(
BasicBlock *BB) {
323 bool MergedLoads =
false;
324 assert(isDiamondHead(BB));
329 int Size1 = Succ1->
size();
342 if (NLoads * Size1 >= MagicCompileTimeControl)
344 if (
LoadInst *L1 = canHoistFromBlock(Succ1, L0)) {
345 bool Res = hoistLoad(BB, L0, L1);
363 bool MergedLoadStoreMotion::isStoreSinkBarrierInRange(
const Instruction &Start,
370 return AA->canInstructionRangeModRef(Start, End, Loc,
MRI_ModRef);
390 !isStoreSinkBarrierInRange(*Store1->getNextNode(), BB1->
back(), Loc1) &&
391 !isStoreSinkBarrierInRange(*Store0->
getNextNode(), BB0->back(), Loc0)) {
412 NewPN->addIncoming(Opd2, S1->
getParent());
413 if (MD && NewPN->getType()->getScalarType()->isPointerTy())
414 MD->invalidateCachedPointerInfo(NewPN);
428 if (A0 && A1 && A0->isIdenticalTo(A1) && A0->hasOneUse() &&
429 (A0->getParent() == S0->
getParent()) && A1->hasOneUse() &&
430 (A1->getParent() == S1->
getParent()) && isa<GetElementPtrInst>(A0)) {
432 dbgs() <<
"Instruction Left\n"; S0->
dump();
dbgs() <<
"\n";
433 dbgs() <<
"Instruction Right\n"; S1->
dump();
dbgs() <<
"\n");
444 ANew->insertBefore(SNew);
450 if (
PHINode *NewPN = getPHIOperand(BB, S0, S1))
452 removeInstruction(S0);
453 removeInstruction(S1);
454 A0->replaceAllUsesWith(ANew);
455 removeInstruction(A0);
456 A1->replaceAllUsesWith(ANew);
457 removeInstruction(A1);
469 bool MergedLoadStoreMotion::mergeStores(
BasicBlock *
T) {
471 bool MergedStores =
false;
472 assert(T &&
"Footer of a diamond cannot be empty");
487 int Size1 = Pred1->
size();
502 if (NStores * Size1 >= MagicCompileTimeControl)
504 if (
StoreInst *S1 = canSinkFromBlock(Pred1, S0)) {
505 bool Res = sinkStore(T, S0, S1);
526 bool Changed =
false;
536 if (isDiamondHead(BB)) {
537 Changed |= mergeLoads(BB);
538 Changed |= mergeStores(getDiamondTail(BB));
545 class MergedLoadStoreMotionLegacyPass :
public FunctionPass {
556 bool runOnFunction(
Function &F)
override {
560 auto *MDWP = getAnalysisIfAvailable<MemoryDependenceWrapperPass>();
561 return Impl.run(F, MDWP ? &MDWP->getMemDep() :
nullptr,
562 getAnalysis<AAResultsWrapperPass>().getAAResults());
581 return new MergedLoadStoreMotionLegacyPass();
585 "MergedLoadStoreMotion",
false,
false)
593 MergedLoadStoreMotion Impl;
596 if (!Impl.run(F, MD, AA))
Legacy wrapper pass to provide the GlobalsAAResult object.
Value * getValueOperand()
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Provides a lazy, caching interface for making common memory aliasing information queries, backed by LLVM's alias analysis passes.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
const Instruction & back() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This is the interface for a simple mod/ref and alias analysis over globals.
void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs)
Drop all unknown metadata except for debug locations.
bool isUsedOutsideOfBlock(const BasicBlock *BB) const
Return true if there are any uses of this instruction in blocks other than the specified block...
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction & front() const
An instruction for reading from memory.
reverse_iterator rbegin()
bool isSafeToLoadUnconditionally(Value *V, unsigned Align, const DataLayout &DL, Instruction *ScanFrom=nullptr, const DominatorTree *DT=nullptr)
Return true if we know that executing a load from this value cannot trap.
The access modifies the value stored in memory.
StringRef getName() const
Return a constant reference to the value's name.
iterator begin()
Instruction iterator methods.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
A Use represents the edge between a Value definition and its users.
mldst MergedLoadStoreMotion
An analysis that produces MemoryDependenceResults for a function.
Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following: ...
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction...
BasicBlock * getSuccessor(unsigned i) const
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
A set of analyses that are preserved following a run of a transformation pass.
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction...
LLVM Basic Block Representation.
BasicBlock * getSuccessor(unsigned idx) const
Return the specified successor.
Conditional or Unconditional Branch instruction.
A manager for alias analyses.
Interval::pred_iterator pred_begin(Interval *I)
pred_begin/pred_end - define methods so that Intervals may be used just like BasicBlocks can with the...
Represent the analysis usage information of a pass.
Analysis pass providing a never-invalidated alias analysis result.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
static const unsigned End
FunctionPass class - This class is used to implement most global optimizations.
Interval::pred_iterator pred_end(Interval *I)
Value * getPointerOperand()
self_iterator getIterator()
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
A wrapper analysis pass for the legacy pass manager that exposes a MemoryDepnedenceResults instance...
void dump() const
Support for debugging, callable in GDB: V->dump()
Representation for a specific memory location.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Iterator for intrusive lists based on ilist_node.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
Type * getType() const
All values are typed, get the type of this value.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
void setPreservesCFG()
This function should be called by the pass, iff they do not:
void setOperand(unsigned i, Value *Val)
FunctionPass * createMergedLoadStoreMotionPass()
createMergedLoadStoreMotionPass - The public interface to this file.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
BasicBlock * getSingleSuccessor()
Return the successor of this block if it has a single successor.
BasicBlock * getSinglePredecessor()
Return the predecessor of this block if it has a single predecessor block.
INITIALIZE_PASS_BEGIN(MergedLoadStoreMotionLegacyPass,"mldst-motion","MergedLoadStoreMotion", false, false) INITIALIZE_PASS_END(MergedLoadStoreMotionLegacyPass
This pass performs merges of loads and stores on both sides of a.
bool mayThrow() const
Return true if this instruction may throw an exception.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
The access both references and modifies the value stored in memory.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void preserve()
Mark an analysis as preserved.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
A container for analyses that lazily runs them and caches their results.
bool isSameOperationAs(const Instruction *I, unsigned flags=0) const
This function determines if the specified instruction executes the same operation as the current one...
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry &)
Value * getPointerOperand()
const BasicBlock * getParent() const