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/X86/debugloc-switch-powers-of-two.ll81
-rw-r--r--llvm/test/Transforms/SimplifyCFG/X86/switch-of-powers-of-two.ll27
-rw-r--r--llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll116
-rw-r--r--llvm/test/Transforms/SimplifyCFG/pr165088.ll186
-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/switch-on-const.ll (renamed from llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll)126
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch-umin.ll246
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch_mask.ll1
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch_undef.ll7
11 files changed, 849 insertions, 11 deletions
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/debugloc-switch-powers-of-two.ll b/llvm/test/Transforms/SimplifyCFG/X86/debugloc-switch-powers-of-two.ll
new file mode 100644
index 0000000..a276067
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/X86/debugloc-switch-powers-of-two.ll
@@ -0,0 +1,81 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool ./build/bin/opt --version 6
+; RUN: opt -passes='simplifycfg<switch-to-lookup>' -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
+;; As we replace the switch statement with a set of instructions that may more
+;; efficiently perform the conditional check, the DILocation of the switch
+;; should be propagated to all of its replacing instructions.
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @switch_of_powers_two_default_reachable(i32 %arg) !dbg !5 {
+; CHECK-LABEL: define i32 @switch_of_powers_two_default_reachable(
+; CHECK-SAME: i32 [[ARG:%.*]]) !dbg [[DBG5:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.ctpop.i32(i32 [[ARG]]), !dbg [[DBG8:![0-9]+]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1, !dbg [[DBG8]]
+; CHECK-NEXT: br i1 [[TMP1]], label %[[ENTRY_SPLIT:.*]], label %[[RETURN:.*]], !dbg [[DBG8]]
+; CHECK: [[ENTRY_SPLIT]]:
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 true), !dbg [[DBG8]]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 7, !dbg [[DBG8]]
+; CHECK-NEXT: br i1 [[TMP3]], label %[[SWITCH_LOOKUP:.*]], label %[[RETURN]], !dbg [[DBG8]]
+; CHECK: [[SWITCH_LOOKUP]]:
+; CHECK-NEXT: [[TMP4:%.*]] = zext nneg i32 [[TMP2]] to i64, !dbg [[DBG8]]
+; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers_two_default_reachable, i64 0, i64 [[TMP4]], !dbg [[DBG8]]
+; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4, !dbg [[DBG8]]
+; CHECK-NEXT: br label %[[RETURN]], !dbg [[DBG8]]
+; CHECK: [[RETURN]]:
+; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 5, %[[ENTRY]] ], [ 5, %[[ENTRY_SPLIT]] ], [ [[SWITCH_LOAD]], %[[SWITCH_LOOKUP]] ]
+; CHECK-NEXT: ret i32 [[PHI]]
+;
+entry:
+ switch i32 %arg, label %default_case [
+ i32 1, label %bb1
+ i32 8, label %bb2
+ i32 16, label %bb3
+ i32 32, label %bb4
+ i32 64, label %bb5
+ ], !dbg !8
+
+default_case: ; preds = %entry
+ br label %return
+
+bb1: ; preds = %entry
+ br label %return
+
+bb2: ; preds = %entry
+ br label %return
+
+bb3: ; preds = %entry
+ br label %return
+
+bb4: ; preds = %entry
+ br label %return
+
+bb5: ; preds = %entry
+ br label %return
+
+return: ; preds = %bb5, %bb4, %bb3, %bb2, %bb1, %default_case
+ %phi = phi i32 [ 3, %bb1 ], [ 2, %bb2 ], [ 1, %bb3 ], [ 0, %bb4 ], [ 42, %bb5 ], [ 5, %default_case ]
+ ret i32 %phi
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.debugify = !{!2, !3}
+!llvm.module.flags = !{!4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "debugloc-switch-powers-of-two.ll", directory: "/")
+!2 = !{i32 9}
+!3 = !{i32 1}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = distinct !DISubprogram(name: "switch_of_powers_two_default_reachable", linkageName: "switch_of_powers_two_default_reachable", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7)
+!6 = !DISubroutineType(types: !7)
+!7 = !{}
+!8 = !DILocation(line: 1, column: 1, scope: !5)
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+; CHECK: [[META1]] = !DIFile(filename: "{{.*}}debugloc-switch-powers-of-two.ll", directory: {{.*}})
+; CHECK: [[DBG5]] = distinct !DISubprogram(name: "switch_of_powers_two_default_reachable", linkageName: "switch_of_powers_two_default_reachable", scope: null, file: [[META1]], line: 1, type: [[META6:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META7:![0-9]+]])
+; CHECK: [[META6]] = !DISubroutineType(types: [[META7]])
+; CHECK: [[META7]] = !{}
+; CHECK: [[DBG8]] = !DILocation(line: 1, column: 1, scope: [[DBG5]])
+;.
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 8ce94d1..98c0599 100644
--- a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
+++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
@@ -486,3 +486,119 @@ else:
call void @bar()
ret float %op2
}
+
+define void @test_switch_with_unreachable_block_as_default(i1 %c, i32 %x, ptr %ptr) {
+; CHECK-LABEL: @test_switch_with_unreachable_block_as_default(
+; CHECK-NEXT: br i1 [[C:%.*]], label [[SW1:%.*]], label [[SW2:%.*]]
+; CHECK: sw1:
+; CHECK-NEXT: switch i32 [[X:%.*]], label [[UNREACHABLE:%.*]] [
+; CHECK-NEXT: i32 1, label [[COMMON_RET:%.*]]
+; CHECK-NEXT: i32 2, label [[BAR:%.*]]
+; CHECK-NEXT: ]
+; CHECK: sw2:
+; CHECK-NEXT: store i64 42, ptr [[PTR:%.*]], align 4
+; CHECK-NEXT: br label [[COMMON_RET]]
+; CHECK: common.ret:
+; CHECK-NEXT: ret void
+; CHECK: unreachable:
+; CHECK-NEXT: unreachable
+; CHECK: bar:
+; CHECK-NEXT: call void @bar()
+; CHECK-NEXT: br label [[COMMON_RET]]
+;
+ br i1 %c, label %sw1, label %sw2
+
+sw1:
+ ; This switch only exists to have an %unreachable block with multiple predecessors.
+ switch i32 %x, label %unreachable [
+ i32 1, label %foo
+ i32 2, label %bar
+ ]
+
+sw2:
+ switch i32 %x, label %unreachable [
+ i32 1, label %bb1
+ i32 2, label %bb2
+ i32 3, label %bb3
+ ]
+
+bb1:
+ store i64 42, ptr %ptr
+ ret void
+
+bb2:
+ store i64 42, ptr %ptr
+ ret void
+
+bb3:
+ store i64 42, ptr %ptr
+ ret void
+
+unreachable:
+ unreachable
+
+foo:
+ ret void
+
+bar:
+ call void @bar()
+ ret void
+}
+
+define void @test_switch_with_unreachable_block_as_case(i1 %c, i32 %x, ptr %ptr) {
+; CHECK-LABEL: @test_switch_with_unreachable_block_as_case(
+; CHECK-NEXT: br i1 [[C:%.*]], label [[SW1:%.*]], label [[SW2:%.*]]
+; CHECK: sw1:
+; CHECK-NEXT: switch i32 [[X:%.*]], label [[UNREACHABLE:%.*]] [
+; CHECK-NEXT: i32 1, label [[COMMON_RET:%.*]]
+; CHECK-NEXT: i32 2, label [[BAR:%.*]]
+; CHECK-NEXT: ]
+; CHECK: sw2:
+; CHECK-NEXT: store i64 42, ptr [[PTR:%.*]], align 4
+; CHECK-NEXT: br label [[COMMON_RET]]
+; CHECK: common.ret:
+; CHECK-NEXT: ret void
+; CHECK: unreachable:
+; CHECK-NEXT: unreachable
+; CHECK: bar:
+; CHECK-NEXT: call void @bar()
+; CHECK-NEXT: br label [[COMMON_RET]]
+;
+ br i1 %c, label %sw1, label %sw2
+
+sw1:
+ ; This switch only exists to have an %unreachable block with multiple predecessors.
+ switch i32 %x, label %unreachable [
+ i32 1, label %foo
+ i32 2, label %bar
+ ]
+
+sw2:
+ switch i32 %x, label %bb3 [
+ i32 1, label %bb1
+ i32 2, label %bb2
+ i32 3, label %unreachable
+ ]
+
+bb1:
+ store i64 42, ptr %ptr
+ ret void
+
+bb2:
+ store i64 42, ptr %ptr
+ ret void
+
+bb3:
+ store i64 42, ptr %ptr
+ ret void
+
+unreachable:
+ unreachable
+
+foo:
+ ret void
+
+bar:
+ call void @bar()
+ ret void
+}
diff --git a/llvm/test/Transforms/SimplifyCFG/pr165088.ll b/llvm/test/Transforms/SimplifyCFG/pr165088.ll
new file mode 100644
index 0000000..4514a19
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/pr165088.ll
@@ -0,0 +1,186 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes="simplifycfg<switch-range-to-icmp>" < %s | FileCheck %s
+
+; Avoid getting stuck in the cycle pr165088_cycle_[1-4].
+
+define void @pr165088_cycle_1(i8 %x) {
+; CHECK-LABEL: define void @pr165088_cycle_1(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[X]], 2
+; CHECK-NEXT: br i1 [[TMP0]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]
+; CHECK: [[BLOCK1:.*]]:
+; CHECK-NEXT: [[COND2:%.*]] = icmp ugt i8 [[X]], 1
+; CHECK-NEXT: br i1 [[COND2]], label %[[BLOCK3]], label %[[BLOCK2]]
+; CHECK: [[BLOCK2]]:
+; CHECK-NEXT: br label %[[BLOCK3]]
+; CHECK: [[BLOCK3]]:
+; CHECK-NEXT: [[COND3:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: br i1 [[COND3]], label %[[EXIT:.*]], label %[[BLOCK1]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ %switch = icmp uge i8 %x, 2
+ %cond1 = icmp ugt i8 %x, 1
+ %or.cond = and i1 %switch, %cond1
+ br i1 %or.cond, label %block3, label %block2
+
+block1:
+ %cond2 = icmp ugt i8 %x, 1
+ br i1 %cond2, label %block3, label %block2
+
+block2:
+ br label %block3
+
+block3:
+ %cond3 = icmp eq i8 %x, 0
+ br i1 %cond3, label %exit, label %block1
+
+exit:
+ ret void
+}
+
+define void @pr165088_cycle_2(i8 %x) {
+; CHECK-LABEL: define void @pr165088_cycle_2(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[X]], 2
+; CHECK-NEXT: br i1 [[SWITCH]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]
+; CHECK: [[BLOCK1:.*]]:
+; CHECK-NEXT: [[COND2:%.*]] = icmp ugt i8 [[X]], 1
+; CHECK-NEXT: br i1 [[COND2]], label %[[BLOCK3]], label %[[BLOCK2]]
+; CHECK: [[BLOCK2]]:
+; CHECK-NEXT: br label %[[BLOCK3]]
+; CHECK: [[BLOCK3]]:
+; CHECK-NEXT: [[COND3:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: br i1 [[COND3]], label %[[EXIT:.*]], label %[[BLOCK1]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ switch i8 %x, label %block3 [
+ i8 1, label %block2
+ i8 0, label %block2
+ ]
+
+block1: ; preds = %block3
+ %cond2 = icmp ugt i8 %x, 1
+ br i1 %cond2, label %block3, label %block2
+
+block2: ; preds = %entry, %entry, %block1
+ br label %block3
+
+block3: ; preds = %entry, %block2, %block1
+ %cond3 = icmp eq i8 %x, 0
+ br i1 %cond3, label %exit, label %block1
+
+exit: ; preds = %block3
+ ret void
+}
+
+define void @pr165088_cycle_3(i8 %x) {
+; CHECK-LABEL: define void @pr165088_cycle_3(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[BLOCK3:.*]]
+; CHECK: [[BLOCK3]]:
+; CHECK-NEXT: [[COND3:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: br i1 [[COND3]], label %[[EXIT:.*]], label %[[BLOCK3]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ switch i8 %x, label %block1 [
+ i8 1, label %block2
+ i8 0, label %block2
+ ]
+
+block1: ; preds = %entry, %block3
+ %cond2 = icmp ugt i8 %x, 1
+ br i1 %cond2, label %block3, label %block2
+
+block2: ; preds = %entry, %entry, %block1
+ br label %block3
+
+block3: ; preds = %block2, %block1
+ %cond3 = icmp eq i8 %x, 0
+ br i1 %cond3, label %exit, label %block1
+
+exit: ; preds = %block3
+ ret void
+}
+
+define void @pr165088_cycle_4(i8 %x) {
+; CHECK-LABEL: define void @pr165088_cycle_4(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[X]], 2
+; CHECK-NEXT: br i1 [[TMP0]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]
+; CHECK: [[BLOCK1:.*]]:
+; CHECK-NEXT: [[COND2_OLD:%.*]] = icmp ugt i8 [[X]], 1
+; CHECK-NEXT: br i1 [[COND2_OLD]], label %[[BLOCK3]], label %[[BLOCK2]]
+; CHECK: [[BLOCK2]]:
+; CHECK-NEXT: br label %[[BLOCK3]]
+; CHECK: [[BLOCK3]]:
+; CHECK-NEXT: [[COND3:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: br i1 [[COND3]], label %[[EXIT:.*]], label %[[BLOCK1]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ %switch = icmp ult i8 %x, 2
+ br i1 %switch, label %block2, label %block1
+
+block1: ; preds = %entry, %block3
+ %cond2 = icmp ugt i8 %x, 1
+ br i1 %cond2, label %block3, label %block2
+
+block2: ; preds = %entry, %block1
+ br label %block3
+
+block3: ; preds = %block2, %block1
+ %cond3 = icmp eq i8 %x, 0
+ br i1 %cond3, label %exit, label %block1
+
+exit: ; preds = %block3
+ ret void
+}
+
+define void @pr165088_original(i8 %x) {
+; CHECK-LABEL: define void @pr165088_original(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[X]], 2
+; CHECK-NEXT: br i1 [[TMP0]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]
+; CHECK: [[BLOCK1:.*]]:
+; CHECK-NEXT: [[COND3_OLD_OLD:%.*]] = icmp ugt i8 [[X]], 1
+; CHECK-NEXT: br i1 [[COND3_OLD_OLD]], label %[[BLOCK3]], label %[[BLOCK2]]
+; CHECK: [[BLOCK2]]:
+; CHECK-NEXT: br label %[[BLOCK3]]
+; CHECK: [[BLOCK3]]:
+; CHECK-NEXT: [[COND4:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: br i1 [[COND4]], label %[[EXIT:.*]], label %[[BLOCK1]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ %cond = icmp ne i8 %x, 0
+ %cond3 = icmp ne i8 %x, 0
+ %or.cond = and i1 %cond, %cond3
+ br i1 %or.cond, label %block3, label %block2
+
+block1: ; preds = %block3
+ %cond3.old = icmp ugt i8 %x, 1
+ br i1 %cond3.old, label %block3, label %block2
+
+block2: ; preds = %block1, %entry
+ br label %block3
+
+block3: ; preds = %block2, %block1, %entry
+ %cond4 = icmp eq i8 %x, 0
+ br i1 %cond4, label %exit, label %block1
+
+exit: ; preds = %block3
+ 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/switch-on-const-select.ll b/llvm/test/Transforms/SimplifyCFG/switch-on-const.ll
index e8b5863..1ab1b5e 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch-on-const.ll
@@ -154,6 +154,132 @@ bees:
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
+}
+
declare void @llvm.trap() nounwind noreturn
declare void @bees.a() nounwind
declare void @bees.b() nounwind
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_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