[llvm] Reland "[SimplifyCFG] Simplify switch default branch when branch proves operand value" (PR #211427)
Sayan Sivakumaran via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 23 08:59:16 PDT 2026
https://github.com/sivakusayan updated https://github.com/llvm/llvm-project/pull/211427
>From 9d5257b6351156bf93f3d3127760d786b26c599c Mon Sep 17 00:00:00 2001
From: Sayan Sivakumaran <sivakusayan at gmail.com>
Date: Wed, 22 Jul 2026 18:35:49 -0500
Subject: [PATCH 1/2] [SimplifyCFG] Simplify switch default branch when branch
proves operand value
---
llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 41 +++
.../SimplifyCFG/switch-simplify-default.ll | 297 ++++++++++++++++++
2 files changed, 338 insertions(+)
create mode 100644 llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index ca6ae94a9a8d9..5a082bf6575b5 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7857,6 +7857,44 @@ static bool simplifySwitchWhenUMin(SwitchInst *SI, DomTreeUpdater *DTU) {
return true;
}
+static bool simplifySwitchDefaultBranch(SwitchInst *SI, DomTreeUpdater *DTU,
+ const DataLayout &DL,
+ AssumptionCache *AC) {
+ assert(SI);
+ if (SI->defaultDestUnreachable())
+ return false;
+
+ // If it can be proved that the switch condition takes some concrete value
+ // in the default block, we can make some nice simplifications to the
+ // switch.
+ BasicBlock *Default = SI->getDefaultDest();
+ const Instruction *CxtI = &*Default->getFirstNonPHIIt();
+ const KnownBits Known = computeKnownBits(
+ SI->getCondition(),
+ SimplifyQuery(DL, /*DT=*/nullptr, AC, CxtI).allowEphemerals(true));
+ if (!Known.isConstant())
+ return false;
+
+ // At this point, we know that only one value can be mapped to the
+ // default block. So, if a case doesn't exist for it already, we
+ // can create one pointing to the default block.
+ ConstantInt *CaseVal =
+ ConstantInt::get(SI->getContext(), Known.getConstant());
+ const llvm::SwitchInst::CaseIt CaseIt = SI->findCaseValue(CaseVal);
+ if (CaseIt == SI->case_default()) {
+ SwitchInstProfUpdateWrapper SIW(*SI);
+ SIW.addCase(CaseVal, Default, SIW.getSuccessorWeight(0));
+ SIW.setSuccessorWeight(0, 0);
+ }
+ createUnreachableSwitchDefault(SI, DTU, /*RemoveOrigDefaultBlock*/ false);
+
+ assert(SI->getNumCases() > 0 && "Switch should have at least one case");
+ assert(SI->findCaseValue(CaseVal) != SI->case_default() &&
+ "Proven value should have a dedicated case");
+ assert(SI->defaultDestUnreachable());
+ return true;
+}
+
/// Tries to transform switch of powers of two to reduce switch range.
/// For example, switch like:
/// switch (C) { case 1: case 2: case 64: case 128: }
@@ -8397,6 +8435,9 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
if (simplifySwitchWhenUMin(SI, DTU))
return requestResimplify();
+ if (simplifySwitchDefaultBranch(SI, DTU, DL, Options.AC))
+ return requestResimplify();
+
return false;
}
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll b/llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll
new file mode 100644
index 0000000000000..e81911c9064e5
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll
@@ -0,0 +1,297 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
+
+define i32 @default_branch_proves_operand_value(i8 %x) {
+; CHECK-LABEL: @default_branch_proves_operand_value(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: i8 1, label [[DEFAULT:%.*]]
+; CHECK-NEXT: ]
+; CHECK: entry.unreachabledefault:
+; CHECK-NEXT: unreachable
+; CHECK: default:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ ]
+default:
+ %cmp = icmp eq i8 %x, 1
+ call void @llvm.assume(i1 %cmp)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
+ ret i32 %retval
+}
+
+define i32 @default_branch_with_weight_proves_operand_value(i8 %x) {
+; CHECK-LABEL: @default_branch_with_weight_proves_operand_value(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: i8 1, label [[DEFAULT:%.*]]
+; CHECK-NEXT: ], !prof [[PROF0:![0-9]+]]
+; CHECK: entry.unreachabledefault:
+; CHECK-NEXT: unreachable
+; CHECK: default:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ ], !prof !0
+
+default:
+ %cmp = icmp eq i8 %x, 1
+ call void @llvm.assume(i1 %cmp)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
+ ret i32 %retval
+}
+
+define i32 @default_branch_proves_operand_value_different_blocks(i8 %x) {
+; CHECK-LABEL: @default_branch_proves_operand_value_different_blocks(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 1
+; CHECK-NEXT: switch i8 [[X]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: i8 1, label [[DEFAULT:%.*]]
+; CHECK-NEXT: ]
+; CHECK: entry.unreachabledefault:
+; CHECK-NEXT: unreachable
+; CHECK: default:
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+entry:
+ %cmp = icmp eq i8 %x, 1
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ ]
+default:
+ call void @llvm.assume(i1 %cmp)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
+ ret i32 %retval
+}
+
+declare void @foo(i8 %bar) nounwind
+define i32 @default_branch_proves_operand_value_assume_operand_not_ephemeral(i8 %x) {
+; CHECK-LABEL: @default_branch_proves_operand_value_assume_operand_not_ephemeral(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: i8 1, label [[DEFAULT:%.*]]
+; CHECK-NEXT: ]
+; CHECK: entry.unreachabledefault:
+; CHECK-NEXT: unreachable
+; CHECK: default:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: call void @foo(i1 [[CMP]])
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ ]
+default:
+ %cmp = icmp eq i8 %x, 1
+ call void @llvm.assume(i1 %cmp)
+ call void @foo(i1 %cmp)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
+ ret i32 %retval
+}
+
+define i32 @default_branch_proves_operand_value_but_has_existing_case(i8 %x) {
+; CHECK-LABEL: @default_branch_proves_operand_value_but_has_existing_case(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: i8 1, label [[CASE_ONE:%.*]]
+; CHECK-NEXT: ]
+; CHECK: entry.unreachabledefault:
+; CHECK-NEXT: unreachable
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_one:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[CASE_ONE]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ i8 1, label %case_one
+ ]
+
+default:
+ %cmp = icmp eq i8 %x, 1
+ call void @llvm.assume(i1 %cmp)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+case_one:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ], [1, %case_one ]
+ ret i32 %retval
+}
+
+define i32 @default_branch_assume_doesnt_prove_all_bits(i8 %x) {
+; CHECK-LABEL: @default_branch_assume_doesnt_prove_all_bits(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: ]
+; CHECK: default:
+; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[X]], 10
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ ]
+
+default:
+ %cmp = icmp ule i8 %x, 10
+ call void @llvm.assume(i1 %cmp)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
+ ret i32 %retval
+}
+
+declare void @foo_may_unwind()
+define i32 @default_branch_may_throw_before_assume(i8 %x) {
+; CHECK-LABEL: @default_branch_may_throw_before_assume(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: ]
+; CHECK: default:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT: call void @foo_may_unwind()
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[ENTRY_UNREACHABLEDEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ ]
+default:
+ %cmp = icmp eq i8 %x, 1
+ call void @foo_may_unwind()
+ call void @llvm.assume(i1 %cmp)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
+ ret i32 %retval
+}
+
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 0, i32 4, i32 2, i32 8}
+!0 = !{!"branch_weights", i32 8, i32 4, i32 2}
>From f4a8d709067e879cf16a074aba20068bee9d612c Mon Sep 17 00:00:00 2001
From: Sayan Sivakumaran <sivakusayan at gmail.com>
Date: Wed, 22 Jul 2026 18:37:29 -0500
Subject: [PATCH 2/2] Properly handle PHINodes in default branch we are
simplifying
---
llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 2 +
.../SimplifyCFG/switch-simplify-default.ll | 159 ++++++++++++++++++
2 files changed, 161 insertions(+)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 5a082bf6575b5..1cde16d9558e6 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7885,6 +7885,8 @@ static bool simplifySwitchDefaultBranch(SwitchInst *SI, DomTreeUpdater *DTU,
SwitchInstProfUpdateWrapper SIW(*SI);
SIW.addCase(CaseVal, Default, SIW.getSuccessorWeight(0));
SIW.setSuccessorWeight(0, 0);
+ } else {
+ Default->removePredecessor(SI->getParent());
}
createUnreachableSwitchDefault(SI, DTU, /*RemoveOrigDefaultBlock*/ false);
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll b/llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll
index e81911c9064e5..6ea6115147a8f 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll
@@ -293,5 +293,164 @@ return:
ret i32 %retval
}
+; Make sure to properly update PHINode block entries if the default branch
+; happens to have them.
+declare i1 @some_use(i8)
+define i32 @default_branch_has_phi_and_will_be_moved(i8 %x, i1 %y) {
+; CHECK-LABEL: @default_branch_has_phi_and_will_be_moved(
+; CHECK-NEXT: pre-entry:
+; CHECK-NEXT: br i1 [[Y:%.*]], label [[ENTRY:%.*]], label [[DEFAULT:%.*]]
+; CHECK: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: i8 1, label [[DEFAULT]]
+; CHECK-NEXT: ]
+; CHECK: entry.unreachabledefault:
+; CHECK-NEXT: unreachable
+; CHECK: default:
+; CHECK-NEXT: [[Z:%.*]] = phi i8 [ 2, [[PRE_ENTRY:%.*]] ], [ 3, [[ENTRY]] ]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: call void @some_use(i8 [[Z]])
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+pre-entry:
+ br i1 %y, label %entry, label %default
+
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ ]
+default:
+ %z = phi i8 [ 2, %pre-entry], [ 3, %entry]
+ %cmp = icmp eq i8 %x, 1
+ call void @llvm.assume(i1 %cmp)
+ call void @some_use(i8 %z)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
+ ret i32 %retval
+}
+
+define i32 @default_branch_has_phi_and_will_be_removed(i8 %x, i1 %y) {
+; CHECK-LABEL: @default_branch_has_phi_and_will_be_removed(
+; CHECK-NEXT: pre-entry:
+; CHECK-NEXT: br i1 [[Y:%.*]], label [[ENTRY:%.*]], label [[DEFAULT:%.*]]
+; CHECK: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: i8 1, label [[CASE_ONE:%.*]]
+; CHECK-NEXT: ]
+; CHECK: entry.unreachabledefault:
+; CHECK-NEXT: unreachable
+; CHECK: default:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: call void @some_use(i8 2)
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_one:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 1, [[CASE_ONE]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+pre-entry:
+ br i1 %y, label %entry, label %default
+
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ i8 1, label %case_one
+ ]
+default:
+ %z = phi i8 [ 2, %pre-entry], [ 3, %entry]
+ %cmp = icmp eq i8 %x, 1
+ call void @llvm.assume(i1 %cmp)
+ call void @some_use(i8 %z)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+case_one:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ], [ 1, %case_one ]
+ ret i32 %retval
+}
+
+define i32 @default_branch_has_phi_and_will_be_removed_duplicate_phi_entries(i8 %x, i1 %y) {
+; CHECK-LABEL: @default_branch_has_phi_and_will_be_removed_duplicate_phi_entries(
+; CHECK-NEXT: pre-entry:
+; CHECK-NEXT: br i1 [[Y:%.*]], label [[ENTRY:%.*]], label [[DEFAULT:%.*]]
+; CHECK: entry:
+; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
+; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
+; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
+; CHECK-NEXT: i8 1, label [[DEFAULT]]
+; CHECK-NEXT: ]
+; CHECK: entry.unreachabledefault:
+; CHECK-NEXT: unreachable
+; CHECK: default:
+; CHECK-NEXT: [[Z:%.*]] = phi i8 [ 2, [[PRE_ENTRY:%.*]] ], [ 3, [[ENTRY]] ]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: call void @some_use(i8 [[Z]])
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: case_zero:
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY]] ]
+; CHECK-NEXT: ret i32 [[RETVAL]]
+;
+pre-entry:
+ br i1 %y, label %entry, label %default
+
+entry:
+ switch i8 %x, label %default [
+ i8 -1, label %case_neg_one
+ i8 0, label %case_zero
+ i8 1, label %default
+ ]
+default:
+ %z = phi i8 [ 2, %pre-entry], [ 3, %entry], [ 3, %entry ]
+ %cmp = icmp eq i8 %x, 1
+ call void @llvm.assume(i1 %cmp)
+ call void @some_use(i8 %z)
+ br label %return
+
+case_neg_one:
+ br label %return
+
+case_zero:
+ br label %return
+
+return:
+ %retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
+ ret i32 %retval
+}
+
; CHECK: [[PROF0]] = !{!"branch_weights", i32 0, i32 4, i32 2, i32 8}
!0 = !{!"branch_weights", i32 8, i32 4, i32 2}
More information about the llvm-commits
mailing list