forked from OSchip/llvm-project
[New PM][IRCE] port of Inductive Range Check Elimination pass to the new pass manager
There are two nontrivial details here: * Loop structure update interface is quite different with new pass manager, so the code to add new loops was factored out * BranchProbabilityInfo is not a loop analysis, so it can not be just getResult'ed from within the loop pass. It cant even be queried through getCachedResult as LoopCanonicalization sequence (e.g. LoopSimplify) might invalidate BPI results. Complete solution for BPI will likely take some time to discuss and figure out, so for now this was partially solved by making BPI optional in IRCE (skipping a couple of profitability checks if it is absent). Most of the IRCE tests got their corresponding new-pass-manager variant enabled. Only two of them depend on BPI, both marked with TODO, to be turned on when BPI starts being available for loop passes. Reviewers: chandlerc, mkazantsev, sanjoy, asbirlea Reviewed By: mkazantsev Differential Revision: https://reviews.llvm.org/D43795 llvm-svn: 327619
This commit is contained in:
parent
5704dc0c7f
commit
194a407bda
|
@ -166,7 +166,7 @@ void initializeIfConverterPass(PassRegistry&);
|
||||||
void initializeImplicitNullChecksPass(PassRegistry&);
|
void initializeImplicitNullChecksPass(PassRegistry&);
|
||||||
void initializeIndVarSimplifyLegacyPassPass(PassRegistry&);
|
void initializeIndVarSimplifyLegacyPassPass(PassRegistry&);
|
||||||
void initializeIndirectBrExpandPassPass(PassRegistry&);
|
void initializeIndirectBrExpandPassPass(PassRegistry&);
|
||||||
void initializeInductiveRangeCheckEliminationPass(PassRegistry&);
|
void initializeIRCELegacyPassPass(PassRegistry&);
|
||||||
void initializeInferAddressSpacesPass(PassRegistry&);
|
void initializeInferAddressSpacesPass(PassRegistry&);
|
||||||
void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&);
|
void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&);
|
||||||
void initializeInlineCostAnalysisPass(PassRegistry&);
|
void initializeInlineCostAnalysisPass(PassRegistry&);
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
//===- InductiveRangeCheckElimination.h - IRCE ------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file provides the interface for the Inductive Range Check Elimination
|
||||||
|
// loop pass.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H
|
||||||
|
#define LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H
|
||||||
|
|
||||||
|
#include "llvm/IR/PassManager.h"
|
||||||
|
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class IRCEPass : public PassInfoMixin<IRCEPass> {
|
||||||
|
public:
|
||||||
|
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
|
||||||
|
LoopStandardAnalysisResults &AR, LPMUpdater &U);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif // LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H
|
|
@ -103,6 +103,7 @@
|
||||||
#include "llvm/Transforms/Scalar/GuardWidening.h"
|
#include "llvm/Transforms/Scalar/GuardWidening.h"
|
||||||
#include "llvm/Transforms/Scalar/IVUsersPrinter.h"
|
#include "llvm/Transforms/Scalar/IVUsersPrinter.h"
|
||||||
#include "llvm/Transforms/Scalar/IndVarSimplify.h"
|
#include "llvm/Transforms/Scalar/IndVarSimplify.h"
|
||||||
|
#include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h"
|
||||||
#include "llvm/Transforms/Scalar/JumpThreading.h"
|
#include "llvm/Transforms/Scalar/JumpThreading.h"
|
||||||
#include "llvm/Transforms/Scalar/LICM.h"
|
#include "llvm/Transforms/Scalar/LICM.h"
|
||||||
#include "llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h"
|
#include "llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h"
|
||||||
|
|
|
@ -237,6 +237,7 @@ LOOP_PASS("loop-deletion", LoopDeletionPass())
|
||||||
LOOP_PASS("simplify-cfg", LoopSimplifyCFGPass())
|
LOOP_PASS("simplify-cfg", LoopSimplifyCFGPass())
|
||||||
LOOP_PASS("strength-reduce", LoopStrengthReducePass())
|
LOOP_PASS("strength-reduce", LoopStrengthReducePass())
|
||||||
LOOP_PASS("indvars", IndVarSimplifyPass())
|
LOOP_PASS("indvars", IndVarSimplifyPass())
|
||||||
|
LOOP_PASS("irce", IRCEPass())
|
||||||
LOOP_PASS("unroll-full", LoopFullUnrollPass())
|
LOOP_PASS("unroll-full", LoopFullUnrollPass())
|
||||||
LOOP_PASS("unswitch", SimpleLoopUnswitchPass())
|
LOOP_PASS("unswitch", SimpleLoopUnswitchPass())
|
||||||
LOOP_PASS("print-access-info", LoopAccessInfoPrinterPass(dbgs()))
|
LOOP_PASS("print-access-info", LoopAccessInfoPrinterPass(dbgs()))
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h"
|
||||||
#include "llvm/ADT/APInt.h"
|
#include "llvm/ADT/APInt.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/None.h"
|
#include "llvm/ADT/None.h"
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
||||||
|
#include "llvm/Analysis/LoopAnalysisManager.h"
|
||||||
#include "llvm/Analysis/LoopInfo.h"
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
#include "llvm/Analysis/LoopPass.h"
|
#include "llvm/Analysis/LoopPass.h"
|
||||||
#include "llvm/Analysis/ScalarEvolution.h"
|
#include "llvm/Analysis/ScalarEvolution.h"
|
||||||
|
@ -235,17 +237,31 @@ public:
|
||||||
/// checks, and hence don't end up in \p Checks.
|
/// checks, and hence don't end up in \p Checks.
|
||||||
static void
|
static void
|
||||||
extractRangeChecksFromBranch(BranchInst *BI, Loop *L, ScalarEvolution &SE,
|
extractRangeChecksFromBranch(BranchInst *BI, Loop *L, ScalarEvolution &SE,
|
||||||
BranchProbabilityInfo &BPI,
|
BranchProbabilityInfo *BPI,
|
||||||
SmallVectorImpl<InductiveRangeCheck> &Checks);
|
SmallVectorImpl<InductiveRangeCheck> &Checks);
|
||||||
};
|
};
|
||||||
|
|
||||||
class InductiveRangeCheckElimination : public LoopPass {
|
class InductiveRangeCheckElimination {
|
||||||
|
ScalarEvolution &SE;
|
||||||
|
BranchProbabilityInfo *BPI;
|
||||||
|
DominatorTree &DT;
|
||||||
|
LoopInfo &LI;
|
||||||
|
|
||||||
|
public:
|
||||||
|
InductiveRangeCheckElimination(ScalarEvolution &SE,
|
||||||
|
BranchProbabilityInfo *BPI, DominatorTree &DT,
|
||||||
|
LoopInfo &LI)
|
||||||
|
: SE(SE), BPI(BPI), DT(DT), LI(LI) {}
|
||||||
|
|
||||||
|
bool run(Loop *L, function_ref<void(Loop *, bool)> LPMAddNewLoop);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRCELegacyPass : public LoopPass {
|
||||||
public:
|
public:
|
||||||
static char ID;
|
static char ID;
|
||||||
|
|
||||||
InductiveRangeCheckElimination() : LoopPass(ID) {
|
IRCELegacyPass() : LoopPass(ID) {
|
||||||
initializeInductiveRangeCheckEliminationPass(
|
initializeIRCELegacyPassPass(*PassRegistry::getPassRegistry());
|
||||||
*PassRegistry::getPassRegistry());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||||
|
@ -258,14 +274,14 @@ public:
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
char InductiveRangeCheckElimination::ID = 0;
|
char IRCELegacyPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS_BEGIN(InductiveRangeCheckElimination, "irce",
|
INITIALIZE_PASS_BEGIN(IRCELegacyPass, "irce",
|
||||||
"Inductive range check elimination", false, false)
|
"Inductive range check elimination", false, false)
|
||||||
INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)
|
||||||
INITIALIZE_PASS_DEPENDENCY(LoopPass)
|
INITIALIZE_PASS_DEPENDENCY(LoopPass)
|
||||||
INITIALIZE_PASS_END(InductiveRangeCheckElimination, "irce",
|
INITIALIZE_PASS_END(IRCELegacyPass, "irce", "Inductive range check elimination",
|
||||||
"Inductive range check elimination", false, false)
|
false, false)
|
||||||
|
|
||||||
StringRef InductiveRangeCheck::rangeCheckKindToStr(
|
StringRef InductiveRangeCheck::rangeCheckKindToStr(
|
||||||
InductiveRangeCheck::RangeCheckKind RCK) {
|
InductiveRangeCheck::RangeCheckKind RCK) {
|
||||||
|
@ -417,15 +433,15 @@ void InductiveRangeCheck::extractRangeChecksFromCond(
|
||||||
}
|
}
|
||||||
|
|
||||||
void InductiveRangeCheck::extractRangeChecksFromBranch(
|
void InductiveRangeCheck::extractRangeChecksFromBranch(
|
||||||
BranchInst *BI, Loop *L, ScalarEvolution &SE, BranchProbabilityInfo &BPI,
|
BranchInst *BI, Loop *L, ScalarEvolution &SE, BranchProbabilityInfo *BPI,
|
||||||
SmallVectorImpl<InductiveRangeCheck> &Checks) {
|
SmallVectorImpl<InductiveRangeCheck> &Checks) {
|
||||||
if (BI->isUnconditional() || BI->getParent() == L->getLoopLatch())
|
if (BI->isUnconditional() || BI->getParent() == L->getLoopLatch())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BranchProbability LikelyTaken(15, 16);
|
BranchProbability LikelyTaken(15, 16);
|
||||||
|
|
||||||
if (!SkipProfitabilityChecks &&
|
if (!SkipProfitabilityChecks && BPI &&
|
||||||
BPI.getEdgeProbability(BI->getParent(), (unsigned)0) < LikelyTaken)
|
BPI->getEdgeProbability(BI->getParent(), (unsigned)0) < LikelyTaken)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SmallPtrSet<Value *, 8> Visited;
|
SmallPtrSet<Value *, 8> Visited;
|
||||||
|
@ -516,9 +532,8 @@ struct LoopStructure {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Optional<LoopStructure> parseLoopStructure(ScalarEvolution &,
|
static Optional<LoopStructure> parseLoopStructure(ScalarEvolution &,
|
||||||
BranchProbabilityInfo &BPI,
|
BranchProbabilityInfo *BPI,
|
||||||
Loop &,
|
Loop &, const char *&);
|
||||||
const char *&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This class is used to constrain loops to run within a given iteration space.
|
/// This class is used to constrain loops to run within a given iteration space.
|
||||||
|
@ -585,7 +600,7 @@ class LoopConstrainer {
|
||||||
// Create the appropriate loop structure needed to describe a cloned copy of
|
// Create the appropriate loop structure needed to describe a cloned copy of
|
||||||
// `Original`. The clone is described by `VM`.
|
// `Original`. The clone is described by `VM`.
|
||||||
Loop *createClonedLoopStructure(Loop *Original, Loop *Parent,
|
Loop *createClonedLoopStructure(Loop *Original, Loop *Parent,
|
||||||
ValueToValueMapTy &VM);
|
ValueToValueMapTy &VM, bool IsSubloop);
|
||||||
|
|
||||||
// Rewrite the iteration space of the loop denoted by (LS, Preheader). The
|
// Rewrite the iteration space of the loop denoted by (LS, Preheader). The
|
||||||
// iteration space of the rewritten loop ends at ExitLoopAt. The start of the
|
// iteration space of the rewritten loop ends at ExitLoopAt. The start of the
|
||||||
|
@ -637,8 +652,8 @@ class LoopConstrainer {
|
||||||
LLVMContext &Ctx;
|
LLVMContext &Ctx;
|
||||||
ScalarEvolution &SE;
|
ScalarEvolution &SE;
|
||||||
DominatorTree &DT;
|
DominatorTree &DT;
|
||||||
LPPassManager &LPM;
|
|
||||||
LoopInfo &LI;
|
LoopInfo &LI;
|
||||||
|
function_ref<void(Loop *, bool)> LPMAddNewLoop;
|
||||||
|
|
||||||
// Information about the original loop we started out with.
|
// Information about the original loop we started out with.
|
||||||
Loop &OriginalLoop;
|
Loop &OriginalLoop;
|
||||||
|
@ -658,12 +673,13 @@ class LoopConstrainer {
|
||||||
LoopStructure MainLoopStructure;
|
LoopStructure MainLoopStructure;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LoopConstrainer(Loop &L, LoopInfo &LI, LPPassManager &LPM,
|
LoopConstrainer(Loop &L, LoopInfo &LI,
|
||||||
|
function_ref<void(Loop *, bool)> LPMAddNewLoop,
|
||||||
const LoopStructure &LS, ScalarEvolution &SE,
|
const LoopStructure &LS, ScalarEvolution &SE,
|
||||||
DominatorTree &DT, InductiveRangeCheck::Range R)
|
DominatorTree &DT, InductiveRangeCheck::Range R)
|
||||||
: F(*L.getHeader()->getParent()), Ctx(L.getHeader()->getContext()),
|
: F(*L.getHeader()->getParent()), Ctx(L.getHeader()->getContext()),
|
||||||
SE(SE), DT(DT), LPM(LPM), LI(LI), OriginalLoop(L), Range(R),
|
SE(SE), DT(DT), LI(LI), LPMAddNewLoop(LPMAddNewLoop), OriginalLoop(L),
|
||||||
MainLoopStructure(LS) {}
|
Range(R), MainLoopStructure(LS) {}
|
||||||
|
|
||||||
// Entry point for the algorithm. Returns true on success.
|
// Entry point for the algorithm. Returns true on success.
|
||||||
bool run();
|
bool run();
|
||||||
|
@ -726,8 +742,8 @@ static bool SumCanReachMin(ScalarEvolution &SE, const SCEV *S1, const SCEV *S2,
|
||||||
|
|
||||||
Optional<LoopStructure>
|
Optional<LoopStructure>
|
||||||
LoopStructure::parseLoopStructure(ScalarEvolution &SE,
|
LoopStructure::parseLoopStructure(ScalarEvolution &SE,
|
||||||
BranchProbabilityInfo &BPI,
|
BranchProbabilityInfo *BPI, Loop &L,
|
||||||
Loop &L, const char *&FailureReason) {
|
const char *&FailureReason) {
|
||||||
if (!L.isLoopSimplifyForm()) {
|
if (!L.isLoopSimplifyForm()) {
|
||||||
FailureReason = "loop not in LoopSimplify form";
|
FailureReason = "loop not in LoopSimplify form";
|
||||||
return None;
|
return None;
|
||||||
|
@ -762,7 +778,8 @@ LoopStructure::parseLoopStructure(ScalarEvolution &SE,
|
||||||
unsigned LatchBrExitIdx = LatchBr->getSuccessor(0) == Header ? 1 : 0;
|
unsigned LatchBrExitIdx = LatchBr->getSuccessor(0) == Header ? 1 : 0;
|
||||||
|
|
||||||
BranchProbability ExitProbability =
|
BranchProbability ExitProbability =
|
||||||
BPI.getEdgeProbability(LatchBr->getParent(), LatchBrExitIdx);
|
BPI ? BPI->getEdgeProbability(LatchBr->getParent(), LatchBrExitIdx)
|
||||||
|
: BranchProbability::getZero();
|
||||||
|
|
||||||
if (!SkipProfitabilityChecks &&
|
if (!SkipProfitabilityChecks &&
|
||||||
ExitProbability > BranchProbability(1, MaxExitProbReciprocal)) {
|
ExitProbability > BranchProbability(1, MaxExitProbReciprocal)) {
|
||||||
|
@ -1396,13 +1413,14 @@ void LoopConstrainer::addToParentLoopIfNeeded(ArrayRef<BasicBlock *> BBs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Loop *LoopConstrainer::createClonedLoopStructure(Loop *Original, Loop *Parent,
|
Loop *LoopConstrainer::createClonedLoopStructure(Loop *Original, Loop *Parent,
|
||||||
ValueToValueMapTy &VM) {
|
ValueToValueMapTy &VM,
|
||||||
|
bool IsSubloop) {
|
||||||
Loop &New = *LI.AllocateLoop();
|
Loop &New = *LI.AllocateLoop();
|
||||||
if (Parent)
|
if (Parent)
|
||||||
Parent->addChildLoop(&New);
|
Parent->addChildLoop(&New);
|
||||||
else
|
else
|
||||||
LI.addTopLevelLoop(&New);
|
LI.addTopLevelLoop(&New);
|
||||||
LPM.addLoop(New);
|
LPMAddNewLoop(&New, IsSubloop);
|
||||||
|
|
||||||
// Add all of the blocks in Original to the new loop.
|
// Add all of the blocks in Original to the new loop.
|
||||||
for (auto *BB : Original->blocks())
|
for (auto *BB : Original->blocks())
|
||||||
|
@ -1411,7 +1429,7 @@ Loop *LoopConstrainer::createClonedLoopStructure(Loop *Original, Loop *Parent,
|
||||||
|
|
||||||
// Add all of the subloops to the new loop.
|
// Add all of the subloops to the new loop.
|
||||||
for (Loop *SubLoop : *Original)
|
for (Loop *SubLoop : *Original)
|
||||||
createClonedLoopStructure(SubLoop, &New, VM);
|
createClonedLoopStructure(SubLoop, &New, VM, /* IsSubloop */ true);
|
||||||
|
|
||||||
return &New;
|
return &New;
|
||||||
}
|
}
|
||||||
|
@ -1561,13 +1579,15 @@ bool LoopConstrainer::run() {
|
||||||
// LI when LoopSimplifyForm is generated.
|
// LI when LoopSimplifyForm is generated.
|
||||||
Loop *PreL = nullptr, *PostL = nullptr;
|
Loop *PreL = nullptr, *PostL = nullptr;
|
||||||
if (!PreLoop.Blocks.empty()) {
|
if (!PreLoop.Blocks.empty()) {
|
||||||
PreL = createClonedLoopStructure(
|
PreL = createClonedLoopStructure(&OriginalLoop,
|
||||||
&OriginalLoop, OriginalLoop.getParentLoop(), PreLoop.Map);
|
OriginalLoop.getParentLoop(), PreLoop.Map,
|
||||||
|
/* IsSubLoop */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PostLoop.Blocks.empty()) {
|
if (!PostLoop.Blocks.empty()) {
|
||||||
PostL = createClonedLoopStructure(
|
PostL =
|
||||||
&OriginalLoop, OriginalLoop.getParentLoop(), PostLoop.Map);
|
createClonedLoopStructure(&OriginalLoop, OriginalLoop.getParentLoop(),
|
||||||
|
PostLoop.Map, /* IsSubLoop */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function canonicalizes the loop into Loop-Simplify and LCSSA forms.
|
// This function canonicalizes the loop into Loop-Simplify and LCSSA forms.
|
||||||
|
@ -1738,12 +1758,45 @@ IntersectUnsignedRange(ScalarEvolution &SE,
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
|
PreservedAnalyses IRCEPass::run(Loop &L, LoopAnalysisManager &AM,
|
||||||
|
LoopStandardAnalysisResults &AR,
|
||||||
|
LPMUpdater &U) {
|
||||||
|
Function *F = L.getHeader()->getParent();
|
||||||
|
const auto &FAM =
|
||||||
|
AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR).getManager();
|
||||||
|
auto *BPI = FAM.getCachedResult<BranchProbabilityAnalysis>(*F);
|
||||||
|
InductiveRangeCheckElimination IRCE(AR.SE, BPI, AR.DT, AR.LI);
|
||||||
|
auto LPMAddNewLoop = [&U](Loop *NL, bool IsSubloop) {
|
||||||
|
if (!IsSubloop)
|
||||||
|
U.addSiblingLoops(NL);
|
||||||
|
};
|
||||||
|
bool Changed = IRCE.run(&L, LPMAddNewLoop);
|
||||||
|
if (!Changed)
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
|
||||||
|
return getLoopPassPreservedAnalyses();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRCELegacyPass::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||||
if (skipLoop(L))
|
if (skipLoop(L))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||||
|
BranchProbabilityInfo &BPI =
|
||||||
|
getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||||
|
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||||
|
auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||||
|
InductiveRangeCheckElimination IRCE(SE, &BPI, DT, LI);
|
||||||
|
auto LPMAddNewLoop = [&LPM](Loop *NL, bool /* IsSubLoop */) {
|
||||||
|
LPM.addLoop(*NL);
|
||||||
|
};
|
||||||
|
return IRCE.run(L, LPMAddNewLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InductiveRangeCheckElimination::run(
|
||||||
|
Loop *L, function_ref<void(Loop *, bool)> LPMAddNewLoop) {
|
||||||
if (L->getBlocks().size() >= LoopSizeCutoff) {
|
if (L->getBlocks().size() >= LoopSizeCutoff) {
|
||||||
DEBUG(dbgs() << "irce: giving up constraining loop, too large\n";);
|
DEBUG(dbgs() << "irce: giving up constraining loop, too large\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1755,9 +1808,6 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||||
|
|
||||||
LLVMContext &Context = Preheader->getContext();
|
LLVMContext &Context = Preheader->getContext();
|
||||||
SmallVector<InductiveRangeCheck, 16> RangeChecks;
|
SmallVector<InductiveRangeCheck, 16> RangeChecks;
|
||||||
ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
|
||||||
BranchProbabilityInfo &BPI =
|
|
||||||
getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
|
||||||
|
|
||||||
for (auto BBI : L->getBlocks())
|
for (auto BBI : L->getBlocks())
|
||||||
if (BranchInst *TBI = dyn_cast<BranchInst>(BBI->getTerminator()))
|
if (BranchInst *TBI = dyn_cast<BranchInst>(BBI->getTerminator()))
|
||||||
|
@ -1823,9 +1873,8 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||||
if (!SafeIterRange.hasValue())
|
if (!SafeIterRange.hasValue())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
LoopConstrainer LC(*L, LI, LPMAddNewLoop, LS, SE, DT,
|
||||||
LoopConstrainer LC(*L, getAnalysis<LoopInfoWrapperPass>().getLoopInfo(), LPM,
|
SafeIterRange.getValue());
|
||||||
LS, SE, DT, SafeIterRange.getValue());
|
|
||||||
bool Changed = LC.run();
|
bool Changed = LC.run();
|
||||||
|
|
||||||
if (Changed) {
|
if (Changed) {
|
||||||
|
@ -1855,5 +1904,5 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Pass *llvm::createInductiveRangeCheckEliminationPass() {
|
Pass *llvm::createInductiveRangeCheckEliminationPass() {
|
||||||
return new InductiveRangeCheckElimination;
|
return new IRCELegacyPass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) {
|
||||||
initializeGVNHoistLegacyPassPass(Registry);
|
initializeGVNHoistLegacyPassPass(Registry);
|
||||||
initializeGVNSinkLegacyPassPass(Registry);
|
initializeGVNSinkLegacyPassPass(Registry);
|
||||||
initializeFlattenCFGPassPass(Registry);
|
initializeFlattenCFGPassPass(Registry);
|
||||||
initializeInductiveRangeCheckEliminationPass(Registry);
|
initializeIRCELegacyPassPass(Registry);
|
||||||
initializeIndVarSimplifyLegacyPassPass(Registry);
|
initializeIndVarSimplifyLegacyPassPass(Registry);
|
||||||
initializeInferAddressSpacesPass(Registry);
|
initializeInferAddressSpacesPass(Registry);
|
||||||
initializeJumpThreadingPass(Registry);
|
initializeJumpThreadingPass(Registry);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; test that the pre and post loops have loop metadata which disables any further
|
; test that the pre and post loops have loop metadata which disables any further
|
||||||
; loop optimizations.
|
; loop optimizations.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -S -irce -irce-print-changed-loops=true < %s | FileCheck %s
|
; RUN: opt -S -irce -irce-print-changed-loops=true < %s | FileCheck %s
|
||||||
|
; RUN: opt -S -passes='require<branch-prob>,loop(irce)' -irce-print-changed-loops=true < %s | FileCheck %s
|
||||||
|
|
||||||
; CHECK-NOT: irce
|
; CHECK-NOT: irce
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
|
||||||
target triple = "x86_64-unknown-linux-gnu"
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -irce-print-changed-loops -S -verify-loop-info -irce -verify < %s 2>&1 | FileCheck %s
|
; RUN: opt -irce-print-changed-loops -S -verify-loop-info -irce -verify < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -irce-print-changed-loops -S -verify-loop-info -passes='require<branch-prob>,loop(irce)' -verify < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK-NOT: constrained loop
|
; CHECK-NOT: constrained loop
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce -S < %s
|
; RUN: opt -verify-loop-info -irce -S < %s
|
||||||
|
; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s
|
||||||
|
|
||||||
; These test cases don't check the correctness of the transform, but
|
; These test cases don't check the correctness of the transform, but
|
||||||
; that -irce does not crash in the presence of certain things in
|
; that -irce does not crash in the presence of certain things in
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; The test demonstrates that incorrect behavior of Clamp may lead to incorrect
|
; The test demonstrates that incorrect behavior of Clamp may lead to incorrect
|
||||||
; calculation of post-loop exit condition.
|
; calculation of post-loop exit condition.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -S -verify-loop-info -irce < %s | FileCheck %s
|
; RUN: opt -S -verify-loop-info -irce < %s | FileCheck %s
|
||||||
|
; RUN: opt -S -verify-loop-info -passes='require<branch-prob>,loop(irce)' < %s | FileCheck %s
|
||||||
|
|
||||||
define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) {
|
define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) {
|
||||||
; CHECK-LABEL: @f_0(
|
; CHECK-LABEL: @f_0(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||||
; RUN: opt -irce < %s -S | FileCheck %s
|
; RUN: opt -irce < %s -S | FileCheck %s
|
||||||
|
; RUN: opt -passes='require<branch-prob>,loop(irce)' < %s -S | FileCheck %s
|
||||||
|
|
||||||
; REQUIRES: asserts
|
; REQUIRES: asserts
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
|
||||||
|
|
||||||
define void @decrementing_loop(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
define void @decrementing_loop(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
||||||
entry:
|
entry:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S
|
||||||
|
|
||||||
; Make sure that IRCE doesn't apply in case of empty ranges.
|
; Make sure that IRCE doesn't apply in case of empty ranges.
|
||||||
; (i + 30 < 40) if i in [-30, 10).
|
; (i + 30 < 40) if i in [-30, 10).
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
; CHECK: irce: in function test_01u: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_01u: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
; RUN: opt -irce-print-changed-loops -verify-loop-info -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -irce-print-changed-loops -verify-loop-info -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
;
|
||||||
|
; TODO: new-pm version should be enabled after we decide on branch-probability handling for loop passes
|
||||||
|
; TODO: opt -irce-print-changed-loops -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK-NOT: constrained Loop
|
; CHECK-NOT: constrained Loop
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
|
||||||
|
|
||||||
define void @multiple_access_no_preloop(
|
define void @multiple_access_no_preloop(
|
||||||
i32* %arr_a, i32* %a_len_ptr, i32* %arr_b, i32* %b_len_ptr, i32 %n) {
|
i32* %arr_a, i32* %a_len_ptr, i32* %arr_b, i32* %b_len_ptr, i32 %n) {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
|
||||||
|
;
|
||||||
|
; TODO: new-pm version should be enabled after we decide on branch-probability handling for loop passes
|
||||||
|
; TODO: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK-NOT: constrained Loop
|
; CHECK-NOT: constrained Loop
|
||||||
|
|
||||||
|
@ -37,4 +40,4 @@ define void @multiple_access_no_preloop(
|
||||||
}
|
}
|
||||||
|
|
||||||
!0 = !{i32 0, i32 2147483647}
|
!0 = !{i32 0, i32 2147483647}
|
||||||
!1 = !{!"branch_weights", i32 1, i32 1}
|
!1 = !{!"branch_weights", i32 1, i32 1}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -irce-print-range-checks -irce-print-changed-loops -verify-loop-info -irce < %s 2>&1 | FileCheck %s
|
; RUN: opt -irce-print-range-checks -irce-print-changed-loops -verify-loop-info -irce < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -irce-print-range-checks -irce-print-changed-loops -verify-loop-info -passes='require<branch-prob>,loop(irce)' < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK: irce: loop has 1 inductive range checks:
|
; CHECK: irce: loop has 1 inductive range checks:
|
||||||
; CHECK-NEXT: InductiveRangeCheck:
|
; CHECK-NEXT: InductiveRangeCheck:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK: irce: loop has 1 inductive range checks:
|
; CHECK: irce: loop has 1 inductive range checks:
|
||||||
; CHECK-NEXT:InductiveRangeCheck:
|
; CHECK-NEXT:InductiveRangeCheck:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK-LABEL: irce: in function test_01: constrained Loop at depth 1 containing:
|
; CHECK-LABEL: irce: in function test_01: constrained Loop at depth 1 containing:
|
||||||
; CHECK-LABEL: irce: in function test_02: constrained Loop at depth 1 containing:
|
; CHECK-LABEL: irce: in function test_02: constrained Loop at depth 1 containing:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; Make sure we can eliminate range check with signed latch, unsigned IRC and
|
; Make sure we can eliminate range check with signed latch, unsigned IRC and
|
||||||
; positive offset. The safe iteration space is:
|
; positive offset. The safe iteration space is:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
|
||||||
|
|
||||||
define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
||||||
entry:
|
entry:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
|
||||||
|
|
||||||
define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 %offset) {
|
define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 %offset) {
|
||||||
entry:
|
entry:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -irce-skip-profitability-checks -S -verify-loop-info -irce < %s | FileCheck %s
|
; RUN: opt -irce-skip-profitability-checks -S -verify-loop-info -irce < %s | FileCheck %s
|
||||||
|
; RUN: opt -irce-skip-profitability-checks -S -verify-loop-info -passes='require<branch-prob>,loop(irce)' < %s | FileCheck %s
|
||||||
|
|
||||||
define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
||||||
; CHECK-LABEL: @single_access_no_preloop_no_offset(
|
; CHECK-LABEL: @single_access_no_preloop_no_offset(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -irce-print-changed-loops -verify-loop-info -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -irce-print-changed-loops -verify-loop-info -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -irce-print-changed-loops -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK-NOT: constrained Loop at depth
|
; CHECK-NOT: constrained Loop at depth
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
|
||||||
|
; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' < %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
; This test checks if we update the LoopInfo correctly in the presence
|
; This test checks if we update the LoopInfo correctly in the presence
|
||||||
; of parents, uncles and cousins.
|
; of parents, uncles and cousins.
|
||||||
|
|
Loading…
Reference in New Issue