aboutsummaryrefslogtreecommitdiff
path: root/llvm/test/Transforms/SimplifyCFG
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/Transforms/SimplifyCFG')
-rw-r--r--llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll4
-rw-r--r--llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll27
-rw-r--r--llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll40
-rw-r--r--llvm/test/Transforms/SimplifyCFG/pr165301.ll31
-rw-r--r--llvm/test/Transforms/SimplifyCFG/pr166369.ll37
-rw-r--r--llvm/test/Transforms/SimplifyCFG/rangereduce.ll2
-rw-r--r--llvm/test/Transforms/SimplifyCFG/skip-merging-duplicate-convergence-instrinsics.ll68
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll161
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch-on-const.ll317
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll5
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch-umin.ll246
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch_create.ll130
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch_mask.ll1
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch_undef.ll7
14 files changed, 894 insertions, 182 deletions
diff --git a/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll
index 6def8f4..a51b816 100644
--- a/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll
@@ -15,8 +15,8 @@
; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @c1, ptr @c2, ptr @c3]
; ENABLE: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @g1, ptr @g2, ptr @g3]
; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @g1, ptr @g2, ptr @g3]
-; ENABLE: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @f1, ptr @f2, ptr @f3]
-; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @f1, ptr @f2, ptr @f3]
+; ENABLE: @{{.*}} = private unnamed_addr constant [4 x ptr] [ptr @f1, ptr @f2, ptr @f3, ptr @f4]
+; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [4 x ptr] [ptr @f1, ptr @f2, ptr @f3, ptr @f4]
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armv7a--none-eabi"
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll
index aa95b3f..e48c2b4 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll
@@ -1,8 +1,13 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
; RUN: opt -passes='simplifycfg<switch-to-lookup>' -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
+;.
+; CHECK: @switch.table.switch_of_powers_two = private unnamed_addr constant [7 x i32] [i32 3, i32 poison, i32 poison, i32 2, i32 1, i32 0, i32 42], align 4
+; CHECK: @switch.table.switch_of_powers_two_default_reachable = private unnamed_addr constant [7 x i32] [i32 3, i32 5, i32 5, i32 2, i32 1, i32 0, i32 42], align 4
+; CHECK: @switch.table.switch_of_powers_two_default_reachable_multipreds = private unnamed_addr constant [7 x i32] [i32 3, i32 poison, i32 poison, i32 2, i32 1, i32 0, i32 42], align 4
+;.
define i32 @switch_of_powers_two(i32 %arg) {
; CHECK-LABEL: define i32 @switch_of_powers_two(
; CHECK-SAME: i32 [[ARG:%.*]]) {
@@ -35,17 +40,17 @@ return:
ret i32 %phi
}
-define i32 @switch_of_powers_two_default_reachable(i32 %arg) {
+define i32 @switch_of_powers_two_default_reachable(i32 %arg) !prof !0 {
; CHECK-LABEL: define i32 @switch_of_powers_two_default_reachable(
-; CHECK-SAME: i32 [[ARG:%.*]]) {
+; CHECK-SAME: i32 [[ARG:%.*]]) !prof [[PROF0:![0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.ctpop.i32(i32 [[ARG]])
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
-; CHECK-NEXT: br i1 [[TMP1]], label %[[ENTRY_SPLIT:.*]], label %[[RETURN:.*]]
+; CHECK-NEXT: br i1 [[TMP1]], label %[[ENTRY_SPLIT:.*]], label %[[RETURN:.*]], !prof [[PROF1:![0-9]+]]
; CHECK: [[ENTRY_SPLIT]]:
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 true)
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 7
-; CHECK-NEXT: br i1 [[TMP3]], label %[[SWITCH_LOOKUP:.*]], label %[[RETURN]]
+; CHECK-NEXT: br i1 [[TMP3]], label %[[SWITCH_LOOKUP:.*]], label %[[RETURN]], !prof [[PROF2:![0-9]+]]
; CHECK: [[SWITCH_LOOKUP]]:
; CHECK-NEXT: [[TMP4:%.*]] = zext nneg i32 [[TMP2]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers_two_default_reachable, i64 0, i64 [[TMP4]]
@@ -62,7 +67,7 @@ entry:
i32 16, label %bb3
i32 32, label %bb4
i32 64, label %bb5
- ]
+ ], !prof !1
default_case: br label %return
bb1: br label %return
@@ -128,3 +133,13 @@ return:
%phi = phi i32 [ 3, %bb1 ], [ 2, %bb2 ], [ 1, %bb3 ], [ 0, %bb4 ], [ 42, %bb5 ], [ %pn, %default_case ]
ret i32 %phi
}
+
+!0 = !{!"function_entry_count", i32 10}
+!1 = !{!"branch_weights", i32 10, i32 5, i32 7, i32 11, i32 13, i32 17}
+;.
+; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+;.
+; CHECK: [[PROF0]] = !{!"function_entry_count", i32 10}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 58, i32 5}
+; CHECK: [[PROF2]] = !{!"branch_weights", i32 53, i32 5}
+;.
diff --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
index 98c0599..12378fc 100644
--- a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
+++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
@@ -14,12 +14,12 @@ define void @test(i1 %P, ptr %Q) {
br i1 %P, label %T, label %F
T: ; preds = %0
store i32 1, ptr %Q
- %A = load i32, ptr %Q ; <i32> [#uses=1]
+ %A = load i32, ptr %Q
call void @bar( i32 %A )
ret void
F: ; preds = %0
store i32 1, ptr %Q
- %B = load i32, ptr %Q ; <i32> [#uses=1]
+ %B = load i32, ptr %Q
call void @bar( i32 %B )
ret void
}
@@ -38,17 +38,17 @@ define void @test_switch(i64 %i, ptr %Q) {
]
bb0: ; preds = %0
store i32 1, ptr %Q
- %A = load i32, ptr %Q ; <i32> [#uses=1]
+ %A = load i32, ptr %Q
call void @bar( i32 %A )
ret void
bb1: ; preds = %0
store i32 1, ptr %Q
- %B = load i32, ptr %Q ; <i32> [#uses=1]
+ %B = load i32, ptr %Q
call void @bar( i32 %B )
ret void
bb2: ; preds = %0
store i32 1, ptr %Q
- %C = load i32, ptr %Q ; <i32> [#uses=1]
+ %C = load i32, ptr %Q
call void @bar( i32 %C )
ret void
}
@@ -602,3 +602,33 @@ bar:
call void @bar()
ret void
}
+
+define void @test_switch_with_multicases_dest(i64 %i, ptr %Q) {
+; CHECK-LABEL: @test_switch_with_multicases_dest(
+; CHECK-NEXT: common.ret:
+; CHECK-NEXT: store i32 1, ptr [[Q:%.*]], align 4
+; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[Q]], align 4
+; CHECK-NEXT: call void @bar(i32 [[C]])
+; CHECK-NEXT: ret void
+;
+ switch i64 %i, label %bb0 [
+ i64 1, label %bb1
+ i64 2, label %bb2
+ i64 3, label %bb2
+ ]
+bb0: ; preds = %0
+ store i32 1, ptr %Q
+ %A = load i32, ptr %Q
+ call void @bar( i32 %A )
+ ret void
+bb1: ; preds = %0
+ store i32 1, ptr %Q
+ %B = load i32, ptr %Q
+ call void @bar( i32 %B )
+ ret void
+bb2: ; preds = %0
+ store i32 1, ptr %Q
+ %C = load i32, ptr %Q
+ call void @bar( i32 %C )
+ ret void
+}
diff --git a/llvm/test/Transforms/SimplifyCFG/pr165301.ll b/llvm/test/Transforms/SimplifyCFG/pr165301.ll
new file mode 100644
index 0000000..1df6552
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/pr165301.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 6
+; RUN: opt -S -passes="simplifycfg<switch-range-to-icmp>" < %s | FileCheck %s
+
+; Make sure there's no use after free when removing incoming values from PHI nodes
+
+define i32 @pr165301(i1 %cond) !prof !0 {
+; CHECK-LABEL: define i32 @pr165301(
+; CHECK-SAME: i1 [[COND:%.*]]) !prof [[PROF0:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[SWITCHBB:.*]]
+; CHECK: [[SWITCHBB]]:
+; CHECK-NEXT: br label %[[SWITCHBB]]
+;
+entry:
+ br label %switchbb
+
+switchbb:
+ switch i1 %cond, label %default [
+ i1 false, label %switchbb
+ i1 true, label %switchbb
+ ], !prof !1
+
+default:
+ %phi.lcssa = phi i32 [ 0, %switchbb ]
+ ret i32 %phi.lcssa
+}
+!0 = !{!"function_entry_count", i32 10}
+!1 = !{!"branch_weights", i32 2, i32 3, i32 5}
+;.
+; CHECK: [[PROF0]] = !{!"function_entry_count", i32 10}
+;.
diff --git a/llvm/test/Transforms/SimplifyCFG/pr166369.ll b/llvm/test/Transforms/SimplifyCFG/pr166369.ll
new file mode 100644
index 0000000..c0a85c0
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/pr166369.ll
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=simplifycfg < %s | FileCheck %s
+
+; Make sure we handle full-set ranges correctly.
+define void @test_i1() {
+; CHECK-LABEL: define void @test_i1() {
+; CHECK-NEXT: [[BB:.*:]]
+; CHECK-NEXT: ret void
+;
+bb:
+ %icmp = icmp ugt i1 false, true
+ br label %bb5
+
+bb5:
+ %select = select i1 %icmp, i1 %icmp, i1 false
+ br i1 %select, label %bb5, label %bb6
+
+bb6:
+ ret void
+}
+
+define void @test_i3() {
+; CHECK-LABEL: define void @test_i3() {
+; CHECK-NEXT: [[BB:.*:]]
+; CHECK-NEXT: ret void
+;
+bb:
+ %icmp = icmp ugt i3 0, 7
+ br label %bb5
+
+bb5:
+ %select = select i1 %icmp, i1 %icmp, i1 false
+ br i1 %select, label %bb5, label %bb6
+
+bb6:
+ ret void
+}
diff --git a/llvm/test/Transforms/SimplifyCFG/rangereduce.ll b/llvm/test/Transforms/SimplifyCFG/rangereduce.ll
index d1fba91..169803f 100644
--- a/llvm/test/Transforms/SimplifyCFG/rangereduce.ll
+++ b/llvm/test/Transforms/SimplifyCFG/rangereduce.ll
@@ -321,7 +321,7 @@ three:
!1 = !{!"branch_weights", i32 5, i32 7, i32 11, i32 13, i32 17}
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { optsize }
-; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
;.
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i32 100}
; CHECK: [[PROF1]] = !{!"branch_weights", i32 48, i32 5}
diff --git a/llvm/test/Transforms/SimplifyCFG/skip-merging-duplicate-convergence-instrinsics.ll b/llvm/test/Transforms/SimplifyCFG/skip-merging-duplicate-convergence-instrinsics.ll
new file mode 100644
index 0000000..368ae96
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/skip-merging-duplicate-convergence-instrinsics.ll
@@ -0,0 +1,68 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -passes=simplifycfg | FileCheck %s
+
+declare token @llvm.experimental.convergence.entry() #0
+
+define void @nested(i32 %tidx, i32 %tidy, ptr %array) #0 {
+; CHECK-LABEL: @nested(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = tail call token @llvm.experimental.convergence.entry()
+; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TIDY:%.*]], [[TIDX:%.*]]
+; CHECK-NEXT: [[OR_COND_I:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT: br label [[FOR_COND_I:%.*]]
+; CHECK: for.cond.i:
+; CHECK-NEXT: [[TMP2:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[TMP0]]) ]
+; CHECK-NEXT: br label [[FOR_COND1_I:%.*]]
+; CHECK: for.cond1.i:
+; CHECK-NEXT: [[CMP2_I:%.*]] = phi i1 [ false, [[FOR_BODY4_I:%.*]] ], [ true, [[FOR_COND_I]] ]
+; CHECK-NEXT: [[TMP3:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[TMP2]]) ]
+; CHECK-NEXT: br i1 [[CMP2_I]], label [[FOR_BODY4_I]], label [[EXIT:%.*]]
+; CHECK: for.body4.i:
+; CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[FOR_COND1_I]]
+; CHECK: if.then.i:
+; CHECK-NEXT: [[TEST_VAL:%.*]] = call spir_func i32 @func_test(i32 0) [ "convergencectrl"(token [[TMP3]]) ]
+; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i32 0
+; CHECK-NEXT: store i32 [[TEST_VAL]], ptr [[TMP4]], align 4
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %0 = tail call token @llvm.experimental.convergence.entry()
+ %2 = or i32 %tidy, %tidx
+ %or.cond.i = icmp eq i32 %2, 0
+ br label %for.cond.i
+
+for.cond.i:
+ %3 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
+ br label %for.cond1.i
+
+for.cond1.i:
+ %cmp2.i = phi i1 [ false, %for.body4.i ], [ true, %for.cond.i ]
+ %4 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %3) ]
+ br i1 %cmp2.i, label %for.body4.i, label %cleanup.i.loopexit
+
+for.body4.i:
+ br i1 %or.cond.i, label %if.then.i, label %for.cond1.i
+
+if.then.i:
+ %test.val = call spir_func i32 @func_test(i32 0) [ "convergencectrl"(token %4) ]
+ %5 = getelementptr inbounds i32, ptr %array, i32 0
+ store i32 %test.val, ptr %5, align 4
+ br label %cleanup.i
+
+cleanup.i.loopexit:
+ br label %cleanup.i
+
+cleanup.i:
+ br label %exit
+
+exit:
+ ret void
+}
+
+declare token @llvm.experimental.convergence.loop() #0
+
+declare i32 @func_test(i32) #0
+
+attributes #0 = { convergent }
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll b/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll
deleted file mode 100644
index e8b5863..0000000
--- a/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll
+++ /dev/null
@@ -1,161 +0,0 @@
-; 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
-
-; Test basic folding to a conditional branch.
-define i32 @foo(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: @foo(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: br i1 [[EQ]], label [[B:%.*]], label [[SWITCH:%.*]]
-; CHECK: switch:
-; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X]], [[Y]]
-; CHECK-NEXT: br i1 [[LT]], label [[A:%.*]], label [[B]]
-; CHECK: common.ret:
-; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 1, [[A]] ], [ [[RETVAL:%.*]], [[B]] ]
-; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
-; CHECK: a:
-; CHECK-NEXT: tail call void @bees.a() #[[ATTR0:[0-9]+]]
-; CHECK-NEXT: br label [[COMMON_RET:%.*]]
-; CHECK: b:
-; CHECK-NEXT: [[RETVAL]] = phi i32 [ 0, [[SWITCH]] ], [ 2, [[ENTRY:%.*]] ]
-; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
-; CHECK-NEXT: br label [[COMMON_RET]]
-;
-entry:
- %eq = icmp eq i64 %x, %y
- br i1 %eq, label %b, label %switch
-switch:
- %lt = icmp slt i64 %x, %y
- %qux = select i1 %lt, i32 0, i32 2
- switch i32 %qux, label %bees [
- i32 0, label %a
- i32 1, label %b
- i32 2, label %b
- ]
-a:
- tail call void @bees.a() nounwind
- ret i32 1
-b:
- %retval = phi i32 [0, %switch], [0, %switch], [2, %entry]
- tail call void @bees.b() nounwind
- ret i32 %retval
-bees:
- tail call void @llvm.trap() nounwind
- unreachable
-}
-
-; Test basic folding to an unconditional branch.
-define i32 @bar(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: @bar(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
-; CHECK-NEXT: ret i32 0
-;
-entry:
- %lt = icmp slt i64 %x, %y
- %qux = select i1 %lt, i32 0, i32 2
- switch i32 %qux, label %bees [
- i32 0, label %a
- i32 1, label %b
- i32 2, label %a
- ]
-a:
- %retval = phi i32 [0, %entry], [0, %entry], [1, %b]
- tail call void @bees.a() nounwind
- ret i32 0
-b:
- tail call void @bees.b() nounwind
- br label %a
-bees:
- tail call void @llvm.trap() nounwind
- unreachable
-}
-
-; Test the edge case where both values from the select are the default case.
-define void @bazz(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: @bazz(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
-; CHECK-NEXT: ret void
-;
-entry:
- %lt = icmp slt i64 %x, %y
- %qux = select i1 %lt, i32 10, i32 12
- switch i32 %qux, label %b [
- i32 0, label %a
- i32 1, label %bees
- i32 2, label %bees
- ]
-a:
- tail call void @bees.a() nounwind
- ret void
-b:
- tail call void @bees.b() nounwind
- ret void
-bees:
- tail call void @llvm.trap()
- unreachable
-}
-
-; Test the edge case where both values from the select are equal.
-define void @quux(i64 %x, i64 %y) nounwind {
-; CHECK-LABEL: @quux(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
-; CHECK-NEXT: ret void
-;
-entry:
- %lt = icmp slt i64 %x, %y
- %qux = select i1 %lt, i32 0, i32 0
- switch i32 %qux, label %b [
- i32 0, label %a
- i32 1, label %bees
- i32 2, label %bees
- ]
-a:
- tail call void @bees.a() nounwind
- ret void
-b:
- tail call void @bees.b() nounwind
- ret void
-bees:
- tail call void @llvm.trap()
- unreachable
-}
-
-; A final test, for phi node munging.
-define i32 @xyzzy(i64 %x, i64 %y) {
-; CHECK-LABEL: @xyzzy(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X]], [[Y]]
-; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[LT]], i32 -1, i32 1
-; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = select i1 [[EQ]], i32 0, i32 [[SPEC_SELECT]]
-; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
-;
-entry:
- %eq = icmp eq i64 %x, %y
- br i1 %eq, label %r, label %cont
-cont:
- %lt = icmp slt i64 %x, %y
- %qux = select i1 %lt, i32 0, i32 2
- switch i32 %qux, label %bees [
- i32 0, label %a
- i32 1, label %r
- i32 2, label %r
- ]
-r:
- %val = phi i32 [0, %entry], [1, %cont], [1, %cont]
- ret i32 %val
-a:
- ret i32 -1
-bees:
- tail call void @llvm.trap()
- unreachable
-}
-
-declare void @llvm.trap() nounwind noreturn
-declare void @bees.a() nounwind
-declare void @bees.b() nounwind
-
-; CHECK: attributes #1 = { cold noreturn nounwind memory(inaccessiblemem: write) }
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-on-const.ll b/llvm/test/Transforms/SimplifyCFG/switch-on-const.ll
new file mode 100644
index 0000000..541bdf5
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/switch-on-const.ll
@@ -0,0 +1,317 @@
+; 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
+
+; Test basic folding to a conditional branch.
+define i32 @foo(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[EQ]], label [[B:%.*]], label [[SWITCH:%.*]]
+; CHECK: switch:
+; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[LT]], label [[A:%.*]], label [[B]]
+; CHECK: common.ret:
+; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 1, [[A]] ], [ [[RETVAL:%.*]], [[B]] ]
+; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
+; CHECK: a:
+; CHECK-NEXT: tail call void @bees.a() #[[ATTR0:[0-9]+]]
+; CHECK-NEXT: br label [[COMMON_RET:%.*]]
+; CHECK: b:
+; CHECK-NEXT: [[RETVAL]] = phi i32 [ 0, [[SWITCH]] ], [ 2, [[ENTRY:%.*]] ]
+; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
+; CHECK-NEXT: br label [[COMMON_RET]]
+;
+entry:
+ %eq = icmp eq i64 %x, %y
+ br i1 %eq, label %b, label %switch
+switch:
+ %lt = icmp slt i64 %x, %y
+ %qux = select i1 %lt, i32 0, i32 2
+ switch i32 %qux, label %bees [
+ i32 0, label %a
+ i32 1, label %b
+ i32 2, label %b
+ ]
+a:
+ tail call void @bees.a() nounwind
+ ret i32 1
+b:
+ %retval = phi i32 [0, %switch], [0, %switch], [2, %entry]
+ tail call void @bees.b() nounwind
+ ret i32 %retval
+bees:
+ tail call void @llvm.trap() nounwind
+ unreachable
+}
+
+; Test basic folding to an unconditional branch.
+define i32 @bar(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @bar(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ %lt = icmp slt i64 %x, %y
+ %qux = select i1 %lt, i32 0, i32 2
+ switch i32 %qux, label %bees [
+ i32 0, label %a
+ i32 1, label %b
+ i32 2, label %a
+ ]
+a:
+ %retval = phi i32 [0, %entry], [0, %entry], [1, %b]
+ tail call void @bees.a() nounwind
+ ret i32 0
+b:
+ tail call void @bees.b() nounwind
+ br label %a
+bees:
+ tail call void @llvm.trap() nounwind
+ unreachable
+}
+
+; Test the edge case where both values from the select are the default case.
+define void @bazz(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @bazz(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
+; CHECK-NEXT: ret void
+;
+entry:
+ %lt = icmp slt i64 %x, %y
+ %qux = select i1 %lt, i32 10, i32 12
+ switch i32 %qux, label %b [
+ i32 0, label %a
+ i32 1, label %bees
+ i32 2, label %bees
+ ]
+a:
+ tail call void @bees.a() nounwind
+ ret void
+b:
+ tail call void @bees.b() nounwind
+ ret void
+bees:
+ tail call void @llvm.trap()
+ unreachable
+}
+
+; Test the edge case where both values from the select are equal.
+define void @quux(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @quux(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
+; CHECK-NEXT: ret void
+;
+entry:
+ %lt = icmp slt i64 %x, %y
+ %qux = select i1 %lt, i32 0, i32 0
+ switch i32 %qux, label %b [
+ i32 0, label %a
+ i32 1, label %bees
+ i32 2, label %bees
+ ]
+a:
+ tail call void @bees.a() nounwind
+ ret void
+b:
+ tail call void @bees.b() nounwind
+ ret void
+bees:
+ tail call void @llvm.trap()
+ unreachable
+}
+
+; A final test, for phi node munging.
+define i32 @xyzzy(i64 %x, i64 %y) {
+; CHECK-LABEL: @xyzzy(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X]], [[Y]]
+; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[LT]], i32 -1, i32 1
+; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = select i1 [[EQ]], i32 0, i32 [[SPEC_SELECT]]
+; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
+;
+entry:
+ %eq = icmp eq i64 %x, %y
+ br i1 %eq, label %r, label %cont
+cont:
+ %lt = icmp slt i64 %x, %y
+ %qux = select i1 %lt, i32 0, i32 2
+ switch i32 %qux, label %bees [
+ i32 0, label %a
+ i32 1, label %r
+ i32 2, label %r
+ ]
+r:
+ %val = phi i32 [0, %entry], [1, %cont], [1, %cont]
+ ret i32 %val
+a:
+ ret i32 -1
+bees:
+ tail call void @llvm.trap()
+ unreachable
+}
+
+define void @pr165179(i1 %cond) {
+; CHECK-LABEL: @pr165179(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
+; CHECK-NEXT: br label [[SWITCHBB:%.*]]
+; CHECK: if.else:
+; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
+; CHECK-NEXT: br label [[SWITCHBB]]
+; CHECK: exit:
+; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
+; CHECK-NEXT: ret void
+;
+entry:
+ br i1 %cond, label %if.then, label %if.else
+
+if.then:
+ tail call void @bees.a() nounwind
+ br label %switchbb
+
+if.else:
+ tail call void @bees.b() nounwind
+ br label %switchbb
+
+switchbb:
+ %cond1 = phi i32 [ 1, %if.else ], [ -1, %if.then ]
+ switch i32 %cond1, label %default [
+ i32 1, label %exit
+ i32 -1, label %exit
+ ]
+
+exit:
+ tail call void @bees.a() nounwind
+ ret void
+
+default:
+ tail call void @bees.b() nounwind
+ ret void
+}
+
+define void @switch_remove_dead_case_phi(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @switch_remove_dead_case_phi(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[COND1:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
+; CHECK-NEXT: br i1 [[COND2:%.*]], label [[SWITCHBB:%.*]], label [[IF_ELSE]]
+; CHECK: if.else:
+; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 3, [[ENTRY:%.*]] ], [ -1, [[IF_THEN]] ]
+; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
+; CHECK-NEXT: br label [[SWITCHBB]]
+; CHECK: switchbb:
+; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[PHI]], [[IF_ELSE]] ], [ 5, [[IF_THEN]] ]
+; CHECK-NEXT: [[COND3:%.*]] = icmp eq i32 [[COND]], -1
+; CHECK-NEXT: br i1 [[COND3]], label [[EXIT:%.*]], label [[DEFAULT:%.*]]
+; CHECK: common.ret:
+; CHECK-NEXT: ret void
+; CHECK: exit:
+; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
+; CHECK-NEXT: br label [[COMMON_RET:%.*]]
+; CHECK: default:
+; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
+; CHECK-NEXT: br label [[COMMON_RET]]
+;
+entry:
+ br i1 %cond1, label %if.then, label %if.else
+
+if.then:
+ tail call void @bees.a() nounwind
+ br i1 %cond2, label %switchbb, label %if.else
+
+if.else:
+ %phi = phi i32 [ 3, %entry ], [ -1, %if.then ]
+ tail call void @bees.b() nounwind
+ br label %switchbb
+
+switchbb:
+ %cond = phi i32 [ %phi, %if.else ], [ 5, %if.then ]
+ switch i32 %cond, label %default [
+ i32 1, label %exit
+ i32 -1, label %exit
+ ]
+
+exit:
+ tail call void @bees.a() nounwind
+ ret void
+
+default:
+ tail call void @bees.b() nounwind
+ ret void
+}
+
+define void @switch_remove_dead_case_select(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @switch_remove_dead_case_select(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[X:%.*]] = select i1 [[COND1:%.*]], i32 -1, i32 3
+; CHECK-NEXT: [[Y:%.*]] = select i1 [[COND2:%.*]], i32 [[X]], i32 5
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[Y]], -1
+; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[DEFAULT:%.*]]
+; CHECK: common.ret:
+; CHECK-NEXT: ret void
+; CHECK: exit:
+; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
+; CHECK-NEXT: br label [[COMMON_RET:%.*]]
+; CHECK: default:
+; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
+; CHECK-NEXT: br label [[COMMON_RET]]
+;
+entry:
+ %x = select i1 %cond1, i32 -1, i32 3
+ %y = select i1 %cond2, i32 %x, i32 5
+ switch i32 %y, label %default [
+ i32 1, label %exit
+ i32 -1, label %exit
+ ]
+
+exit:
+ tail call void @bees.a() nounwind
+ ret void
+
+default:
+ tail call void @bees.b() nounwind
+ ret void
+}
+
+@G = constant i16 zeroinitializer, align 1
+
+; Make sure we don't remove edges when the condition is a unresolved constant expression.
+
+define i16 @switch_on_nonimmediate_constant_expr() {
+; CHECK-LABEL: @switch_on_nonimmediate_constant_expr(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 ptrtoint (ptr @G to i32), 2
+; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i16 456, i16 789
+; CHECK-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 ptrtoint (ptr @G to i32), 1
+; CHECK-NEXT: [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i16 123, i16 [[SWITCH_SELECT]]
+; CHECK-NEXT: ret i16 [[SWITCH_SELECT2]]
+;
+entry:
+ switch i32 ptrtoint (ptr @G to i32), label %sw.default [
+ i32 1, label %sw.bb
+ i32 2, label %sw.bb1
+ ]
+
+sw.bb:
+ ret i16 123
+
+sw.bb1:
+ ret i16 456
+
+sw.default:
+ ret i16 789
+}
+
+
+declare void @llvm.trap() nounwind noreturn
+declare void @bees.a() nounwind
+declare void @bees.b() nounwind
+
+; CHECK: attributes #1 = { cold noreturn nounwind memory(inaccessiblemem: write) }
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll b/llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll
index 25267dc..48be76c 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll
@@ -410,13 +410,12 @@ define i1 @single_value_with_mask(i32 %x) {
; OPTNOLUT-NEXT: i32 21, label %[[END]]
; OPTNOLUT-NEXT: i32 48, label %[[END]]
; OPTNOLUT-NEXT: i32 16, label %[[END]]
+; OPTNOLUT-NEXT: i32 80, label %[[END]]
; OPTNOLUT-NEXT: ]
; OPTNOLUT: [[DEFAULT]]:
-; OPTNOLUT-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 80
-; OPTNOLUT-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i1 false, i1 true
; OPTNOLUT-NEXT: br label %[[END]]
; OPTNOLUT: [[END]]:
-; OPTNOLUT-NEXT: [[RES:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ [[SEL]], %[[DEFAULT]] ]
+; OPTNOLUT-NEXT: [[RES:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ true, %[[DEFAULT]] ], [ false, %[[ENTRY]] ]
; OPTNOLUT-NEXT: ret i1 [[RES]]
;
; TTINOLUT-LABEL: define i1 @single_value_with_mask(
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-umin.ll b/llvm/test/Transforms/SimplifyCFG/switch-umin.ll
new file mode 100644
index 0000000..4466536
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/switch-umin.ll
@@ -0,0 +1,246 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=simplifycfg < %s | FileCheck %s
+
+declare void @a()
+declare void @b()
+declare void @c()
+declare void @d()
+
+define void @switch_replace_default(i32 %x) {
+; CHECK-LABEL: define void @switch_replace_default(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 3)
+; CHECK-NEXT: switch i32 [[X]], label %[[COMMON_RET:.*]] [
+; CHECK-NEXT: i32 0, label %[[CASE0:.*]]
+; CHECK-NEXT: i32 1, label %[[CASE1:.*]]
+; CHECK-NEXT: i32 2, label %[[CASE2:.*]]
+; CHECK-NEXT: ], !prof [[PROF0:![0-9]+]]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret void
+; CHECK: [[CASE0]]:
+; CHECK-NEXT: call void @a()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[CASE1]]:
+; CHECK-NEXT: call void @b()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[CASE2]]:
+; CHECK-NEXT: call void @c()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+;
+ %min = call i32 @llvm.umin.i32(i32 %x, i32 3)
+ switch i32 %min, label %unreachable [
+ i32 0, label %case0
+ i32 1, label %case1
+ i32 2, label %case2
+ i32 3, label %case3
+ ], !prof !0
+
+case0:
+ call void @a()
+ ret void
+
+case1:
+ call void @b()
+ ret void
+
+case2:
+ call void @c()
+ ret void
+
+case3:
+ ret void
+
+unreachable:
+ unreachable
+}
+
+define void @switch_replace_default_and_remove_dead_cases(i32 %x) {
+; CHECK-LABEL: define void @switch_replace_default_and_remove_dead_cases(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 3)
+; CHECK-NEXT: switch i32 [[X]], label %[[COMMON_RET:.*]] [
+; CHECK-NEXT: i32 2, label %[[CASE2:.*]]
+; CHECK-NEXT: i32 1, label %[[CASE1:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret void
+; CHECK: [[CASE1]]:
+; CHECK-NEXT: call void @b()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[CASE2]]:
+; CHECK-NEXT: call void @c()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+;
+ %min = call i32 @llvm.umin.i32(i32 %x, i32 3)
+ switch i32 %min, label %unreachable [
+ i32 4, label %case4
+ i32 1, label %case1
+ i32 2, label %case2
+ i32 3, label %case3
+ ]
+
+case4:
+ call void @a()
+ ret void
+
+case1:
+ call void @b()
+ ret void
+
+case2:
+ call void @c()
+ ret void
+
+case3:
+ ret void
+
+unreachable:
+ unreachable
+}
+
+define void @switch_replace_default_when_holes(i32 %x) {
+; CHECK-LABEL: define void @switch_replace_default_when_holes(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 3)
+; CHECK-NEXT: switch i32 [[X]], label %[[COMMON_RET:.*]] [
+; CHECK-NEXT: i32 1, label %[[CASE1:.*]]
+; CHECK-NEXT: i32 2, label %[[CASE2:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret void
+; CHECK: [[CASE1]]:
+; CHECK-NEXT: call void @b()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[CASE2]]:
+; CHECK-NEXT: call void @c()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+;
+ %min = call i32 @llvm.umin.i32(i32 %x, i32 3)
+ switch i32 %min, label %unreachable [
+ i32 1, label %case1
+ i32 2, label %case2
+ i32 3, label %case3
+ ]
+
+case1:
+ call void @b()
+ ret void
+
+case2:
+ call void @c()
+ ret void
+
+case3:
+ ret void
+
+unreachable:
+ unreachable
+}
+
+define void @do_not_switch_replace_default(i32 %x, i32 %y) {
+; CHECK-LABEL: define void @do_not_switch_replace_default(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: switch i32 [[MIN]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CASE0:.*]]
+; CHECK-NEXT: i32 1, label %[[CASE1:.*]]
+; CHECK-NEXT: i32 2, label %[[CASE2:.*]]
+; CHECK-NEXT: i32 3, label %[[COMMON_RET:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret void
+; CHECK: [[CASE0]]:
+; CHECK-NEXT: call void @a()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[CASE1]]:
+; CHECK-NEXT: call void @b()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[CASE2]]:
+; CHECK-NEXT: call void @c()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
+ %min = call i32 @llvm.umin.i32(i32 %x, i32 %y)
+ switch i32 %min, label %unreachable [
+ i32 0, label %case0
+ i32 1, label %case1
+ i32 2, label %case2
+ i32 3, label %case3
+ ]
+
+case0:
+ call void @a()
+ ret void
+
+case1:
+ call void @b()
+ ret void
+
+case2:
+ call void @c()
+ ret void
+
+case3:
+ ret void
+
+unreachable:
+ unreachable
+}
+
+define void @do_not_replace_switch_default_but_remove_dead_cases(i32 %x) {
+; CHECK-LABEL: define void @do_not_replace_switch_default_but_remove_dead_cases(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 3)
+; CHECK-NEXT: switch i32 [[MIN]], label %[[CASE0:.*]] [
+; CHECK-NEXT: i32 3, label %[[COMMON_RET:.*]]
+; CHECK-NEXT: i32 1, label %[[CASE1:.*]]
+; CHECK-NEXT: i32 2, label %[[CASE2:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret void
+; CHECK: [[CASE0]]:
+; CHECK-NEXT: call void @a()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[CASE1]]:
+; CHECK-NEXT: call void @b()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+; CHECK: [[CASE2]]:
+; CHECK-NEXT: call void @c()
+; CHECK-NEXT: br label %[[COMMON_RET]]
+;
+ %min = call i32 @llvm.umin.i32(i32 %x, i32 3)
+ switch i32 %min, label %case0 [ ; default is reachable, therefore simplification not triggered
+ i32 0, label %case0
+ i32 1, label %case1
+ i32 2, label %case2
+ i32 3, label %case3
+ i32 4, label %case4
+ ]
+
+case0:
+ call void @a()
+ ret void
+
+case1:
+ call void @b()
+ ret void
+
+case2:
+ call void @c()
+ ret void
+
+case3:
+ ret void
+
+case4:
+ call void @d()
+ ret void
+
+}
+
+
+!0 = !{!"branch_weights", i32 1, i32 2, i32 3, i32 99, i32 5}
+;.
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 5, i32 2, i32 3, i32 99}
+;.
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index ef5aee6..64016f3 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -1314,6 +1314,136 @@ if.end:
ret void
}
+define i32 @switch_with_icmp_select_after_it(i32 %x) {
+; CHECK-LABEL: @switch_with_icmp_select_after_it(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT: i32 18, label [[END:%.*]]
+; CHECK-NEXT: i32 21, label [[END]]
+; CHECK-NEXT: i32 48, label [[END]]
+; CHECK-NEXT: i32 16, label [[END]]
+; CHECK-NEXT: i32 80, label [[SWITCH_EDGE:%.*]]
+; CHECK-NEXT: ]
+; CHECK: switch.edge:
+; CHECK-NEXT: br label [[END]]
+; CHECK: default:
+; CHECK-NEXT: br label [[END]]
+; CHECK: end:
+; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 3, [[DEFAULT]] ], [ 2, [[SWITCH_EDGE]] ]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+entry:
+ switch i32 %x, label %default [
+ i32 18, label %end
+ i32 21, label %end
+ i32 48, label %end
+ i32 16, label %end
+ ]
+default:
+ %cmp = icmp eq i32 %x, 80
+ ; Create a new switch case BB for case 80.
+ %sel = select i1 %cmp, i32 2, i32 3
+ br label %end
+end:
+ %res = phi i32 [ 1, %entry ], [ 1, %entry ], [ 1, %entry ], [ 1, %entry ], [ %sel, %default ]
+ ret i32 %res
+}
+
+define i32 @switch_with_icmp_select_after_it2(i32 %x) {
+; CHECK-LABEL: @switch_with_icmp_select_after_it2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT: i32 18, label [[END:%.*]]
+; CHECK-NEXT: i32 21, label [[END]]
+; CHECK-NEXT: i32 48, label [[END]]
+; CHECK-NEXT: i32 16, label [[END]]
+; CHECK-NEXT: i32 80, label [[END]]
+; CHECK-NEXT: ]
+; CHECK: default:
+; CHECK-NEXT: br label [[END]]
+; CHECK: end:
+; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 3, [[DEFAULT]] ], [ 1, [[ENTRY]] ]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+entry:
+ switch i32 %x, label %default [
+ i32 18, label %end
+ i32 21, label %end
+ i32 48, label %end
+ i32 16, label %end
+ ]
+default:
+ %cmp = icmp eq i32 %x, 80
+ ; Should not create new case BB
+ %sel = select i1 %cmp, i32 1, i32 3
+ br label %end
+end:
+ %res = phi i32 [ 1, %entry ], [ 1, %entry ], [ 1, %entry ], [ 1, %entry ], [ %sel, %default ]
+ ret i32 %res
+}
+
+define i32 @switch_with_icmp_select_after_it3(i32 %x) {
+; CHECK-LABEL: @switch_with_icmp_select_after_it3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 80
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 3, i32 1
+; CHECK-NEXT: ret i32 [[SEL]]
+;
+entry:
+ switch i32 %x, label %default [
+ i32 18, label %end
+ i32 21, label %end
+ i32 48, label %end
+ i32 16, label %end
+ ]
+default:
+ %cmp = icmp eq i32 %x, 80
+ ; Should not create new case BB
+ %sel = select i1 %cmp, i32 3, i32 1
+ br label %end
+end:
+ %res = phi i32 [ 1, %entry ], [ 1, %entry ], [ 1, %entry ], [ 1, %entry ], [ %sel, %default ]
+ ret i32 %res
+}
+
+; TODO: support this case (multi-phis).
+define i32 @switch_with_icmp_select_after_it_multi_phis(i32 %x) {
+; CHECK-LABEL: @switch_with_icmp_select_after_it_multi_phis(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT: i32 18, label [[END:%.*]]
+; CHECK-NEXT: i32 21, label [[END]]
+; CHECK-NEXT: i32 48, label [[END]]
+; CHECK-NEXT: i32 16, label [[END]]
+; CHECK-NEXT: ]
+; CHECK: default:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 80
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 2, i32 3
+; CHECK-NEXT: br label [[END]]
+; CHECK: end:
+; CHECK-NEXT: [[RES1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 0, [[ENTRY]] ], [ 0, [[ENTRY]] ], [ 0, [[ENTRY]] ], [ 100, [[DEFAULT]] ]
+; CHECK-NEXT: [[RES2:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ 1, [[ENTRY]] ], [ [[SEL]], [[DEFAULT]] ]
+; CHECK-NEXT: [[RES:%.*]] = xor i32 [[RES1]], [[RES2]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+entry:
+ switch i32 %x, label %default [
+ i32 18, label %end
+ i32 21, label %end
+ i32 48, label %end
+ i32 16, label %end
+ ]
+default:
+ %cmp = icmp eq i32 %x, 80
+ %sel = select i1 %cmp, i32 2, i32 3
+ br label %end
+end:
+ %res1 = phi i32 [ 0, %entry ], [ 0, %entry ], [ 0, %entry ], [ 0, %entry ], [ 100, %default ]
+ %res2 = phi i32 [ 1, %entry ], [ 1, %entry ], [ 1, %entry ], [ 1, %entry ], [ %sel, %default ]
+ %res = xor i32 %res1, %res2
+ ret i32 %res
+}
+
!0 = !{!"function_entry_count", i32 100}
!1 = !{!"branch_weights", i32 6, i32 10}
;.
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_mask.ll b/llvm/test/Transforms/SimplifyCFG/switch_mask.ll
index f8bcbc0..428c18f 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_mask.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_mask.ll
@@ -221,6 +221,7 @@ define i1 @pr88607() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND:%.*]] = select i1 false, i32 4, i32 1
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 false, i32 2, i32 [[COND]]
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[SPEC_SELECT]], 1
; CHECK-NEXT: ret i1 false
;
entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_undef.ll b/llvm/test/Transforms/SimplifyCFG/switch_undef.ll
index 88a729b..4de5ea9 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_undef.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_undef.ll
@@ -5,12 +5,11 @@
define void @f6() #0 {
; CHECK-LABEL: @f6(
; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[FOR_COND_I:%.*]]
-; CHECK: for.cond.i:
+; CHECK-NEXT: br label [[F1_EXIT_I:%.*]]
+; CHECK: f1.exit.i:
; CHECK-NEXT: [[TOBOOL7_I:%.*]] = icmp ne i16 1, 0
-; CHECK-NEXT: br label [[FOR_COND_I]]
+; CHECK-NEXT: br label [[F1_EXIT_I]]
;
-
entry:
br label %for.cond.i