10b57cec5SDimitry Andric //===- LoopVersioning.cpp - Utility to version a loop ---------------------===// 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 // This file defines a utility class to perform loop versioning. The versioned 100b57cec5SDimitry Andric // loop speculates that otherwise may-aliasing memory accesses don't overlap and 110b57cec5SDimitry Andric // emits checks to prove this. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/Transforms/Utils/LoopVersioning.h" 165ffd83dbSDimitry Andric #include "llvm/ADT/ArrayRef.h" 170b57cec5SDimitry Andric #include "llvm/Analysis/LoopAccessAnalysis.h" 180b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h" 19*e8d8bef9SDimitry Andric #include "llvm/Analysis/MemorySSA.h" 20*e8d8bef9SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h" 21*e8d8bef9SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 220b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 230b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h" 24*e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h" 25480093f4SDimitry Andric #include "llvm/InitializePasses.h" 26480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 270b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 280b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 295ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h" 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace llvm; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric static cl::opt<bool> 340b57cec5SDimitry Andric AnnotateNoAlias("loop-version-annotate-no-alias", cl::init(true), 350b57cec5SDimitry Andric cl::Hidden, 360b57cec5SDimitry Andric cl::desc("Add no-alias annotation for instructions that " 370b57cec5SDimitry Andric "are disambiguated by memchecks")); 380b57cec5SDimitry Andric 39*e8d8bef9SDimitry Andric LoopVersioning::LoopVersioning(const LoopAccessInfo &LAI, 40*e8d8bef9SDimitry Andric ArrayRef<RuntimePointerCheck> Checks, Loop *L, 41*e8d8bef9SDimitry Andric LoopInfo *LI, DominatorTree *DT, 42*e8d8bef9SDimitry Andric ScalarEvolution *SE) 43*e8d8bef9SDimitry Andric : VersionedLoop(L), NonVersionedLoop(nullptr), 44*e8d8bef9SDimitry Andric AliasChecks(Checks.begin(), Checks.end()), 45*e8d8bef9SDimitry Andric Preds(LAI.getPSE().getUnionPredicate()), LAI(LAI), LI(LI), DT(DT), 460b57cec5SDimitry Andric SE(SE) { 47*e8d8bef9SDimitry Andric assert(L->getUniqueExitBlock() && "No single exit block"); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric void LoopVersioning::versionLoop( 510b57cec5SDimitry Andric const SmallVectorImpl<Instruction *> &DefsUsedOutside) { 52*e8d8bef9SDimitry Andric assert(VersionedLoop->isLoopSimplifyForm() && 53*e8d8bef9SDimitry Andric "Loop is not in loop-simplify form"); 54*e8d8bef9SDimitry Andric 550b57cec5SDimitry Andric Instruction *FirstCheckInst; 560b57cec5SDimitry Andric Instruction *MemRuntimeCheck; 570b57cec5SDimitry Andric Value *SCEVRuntimeCheck; 580b57cec5SDimitry Andric Value *RuntimeCheck = nullptr; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // Add the memcheck in the original preheader (this is empty initially). 610b57cec5SDimitry Andric BasicBlock *RuntimeCheckBB = VersionedLoop->getLoopPreheader(); 625ffd83dbSDimitry Andric const auto &RtPtrChecking = *LAI.getRuntimePointerChecking(); 630b57cec5SDimitry Andric std::tie(FirstCheckInst, MemRuntimeCheck) = 645ffd83dbSDimitry Andric addRuntimeChecks(RuntimeCheckBB->getTerminator(), VersionedLoop, 655ffd83dbSDimitry Andric AliasChecks, RtPtrChecking.getSE()); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric SCEVExpander Exp(*SE, RuntimeCheckBB->getModule()->getDataLayout(), 680b57cec5SDimitry Andric "scev.check"); 690b57cec5SDimitry Andric SCEVRuntimeCheck = 70*e8d8bef9SDimitry Andric Exp.expandCodeForPredicate(&Preds, RuntimeCheckBB->getTerminator()); 710b57cec5SDimitry Andric auto *CI = dyn_cast<ConstantInt>(SCEVRuntimeCheck); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric // Discard the SCEV runtime check if it is always true. 740b57cec5SDimitry Andric if (CI && CI->isZero()) 750b57cec5SDimitry Andric SCEVRuntimeCheck = nullptr; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric if (MemRuntimeCheck && SCEVRuntimeCheck) { 780b57cec5SDimitry Andric RuntimeCheck = BinaryOperator::Create(Instruction::Or, MemRuntimeCheck, 790b57cec5SDimitry Andric SCEVRuntimeCheck, "lver.safe"); 800b57cec5SDimitry Andric if (auto *I = dyn_cast<Instruction>(RuntimeCheck)) 810b57cec5SDimitry Andric I->insertBefore(RuntimeCheckBB->getTerminator()); 820b57cec5SDimitry Andric } else 830b57cec5SDimitry Andric RuntimeCheck = MemRuntimeCheck ? MemRuntimeCheck : SCEVRuntimeCheck; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric assert(RuntimeCheck && "called even though we don't need " 860b57cec5SDimitry Andric "any runtime checks"); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric // Rename the block to make the IR more readable. 890b57cec5SDimitry Andric RuntimeCheckBB->setName(VersionedLoop->getHeader()->getName() + 900b57cec5SDimitry Andric ".lver.check"); 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // Create empty preheader for the loop (and after cloning for the 930b57cec5SDimitry Andric // non-versioned loop). 940b57cec5SDimitry Andric BasicBlock *PH = 958bcb0991SDimitry Andric SplitBlock(RuntimeCheckBB, RuntimeCheckBB->getTerminator(), DT, LI, 968bcb0991SDimitry Andric nullptr, VersionedLoop->getHeader()->getName() + ".ph"); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric // Clone the loop including the preheader. 990b57cec5SDimitry Andric // 1000b57cec5SDimitry Andric // FIXME: This does not currently preserve SimplifyLoop because the exit 1010b57cec5SDimitry Andric // block is a join between the two loops. 1020b57cec5SDimitry Andric SmallVector<BasicBlock *, 8> NonVersionedLoopBlocks; 1030b57cec5SDimitry Andric NonVersionedLoop = 1040b57cec5SDimitry Andric cloneLoopWithPreheader(PH, RuntimeCheckBB, VersionedLoop, VMap, 1050b57cec5SDimitry Andric ".lver.orig", LI, DT, NonVersionedLoopBlocks); 1060b57cec5SDimitry Andric remapInstructionsInBlocks(NonVersionedLoopBlocks, VMap); 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric // Insert the conditional branch based on the result of the memchecks. 1090b57cec5SDimitry Andric Instruction *OrigTerm = RuntimeCheckBB->getTerminator(); 1100b57cec5SDimitry Andric BranchInst::Create(NonVersionedLoop->getLoopPreheader(), 1110b57cec5SDimitry Andric VersionedLoop->getLoopPreheader(), RuntimeCheck, OrigTerm); 1120b57cec5SDimitry Andric OrigTerm->eraseFromParent(); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // The loops merge in the original exit block. This is now dominated by the 1150b57cec5SDimitry Andric // memchecking block. 1160b57cec5SDimitry Andric DT->changeImmediateDominator(VersionedLoop->getExitBlock(), RuntimeCheckBB); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // Adds the necessary PHI nodes for the versioned loops based on the 1190b57cec5SDimitry Andric // loop-defined values used outside of the loop. 1200b57cec5SDimitry Andric addPHINodes(DefsUsedOutside); 121*e8d8bef9SDimitry Andric formDedicatedExitBlocks(NonVersionedLoop, DT, LI, nullptr, true); 122*e8d8bef9SDimitry Andric formDedicatedExitBlocks(VersionedLoop, DT, LI, nullptr, true); 123*e8d8bef9SDimitry Andric assert(NonVersionedLoop->isLoopSimplifyForm() && 124*e8d8bef9SDimitry Andric VersionedLoop->isLoopSimplifyForm() && 125*e8d8bef9SDimitry Andric "The versioned loops should be in simplify form."); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric void LoopVersioning::addPHINodes( 1290b57cec5SDimitry Andric const SmallVectorImpl<Instruction *> &DefsUsedOutside) { 1300b57cec5SDimitry Andric BasicBlock *PHIBlock = VersionedLoop->getExitBlock(); 1310b57cec5SDimitry Andric assert(PHIBlock && "No single successor to loop exit block"); 1320b57cec5SDimitry Andric PHINode *PN; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric // First add a single-operand PHI for each DefsUsedOutside if one does not 1350b57cec5SDimitry Andric // exists yet. 1360b57cec5SDimitry Andric for (auto *Inst : DefsUsedOutside) { 1370b57cec5SDimitry Andric // See if we have a single-operand PHI with the value defined by the 1380b57cec5SDimitry Andric // original loop. 1390b57cec5SDimitry Andric for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) { 1400b57cec5SDimitry Andric if (PN->getIncomingValue(0) == Inst) 1410b57cec5SDimitry Andric break; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric // If not create it. 1440b57cec5SDimitry Andric if (!PN) { 1450b57cec5SDimitry Andric PN = PHINode::Create(Inst->getType(), 2, Inst->getName() + ".lver", 1460b57cec5SDimitry Andric &PHIBlock->front()); 1470b57cec5SDimitry Andric SmallVector<User*, 8> UsersToUpdate; 1480b57cec5SDimitry Andric for (User *U : Inst->users()) 1490b57cec5SDimitry Andric if (!VersionedLoop->contains(cast<Instruction>(U)->getParent())) 1500b57cec5SDimitry Andric UsersToUpdate.push_back(U); 1510b57cec5SDimitry Andric for (User *U : UsersToUpdate) 1520b57cec5SDimitry Andric U->replaceUsesOfWith(Inst, PN); 1530b57cec5SDimitry Andric PN->addIncoming(Inst, VersionedLoop->getExitingBlock()); 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric // Then for each PHI add the operand for the edge from the cloned loop. 1580b57cec5SDimitry Andric for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) { 1590b57cec5SDimitry Andric assert(PN->getNumOperands() == 1 && 1600b57cec5SDimitry Andric "Exit block should only have on predecessor"); 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // If the definition was cloned used that otherwise use the same value. 1630b57cec5SDimitry Andric Value *ClonedValue = PN->getIncomingValue(0); 1640b57cec5SDimitry Andric auto Mapped = VMap.find(ClonedValue); 1650b57cec5SDimitry Andric if (Mapped != VMap.end()) 1660b57cec5SDimitry Andric ClonedValue = Mapped->second; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric PN->addIncoming(ClonedValue, NonVersionedLoop->getExitingBlock()); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric void LoopVersioning::prepareNoAliasMetadata() { 1730b57cec5SDimitry Andric // We need to turn the no-alias relation between pointer checking groups into 1740b57cec5SDimitry Andric // no-aliasing annotations between instructions. 1750b57cec5SDimitry Andric // 1760b57cec5SDimitry Andric // We accomplish this by mapping each pointer checking group (a set of 1770b57cec5SDimitry Andric // pointers memchecked together) to an alias scope and then also mapping each 1780b57cec5SDimitry Andric // group to the list of scopes it can't alias. 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric const RuntimePointerChecking *RtPtrChecking = LAI.getRuntimePointerChecking(); 1810b57cec5SDimitry Andric LLVMContext &Context = VersionedLoop->getHeader()->getContext(); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric // First allocate an aliasing scope for each pointer checking group. 1840b57cec5SDimitry Andric // 1850b57cec5SDimitry Andric // While traversing through the checking groups in the loop, also create a 1860b57cec5SDimitry Andric // reverse map from pointers to the pointer checking group they were assigned 1870b57cec5SDimitry Andric // to. 1880b57cec5SDimitry Andric MDBuilder MDB(Context); 1890b57cec5SDimitry Andric MDNode *Domain = MDB.createAnonymousAliasScopeDomain("LVerDomain"); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric for (const auto &Group : RtPtrChecking->CheckingGroups) { 1920b57cec5SDimitry Andric GroupToScope[&Group] = MDB.createAnonymousAliasScope(Domain); 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric for (unsigned PtrIdx : Group.Members) 1950b57cec5SDimitry Andric PtrToGroup[RtPtrChecking->getPointerInfo(PtrIdx).PointerValue] = &Group; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric // Go through the checks and for each pointer group, collect the scopes for 1990b57cec5SDimitry Andric // each non-aliasing pointer group. 2005ffd83dbSDimitry Andric DenseMap<const RuntimeCheckingPtrGroup *, SmallVector<Metadata *, 4>> 2010b57cec5SDimitry Andric GroupToNonAliasingScopes; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric for (const auto &Check : AliasChecks) 2040b57cec5SDimitry Andric GroupToNonAliasingScopes[Check.first].push_back(GroupToScope[Check.second]); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // Finally, transform the above to actually map to scope list which is what 2070b57cec5SDimitry Andric // the metadata uses. 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric for (auto Pair : GroupToNonAliasingScopes) 2100b57cec5SDimitry Andric GroupToNonAliasingScopeList[Pair.first] = MDNode::get(Context, Pair.second); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric void LoopVersioning::annotateLoopWithNoAlias() { 2140b57cec5SDimitry Andric if (!AnnotateNoAlias) 2150b57cec5SDimitry Andric return; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric // First prepare the maps. 2180b57cec5SDimitry Andric prepareNoAliasMetadata(); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric // Add the scope and no-alias metadata to the instructions. 2210b57cec5SDimitry Andric for (Instruction *I : LAI.getDepChecker().getMemoryInstructions()) { 2220b57cec5SDimitry Andric annotateInstWithNoAlias(I); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric void LoopVersioning::annotateInstWithNoAlias(Instruction *VersionedInst, 2270b57cec5SDimitry Andric const Instruction *OrigInst) { 2280b57cec5SDimitry Andric if (!AnnotateNoAlias) 2290b57cec5SDimitry Andric return; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric LLVMContext &Context = VersionedLoop->getHeader()->getContext(); 2320b57cec5SDimitry Andric const Value *Ptr = isa<LoadInst>(OrigInst) 2330b57cec5SDimitry Andric ? cast<LoadInst>(OrigInst)->getPointerOperand() 2340b57cec5SDimitry Andric : cast<StoreInst>(OrigInst)->getPointerOperand(); 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric // Find the group for the pointer and then add the scope metadata. 2370b57cec5SDimitry Andric auto Group = PtrToGroup.find(Ptr); 2380b57cec5SDimitry Andric if (Group != PtrToGroup.end()) { 2390b57cec5SDimitry Andric VersionedInst->setMetadata( 2400b57cec5SDimitry Andric LLVMContext::MD_alias_scope, 2410b57cec5SDimitry Andric MDNode::concatenate( 2420b57cec5SDimitry Andric VersionedInst->getMetadata(LLVMContext::MD_alias_scope), 2430b57cec5SDimitry Andric MDNode::get(Context, GroupToScope[Group->second]))); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric // Add the no-alias metadata. 2460b57cec5SDimitry Andric auto NonAliasingScopeList = GroupToNonAliasingScopeList.find(Group->second); 2470b57cec5SDimitry Andric if (NonAliasingScopeList != GroupToNonAliasingScopeList.end()) 2480b57cec5SDimitry Andric VersionedInst->setMetadata( 2490b57cec5SDimitry Andric LLVMContext::MD_noalias, 2500b57cec5SDimitry Andric MDNode::concatenate( 2510b57cec5SDimitry Andric VersionedInst->getMetadata(LLVMContext::MD_noalias), 2520b57cec5SDimitry Andric NonAliasingScopeList->second)); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric namespace { 257*e8d8bef9SDimitry Andric bool runImpl(LoopInfo *LI, function_ref<const LoopAccessInfo &(Loop &)> GetLAA, 258*e8d8bef9SDimitry Andric DominatorTree *DT, ScalarEvolution *SE) { 2590b57cec5SDimitry Andric // Build up a worklist of inner-loops to version. This is necessary as the 2600b57cec5SDimitry Andric // act of versioning a loop creates new loops and can invalidate iterators 2610b57cec5SDimitry Andric // across the loops. 2620b57cec5SDimitry Andric SmallVector<Loop *, 8> Worklist; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric for (Loop *TopLevelLoop : *LI) 2650b57cec5SDimitry Andric for (Loop *L : depth_first(TopLevelLoop)) 2660b57cec5SDimitry Andric // We only handle inner-most loops. 267*e8d8bef9SDimitry Andric if (L->isInnermost()) 2680b57cec5SDimitry Andric Worklist.push_back(L); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric // Now walk the identified inner loops. 2710b57cec5SDimitry Andric bool Changed = false; 2720b57cec5SDimitry Andric for (Loop *L : Worklist) { 273*e8d8bef9SDimitry Andric if (!L->isLoopSimplifyForm() || !L->isRotatedForm() || 274*e8d8bef9SDimitry Andric !L->getExitingBlock()) 275*e8d8bef9SDimitry Andric continue; 276*e8d8bef9SDimitry Andric const LoopAccessInfo &LAI = GetLAA(*L); 277*e8d8bef9SDimitry Andric if (!LAI.hasConvergentOp() && 2780b57cec5SDimitry Andric (LAI.getNumRuntimePointerChecks() || 2790b57cec5SDimitry Andric !LAI.getPSE().getUnionPredicate().isAlwaysTrue())) { 280*e8d8bef9SDimitry Andric LoopVersioning LVer(LAI, LAI.getRuntimePointerChecking()->getChecks(), L, 281*e8d8bef9SDimitry Andric LI, DT, SE); 2820b57cec5SDimitry Andric LVer.versionLoop(); 2830b57cec5SDimitry Andric LVer.annotateLoopWithNoAlias(); 2840b57cec5SDimitry Andric Changed = true; 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric return Changed; 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 291*e8d8bef9SDimitry Andric /// Also expose this is a pass. Currently this is only used for 292*e8d8bef9SDimitry Andric /// unit-testing. It adds all memchecks necessary to remove all may-aliasing 293*e8d8bef9SDimitry Andric /// array accesses from the loop. 294*e8d8bef9SDimitry Andric class LoopVersioningLegacyPass : public FunctionPass { 295*e8d8bef9SDimitry Andric public: 296*e8d8bef9SDimitry Andric LoopVersioningLegacyPass() : FunctionPass(ID) { 297*e8d8bef9SDimitry Andric initializeLoopVersioningLegacyPassPass(*PassRegistry::getPassRegistry()); 298*e8d8bef9SDimitry Andric } 299*e8d8bef9SDimitry Andric 300*e8d8bef9SDimitry Andric bool runOnFunction(Function &F) override { 301*e8d8bef9SDimitry Andric auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 302*e8d8bef9SDimitry Andric auto GetLAA = [&](Loop &L) -> const LoopAccessInfo & { 303*e8d8bef9SDimitry Andric return getAnalysis<LoopAccessLegacyAnalysis>().getInfo(&L); 304*e8d8bef9SDimitry Andric }; 305*e8d8bef9SDimitry Andric 306*e8d8bef9SDimitry Andric auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 307*e8d8bef9SDimitry Andric auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 308*e8d8bef9SDimitry Andric 309*e8d8bef9SDimitry Andric return runImpl(LI, GetLAA, DT, SE); 310*e8d8bef9SDimitry Andric } 311*e8d8bef9SDimitry Andric 3120b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 3130b57cec5SDimitry Andric AU.addRequired<LoopInfoWrapperPass>(); 3140b57cec5SDimitry Andric AU.addPreserved<LoopInfoWrapperPass>(); 3150b57cec5SDimitry Andric AU.addRequired<LoopAccessLegacyAnalysis>(); 3160b57cec5SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 3170b57cec5SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 3180b57cec5SDimitry Andric AU.addRequired<ScalarEvolutionWrapperPass>(); 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric static char ID; 3220b57cec5SDimitry Andric }; 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric #define LVER_OPTION "loop-versioning" 3260b57cec5SDimitry Andric #define DEBUG_TYPE LVER_OPTION 3270b57cec5SDimitry Andric 328*e8d8bef9SDimitry Andric char LoopVersioningLegacyPass::ID; 3290b57cec5SDimitry Andric static const char LVer_name[] = "Loop Versioning"; 3300b57cec5SDimitry Andric 331*e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(LoopVersioningLegacyPass, LVER_OPTION, LVer_name, false, 332*e8d8bef9SDimitry Andric false) 3330b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 3340b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopAccessLegacyAnalysis) 3350b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 3360b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) 337*e8d8bef9SDimitry Andric INITIALIZE_PASS_END(LoopVersioningLegacyPass, LVER_OPTION, LVer_name, false, 338*e8d8bef9SDimitry Andric false) 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric namespace llvm { 341*e8d8bef9SDimitry Andric FunctionPass *createLoopVersioningLegacyPass() { 342*e8d8bef9SDimitry Andric return new LoopVersioningLegacyPass(); 3430b57cec5SDimitry Andric } 344*e8d8bef9SDimitry Andric 345*e8d8bef9SDimitry Andric PreservedAnalyses LoopVersioningPass::run(Function &F, 346*e8d8bef9SDimitry Andric FunctionAnalysisManager &AM) { 347*e8d8bef9SDimitry Andric auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F); 348*e8d8bef9SDimitry Andric auto &LI = AM.getResult<LoopAnalysis>(F); 349*e8d8bef9SDimitry Andric auto &TTI = AM.getResult<TargetIRAnalysis>(F); 350*e8d8bef9SDimitry Andric auto &DT = AM.getResult<DominatorTreeAnalysis>(F); 351*e8d8bef9SDimitry Andric auto &TLI = AM.getResult<TargetLibraryAnalysis>(F); 352*e8d8bef9SDimitry Andric auto &AA = AM.getResult<AAManager>(F); 353*e8d8bef9SDimitry Andric auto &AC = AM.getResult<AssumptionAnalysis>(F); 354*e8d8bef9SDimitry Andric MemorySSA *MSSA = EnableMSSALoopDependency 355*e8d8bef9SDimitry Andric ? &AM.getResult<MemorySSAAnalysis>(F).getMSSA() 356*e8d8bef9SDimitry Andric : nullptr; 357*e8d8bef9SDimitry Andric 358*e8d8bef9SDimitry Andric auto &LAM = AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager(); 359*e8d8bef9SDimitry Andric auto GetLAA = [&](Loop &L) -> const LoopAccessInfo & { 360*e8d8bef9SDimitry Andric LoopStandardAnalysisResults AR = {AA, AC, DT, LI, SE, 361*e8d8bef9SDimitry Andric TLI, TTI, nullptr, MSSA}; 362*e8d8bef9SDimitry Andric return LAM.getResult<LoopAccessAnalysis>(L, AR); 363*e8d8bef9SDimitry Andric }; 364*e8d8bef9SDimitry Andric 365*e8d8bef9SDimitry Andric if (runImpl(&LI, GetLAA, &DT, &SE)) 366*e8d8bef9SDimitry Andric return PreservedAnalyses::none(); 367*e8d8bef9SDimitry Andric return PreservedAnalyses::all(); 3680b57cec5SDimitry Andric } 369*e8d8bef9SDimitry Andric } // namespace llvm 370