Skip to content

Commit

Permalink
[New PM][IRCE] port of Inductive Range Check Elimination pass to the …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Fedor Sergeev committed Mar 15, 2018
1 parent 5704dc0 commit 194a407
Show file tree
Hide file tree
Showing 33 changed files with 155 additions and 42 deletions.
2 changes: 1 addition & 1 deletion llvm/include/llvm/InitializePasses.h
Expand Up @@ -166,7 +166,7 @@ void initializeIfConverterPass(PassRegistry&);
void initializeImplicitNullChecksPass(PassRegistry&);
void initializeIndVarSimplifyLegacyPassPass(PassRegistry&);
void initializeIndirectBrExpandPassPass(PassRegistry&);
void initializeInductiveRangeCheckEliminationPass(PassRegistry&);
void initializeIRCELegacyPassPass(PassRegistry&);
void initializeInferAddressSpacesPass(PassRegistry&);
void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&);
void initializeInlineCostAnalysisPass(PassRegistry&);
Expand Down
@@ -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
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Expand Up @@ -103,6 +103,7 @@
#include "llvm/Transforms/Scalar/GuardWidening.h"
#include "llvm/Transforms/Scalar/IVUsersPrinter.h"
#include "llvm/Transforms/Scalar/IndVarSimplify.h"
#include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h"
#include "llvm/Transforms/Scalar/JumpThreading.h"
#include "llvm/Transforms/Scalar/LICM.h"
#include "llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h"
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassRegistry.def
Expand Up @@ -237,6 +237,7 @@ LOOP_PASS("loop-deletion", LoopDeletionPass())
LOOP_PASS("simplify-cfg", LoopSimplifyCFGPass())
LOOP_PASS("strength-reduce", LoopStrengthReducePass())
LOOP_PASS("indvars", IndVarSimplifyPass())
LOOP_PASS("irce", IRCEPass())
LOOP_PASS("unroll-full", LoopFullUnrollPass())
LOOP_PASS("unswitch", SimpleLoopUnswitchPass())
LOOP_PASS("print-access-info", LoopAccessInfoPrinterPass(dbgs()))
Expand Down
127 changes: 88 additions & 39 deletions llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
Expand Up @@ -43,6 +43,7 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
Expand All @@ -52,6 +53,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/LoopAnalysisManager.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/ScalarEvolution.h"
Expand Down Expand Up @@ -235,17 +237,31 @@ class InductiveRangeCheck {
/// checks, and hence don't end up in \p Checks.
static void
extractRangeChecksFromBranch(BranchInst *BI, Loop *L, ScalarEvolution &SE,
BranchProbabilityInfo &BPI,
BranchProbabilityInfo *BPI,
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:
static char ID;

InductiveRangeCheckElimination() : LoopPass(ID) {
initializeInductiveRangeCheckEliminationPass(
*PassRegistry::getPassRegistry());
IRCELegacyPass() : LoopPass(ID) {
initializeIRCELegacyPassPass(*PassRegistry::getPassRegistry());
}

void getAnalysisUsage(AnalysisUsage &AU) const override {
Expand All @@ -258,14 +274,14 @@ class InductiveRangeCheckElimination : public LoopPass {

} // 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)
INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopPass)
INITIALIZE_PASS_END(InductiveRangeCheckElimination, "irce",
"Inductive range check elimination", false, false)
INITIALIZE_PASS_END(IRCELegacyPass, "irce", "Inductive range check elimination",
false, false)

StringRef InductiveRangeCheck::rangeCheckKindToStr(
InductiveRangeCheck::RangeCheckKind RCK) {
Expand Down Expand Up @@ -417,15 +433,15 @@ void InductiveRangeCheck::extractRangeChecksFromCond(
}

void InductiveRangeCheck::extractRangeChecksFromBranch(
BranchInst *BI, Loop *L, ScalarEvolution &SE, BranchProbabilityInfo &BPI,
BranchInst *BI, Loop *L, ScalarEvolution &SE, BranchProbabilityInfo *BPI,
SmallVectorImpl<InductiveRangeCheck> &Checks) {
if (BI->isUnconditional() || BI->getParent() == L->getLoopLatch())
return;

BranchProbability LikelyTaken(15, 16);

if (!SkipProfitabilityChecks &&
BPI.getEdgeProbability(BI->getParent(), (unsigned)0) < LikelyTaken)
if (!SkipProfitabilityChecks && BPI &&
BPI->getEdgeProbability(BI->getParent(), (unsigned)0) < LikelyTaken)
return;

SmallPtrSet<Value *, 8> Visited;
Expand Down Expand Up @@ -516,9 +532,8 @@ struct LoopStructure {
}

static Optional<LoopStructure> parseLoopStructure(ScalarEvolution &,
BranchProbabilityInfo &BPI,
Loop &,
const char *&);
BranchProbabilityInfo *BPI,
Loop &, const char *&);
};

/// This class is used to constrain loops to run within a given iteration space.
Expand Down Expand Up @@ -585,7 +600,7 @@ class LoopConstrainer {
// Create the appropriate loop structure needed to describe a cloned copy of
// `Original`. The clone is described by `VM`.
Loop *createClonedLoopStructure(Loop *Original, Loop *Parent,
ValueToValueMapTy &VM);
ValueToValueMapTy &VM, bool IsSubloop);

// 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
Expand Down Expand Up @@ -637,8 +652,8 @@ class LoopConstrainer {
LLVMContext &Ctx;
ScalarEvolution &SE;
DominatorTree &DT;
LPPassManager &LPM;
LoopInfo &LI;
function_ref<void(Loop *, bool)> LPMAddNewLoop;

// Information about the original loop we started out with.
Loop &OriginalLoop;
Expand All @@ -658,12 +673,13 @@ class LoopConstrainer {
LoopStructure MainLoopStructure;

public:
LoopConstrainer(Loop &L, LoopInfo &LI, LPPassManager &LPM,
LoopConstrainer(Loop &L, LoopInfo &LI,
function_ref<void(Loop *, bool)> LPMAddNewLoop,
const LoopStructure &LS, ScalarEvolution &SE,
DominatorTree &DT, InductiveRangeCheck::Range R)
: F(*L.getHeader()->getParent()), Ctx(L.getHeader()->getContext()),
SE(SE), DT(DT), LPM(LPM), LI(LI), OriginalLoop(L), Range(R),
MainLoopStructure(LS) {}
SE(SE), DT(DT), LI(LI), LPMAddNewLoop(LPMAddNewLoop), OriginalLoop(L),
Range(R), MainLoopStructure(LS) {}

// Entry point for the algorithm. Returns true on success.
bool run();
Expand Down Expand Up @@ -726,8 +742,8 @@ static bool SumCanReachMin(ScalarEvolution &SE, const SCEV *S1, const SCEV *S2,

Optional<LoopStructure>
LoopStructure::parseLoopStructure(ScalarEvolution &SE,
BranchProbabilityInfo &BPI,
Loop &L, const char *&FailureReason) {
BranchProbabilityInfo *BPI, Loop &L,
const char *&FailureReason) {
if (!L.isLoopSimplifyForm()) {
FailureReason = "loop not in LoopSimplify form";
return None;
Expand Down Expand Up @@ -762,7 +778,8 @@ LoopStructure::parseLoopStructure(ScalarEvolution &SE,
unsigned LatchBrExitIdx = LatchBr->getSuccessor(0) == Header ? 1 : 0;

BranchProbability ExitProbability =
BPI.getEdgeProbability(LatchBr->getParent(), LatchBrExitIdx);
BPI ? BPI->getEdgeProbability(LatchBr->getParent(), LatchBrExitIdx)
: BranchProbability::getZero();

if (!SkipProfitabilityChecks &&
ExitProbability > BranchProbability(1, MaxExitProbReciprocal)) {
Expand Down Expand Up @@ -1396,13 +1413,14 @@ void LoopConstrainer::addToParentLoopIfNeeded(ArrayRef<BasicBlock *> BBs) {
}

Loop *LoopConstrainer::createClonedLoopStructure(Loop *Original, Loop *Parent,
ValueToValueMapTy &VM) {
ValueToValueMapTy &VM,
bool IsSubloop) {
Loop &New = *LI.AllocateLoop();
if (Parent)
Parent->addChildLoop(&New);
else
LI.addTopLevelLoop(&New);
LPM.addLoop(New);
LPMAddNewLoop(&New, IsSubloop);

// Add all of the blocks in Original to the new loop.
for (auto *BB : Original->blocks())
Expand All @@ -1411,7 +1429,7 @@ Loop *LoopConstrainer::createClonedLoopStructure(Loop *Original, Loop *Parent,

// Add all of the subloops to the new loop.
for (Loop *SubLoop : *Original)
createClonedLoopStructure(SubLoop, &New, VM);
createClonedLoopStructure(SubLoop, &New, VM, /* IsSubloop */ true);

return &New;
}
Expand Down Expand Up @@ -1561,13 +1579,15 @@ bool LoopConstrainer::run() {
// LI when LoopSimplifyForm is generated.
Loop *PreL = nullptr, *PostL = nullptr;
if (!PreLoop.Blocks.empty()) {
PreL = createClonedLoopStructure(
&OriginalLoop, OriginalLoop.getParentLoop(), PreLoop.Map);
PreL = createClonedLoopStructure(&OriginalLoop,
OriginalLoop.getParentLoop(), PreLoop.Map,
/* IsSubLoop */ false);
}

if (!PostLoop.Blocks.empty()) {
PostL = createClonedLoopStructure(
&OriginalLoop, OriginalLoop.getParentLoop(), PostLoop.Map);
PostL =
createClonedLoopStructure(&OriginalLoop, OriginalLoop.getParentLoop(),
PostLoop.Map, /* IsSubLoop */ false);
}

// This function canonicalizes the loop into Loop-Simplify and LCSSA forms.
Expand Down Expand Up @@ -1738,12 +1758,45 @@ IntersectUnsignedRange(ScalarEvolution &SE,
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))
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) {
DEBUG(dbgs() << "irce: giving up constraining loop, too large\n";);
DEBUG(dbgs() << "irce: giving up constraining loop, too large\n");
return false;
}

Expand All @@ -1755,9 +1808,6 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {

LLVMContext &Context = Preheader->getContext();
SmallVector<InductiveRangeCheck, 16> RangeChecks;
ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
BranchProbabilityInfo &BPI =
getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();

for (auto BBI : L->getBlocks())
if (BranchInst *TBI = dyn_cast<BranchInst>(BBI->getTerminator()))
Expand Down Expand Up @@ -1823,9 +1873,8 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
if (!SafeIterRange.hasValue())
return false;

auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
LoopConstrainer LC(*L, getAnalysis<LoopInfoWrapperPass>().getLoopInfo(), LPM,
LS, SE, DT, SafeIterRange.getValue());
LoopConstrainer LC(*L, LI, LPMAddNewLoop, LS, SE, DT,
SafeIterRange.getValue());
bool Changed = LC.run();

if (Changed) {
Expand Down Expand Up @@ -1855,5 +1904,5 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
}

Pass *llvm::createInductiveRangeCheckEliminationPass() {
return new InductiveRangeCheckElimination;
return new IRCELegacyPass();
}
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/Scalar.cpp
Expand Up @@ -52,7 +52,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) {
initializeGVNHoistLegacyPassPass(Registry);
initializeGVNSinkLegacyPassPass(Registry);
initializeFlattenCFGPassPass(Registry);
initializeInductiveRangeCheckEliminationPass(Registry);
initializeIRCELegacyPassPass(Registry);
initializeIndVarSimplifyLegacyPassPass(Registry);
initializeInferAddressSpacesPass(Registry);
initializeJumpThreadingPass(Registry);
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/IRCE/add-metadata-pre-post-loops.ll
@@ -1,4 +1,5 @@
; 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
; loop optimizations.
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/IRCE/bad-loop-structure.ll
@@ -1,4 +1,5 @@
; 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

Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/IRCE/bad_expander.ll
@@ -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 -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 triple = "x86_64-unknown-linux-gnu"
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/IRCE/bug-loop-varying-upper-limit.ll
@@ -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 -passes='require<branch-prob>,loop(irce)' -verify < %s 2>&1 | FileCheck %s

; CHECK-NOT: constrained loop

Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/IRCE/bug-mismatched-types.ll
@@ -1,4 +1,5 @@
; 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
; that -irce does not crash in the presence of certain things in
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/IRCE/clamp.ll
@@ -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 -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s

; The test demonstrates that incorrect behavior of Clamp may lead to incorrect
; calculation of post-loop exit condition.
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/IRCE/conjunctive-checks.ll
@@ -1,4 +1,5 @@
; 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) {
; CHECK-LABEL: @f_0(
Expand Down
1 change: 1 addition & 0 deletions llvm/test/Transforms/IRCE/correct-loop-info.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -irce < %s -S | FileCheck %s
; RUN: opt -passes='require<branch-prob>,loop(irce)' < %s -S | FileCheck %s

; REQUIRES: asserts

Expand Down

0 comments on commit 194a407

Please sign in to comment.