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" 17349cc55cSDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 1804eeddc0SDimitry Andric #include "llvm/Analysis/InstSimplifyFolder.h" 190b57cec5SDimitry Andric #include "llvm/Analysis/LoopAccessAnalysis.h" 200b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h" 21e8d8bef9SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h" 22e8d8bef9SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 230b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 240b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h" 25e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h" 26480093f4SDimitry Andric #include "llvm/InitializePasses.h" 27480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 280b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 290b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 305ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h" 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric using namespace llvm; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric static cl::opt<bool> 350b57cec5SDimitry Andric AnnotateNoAlias("loop-version-annotate-no-alias", cl::init(true), 360b57cec5SDimitry Andric cl::Hidden, 370b57cec5SDimitry Andric cl::desc("Add no-alias annotation for instructions that " 380b57cec5SDimitry Andric "are disambiguated by memchecks")); 390b57cec5SDimitry Andric 40e8d8bef9SDimitry Andric LoopVersioning::LoopVersioning(const LoopAccessInfo &LAI, 41e8d8bef9SDimitry Andric ArrayRef<RuntimePointerCheck> Checks, Loop *L, 42e8d8bef9SDimitry Andric LoopInfo *LI, DominatorTree *DT, 43e8d8bef9SDimitry Andric ScalarEvolution *SE) 44*81ad6265SDimitry Andric : VersionedLoop(L), AliasChecks(Checks.begin(), Checks.end()), 45*81ad6265SDimitry Andric Preds(LAI.getPSE().getPredicate()), LAI(LAI), LI(LI), DT(DT), 460b57cec5SDimitry Andric SE(SE) { 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric void LoopVersioning::versionLoop( 500b57cec5SDimitry Andric const SmallVectorImpl<Instruction *> &DefsUsedOutside) { 51fe6060f1SDimitry Andric assert(VersionedLoop->getUniqueExitBlock() && "No single exit block"); 52e8d8bef9SDimitry Andric assert(VersionedLoop->isLoopSimplifyForm() && 53e8d8bef9SDimitry Andric "Loop is not in loop-simplify form"); 54e8d8bef9SDimitry Andric 55349cc55cSDimitry Andric Value *MemRuntimeCheck; 560b57cec5SDimitry Andric Value *SCEVRuntimeCheck; 570b57cec5SDimitry Andric Value *RuntimeCheck = nullptr; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Add the memcheck in the original preheader (this is empty initially). 600b57cec5SDimitry Andric BasicBlock *RuntimeCheckBB = VersionedLoop->getLoopPreheader(); 615ffd83dbSDimitry Andric const auto &RtPtrChecking = *LAI.getRuntimePointerChecking(); 62fe6060f1SDimitry Andric 63fe6060f1SDimitry Andric SCEVExpander Exp2(*RtPtrChecking.getSE(), 64fe6060f1SDimitry Andric VersionedLoop->getHeader()->getModule()->getDataLayout(), 65fe6060f1SDimitry Andric "induction"); 66349cc55cSDimitry Andric MemRuntimeCheck = addRuntimeChecks(RuntimeCheckBB->getTerminator(), 67349cc55cSDimitry Andric VersionedLoop, AliasChecks, Exp2); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric SCEVExpander Exp(*SE, RuntimeCheckBB->getModule()->getDataLayout(), 700b57cec5SDimitry Andric "scev.check"); 710b57cec5SDimitry Andric SCEVRuntimeCheck = 72e8d8bef9SDimitry Andric Exp.expandCodeForPredicate(&Preds, RuntimeCheckBB->getTerminator()); 730b57cec5SDimitry Andric 7404eeddc0SDimitry Andric IRBuilder<InstSimplifyFolder> Builder( 7504eeddc0SDimitry Andric RuntimeCheckBB->getContext(), 7604eeddc0SDimitry Andric InstSimplifyFolder(RuntimeCheckBB->getModule()->getDataLayout())); 770b57cec5SDimitry Andric if (MemRuntimeCheck && SCEVRuntimeCheck) { 7804eeddc0SDimitry Andric Builder.SetInsertPoint(RuntimeCheckBB->getTerminator()); 7904eeddc0SDimitry Andric RuntimeCheck = 8004eeddc0SDimitry Andric Builder.CreateOr(MemRuntimeCheck, SCEVRuntimeCheck, "lver.safe"); 810b57cec5SDimitry Andric } else 820b57cec5SDimitry Andric RuntimeCheck = MemRuntimeCheck ? MemRuntimeCheck : SCEVRuntimeCheck; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric assert(RuntimeCheck && "called even though we don't need " 850b57cec5SDimitry Andric "any runtime checks"); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // Rename the block to make the IR more readable. 880b57cec5SDimitry Andric RuntimeCheckBB->setName(VersionedLoop->getHeader()->getName() + 890b57cec5SDimitry Andric ".lver.check"); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric // Create empty preheader for the loop (and after cloning for the 920b57cec5SDimitry Andric // non-versioned loop). 930b57cec5SDimitry Andric BasicBlock *PH = 948bcb0991SDimitry Andric SplitBlock(RuntimeCheckBB, RuntimeCheckBB->getTerminator(), DT, LI, 958bcb0991SDimitry Andric nullptr, VersionedLoop->getHeader()->getName() + ".ph"); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric // Clone the loop including the preheader. 980b57cec5SDimitry Andric // 990b57cec5SDimitry Andric // FIXME: This does not currently preserve SimplifyLoop because the exit 1000b57cec5SDimitry Andric // block is a join between the two loops. 1010b57cec5SDimitry Andric SmallVector<BasicBlock *, 8> NonVersionedLoopBlocks; 1020b57cec5SDimitry Andric NonVersionedLoop = 1030b57cec5SDimitry Andric cloneLoopWithPreheader(PH, RuntimeCheckBB, VersionedLoop, VMap, 1040b57cec5SDimitry Andric ".lver.orig", LI, DT, NonVersionedLoopBlocks); 1050b57cec5SDimitry Andric remapInstructionsInBlocks(NonVersionedLoopBlocks, VMap); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // Insert the conditional branch based on the result of the memchecks. 1080b57cec5SDimitry Andric Instruction *OrigTerm = RuntimeCheckBB->getTerminator(); 10904eeddc0SDimitry Andric Builder.SetInsertPoint(OrigTerm); 11004eeddc0SDimitry Andric Builder.CreateCondBr(RuntimeCheck, NonVersionedLoop->getLoopPreheader(), 11104eeddc0SDimitry Andric VersionedLoop->getLoopPreheader()); 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); 121e8d8bef9SDimitry Andric formDedicatedExitBlocks(NonVersionedLoop, DT, LI, nullptr, true); 122e8d8bef9SDimitry Andric formDedicatedExitBlocks(VersionedLoop, DT, LI, nullptr, true); 123e8d8bef9SDimitry Andric assert(NonVersionedLoop->isLoopSimplifyForm() && 124e8d8bef9SDimitry Andric VersionedLoop->isLoopSimplifyForm() && 125e8d8bef9SDimitry 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 { 257e8d8bef9SDimitry Andric bool runImpl(LoopInfo *LI, function_ref<const LoopAccessInfo &(Loop &)> GetLAA, 258e8d8bef9SDimitry 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. 267e8d8bef9SDimitry 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) { 273e8d8bef9SDimitry Andric if (!L->isLoopSimplifyForm() || !L->isRotatedForm() || 274e8d8bef9SDimitry Andric !L->getExitingBlock()) 275e8d8bef9SDimitry Andric continue; 276e8d8bef9SDimitry Andric const LoopAccessInfo &LAI = GetLAA(*L); 277e8d8bef9SDimitry Andric if (!LAI.hasConvergentOp() && 2780b57cec5SDimitry Andric (LAI.getNumRuntimePointerChecks() || 279*81ad6265SDimitry Andric !LAI.getPSE().getPredicate().isAlwaysTrue())) { 280e8d8bef9SDimitry Andric LoopVersioning LVer(LAI, LAI.getRuntimePointerChecking()->getChecks(), L, 281e8d8bef9SDimitry 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 291e8d8bef9SDimitry Andric /// Also expose this is a pass. Currently this is only used for 292e8d8bef9SDimitry Andric /// unit-testing. It adds all memchecks necessary to remove all may-aliasing 293e8d8bef9SDimitry Andric /// array accesses from the loop. 294e8d8bef9SDimitry Andric class LoopVersioningLegacyPass : public FunctionPass { 295e8d8bef9SDimitry Andric public: 296e8d8bef9SDimitry Andric LoopVersioningLegacyPass() : FunctionPass(ID) { 297e8d8bef9SDimitry Andric initializeLoopVersioningLegacyPassPass(*PassRegistry::getPassRegistry()); 298e8d8bef9SDimitry Andric } 299e8d8bef9SDimitry Andric 300e8d8bef9SDimitry Andric bool runOnFunction(Function &F) override { 301e8d8bef9SDimitry Andric auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 302e8d8bef9SDimitry Andric auto GetLAA = [&](Loop &L) -> const LoopAccessInfo & { 303e8d8bef9SDimitry Andric return getAnalysis<LoopAccessLegacyAnalysis>().getInfo(&L); 304e8d8bef9SDimitry Andric }; 305e8d8bef9SDimitry Andric 306e8d8bef9SDimitry Andric auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 307e8d8bef9SDimitry Andric auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 308e8d8bef9SDimitry Andric 309e8d8bef9SDimitry Andric return runImpl(LI, GetLAA, DT, SE); 310e8d8bef9SDimitry Andric } 311e8d8bef9SDimitry 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 328e8d8bef9SDimitry Andric char LoopVersioningLegacyPass::ID; 3290b57cec5SDimitry Andric static const char LVer_name[] = "Loop Versioning"; 3300b57cec5SDimitry Andric 331e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(LoopVersioningLegacyPass, LVER_OPTION, LVer_name, false, 332e8d8bef9SDimitry 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) 337e8d8bef9SDimitry Andric INITIALIZE_PASS_END(LoopVersioningLegacyPass, LVER_OPTION, LVer_name, false, 338e8d8bef9SDimitry Andric false) 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric namespace llvm { 341e8d8bef9SDimitry Andric FunctionPass *createLoopVersioningLegacyPass() { 342e8d8bef9SDimitry Andric return new LoopVersioningLegacyPass(); 3430b57cec5SDimitry Andric } 344e8d8bef9SDimitry Andric 345e8d8bef9SDimitry Andric PreservedAnalyses LoopVersioningPass::run(Function &F, 346e8d8bef9SDimitry Andric FunctionAnalysisManager &AM) { 347e8d8bef9SDimitry Andric auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F); 348e8d8bef9SDimitry Andric auto &LI = AM.getResult<LoopAnalysis>(F); 349e8d8bef9SDimitry Andric auto &TTI = AM.getResult<TargetIRAnalysis>(F); 350e8d8bef9SDimitry Andric auto &DT = AM.getResult<DominatorTreeAnalysis>(F); 351e8d8bef9SDimitry Andric auto &TLI = AM.getResult<TargetLibraryAnalysis>(F); 352e8d8bef9SDimitry Andric auto &AA = AM.getResult<AAManager>(F); 353e8d8bef9SDimitry Andric auto &AC = AM.getResult<AssumptionAnalysis>(F); 354e8d8bef9SDimitry Andric 355e8d8bef9SDimitry Andric auto &LAM = AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager(); 356e8d8bef9SDimitry Andric auto GetLAA = [&](Loop &L) -> const LoopAccessInfo & { 357e8d8bef9SDimitry Andric LoopStandardAnalysisResults AR = {AA, AC, DT, LI, SE, 358349cc55cSDimitry Andric TLI, TTI, nullptr, nullptr, nullptr}; 359e8d8bef9SDimitry Andric return LAM.getResult<LoopAccessAnalysis>(L, AR); 360e8d8bef9SDimitry Andric }; 361e8d8bef9SDimitry Andric 362e8d8bef9SDimitry Andric if (runImpl(&LI, GetLAA, &DT, &SE)) 363e8d8bef9SDimitry Andric return PreservedAnalyses::none(); 364e8d8bef9SDimitry Andric return PreservedAnalyses::all(); 3650b57cec5SDimitry Andric } 366e8d8bef9SDimitry Andric } // namespace llvm 367