[llvm] Reland "[SimplifyCFG] Simplify switch default branch when branch proves operand value" (PR #211427)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 24 06:33:05 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Sayan Sivakumaran (sivakusayan)

<details>
<summary>Changes</summary>

Original PR: https://github.com/llvm/llvm-project/pull/206597
Revert PR: https://github.com/llvm/llvm-project/pull/211341

Relands abe757b. It was reverted due to my PR failing to update PHINode entries in the default block, causing invalid IR in certain circumstances. Original reproducer can be found [here](https://github.com/llvm/llvm-project/pull/206597#issuecomment-5049789740). 

We will now properly remove a PHINode entry if we remove a path from the switch's block to the default block.

-------------------------------------------------------

If the default branch of a switch proves that there is only one value that can be sent to the default branch, we can transform the default branch into an explicit case of the switch. This can assist in further simplification of the CFG during the simplification loop.

For example, we should be able to create an explicit case for the default block in cases like the following:

```llvm-ir
switch_bb:
    switch i8 %x, label %default_bb [...]

default_bb:
    %cmp = icmp eq i8 %x, 1
    call void llvm.assume(i1 %cmp) ; Implies %x must be 1
```

Related to #<!-- -->50665.

---
Full diff: https://github.com/llvm/llvm-project/pull/211427.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Utils/SimplifyCFG.cpp (+47) 
- (added) llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll (+456) 


``````````diff
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index ca6ae94a9a8d9..14efc3c4f5c00 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7857,6 +7857,50 @@ 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);
+  } else {
+    // On the other hand, if there is a pre-existing case for the
+    // constant, the default branch will be removed rather than being
+    // moved. Thus, we are removing an edge in the CFG, and need to
+    // update any PHIs in the default block.
+    Default->removePredecessor(SI->getParent());
+  }
+  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 +8441,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..6ea6115147a8f
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/switch-simplify-default.ll
@@ -0,0 +1,456 @@
+; 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
+}
+
+; 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}

``````````

</details>


https://github.com/llvm/llvm-project/pull/211427


More information about the llvm-commits mailing list