1875ed548SDimitry Andric //===- LoopVersioning.cpp - Utility to version a loop ---------------------===//
2875ed548SDimitry Andric //
3875ed548SDimitry Andric // The LLVM Compiler Infrastructure
4875ed548SDimitry Andric //
5875ed548SDimitry Andric // This file is distributed under the University of Illinois Open Source
6875ed548SDimitry Andric // License. See LICENSE.TXT for details.
7875ed548SDimitry Andric //
8875ed548SDimitry Andric //===----------------------------------------------------------------------===//
9875ed548SDimitry Andric //
10875ed548SDimitry Andric // This file defines a utility class to perform loop versioning. The versioned
11875ed548SDimitry Andric // loop speculates that otherwise may-aliasing memory accesses don't overlap and
12875ed548SDimitry Andric // emits checks to prove this.
13875ed548SDimitry Andric //
14875ed548SDimitry Andric //===----------------------------------------------------------------------===//
15875ed548SDimitry Andric
167d523365SDimitry Andric #include "llvm/Transforms/Utils/LoopVersioning.h"
17875ed548SDimitry Andric #include "llvm/Analysis/LoopAccessAnalysis.h"
18875ed548SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
197d523365SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpander.h"
20875ed548SDimitry Andric #include "llvm/IR/Dominators.h"
213ca95b02SDimitry Andric #include "llvm/IR/MDBuilder.h"
22875ed548SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
23875ed548SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
24875ed548SDimitry Andric
25875ed548SDimitry Andric using namespace llvm;
26875ed548SDimitry Andric
273ca95b02SDimitry Andric static cl::opt<bool>
283ca95b02SDimitry Andric AnnotateNoAlias("loop-version-annotate-no-alias", cl::init(true),
293ca95b02SDimitry Andric cl::Hidden,
303ca95b02SDimitry Andric cl::desc("Add no-alias annotation for instructions that "
313ca95b02SDimitry Andric "are disambiguated by memchecks"));
323ca95b02SDimitry Andric
LoopVersioning(const LoopAccessInfo & LAI,Loop * L,LoopInfo * LI,DominatorTree * DT,ScalarEvolution * SE,bool UseLAIChecks)33875ed548SDimitry Andric LoopVersioning::LoopVersioning(const LoopAccessInfo &LAI, Loop *L, LoopInfo *LI,
347d523365SDimitry Andric DominatorTree *DT, ScalarEvolution *SE,
357d523365SDimitry Andric bool UseLAIChecks)
367d523365SDimitry Andric : VersionedLoop(L), NonVersionedLoop(nullptr), LAI(LAI), LI(LI), DT(DT),
377d523365SDimitry Andric SE(SE) {
38875ed548SDimitry Andric assert(L->getExitBlock() && "No single exit block");
39d88c1a5aSDimitry Andric assert(L->isLoopSimplifyForm() && "Loop is not in loop-simplify form");
407d523365SDimitry Andric if (UseLAIChecks) {
417d523365SDimitry Andric setAliasChecks(LAI.getRuntimePointerChecking()->getChecks());
423ca95b02SDimitry Andric setSCEVChecks(LAI.getPSE().getUnionPredicate());
437d523365SDimitry Andric }
44875ed548SDimitry Andric }
45875ed548SDimitry Andric
setAliasChecks(SmallVector<RuntimePointerChecking::PointerCheck,4> Checks)467d523365SDimitry Andric void LoopVersioning::setAliasChecks(
473ca95b02SDimitry Andric SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks) {
487d523365SDimitry Andric AliasChecks = std::move(Checks);
49875ed548SDimitry Andric }
50875ed548SDimitry Andric
setSCEVChecks(SCEVUnionPredicate Check)517d523365SDimitry Andric void LoopVersioning::setSCEVChecks(SCEVUnionPredicate Check) {
527d523365SDimitry Andric Preds = std::move(Check);
537d523365SDimitry Andric }
547d523365SDimitry Andric
versionLoop(const SmallVectorImpl<Instruction * > & DefsUsedOutside)557d523365SDimitry Andric void LoopVersioning::versionLoop(
567d523365SDimitry Andric const SmallVectorImpl<Instruction *> &DefsUsedOutside) {
57875ed548SDimitry Andric Instruction *FirstCheckInst;
58875ed548SDimitry Andric Instruction *MemRuntimeCheck;
597d523365SDimitry Andric Value *SCEVRuntimeCheck;
607d523365SDimitry Andric Value *RuntimeCheck = nullptr;
617d523365SDimitry Andric
62875ed548SDimitry Andric // Add the memcheck in the original preheader (this is empty initially).
637d523365SDimitry Andric BasicBlock *RuntimeCheckBB = VersionedLoop->getLoopPreheader();
64875ed548SDimitry Andric std::tie(FirstCheckInst, MemRuntimeCheck) =
657d523365SDimitry Andric LAI.addRuntimeChecks(RuntimeCheckBB->getTerminator(), AliasChecks);
66875ed548SDimitry Andric
673ca95b02SDimitry Andric const SCEVUnionPredicate &Pred = LAI.getPSE().getUnionPredicate();
687d523365SDimitry Andric SCEVExpander Exp(*SE, RuntimeCheckBB->getModule()->getDataLayout(),
697d523365SDimitry Andric "scev.check");
707d523365SDimitry Andric SCEVRuntimeCheck =
717d523365SDimitry Andric Exp.expandCodeForPredicate(&Pred, RuntimeCheckBB->getTerminator());
727d523365SDimitry Andric auto *CI = dyn_cast<ConstantInt>(SCEVRuntimeCheck);
737d523365SDimitry Andric
747d523365SDimitry Andric // Discard the SCEV runtime check if it is always true.
757d523365SDimitry Andric if (CI && CI->isZero())
767d523365SDimitry Andric SCEVRuntimeCheck = nullptr;
777d523365SDimitry Andric
787d523365SDimitry Andric if (MemRuntimeCheck && SCEVRuntimeCheck) {
797d523365SDimitry Andric RuntimeCheck = BinaryOperator::Create(Instruction::Or, MemRuntimeCheck,
803ca95b02SDimitry Andric SCEVRuntimeCheck, "lver.safe");
817d523365SDimitry Andric if (auto *I = dyn_cast<Instruction>(RuntimeCheck))
827d523365SDimitry Andric I->insertBefore(RuntimeCheckBB->getTerminator());
837d523365SDimitry Andric } else
847d523365SDimitry Andric RuntimeCheck = MemRuntimeCheck ? MemRuntimeCheck : SCEVRuntimeCheck;
857d523365SDimitry Andric
867d523365SDimitry Andric assert(RuntimeCheck && "called even though we don't need "
877d523365SDimitry Andric "any runtime checks");
887d523365SDimitry Andric
89875ed548SDimitry Andric // Rename the block to make the IR more readable.
907d523365SDimitry Andric RuntimeCheckBB->setName(VersionedLoop->getHeader()->getName() +
917d523365SDimitry Andric ".lver.check");
92875ed548SDimitry Andric
93875ed548SDimitry Andric // Create empty preheader for the loop (and after cloning for the
94875ed548SDimitry Andric // non-versioned loop).
957d523365SDimitry Andric BasicBlock *PH =
967d523365SDimitry Andric SplitBlock(RuntimeCheckBB, RuntimeCheckBB->getTerminator(), DT, LI);
97875ed548SDimitry Andric PH->setName(VersionedLoop->getHeader()->getName() + ".ph");
98875ed548SDimitry Andric
99875ed548SDimitry Andric // Clone the loop including the preheader.
100875ed548SDimitry Andric //
101875ed548SDimitry Andric // FIXME: This does not currently preserve SimplifyLoop because the exit
102875ed548SDimitry Andric // block is a join between the two loops.
103875ed548SDimitry Andric SmallVector<BasicBlock *, 8> NonVersionedLoopBlocks;
104875ed548SDimitry Andric NonVersionedLoop =
1057d523365SDimitry Andric cloneLoopWithPreheader(PH, RuntimeCheckBB, VersionedLoop, VMap,
1067d523365SDimitry Andric ".lver.orig", LI, DT, NonVersionedLoopBlocks);
107875ed548SDimitry Andric remapInstructionsInBlocks(NonVersionedLoopBlocks, VMap);
108875ed548SDimitry Andric
109875ed548SDimitry Andric // Insert the conditional branch based on the result of the memchecks.
1107d523365SDimitry Andric Instruction *OrigTerm = RuntimeCheckBB->getTerminator();
111875ed548SDimitry Andric BranchInst::Create(NonVersionedLoop->getLoopPreheader(),
1127d523365SDimitry Andric VersionedLoop->getLoopPreheader(), RuntimeCheck, OrigTerm);
113875ed548SDimitry Andric OrigTerm->eraseFromParent();
114875ed548SDimitry Andric
115875ed548SDimitry Andric // The loops merge in the original exit block. This is now dominated by the
116875ed548SDimitry Andric // memchecking block.
1177d523365SDimitry Andric DT->changeImmediateDominator(VersionedLoop->getExitBlock(), RuntimeCheckBB);
1187d523365SDimitry Andric
1197d523365SDimitry Andric // Adds the necessary PHI nodes for the versioned loops based on the
1207d523365SDimitry Andric // loop-defined values used outside of the loop.
1217d523365SDimitry Andric addPHINodes(DefsUsedOutside);
122875ed548SDimitry Andric }
123875ed548SDimitry Andric
addPHINodes(const SmallVectorImpl<Instruction * > & DefsUsedOutside)124875ed548SDimitry Andric void LoopVersioning::addPHINodes(
125875ed548SDimitry Andric const SmallVectorImpl<Instruction *> &DefsUsedOutside) {
126875ed548SDimitry Andric BasicBlock *PHIBlock = VersionedLoop->getExitBlock();
127875ed548SDimitry Andric assert(PHIBlock && "No single successor to loop exit block");
128875ed548SDimitry Andric PHINode *PN;
129875ed548SDimitry Andric
1303ca95b02SDimitry Andric // First add a single-operand PHI for each DefsUsedOutside if one does not
1313ca95b02SDimitry Andric // exists yet.
1323ca95b02SDimitry Andric for (auto *Inst : DefsUsedOutside) {
1333ca95b02SDimitry Andric // See if we have a single-operand PHI with the value defined by the
134875ed548SDimitry Andric // original loop.
135875ed548SDimitry Andric for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) {
136875ed548SDimitry Andric if (PN->getIncomingValue(0) == Inst)
137875ed548SDimitry Andric break;
138875ed548SDimitry Andric }
139875ed548SDimitry Andric // If not create it.
140875ed548SDimitry Andric if (!PN) {
141875ed548SDimitry Andric PN = PHINode::Create(Inst->getType(), 2, Inst->getName() + ".lver",
1427d523365SDimitry Andric &PHIBlock->front());
143*4ba319b5SDimitry Andric SmallVector<User*, 8> UsersToUpdate;
144*4ba319b5SDimitry Andric for (User *U : Inst->users())
145*4ba319b5SDimitry Andric if (!VersionedLoop->contains(cast<Instruction>(U)->getParent()))
146*4ba319b5SDimitry Andric UsersToUpdate.push_back(U);
147*4ba319b5SDimitry Andric for (User *U : UsersToUpdate)
148*4ba319b5SDimitry Andric U->replaceUsesOfWith(Inst, PN);
149875ed548SDimitry Andric PN->addIncoming(Inst, VersionedLoop->getExitingBlock());
150875ed548SDimitry Andric }
1513ca95b02SDimitry Andric }
1523ca95b02SDimitry Andric
1533ca95b02SDimitry Andric // Then for each PHI add the operand for the edge from the cloned loop.
1543ca95b02SDimitry Andric for (auto I = PHIBlock->begin(); (PN = dyn_cast<PHINode>(I)); ++I) {
1553ca95b02SDimitry Andric assert(PN->getNumOperands() == 1 &&
1563ca95b02SDimitry Andric "Exit block should only have on predecessor");
1573ca95b02SDimitry Andric
1583ca95b02SDimitry Andric // If the definition was cloned used that otherwise use the same value.
1593ca95b02SDimitry Andric Value *ClonedValue = PN->getIncomingValue(0);
1603ca95b02SDimitry Andric auto Mapped = VMap.find(ClonedValue);
1613ca95b02SDimitry Andric if (Mapped != VMap.end())
1623ca95b02SDimitry Andric ClonedValue = Mapped->second;
1633ca95b02SDimitry Andric
1643ca95b02SDimitry Andric PN->addIncoming(ClonedValue, NonVersionedLoop->getExitingBlock());
1653ca95b02SDimitry Andric }
1663ca95b02SDimitry Andric }
1673ca95b02SDimitry Andric
prepareNoAliasMetadata()1683ca95b02SDimitry Andric void LoopVersioning::prepareNoAliasMetadata() {
1693ca95b02SDimitry Andric // We need to turn the no-alias relation between pointer checking groups into
1703ca95b02SDimitry Andric // no-aliasing annotations between instructions.
1713ca95b02SDimitry Andric //
1723ca95b02SDimitry Andric // We accomplish this by mapping each pointer checking group (a set of
1733ca95b02SDimitry Andric // pointers memchecked together) to an alias scope and then also mapping each
1743ca95b02SDimitry Andric // group to the list of scopes it can't alias.
1753ca95b02SDimitry Andric
1763ca95b02SDimitry Andric const RuntimePointerChecking *RtPtrChecking = LAI.getRuntimePointerChecking();
1773ca95b02SDimitry Andric LLVMContext &Context = VersionedLoop->getHeader()->getContext();
1783ca95b02SDimitry Andric
1793ca95b02SDimitry Andric // First allocate an aliasing scope for each pointer checking group.
1803ca95b02SDimitry Andric //
1813ca95b02SDimitry Andric // While traversing through the checking groups in the loop, also create a
1823ca95b02SDimitry Andric // reverse map from pointers to the pointer checking group they were assigned
1833ca95b02SDimitry Andric // to.
1843ca95b02SDimitry Andric MDBuilder MDB(Context);
1853ca95b02SDimitry Andric MDNode *Domain = MDB.createAnonymousAliasScopeDomain("LVerDomain");
1863ca95b02SDimitry Andric
1873ca95b02SDimitry Andric for (const auto &Group : RtPtrChecking->CheckingGroups) {
1883ca95b02SDimitry Andric GroupToScope[&Group] = MDB.createAnonymousAliasScope(Domain);
1893ca95b02SDimitry Andric
1903ca95b02SDimitry Andric for (unsigned PtrIdx : Group.Members)
1913ca95b02SDimitry Andric PtrToGroup[RtPtrChecking->getPointerInfo(PtrIdx).PointerValue] = &Group;
1923ca95b02SDimitry Andric }
1933ca95b02SDimitry Andric
1943ca95b02SDimitry Andric // Go through the checks and for each pointer group, collect the scopes for
1953ca95b02SDimitry Andric // each non-aliasing pointer group.
1963ca95b02SDimitry Andric DenseMap<const RuntimePointerChecking::CheckingPtrGroup *,
1973ca95b02SDimitry Andric SmallVector<Metadata *, 4>>
1983ca95b02SDimitry Andric GroupToNonAliasingScopes;
1993ca95b02SDimitry Andric
2003ca95b02SDimitry Andric for (const auto &Check : AliasChecks)
2013ca95b02SDimitry Andric GroupToNonAliasingScopes[Check.first].push_back(GroupToScope[Check.second]);
2023ca95b02SDimitry Andric
2033ca95b02SDimitry Andric // Finally, transform the above to actually map to scope list which is what
2043ca95b02SDimitry Andric // the metadata uses.
2053ca95b02SDimitry Andric
2063ca95b02SDimitry Andric for (auto Pair : GroupToNonAliasingScopes)
2073ca95b02SDimitry Andric GroupToNonAliasingScopeList[Pair.first] = MDNode::get(Context, Pair.second);
2083ca95b02SDimitry Andric }
2093ca95b02SDimitry Andric
annotateLoopWithNoAlias()2103ca95b02SDimitry Andric void LoopVersioning::annotateLoopWithNoAlias() {
2113ca95b02SDimitry Andric if (!AnnotateNoAlias)
2123ca95b02SDimitry Andric return;
2133ca95b02SDimitry Andric
2143ca95b02SDimitry Andric // First prepare the maps.
2153ca95b02SDimitry Andric prepareNoAliasMetadata();
2163ca95b02SDimitry Andric
2173ca95b02SDimitry Andric // Add the scope and no-alias metadata to the instructions.
2183ca95b02SDimitry Andric for (Instruction *I : LAI.getDepChecker().getMemoryInstructions()) {
2193ca95b02SDimitry Andric annotateInstWithNoAlias(I);
2203ca95b02SDimitry Andric }
2213ca95b02SDimitry Andric }
2223ca95b02SDimitry Andric
annotateInstWithNoAlias(Instruction * VersionedInst,const Instruction * OrigInst)2233ca95b02SDimitry Andric void LoopVersioning::annotateInstWithNoAlias(Instruction *VersionedInst,
2243ca95b02SDimitry Andric const Instruction *OrigInst) {
2253ca95b02SDimitry Andric if (!AnnotateNoAlias)
2263ca95b02SDimitry Andric return;
2273ca95b02SDimitry Andric
2283ca95b02SDimitry Andric LLVMContext &Context = VersionedLoop->getHeader()->getContext();
2293ca95b02SDimitry Andric const Value *Ptr = isa<LoadInst>(OrigInst)
2303ca95b02SDimitry Andric ? cast<LoadInst>(OrigInst)->getPointerOperand()
2313ca95b02SDimitry Andric : cast<StoreInst>(OrigInst)->getPointerOperand();
2323ca95b02SDimitry Andric
2333ca95b02SDimitry Andric // Find the group for the pointer and then add the scope metadata.
2343ca95b02SDimitry Andric auto Group = PtrToGroup.find(Ptr);
2353ca95b02SDimitry Andric if (Group != PtrToGroup.end()) {
2363ca95b02SDimitry Andric VersionedInst->setMetadata(
2373ca95b02SDimitry Andric LLVMContext::MD_alias_scope,
2383ca95b02SDimitry Andric MDNode::concatenate(
2393ca95b02SDimitry Andric VersionedInst->getMetadata(LLVMContext::MD_alias_scope),
2403ca95b02SDimitry Andric MDNode::get(Context, GroupToScope[Group->second])));
2413ca95b02SDimitry Andric
2423ca95b02SDimitry Andric // Add the no-alias metadata.
2433ca95b02SDimitry Andric auto NonAliasingScopeList = GroupToNonAliasingScopeList.find(Group->second);
2443ca95b02SDimitry Andric if (NonAliasingScopeList != GroupToNonAliasingScopeList.end())
2453ca95b02SDimitry Andric VersionedInst->setMetadata(
2463ca95b02SDimitry Andric LLVMContext::MD_noalias,
2473ca95b02SDimitry Andric MDNode::concatenate(
2483ca95b02SDimitry Andric VersionedInst->getMetadata(LLVMContext::MD_noalias),
2493ca95b02SDimitry Andric NonAliasingScopeList->second));
2503ca95b02SDimitry Andric }
2513ca95b02SDimitry Andric }
2523ca95b02SDimitry Andric
2533ca95b02SDimitry Andric namespace {
254*4ba319b5SDimitry Andric /// Also expose this is a pass. Currently this is only used for
2553ca95b02SDimitry Andric /// unit-testing. It adds all memchecks necessary to remove all may-aliasing
2563ca95b02SDimitry Andric /// array accesses from the loop.
2573ca95b02SDimitry Andric class LoopVersioningPass : public FunctionPass {
2583ca95b02SDimitry Andric public:
LoopVersioningPass()2593ca95b02SDimitry Andric LoopVersioningPass() : FunctionPass(ID) {
2603ca95b02SDimitry Andric initializeLoopVersioningPassPass(*PassRegistry::getPassRegistry());
2613ca95b02SDimitry Andric }
2623ca95b02SDimitry Andric
runOnFunction(Function & F)2633ca95b02SDimitry Andric bool runOnFunction(Function &F) override {
2643ca95b02SDimitry Andric auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
2653ca95b02SDimitry Andric auto *LAA = &getAnalysis<LoopAccessLegacyAnalysis>();
2663ca95b02SDimitry Andric auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2673ca95b02SDimitry Andric auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
2683ca95b02SDimitry Andric
2693ca95b02SDimitry Andric // Build up a worklist of inner-loops to version. This is necessary as the
2703ca95b02SDimitry Andric // act of versioning a loop creates new loops and can invalidate iterators
2713ca95b02SDimitry Andric // across the loops.
2723ca95b02SDimitry Andric SmallVector<Loop *, 8> Worklist;
2733ca95b02SDimitry Andric
2743ca95b02SDimitry Andric for (Loop *TopLevelLoop : *LI)
2753ca95b02SDimitry Andric for (Loop *L : depth_first(TopLevelLoop))
2763ca95b02SDimitry Andric // We only handle inner-most loops.
2773ca95b02SDimitry Andric if (L->empty())
2783ca95b02SDimitry Andric Worklist.push_back(L);
2793ca95b02SDimitry Andric
2803ca95b02SDimitry Andric // Now walk the identified inner loops.
2813ca95b02SDimitry Andric bool Changed = false;
2823ca95b02SDimitry Andric for (Loop *L : Worklist) {
2833ca95b02SDimitry Andric const LoopAccessInfo &LAI = LAA->getInfo(L);
284d88c1a5aSDimitry Andric if (L->isLoopSimplifyForm() && (LAI.getNumRuntimePointerChecks() ||
285d88c1a5aSDimitry Andric !LAI.getPSE().getUnionPredicate().isAlwaysTrue())) {
2863ca95b02SDimitry Andric LoopVersioning LVer(LAI, L, LI, DT, SE);
2873ca95b02SDimitry Andric LVer.versionLoop();
2883ca95b02SDimitry Andric LVer.annotateLoopWithNoAlias();
2893ca95b02SDimitry Andric Changed = true;
2903ca95b02SDimitry Andric }
2913ca95b02SDimitry Andric }
2923ca95b02SDimitry Andric
2933ca95b02SDimitry Andric return Changed;
2943ca95b02SDimitry Andric }
2953ca95b02SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const2963ca95b02SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
2973ca95b02SDimitry Andric AU.addRequired<LoopInfoWrapperPass>();
2983ca95b02SDimitry Andric AU.addPreserved<LoopInfoWrapperPass>();
2993ca95b02SDimitry Andric AU.addRequired<LoopAccessLegacyAnalysis>();
3003ca95b02SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>();
3013ca95b02SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>();
3023ca95b02SDimitry Andric AU.addRequired<ScalarEvolutionWrapperPass>();
3033ca95b02SDimitry Andric }
3043ca95b02SDimitry Andric
3053ca95b02SDimitry Andric static char ID;
3063ca95b02SDimitry Andric };
3073ca95b02SDimitry Andric }
3083ca95b02SDimitry Andric
3093ca95b02SDimitry Andric #define LVER_OPTION "loop-versioning"
3103ca95b02SDimitry Andric #define DEBUG_TYPE LVER_OPTION
3113ca95b02SDimitry Andric
3123ca95b02SDimitry Andric char LoopVersioningPass::ID;
3133ca95b02SDimitry Andric static const char LVer_name[] = "Loop Versioning";
3143ca95b02SDimitry Andric
3153ca95b02SDimitry Andric INITIALIZE_PASS_BEGIN(LoopVersioningPass, LVER_OPTION, LVer_name, false, false)
3163ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
3173ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopAccessLegacyAnalysis)
3183ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
3193ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
3203ca95b02SDimitry Andric INITIALIZE_PASS_END(LoopVersioningPass, LVER_OPTION, LVer_name, false, false)
3213ca95b02SDimitry Andric
3223ca95b02SDimitry Andric namespace llvm {
createLoopVersioningPass()3233ca95b02SDimitry Andric FunctionPass *createLoopVersioningPass() {
3243ca95b02SDimitry Andric return new LoopVersioningPass();
325875ed548SDimitry Andric }
326875ed548SDimitry Andric }
327