[llvm] 28a9147 - [GuardWidening] Remove WidenFrequentBranches transform
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 19 15:15:57 PST 2019
Author: Philip Reames
Date: 2019-11-19T15:15:52-08:00
New Revision: 28a91473e33eb3585a87514e4cf2523a9a587d82
URL: https://github.com/llvm/llvm-project/commit/28a91473e33eb3585a87514e4cf2523a9a587d82
DIFF: https://github.com/llvm/llvm-project/commit/28a91473e33eb3585a87514e4cf2523a9a587d82.diff
LOG: [GuardWidening] Remove WidenFrequentBranches transform
This code has never been enabled. While it is tested, it's complicating some refactoring. If we decide to re-implement this, doing it in SimplifyCFG would probably make more sense anyways.
Added:
Modified:
llvm/lib/Transforms/Scalar/GuardWidening.cpp
Removed:
llvm/test/Transforms/GuardWidening/widen-frequent-branches.ll
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/GuardWidening.cpp b/llvm/lib/Transforms/Scalar/GuardWidening.cpp
index 943cc9ac5938..69d9507b3564 100644
--- a/llvm/lib/Transforms/Scalar/GuardWidening.cpp
+++ b/llvm/lib/Transforms/Scalar/GuardWidening.cpp
@@ -69,22 +69,6 @@ using namespace llvm;
STATISTIC(GuardsEliminated, "Number of eliminated guards");
STATISTIC(CondBranchEliminated, "Number of eliminated conditional branches");
-static cl::opt<bool> WidenFrequentBranches(
- "guard-widening-widen-frequent-branches", cl::Hidden,
- cl::desc("Widen conditions of explicit branches into dominating guards in "
- "case if their taken frequency exceeds threshold set by "
- "guard-widening-frequent-branch-threshold option"),
- cl::init(false));
-
-static cl::opt<unsigned> FrequentBranchThreshold(
- "guard-widening-frequent-branch-threshold", cl::Hidden,
- cl::desc("When WidenFrequentBranches is set to true, this option is used "
- "to determine which branches are frequently taken. The criteria "
- "that a branch is taken more often than "
- "((FrequentBranchThreshold - 1) / FrequentBranchThreshold), then "
- "it is considered frequently taken"),
- cl::init(1000));
-
static cl::opt<bool>
WidenBranchGuards("guard-widening-widen-branch-guards", cl::Hidden,
cl::desc("Whether or not we should widen guards "
@@ -129,7 +113,6 @@ class GuardWideningImpl {
DominatorTree &DT;
PostDominatorTree *PDT;
LoopInfo &LI;
- BranchProbabilityInfo *BPI;
/// Together, these describe the region of interest. This might be all of
/// the blocks within a function, or only a given loop's blocks and preheader.
@@ -287,10 +270,9 @@ class GuardWideningImpl {
public:
explicit GuardWideningImpl(DominatorTree &DT, PostDominatorTree *PDT,
- LoopInfo &LI, BranchProbabilityInfo *BPI,
- DomTreeNode *Root,
+ LoopInfo &LI, DomTreeNode *Root,
std::function<bool(BasicBlock*)> BlockFilter)
- : DT(DT), PDT(PDT), LI(LI), BPI(BPI), Root(Root), BlockFilter(BlockFilter)
+ : DT(DT), PDT(PDT), LI(LI), Root(Root), BlockFilter(BlockFilter)
{}
/// The entry point for this pass.
@@ -309,13 +291,6 @@ static bool isSupportedGuardInstruction(const Instruction *Insn) {
bool GuardWideningImpl::run() {
DenseMap<BasicBlock *, SmallVector<Instruction *, 8>> GuardsInBlock;
bool Changed = false;
- Optional<BranchProbability> LikelyTaken = None;
- if (WidenFrequentBranches && BPI) {
- unsigned Threshold = FrequentBranchThreshold;
- assert(Threshold > 0 && "Zero threshold makes no sense!");
- LikelyTaken = BranchProbability(Threshold - 1, Threshold);
- }
-
for (auto DFI = df_begin(Root), DFE = df_end(Root);
DFI != DFE; ++DFI) {
auto *BB = (*DFI)->getBlock();
@@ -330,17 +305,6 @@ bool GuardWideningImpl::run() {
for (auto *II : CurrentList)
Changed |= eliminateInstrViaWidening(II, DFI, GuardsInBlock);
- if (WidenFrequentBranches && BPI)
- if (auto *BI = dyn_cast<BranchInst>(BB->getTerminator()))
- if (BI->isConditional()) {
- // If one of branches of a conditional is likely taken, try to
- // eliminate it.
- if (BPI->getEdgeProbability(BB, 0U) >= *LikelyTaken)
- Changed |= eliminateInstrViaWidening(BI, DFI, GuardsInBlock);
- else if (BPI->getEdgeProbability(BB, 1U) >= *LikelyTaken)
- Changed |= eliminateInstrViaWidening(BI, DFI, GuardsInBlock,
- /*InvertCondition*/true);
- }
}
assert(EliminatedGuardsAndBranches.empty() || Changed);
@@ -805,10 +769,7 @@ PreservedAnalyses GuardWideningPass::run(Function &F,
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
auto &LI = AM.getResult<LoopAnalysis>(F);
auto &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);
- BranchProbabilityInfo *BPI = nullptr;
- if (WidenFrequentBranches)
- BPI = AM.getCachedResult<BranchProbabilityAnalysis>(F);
- if (!GuardWideningImpl(DT, &PDT, LI, BPI, DT.getRootNode(),
+ if (!GuardWideningImpl(DT, &PDT, LI, DT.getRootNode(),
[](BasicBlock*) { return true; } ).run())
return PreservedAnalyses::all();
@@ -820,22 +781,13 @@ PreservedAnalyses GuardWideningPass::run(Function &F,
PreservedAnalyses GuardWideningPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &U) {
-
- const auto &FAM =
- AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR).getManager();
- Function &F = *L.getHeader()->getParent();
- BranchProbabilityInfo *BPI = nullptr;
- if (WidenFrequentBranches)
- BPI = FAM.getCachedResult<BranchProbabilityAnalysis>(F);
-
BasicBlock *RootBB = L.getLoopPredecessor();
if (!RootBB)
RootBB = L.getHeader();
auto BlockFilter = [&](BasicBlock *BB) {
return BB == RootBB || L.contains(BB);
};
- if (!GuardWideningImpl(AR.DT, nullptr, AR.LI, BPI,
- AR.DT.getNode(RootBB),
+ if (!GuardWideningImpl(AR.DT, nullptr, AR.LI, AR.DT.getNode(RootBB),
BlockFilter).run())
return PreservedAnalyses::all();
@@ -856,10 +808,7 @@ struct GuardWideningLegacyPass : public FunctionPass {
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
- BranchProbabilityInfo *BPI = nullptr;
- if (WidenFrequentBranches)
- BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
- return GuardWideningImpl(DT, &PDT, LI, BPI, DT.getRootNode(),
+ return GuardWideningImpl(DT, &PDT, LI, DT.getRootNode(),
[](BasicBlock*) { return true; } ).run();
}
@@ -868,8 +817,6 @@ struct GuardWideningLegacyPass : public FunctionPass {
AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<PostDominatorTreeWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
- if (WidenFrequentBranches)
- AU.addRequired<BranchProbabilityInfoWrapperPass>();
}
};
@@ -895,16 +842,11 @@ struct LoopGuardWideningLegacyPass : public LoopPass {
auto BlockFilter = [&](BasicBlock *BB) {
return BB == RootBB || L->contains(BB);
};
- BranchProbabilityInfo *BPI = nullptr;
- if (WidenFrequentBranches)
- BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
- return GuardWideningImpl(DT, PDT, LI, BPI,
+ return GuardWideningImpl(DT, PDT, LI,
DT.getNode(RootBB), BlockFilter).run();
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
- if (WidenFrequentBranches)
- AU.addRequired<BranchProbabilityInfoWrapperPass>();
AU.setPreservesCFG();
getLoopAnalysisUsage(AU);
AU.addPreserved<PostDominatorTreeWrapperPass>();
@@ -920,8 +862,6 @@ INITIALIZE_PASS_BEGIN(GuardWideningLegacyPass, "guard-widening", "Widen guards",
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
-if (WidenFrequentBranches)
- INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)
INITIALIZE_PASS_END(GuardWideningLegacyPass, "guard-widening", "Widen guards",
false, false)
@@ -931,8 +871,6 @@ INITIALIZE_PASS_BEGIN(LoopGuardWideningLegacyPass, "loop-guard-widening",
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
-if (WidenFrequentBranches)
- INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)
INITIALIZE_PASS_END(LoopGuardWideningLegacyPass, "loop-guard-widening",
"Widen guards (within a single loop, as a loop pass)",
false, false)
diff --git a/llvm/test/Transforms/GuardWidening/widen-frequent-branches.ll b/llvm/test/Transforms/GuardWidening/widen-frequent-branches.ll
deleted file mode 100644
index 2f6dceadf497..000000000000
--- a/llvm/test/Transforms/GuardWidening/widen-frequent-branches.ll
+++ /dev/null
@@ -1,820 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -guard-widening-widen-frequent-branches=true -guard-widening-frequent-branch-threshold=1000 -S -guard-widening < %s | FileCheck %s
-; RUN: opt -guard-widening-widen-frequent-branches=true -guard-widening-frequent-branch-threshold=1000 -S -passes='require<branch-prob>,guard-widening' < %s | FileCheck %s
-
-declare void @llvm.experimental.guard(i1,...)
-declare void @foo()
-declare void @bar()
-
-; Check that we don't widen without branch probability.
-define void @test_01(i1 %cond_0, i1 %cond_1) {
-; CHECK-LABEL: @test_01(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- call void @bar()
- br label %merge
-
-merge:
- ret void
-}
-
-; Check that we don't widen with branch probability below threshold.
-define void @test_02(i1 %cond_0, i1 %cond_1) {
-; CHECK-LABEL: @test_02(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !0
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !0
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- call void @bar()
- br label %merge
-
-merge:
- ret void
-}
-
-; Check that we widen conditions of explicit branches into dominating guards
-; when the probability is high enough.
-define void @test_03(i1 %cond_0, i1 %cond_1) {
-; CHECK-LABEL: @test_03(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !1
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- call void @bar()
- br label %merge
-
-merge:
- ret void
-}
-
-; Similar to test_03, but the likely taken branch is the false branch.
-define void @test_03_not_taken(i1 %cond_0, i1 %cond_1) {
-; CHECK-LABEL: @test_03_not_taken(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !3
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- call void @bar()
- br label %merge
-
-merge:
- ret void
-}
-
-; Widen loop-invariant condition into the guard in preheader.
-define void @test_04(i1 %cond_0, i1 %cond_1, i32 %n) {
-; CHECK-LABEL: @test_04(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[MERGE:%.*]] ]
-; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: if.false:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
-; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
-; CHECK: exit:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br label %loop
-
-loop:
- %iv = phi i32 [ 0, %entry ], [ %iv.next, %merge ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !1
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- call void @bar()
- br label %merge
-
-merge:
- %iv.next = add i32 %iv, 1
- %cond = icmp slt i32 %iv.next, %n
- br i1 %cond, label %loop, label %exit
-
-exit:
- ret void
-}
-
-; Similar to test_04, but the likely taken branch is the false branch.
-define void @test_04_not_taken(i1 %cond_0, i1 %cond_1, i32 %n) {
-; CHECK-LABEL: @test_04_not_taken(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[MERGE:%.*]] ]
-; CHECK-NEXT: br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: if.false:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
-; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
-; CHECK: exit:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br label %loop
-
-loop:
- %iv = phi i32 [ 0, %entry ], [ %iv.next, %merge ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !3
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- call void @bar()
- br label %merge
-
-merge:
- %iv.next = add i32 %iv, 1
- %cond = icmp slt i32 %iv.next, %n
- br i1 %cond, label %loop, label %exit
-
-exit:
- ret void
-}
-
-; Widen loop-invariant condition into the guard in the same loop.
-define void @test_05(i1 %cond_0, i1 %cond_1, i32 %n) {
-; CHECK-LABEL: @test_05(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[MERGE:%.*]] ]
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: if.false:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
-; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
-; CHECK: exit:
-; CHECK-NEXT: ret void
-;
-entry:
- br label %loop
-
-loop:
- %iv = phi i32 [ 0, %entry ], [ %iv.next, %merge ]
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !1
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- call void @bar()
- br label %merge
-
-merge:
- %iv.next = add i32 %iv, 1
- %cond = icmp slt i32 %iv.next, %n
- br i1 %cond, label %loop, label %exit
-
-exit:
- ret void
-}
-
-; Similar to test_05, but the likely taken branch is the false branch.
-define void @test_05_not_taken(i1 %cond_0, i1 %cond_1, i32 %n) {
-; CHECK-LABEL: @test_05_not_taken(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[MERGE:%.*]] ]
-; CHECK-NEXT: [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: if.false:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
-; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
-; CHECK: exit:
-; CHECK-NEXT: ret void
-;
-entry:
- br label %loop
-
-loop:
- %iv = phi i32 [ 0, %entry ], [ %iv.next, %merge ]
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !3
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- call void @bar()
- br label %merge
-
-merge:
- %iv.next = add i32 %iv, 1
- %cond = icmp slt i32 %iv.next, %n
- br i1 %cond, label %loop, label %exit
-
-exit:
- ret void
-}
-
-; Some of checks are frequently taken and some are not, make sure that we only
-; widen frequent ones.
-define void @test_06(i1 %cond_0, i1 %cond_1, i1 %cond_2, i1 %cond_3, i1 %cond_4, i32 %n) {
-; CHECK-LABEL: @test_06(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2:%.*]]
-; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_4:%.*]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"() ]
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
-; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]], !prof !3
-; CHECK: if.true_1:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE_1:%.*]]
-; CHECK: if.false_1:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE_1]]
-; CHECK: merge_1:
-; CHECK-NEXT: br i1 true, label [[IF_TRUE_2:%.*]], label [[IF_FALSE_2:%.*]], !prof !1
-; CHECK: if.true_2:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE_2:%.*]]
-; CHECK: if.false_2:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE_2]]
-; CHECK: merge_2:
-; CHECK-NEXT: br i1 [[COND_3:%.*]], label [[IF_TRUE_3:%.*]], label [[IF_FALSE_3:%.*]], !prof !3
-; CHECK: if.true_3:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE_3:%.*]]
-; CHECK: if.false_3:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE_3]]
-; CHECK: merge_3:
-; CHECK-NEXT: br i1 true, label [[IF_TRUE_4:%.*]], label [[IF_FALSE_4:%.*]], !prof !1
-; CHECK: if.true_4:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: if.false_4:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: backedge:
-; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
-; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
-; CHECK: exit:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br label %loop
-
-loop:
- %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
- br i1 %cond_1, label %if.true_1, label %if.false_1, !prof !2
-
-if.true_1:
- call void @foo()
- br label %merge_1
-
-if.false_1:
- call void @bar()
- br label %merge_1
-
-merge_1:
- br i1 %cond_2, label %if.true_2, label %if.false_2, !prof !1
-
-if.true_2:
- call void @foo()
- br label %merge_2
-
-if.false_2:
- call void @bar()
- br label %merge_2
-
-merge_2:
- br i1 %cond_3, label %if.true_3, label %if.false_3, !prof !2
-
-if.true_3:
- call void @foo()
- br label %merge_3
-
-if.false_3:
- call void @bar()
- br label %merge_3
-
-merge_3:
- br i1 %cond_4, label %if.true_4, label %if.false_4, !prof !1
-
-if.true_4:
- call void @foo()
- br label %backedge
-
-if.false_4:
- call void @bar()
- br label %backedge
-
-backedge:
- %iv.next = add i32 %iv, 1
- %cond = icmp slt i32 %iv.next, %n
- br i1 %cond, label %loop, label %exit
-
-exit:
- ret void
-}
-
-; Similar to test_06, but the likely taken branch is the false branch.
-define void @test_06_not_taken(i1 %cond_0, i1 %cond_1, i1 %cond_2, i1 %cond_3, i1 %cond_4, i32 %n) {
-; CHECK-LABEL: @test_06_not_taken(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVERTED:%.*]] = xor i1 [[COND_2:%.*]], true
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
-; CHECK-NEXT: [[INVERTED1:%.*]] = xor i1 [[COND_4:%.*]], true
-; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK]], [[INVERTED1]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
-; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]], !prof !3
-; CHECK: if.true_1:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE_1:%.*]]
-; CHECK: if.false_1:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE_1]]
-; CHECK: merge_1:
-; CHECK-NEXT: br i1 false, label [[IF_TRUE_2:%.*]], label [[IF_FALSE_2:%.*]], !prof !2
-; CHECK: if.true_2:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE_2:%.*]]
-; CHECK: if.false_2:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE_2]]
-; CHECK: merge_2:
-; CHECK-NEXT: br i1 [[COND_3:%.*]], label [[IF_TRUE_3:%.*]], label [[IF_FALSE_3:%.*]], !prof !3
-; CHECK: if.true_3:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE_3:%.*]]
-; CHECK: if.false_3:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[MERGE_3]]
-; CHECK: merge_3:
-; CHECK-NEXT: br i1 false, label [[IF_TRUE_4:%.*]], label [[IF_FALSE_4:%.*]], !prof !2
-; CHECK: if.true_4:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: if.false_4:
-; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: backedge:
-; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
-; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
-; CHECK: exit:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br label %loop
-
-loop:
- %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
- br i1 %cond_1, label %if.true_1, label %if.false_1, !prof !2
-
-if.true_1:
- call void @foo()
- br label %merge_1
-
-if.false_1:
- call void @bar()
- br label %merge_1
-
-merge_1:
- br i1 %cond_2, label %if.true_2, label %if.false_2, !prof !3
-
-if.true_2:
- call void @foo()
- br label %merge_2
-
-if.false_2:
- call void @bar()
- br label %merge_2
-
-merge_2:
- br i1 %cond_3, label %if.true_3, label %if.false_3, !prof !2
-
-if.true_3:
- call void @foo()
- br label %merge_3
-
-if.false_3:
- call void @bar()
- br label %merge_3
-
-merge_3:
- br i1 %cond_4, label %if.true_4, label %if.false_4, !prof !3
-
-if.true_4:
- call void @foo()
- br label %backedge
-
-if.false_4:
- call void @bar()
- br label %backedge
-
-backedge:
- %iv.next = add i32 %iv, 1
- %cond = icmp slt i32 %iv.next, %n
- br i1 %cond, label %loop, label %exit
-
-exit:
- ret void
-}
-
-; Check triangle CFG pattern.
-define void @test_07(i1 %cond_0, i1 %cond_1) {
-; CHECK-LABEL: @test_07(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[MERGE:%.*]], !prof !1
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %merge, !prof !1
-
-if.true:
- call void @foo()
- br label %merge
-
-merge:
- ret void
-}
-
-; Similar to test_07, but the likely taken branch is the false branch.
-define void @test_07_not_taken(i1 %cond_0, i1 %cond_1) {
-; CHECK-LABEL: @test_07_not_taken(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 false, label [[IF_TRUE:%.*]], label [[MERGE:%.*]], !prof !2
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %merge, !prof !3
-
-if.true:
- call void @foo()
- br label %merge
-
-merge:
- ret void
-}
-
-define void @test_08(i1 %cond_0, i1 %cond_1) {
-; CHECK-LABEL: @test_08(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: ret void
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !1
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- ret void
-
-merge:
- ret void
-}
-
-define void @test_08_not_taken(i1 %cond_0, i1 %cond_1) {
-; CHECK-LABEL: @test_08_not_taken(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: ret void
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !3
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- ret void
-
-merge:
- ret void
-}
-
-; Check that L >u C0 && L >u C1 -> L >u max(C0, C1).
-define void @test_09(i32 %L) {
-; CHECK-LABEL: @test_09(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[L:%.*]], 123
-; CHECK-NEXT: [[COND_1:%.*]] = icmp ugt i32 [[L]], 456
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[L]], 457
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: ret void
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- %cond_0 = icmp ugt i32 %L, 123
- %cond_1 = icmp ugt i32 %L, 456
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !1
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- ret void
-
-merge:
- ret void
-}
-
-; Check that L >u C0 && !(L <=u C1) -> L >u max(C0, C1).
-define void @test_09_not_taken(i32 %L) {
-; CHECK-LABEL: @test_09_not_taken(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[L:%.*]], 123
-; CHECK-NEXT: [[COND_1:%.*]] = icmp ule i32 [[L]], 456
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[L]], 457
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: ret void
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- %cond_0 = icmp ugt i32 %L, 123
- %cond_1 = icmp ule i32 %L, 456
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !3
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- ret void
-
-merge:
- ret void
-}
-
-; Check that a profitable transform is preferred over non-profitable.
-define void @test_10(i32 %L, i1 %irrelevant_cond, i1 %infinite_loop_cond) {
-; CHECK-LABEL: @test_10(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[L:%.*]], 123
-; CHECK-NEXT: [[COND_1:%.*]] = icmp ugt i32 [[L]], 456
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[IRRELEVANT_COND:%.*]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 [[INFINITE_LOOP_COND:%.*]], label [[LOOP]], label [[AFTER_LOOP:%.*]]
-; CHECK: after_loop:
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[L]], 457
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- %cond_0 = icmp ugt i32 %L, 123
- %cond_1 = icmp ugt i32 %L, 456
- br label %loop
-
-loop:
- call void(i1, ...) @llvm.experimental.guard(i1 %irrelevant_cond) [ "deopt"() ]
- br i1 %infinite_loop_cond, label %loop, label %after_loop
-
-after_loop:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !1
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- br label %merge
-
-merge:
- ret void
-}
-
-; Check that a profitable transform is preferred over non-profitable.
-
-define void @test_10_not_taken(i32 %L, i1 %irrelevant_cond, i1 %infinite_loop_cond) {
-; CHECK-LABEL: @test_10_not_taken(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[L:%.*]], 123
-; CHECK-NEXT: [[COND_1:%.*]] = icmp ule i32 [[L]], 456
-; CHECK-NEXT: br label [[LOOP:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[IRRELEVANT_COND:%.*]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 [[INFINITE_LOOP_COND:%.*]], label [[LOOP]], label [[AFTER_LOOP:%.*]]
-; CHECK: after_loop:
-; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[L]], 457
-; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
-; CHECK-NEXT: br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
-; CHECK: if.true:
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: if.false:
-; CHECK-NEXT: br label [[MERGE]]
-; CHECK: merge:
-; CHECK-NEXT: ret void
-;
-entry:
- %cond_0 = icmp ugt i32 %L, 123
- %cond_1 = icmp ule i32 %L, 456
- br label %loop
-
-loop:
- call void(i1, ...) @llvm.experimental.guard(i1 %irrelevant_cond) [ "deopt"() ]
- br i1 %infinite_loop_cond, label %loop, label %after_loop
-
-after_loop:
- call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
- br i1 %cond_1, label %if.true, label %if.false, !prof !3
-
-if.true:
- call void @foo()
- br label %merge
-
-if.false:
- br label %merge
-
-merge:
- ret void
-}
-
-!0 = !{!"branch_weights", i32 998, i32 1}
-!1 = !{!"branch_weights", i32 999, i32 1}
-!2 = !{!"branch_weights", i32 500, i32 500}
-!3 = !{!"branch_weights", i32 1, i32 999}
More information about the llvm-commits
mailing list