91#define DEBUG_TYPE "mldst-motion"
104 const int MagicCompileTimeControl = 250;
106 const bool SplitFooterBB;
117 bool isStoreSinkBarrierInRange(
const Instruction &Start,
130 assert(isDiamondHead(BB) &&
"Basic block is not head of a diamond");
137bool MergedLoadStoreMotion::isDiamondHead(
BasicBlock *BB) {
141 if (!BI || !BI->isConditional())
155 if (!Succ0Succ || !Succ1Succ || Succ0Succ != Succ1Succ)
169bool MergedLoadStoreMotion::isStoreSinkBarrierInRange(
const Instruction &Start,
176 return AA->canInstructionRangeModRef(Start,
End, Loc, ModRefInfo::ModRef);
189 auto *Store1 = dyn_cast<StoreInst>(&Inst);
196 if (AA->isMustAlias(Loc0, Loc1) &&
197 !isStoreSinkBarrierInRange(*Store1->getNextNode(), BB1->
back(), Loc1) &&
198 !isStoreSinkBarrierInRange(*Store0->
getNextNode(), BB0->back(), Loc0) &&
202 Store1->getValueOperand()->getType(),
223 NewPN->addIncoming(Opd1, S0->
getParent());
224 NewPN->addIncoming(Opd2, S1->
getParent());
231bool MergedLoadStoreMotion::canSinkStoresAndGEPs(
StoreInst *S0,
237 return GEP0 && GEP1 && GEP0->isIdenticalTo(GEP1) && GEP0->hasOneUse() &&
238 (GEP0->getParent() == S0->
getParent()) && GEP1->hasOneUse() &&
253 dbgs() <<
"Instruction Left\n"; S0->
dump();
dbgs() <<
"\n";
254 dbgs() <<
"Instruction Right\n"; S1->
dump();
dbgs() <<
"\n");
274 if (
PHINode *NewPN = getPHIOperand(BB, S0, S1))
280 auto *GEP0 = cast<GetElementPtrInst>(Ptr0);
281 auto *GEP1 = cast<GetElementPtrInst>(Ptr1);
286 GEP0->replaceAllUsesWith(GEPNew);
287 GEP0->eraseFromParent();
288 GEP1->replaceAllUsesWith(GEPNew);
289 GEP1->eraseFromParent();
299bool MergedLoadStoreMotion::mergeStores(
BasicBlock *HeadBB) {
301 bool MergedStores =
false;
304 assert(SinkBB &&
"Footer of a diamond cannot be empty");
307 assert(SI !=
succ_end(HeadBB) &&
"Diamond head cannot have zero successors");
310 assert(SI !=
succ_end(HeadBB) &&
"Diamond head cannot have single successor");
320 int Size1 = std::distance(InstsNoDbg.begin(), InstsNoDbg.end());
330 auto *S0 = dyn_cast<StoreInst>(
I);
335 if (NStores * Size1 >= MagicCompileTimeControl)
337 if (
StoreInst *S1 = canSinkFromBlock(Pred1, S0)) {
338 if (!canSinkStoresAndGEPs(S0, S1))
354 sinkStoresAndGEPs(SinkBB, S0, S1);
366 bool Changed =
false;
376 if (isDiamondHead(&BB))
377 Changed |= mergeStores(&BB);
382class MergedLoadStoreMotionLegacyPass :
public FunctionPass {
383 const bool SplitFooterBB;
386 MergedLoadStoreMotionLegacyPass(
bool SplitFooterBB =
false)
399 return Impl.run(
F, getAnalysis<AAResultsWrapperPass>().getAAResults());
411char MergedLoadStoreMotionLegacyPass::ID = 0;
418 return new MergedLoadStoreMotionLegacyPass(SplitFooterBB);
422 "MergedLoadStoreMotion",
false,
false)
431 if (!Impl.run(
F, AA))
443 OS, MapClassName2PassName);
This is the interface for a simple mod/ref and alias analysis over globals.
mldst MergedLoadStoreMotion
This pass performs merges of loads and stores on both sides of a.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
A container for analyses that lazily runs them and caches their results.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
LLVM Basic Block Representation.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
reverse_iterator rbegin()
iterator_range< filter_iterator< BasicBlock::const_iterator, std::function< bool(const Instruction &)> > > instructionsWithoutDebug(bool SkipPseudoOp=true) const
Return a const iterator range over the instructions in the block, skipping any debug instructions.
const Instruction & front() const
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::reverse_iterator reverse_iterator
const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
InstListType::iterator iterator
Instruction iterators...
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...
bool hasNPredecessorsOrMore(unsigned N) const
Return true if this block has N predecessors or more.
const Instruction & back() const
Represents analyses that only rely on functions' control flow.
static bool isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, const DataLayout &DL)
Check whether a bitcast, inttoptr, or ptrtoint cast between these types is valid and a no-op.
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
Legacy wrapper pass to provide the GlobalsAAResult object.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
void mergeDIAssignID(ArrayRef< const Instruction * > SourceInstructions)
Merge the DIAssignID metadata from this instruction and those attached to instructions in SourceInstr...
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
const BasicBlock * getParent() const
BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
bool hasSameSpecialState(const Instruction *I2, bool IgnoreAlignment=false) const LLVM_READONLY
This function determines if the speficied instruction has the same "special" characteristics as the c...
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void applyMergedLocation(DILocation *LocA, DILocation *LocB)
Merge 2 debug locations and apply it to the Instruction.
void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs)
Drop all unknown metadata except for debug locations.
Representation for a specific memory location.
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
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...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
An instruction for storing to memory.
Value * getValueOperand()
Value * getPointerOperand()
StringRef - Represent a constant reference to a string, i.e.
void setOperand(unsigned i, Value *Val)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
StringRef getName() const
Return a constant reference to the value's name.
void dump() const
Support for debugging, callable in GDB: V->dump()
An efficient, type-erasing, non-owning reference to a callable.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements an extremely fast bulk output stream that can only output to a stream.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
Interval::succ_iterator succ_end(Interval *I)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
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...
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry &)
FunctionPass * createMergedLoadStoreMotionPass(bool SplitFooterBB=false)
createMergedLoadStoreMotionPass - The public interface to this file.
A CRTP mix-in to automatically provide informational APIs needed for passes.