10b57cec5SDimitry Andric //===- MergedLoadStoreMotion.cpp - merge and hoist/sink load/stores -------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric //! \file 100b57cec5SDimitry Andric //! This pass performs merges of loads and stores on both sides of a 110b57cec5SDimitry Andric // diamond (hammock). It hoists the loads and sinks the stores. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric // The algorithm iteratively hoists two loads to the same address out of a 140b57cec5SDimitry Andric // diamond (hammock) and merges them into a single load in the header. Similar 150b57cec5SDimitry Andric // it sinks and merges two stores to the tail block (footer). The algorithm 160b57cec5SDimitry Andric // iterates over the instructions of one side of the diamond and attempts to 178bcb0991SDimitry Andric // find a matching load/store on the other side. New tail/footer block may be 188bcb0991SDimitry Andric // insterted if the tail/footer block has more predecessors (not only the two 198bcb0991SDimitry Andric // predecessors that are forming the diamond). It hoists / sinks when it thinks 208bcb0991SDimitry Andric // it safe to do so. This optimization helps with eg. hiding load latencies, 218bcb0991SDimitry Andric // triggering if-conversion, and reducing static code size. 220b57cec5SDimitry Andric // 230b57cec5SDimitry Andric // NOTE: This code no longer performs load hoisting, it is subsumed by GVNHoist. 240b57cec5SDimitry Andric // 250b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 260b57cec5SDimitry Andric // 270b57cec5SDimitry Andric // 280b57cec5SDimitry Andric // Example: 290b57cec5SDimitry Andric // Diamond shaped code before merge: 300b57cec5SDimitry Andric // 310b57cec5SDimitry Andric // header: 320b57cec5SDimitry Andric // br %cond, label %if.then, label %if.else 330b57cec5SDimitry Andric // + + 340b57cec5SDimitry Andric // + + 350b57cec5SDimitry Andric // + + 360b57cec5SDimitry Andric // if.then: if.else: 370b57cec5SDimitry Andric // %lt = load %addr_l %le = load %addr_l 380b57cec5SDimitry Andric // <use %lt> <use %le> 390b57cec5SDimitry Andric // <...> <...> 400b57cec5SDimitry Andric // store %st, %addr_s store %se, %addr_s 410b57cec5SDimitry Andric // br label %if.end br label %if.end 420b57cec5SDimitry Andric // + + 430b57cec5SDimitry Andric // + + 440b57cec5SDimitry Andric // + + 450b57cec5SDimitry Andric // if.end ("footer"): 460b57cec5SDimitry Andric // <...> 470b57cec5SDimitry Andric // 480b57cec5SDimitry Andric // Diamond shaped code after merge: 490b57cec5SDimitry Andric // 500b57cec5SDimitry Andric // header: 510b57cec5SDimitry Andric // %l = load %addr_l 520b57cec5SDimitry Andric // br %cond, label %if.then, label %if.else 530b57cec5SDimitry Andric // + + 540b57cec5SDimitry Andric // + + 550b57cec5SDimitry Andric // + + 560b57cec5SDimitry Andric // if.then: if.else: 570b57cec5SDimitry Andric // <use %l> <use %l> 580b57cec5SDimitry Andric // <...> <...> 590b57cec5SDimitry Andric // br label %if.end br label %if.end 600b57cec5SDimitry Andric // + + 610b57cec5SDimitry Andric // + + 620b57cec5SDimitry Andric // + + 630b57cec5SDimitry Andric // if.end ("footer"): 640b57cec5SDimitry Andric // %s.sink = phi [%st, if.then], [%se, if.else] 650b57cec5SDimitry Andric // <...> 660b57cec5SDimitry Andric // store %s.sink, %addr_s 670b57cec5SDimitry Andric // <...> 680b57cec5SDimitry Andric // 690b57cec5SDimitry Andric // 700b57cec5SDimitry Andric //===----------------------- TODO -----------------------------------------===// 710b57cec5SDimitry Andric // 720b57cec5SDimitry Andric // 1) Generalize to regions other than diamonds 730b57cec5SDimitry Andric // 2) Be more aggressive merging memory operations 740b57cec5SDimitry Andric // Note that both changes require register pressure control 750b57cec5SDimitry Andric // 760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" 790b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 800b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h" 8106c3fb27SDimitry Andric #include "llvm/IR/IRBuilder.h" 8281ad6265SDimitry Andric #include "llvm/IR/Instructions.h" 830b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 840b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 850b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 860b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric using namespace llvm; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric #define DEBUG_TYPE "mldst-motion" 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric namespace { 930b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 940b57cec5SDimitry Andric // MergedLoadStoreMotion Pass 950b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 960b57cec5SDimitry Andric class MergedLoadStoreMotion { 970b57cec5SDimitry Andric AliasAnalysis *AA = nullptr; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric // The mergeLoad/Store algorithms could have Size0 * Size1 complexity, 1000b57cec5SDimitry Andric // where Size0 and Size1 are the #instructions on the two sides of 1010b57cec5SDimitry Andric // the diamond. The constant chosen here is arbitrary. Compiler Time 1020b57cec5SDimitry Andric // Control is enforced by the check Size0 * Size1 < MagicCompileTimeControl. 1030b57cec5SDimitry Andric const int MagicCompileTimeControl = 250; 1040b57cec5SDimitry Andric 1058bcb0991SDimitry Andric const bool SplitFooterBB; 1060b57cec5SDimitry Andric public: 1078bcb0991SDimitry Andric MergedLoadStoreMotion(bool SplitFooterBB) : SplitFooterBB(SplitFooterBB) {} 1080b57cec5SDimitry Andric bool run(Function &F, AliasAnalysis &AA); 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric private: 1110b57cec5SDimitry Andric BasicBlock *getDiamondTail(BasicBlock *BB); 1120b57cec5SDimitry Andric bool isDiamondHead(BasicBlock *BB); 1130b57cec5SDimitry Andric // Routines for sinking stores 1140b57cec5SDimitry Andric StoreInst *canSinkFromBlock(BasicBlock *BB, StoreInst *SI); 1150b57cec5SDimitry Andric PHINode *getPHIOperand(BasicBlock *BB, StoreInst *S0, StoreInst *S1); 1160b57cec5SDimitry Andric bool isStoreSinkBarrierInRange(const Instruction &Start, 1170b57cec5SDimitry Andric const Instruction &End, MemoryLocation Loc); 1188bcb0991SDimitry Andric bool canSinkStoresAndGEPs(StoreInst *S0, StoreInst *S1) const; 1198bcb0991SDimitry Andric void sinkStoresAndGEPs(BasicBlock *BB, StoreInst *SinkCand, 1208bcb0991SDimitry Andric StoreInst *ElseInst); 1210b57cec5SDimitry Andric bool mergeStores(BasicBlock *BB); 1220b57cec5SDimitry Andric }; 1230b57cec5SDimitry Andric } // end anonymous namespace 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric /// 1260b57cec5SDimitry Andric /// Return tail block of a diamond. 1270b57cec5SDimitry Andric /// 1280b57cec5SDimitry Andric BasicBlock *MergedLoadStoreMotion::getDiamondTail(BasicBlock *BB) { 1290b57cec5SDimitry Andric assert(isDiamondHead(BB) && "Basic block is not head of a diamond"); 1300b57cec5SDimitry Andric return BB->getTerminator()->getSuccessor(0)->getSingleSuccessor(); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric /// 1340b57cec5SDimitry Andric /// True when BB is the head of a diamond (hammock) 1350b57cec5SDimitry Andric /// 1360b57cec5SDimitry Andric bool MergedLoadStoreMotion::isDiamondHead(BasicBlock *BB) { 1370b57cec5SDimitry Andric if (!BB) 1380b57cec5SDimitry Andric return false; 1390b57cec5SDimitry Andric auto *BI = dyn_cast<BranchInst>(BB->getTerminator()); 1400b57cec5SDimitry Andric if (!BI || !BI->isConditional()) 1410b57cec5SDimitry Andric return false; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric BasicBlock *Succ0 = BI->getSuccessor(0); 1440b57cec5SDimitry Andric BasicBlock *Succ1 = BI->getSuccessor(1); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric if (!Succ0->getSinglePredecessor()) 1470b57cec5SDimitry Andric return false; 1480b57cec5SDimitry Andric if (!Succ1->getSinglePredecessor()) 1490b57cec5SDimitry Andric return false; 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric BasicBlock *Succ0Succ = Succ0->getSingleSuccessor(); 1520b57cec5SDimitry Andric BasicBlock *Succ1Succ = Succ1->getSingleSuccessor(); 1530b57cec5SDimitry Andric // Ignore triangles. 1540b57cec5SDimitry Andric if (!Succ0Succ || !Succ1Succ || Succ0Succ != Succ1Succ) 1550b57cec5SDimitry Andric return false; 1560b57cec5SDimitry Andric return true; 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric /// 1610b57cec5SDimitry Andric /// True when instruction is a sink barrier for a store 1620b57cec5SDimitry Andric /// located in Loc 1630b57cec5SDimitry Andric /// 1640b57cec5SDimitry Andric /// Whenever an instruction could possibly read or modify the 1650b57cec5SDimitry Andric /// value being stored or protect against the store from 1660b57cec5SDimitry Andric /// happening it is considered a sink barrier. 1670b57cec5SDimitry Andric /// 1680b57cec5SDimitry Andric bool MergedLoadStoreMotion::isStoreSinkBarrierInRange(const Instruction &Start, 1690b57cec5SDimitry Andric const Instruction &End, 1700b57cec5SDimitry Andric MemoryLocation Loc) { 1710b57cec5SDimitry Andric for (const Instruction &Inst : 1720b57cec5SDimitry Andric make_range(Start.getIterator(), End.getIterator())) 1730b57cec5SDimitry Andric if (Inst.mayThrow()) 1740b57cec5SDimitry Andric return true; 1750b57cec5SDimitry Andric return AA->canInstructionRangeModRef(Start, End, Loc, ModRefInfo::ModRef); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric /// 1790b57cec5SDimitry Andric /// Check if \p BB contains a store to the same address as \p SI 1800b57cec5SDimitry Andric /// 1810b57cec5SDimitry Andric /// \return The store in \p when it is safe to sink. Otherwise return Null. 1820b57cec5SDimitry Andric /// 1830b57cec5SDimitry Andric StoreInst *MergedLoadStoreMotion::canSinkFromBlock(BasicBlock *BB1, 1840b57cec5SDimitry Andric StoreInst *Store0) { 1850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "can Sink? : "; Store0->dump(); dbgs() << "\n"); 1860b57cec5SDimitry Andric BasicBlock *BB0 = Store0->getParent(); 1870b57cec5SDimitry Andric for (Instruction &Inst : reverse(*BB1)) { 1880b57cec5SDimitry Andric auto *Store1 = dyn_cast<StoreInst>(&Inst); 1890b57cec5SDimitry Andric if (!Store1) 1900b57cec5SDimitry Andric continue; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric MemoryLocation Loc0 = MemoryLocation::get(Store0); 1930b57cec5SDimitry Andric MemoryLocation Loc1 = MemoryLocation::get(Store1); 19406c3fb27SDimitry Andric 19506c3fb27SDimitry Andric if (AA->isMustAlias(Loc0, Loc1) && 1960b57cec5SDimitry Andric !isStoreSinkBarrierInRange(*Store1->getNextNode(), BB1->back(), Loc1) && 19706c3fb27SDimitry Andric !isStoreSinkBarrierInRange(*Store0->getNextNode(), BB0->back(), Loc0) && 19806c3fb27SDimitry Andric Store0->hasSameSpecialState(Store1) && 19906c3fb27SDimitry Andric CastInst::isBitOrNoopPointerCastable( 20006c3fb27SDimitry Andric Store0->getValueOperand()->getType(), 20106c3fb27SDimitry Andric Store1->getValueOperand()->getType(), 202*0fca6ea1SDimitry Andric Store0->getDataLayout())) 2030b57cec5SDimitry Andric return Store1; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric return nullptr; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric /// 2090b57cec5SDimitry Andric /// Create a PHI node in BB for the operands of S0 and S1 2100b57cec5SDimitry Andric /// 2110b57cec5SDimitry Andric PHINode *MergedLoadStoreMotion::getPHIOperand(BasicBlock *BB, StoreInst *S0, 2120b57cec5SDimitry Andric StoreInst *S1) { 2130b57cec5SDimitry Andric // Create a phi if the values mismatch. 2140b57cec5SDimitry Andric Value *Opd1 = S0->getValueOperand(); 2150b57cec5SDimitry Andric Value *Opd2 = S1->getValueOperand(); 2160b57cec5SDimitry Andric if (Opd1 == Opd2) 2170b57cec5SDimitry Andric return nullptr; 2180b57cec5SDimitry Andric 2195f757f3fSDimitry Andric auto *NewPN = PHINode::Create(Opd1->getType(), 2, Opd2->getName() + ".sink"); 2205f757f3fSDimitry Andric NewPN->insertBefore(BB->begin()); 2210b57cec5SDimitry Andric NewPN->applyMergedLocation(S0->getDebugLoc(), S1->getDebugLoc()); 2220b57cec5SDimitry Andric NewPN->addIncoming(Opd1, S0->getParent()); 2230b57cec5SDimitry Andric NewPN->addIncoming(Opd2, S1->getParent()); 2240b57cec5SDimitry Andric return NewPN; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric /// 228bdd1243dSDimitry Andric /// Check if 2 stores can be sunk, optionally together with corresponding GEPs. 2298bcb0991SDimitry Andric /// 2308bcb0991SDimitry Andric bool MergedLoadStoreMotion::canSinkStoresAndGEPs(StoreInst *S0, 2318bcb0991SDimitry Andric StoreInst *S1) const { 232bdd1243dSDimitry Andric if (S0->getPointerOperand() == S1->getPointerOperand()) 233bdd1243dSDimitry Andric return true; 234bdd1243dSDimitry Andric auto *GEP0 = dyn_cast<GetElementPtrInst>(S0->getPointerOperand()); 235bdd1243dSDimitry Andric auto *GEP1 = dyn_cast<GetElementPtrInst>(S1->getPointerOperand()); 236bdd1243dSDimitry Andric return GEP0 && GEP1 && GEP0->isIdenticalTo(GEP1) && GEP0->hasOneUse() && 237bdd1243dSDimitry Andric (GEP0->getParent() == S0->getParent()) && GEP1->hasOneUse() && 238bdd1243dSDimitry Andric (GEP1->getParent() == S1->getParent()); 2398bcb0991SDimitry Andric } 2408bcb0991SDimitry Andric 2418bcb0991SDimitry Andric /// 2420b57cec5SDimitry Andric /// Merge two stores to same address and sink into \p BB 2430b57cec5SDimitry Andric /// 244bdd1243dSDimitry Andric /// Optionally also sinks GEP instruction computing the store address 2450b57cec5SDimitry Andric /// 2468bcb0991SDimitry Andric void MergedLoadStoreMotion::sinkStoresAndGEPs(BasicBlock *BB, StoreInst *S0, 2470b57cec5SDimitry Andric StoreInst *S1) { 248bdd1243dSDimitry Andric Value *Ptr0 = S0->getPointerOperand(); 249bdd1243dSDimitry Andric Value *Ptr1 = S1->getPointerOperand(); 2500b57cec5SDimitry Andric // Only one definition? 2510b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Sink Instruction into BB \n"; BB->dump(); 2520b57cec5SDimitry Andric dbgs() << "Instruction Left\n"; S0->dump(); dbgs() << "\n"; 2530b57cec5SDimitry Andric dbgs() << "Instruction Right\n"; S1->dump(); dbgs() << "\n"); 2540b57cec5SDimitry Andric // Hoist the instruction. 2550b57cec5SDimitry Andric BasicBlock::iterator InsertPt = BB->getFirstInsertionPt(); 2560b57cec5SDimitry Andric // Intersect optional metadata. 2570b57cec5SDimitry Andric S0->andIRFlags(S1); 2580b57cec5SDimitry Andric S0->dropUnknownNonDebugMetadata(); 259bdd1243dSDimitry Andric S0->applyMergedLocation(S0->getDebugLoc(), S1->getDebugLoc()); 260bdd1243dSDimitry Andric S0->mergeDIAssignID(S1); 2610b57cec5SDimitry Andric 26206c3fb27SDimitry Andric // Insert bitcast for conflicting typed stores (or just use original value if 26306c3fb27SDimitry Andric // same type). 26406c3fb27SDimitry Andric IRBuilder<> Builder(S0); 26506c3fb27SDimitry Andric auto Cast = Builder.CreateBitOrPointerCast(S0->getValueOperand(), 26606c3fb27SDimitry Andric S1->getValueOperand()->getType()); 26706c3fb27SDimitry Andric S0->setOperand(0, Cast); 26806c3fb27SDimitry Andric 2690b57cec5SDimitry Andric // Create the new store to be inserted at the join point. 2700b57cec5SDimitry Andric StoreInst *SNew = cast<StoreInst>(S0->clone()); 2715f757f3fSDimitry Andric SNew->insertBefore(InsertPt); 2720b57cec5SDimitry Andric // New PHI operand? Use it. 2730b57cec5SDimitry Andric if (PHINode *NewPN = getPHIOperand(BB, S0, S1)) 2740b57cec5SDimitry Andric SNew->setOperand(0, NewPN); 2750b57cec5SDimitry Andric S0->eraseFromParent(); 2760b57cec5SDimitry Andric S1->eraseFromParent(); 277bdd1243dSDimitry Andric 278bdd1243dSDimitry Andric if (Ptr0 != Ptr1) { 279bdd1243dSDimitry Andric auto *GEP0 = cast<GetElementPtrInst>(Ptr0); 280bdd1243dSDimitry Andric auto *GEP1 = cast<GetElementPtrInst>(Ptr1); 281bdd1243dSDimitry Andric Instruction *GEPNew = GEP0->clone(); 282bdd1243dSDimitry Andric GEPNew->insertBefore(SNew); 283bdd1243dSDimitry Andric GEPNew->applyMergedLocation(GEP0->getDebugLoc(), GEP1->getDebugLoc()); 284bdd1243dSDimitry Andric SNew->setOperand(1, GEPNew); 285bdd1243dSDimitry Andric GEP0->replaceAllUsesWith(GEPNew); 286bdd1243dSDimitry Andric GEP0->eraseFromParent(); 287bdd1243dSDimitry Andric GEP1->replaceAllUsesWith(GEPNew); 288bdd1243dSDimitry Andric GEP1->eraseFromParent(); 289bdd1243dSDimitry Andric } 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric /// 2930b57cec5SDimitry Andric /// True when two stores are equivalent and can sink into the footer 2940b57cec5SDimitry Andric /// 2958bcb0991SDimitry Andric /// Starting from a diamond head block, iterate over the instructions in one 2968bcb0991SDimitry Andric /// successor block and try to match a store in the second successor. 2970b57cec5SDimitry Andric /// 2988bcb0991SDimitry Andric bool MergedLoadStoreMotion::mergeStores(BasicBlock *HeadBB) { 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric bool MergedStores = false; 3018bcb0991SDimitry Andric BasicBlock *TailBB = getDiamondTail(HeadBB); 3028bcb0991SDimitry Andric BasicBlock *SinkBB = TailBB; 3038bcb0991SDimitry Andric assert(SinkBB && "Footer of a diamond cannot be empty"); 3040b57cec5SDimitry Andric 3058bcb0991SDimitry Andric succ_iterator SI = succ_begin(HeadBB); 3068bcb0991SDimitry Andric assert(SI != succ_end(HeadBB) && "Diamond head cannot have zero successors"); 3078bcb0991SDimitry Andric BasicBlock *Pred0 = *SI; 3088bcb0991SDimitry Andric ++SI; 3098bcb0991SDimitry Andric assert(SI != succ_end(HeadBB) && "Diamond head cannot have single successor"); 3108bcb0991SDimitry Andric BasicBlock *Pred1 = *SI; 3110b57cec5SDimitry Andric // tail block of a diamond/hammock? 3120b57cec5SDimitry Andric if (Pred0 == Pred1) 3130b57cec5SDimitry Andric return false; // No. 3148bcb0991SDimitry Andric // bail out early if we can not merge into the footer BB 3158bcb0991SDimitry Andric if (!SplitFooterBB && TailBB->hasNPredecessorsOrMore(3)) 3168bcb0991SDimitry Andric return false; 3178bcb0991SDimitry Andric // #Instructions in Pred1 for Compile Time Control 3180b57cec5SDimitry Andric auto InstsNoDbg = Pred1->instructionsWithoutDebug(); 3190b57cec5SDimitry Andric int Size1 = std::distance(InstsNoDbg.begin(), InstsNoDbg.end()); 3200b57cec5SDimitry Andric int NStores = 0; 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric for (BasicBlock::reverse_iterator RBI = Pred0->rbegin(), RBE = Pred0->rend(); 3230b57cec5SDimitry Andric RBI != RBE;) { 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric Instruction *I = &*RBI; 3260b57cec5SDimitry Andric ++RBI; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric // Don't sink non-simple (atomic, volatile) stores. 3290b57cec5SDimitry Andric auto *S0 = dyn_cast<StoreInst>(I); 3300b57cec5SDimitry Andric if (!S0 || !S0->isSimple()) 3310b57cec5SDimitry Andric continue; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric ++NStores; 3340b57cec5SDimitry Andric if (NStores * Size1 >= MagicCompileTimeControl) 3350b57cec5SDimitry Andric break; 3360b57cec5SDimitry Andric if (StoreInst *S1 = canSinkFromBlock(Pred1, S0)) { 3378bcb0991SDimitry Andric if (!canSinkStoresAndGEPs(S0, S1)) 3380b57cec5SDimitry Andric // Don't attempt to sink below stores that had to stick around 3390b57cec5SDimitry Andric // But after removal of a store and some of its feeding 3400b57cec5SDimitry Andric // instruction search again from the beginning since the iterator 3410b57cec5SDimitry Andric // is likely stale at this point. 3420b57cec5SDimitry Andric break; 3438bcb0991SDimitry Andric 3448bcb0991SDimitry Andric if (SinkBB == TailBB && TailBB->hasNPredecessorsOrMore(3)) { 3458bcb0991SDimitry Andric // We have more than 2 predecessors. Insert a new block 3468bcb0991SDimitry Andric // postdominating 2 predecessors we're going to sink from. 3478bcb0991SDimitry Andric SinkBB = SplitBlockPredecessors(TailBB, {Pred0, Pred1}, ".sink.split"); 3488bcb0991SDimitry Andric if (!SinkBB) 3498bcb0991SDimitry Andric break; 3508bcb0991SDimitry Andric } 3518bcb0991SDimitry Andric 3528bcb0991SDimitry Andric MergedStores = true; 3538bcb0991SDimitry Andric sinkStoresAndGEPs(SinkBB, S0, S1); 3540b57cec5SDimitry Andric RBI = Pred0->rbegin(); 3550b57cec5SDimitry Andric RBE = Pred0->rend(); 3560b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Search again\n"; Instruction *I = &*RBI; I->dump()); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric return MergedStores; 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric bool MergedLoadStoreMotion::run(Function &F, AliasAnalysis &AA) { 3630b57cec5SDimitry Andric this->AA = &AA; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric bool Changed = false; 3660b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Instruction Merger\n"); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric // Merge unconditional branches, allowing PRE to catch more 3690b57cec5SDimitry Andric // optimization opportunities. 3708bcb0991SDimitry Andric // This loop doesn't care about newly inserted/split blocks 3718bcb0991SDimitry Andric // since they never will be diamond heads. 3725ffd83dbSDimitry Andric for (BasicBlock &BB : make_early_inc_range(F)) 3730b57cec5SDimitry Andric // Hoist equivalent loads and sink stores 3740b57cec5SDimitry Andric // outside diamonds when possible 3755ffd83dbSDimitry Andric if (isDiamondHead(&BB)) 3765ffd83dbSDimitry Andric Changed |= mergeStores(&BB); 3770b57cec5SDimitry Andric return Changed; 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric PreservedAnalyses 3810b57cec5SDimitry Andric MergedLoadStoreMotionPass::run(Function &F, FunctionAnalysisManager &AM) { 3828bcb0991SDimitry Andric MergedLoadStoreMotion Impl(Options.SplitFooterBB); 3830b57cec5SDimitry Andric auto &AA = AM.getResult<AAManager>(F); 3840b57cec5SDimitry Andric if (!Impl.run(F, AA)) 3850b57cec5SDimitry Andric return PreservedAnalyses::all(); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric PreservedAnalyses PA; 3888bcb0991SDimitry Andric if (!Options.SplitFooterBB) 3890b57cec5SDimitry Andric PA.preserveSet<CFGAnalyses>(); 3900b57cec5SDimitry Andric return PA; 3910b57cec5SDimitry Andric } 392349cc55cSDimitry Andric 393349cc55cSDimitry Andric void MergedLoadStoreMotionPass::printPipeline( 394349cc55cSDimitry Andric raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { 395349cc55cSDimitry Andric static_cast<PassInfoMixin<MergedLoadStoreMotionPass> *>(this)->printPipeline( 396349cc55cSDimitry Andric OS, MapClassName2PassName); 39706c3fb27SDimitry Andric OS << '<'; 398349cc55cSDimitry Andric OS << (Options.SplitFooterBB ? "" : "no-") << "split-footer-bb"; 39906c3fb27SDimitry Andric OS << '>'; 400349cc55cSDimitry Andric } 401