1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt %s -simplifycfg -S | FileCheck %s
3
4declare i32 @f(i32)
5
6define i32 @basic(i32 %x) {
7; CHECK-LABEL: @basic(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -5
10; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3
11; CHECK-NEXT:    br i1 [[SWITCH]], label [[A:%.*]], label [[DEFAULT:%.*]]
12; CHECK:       default:
13; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @f(i32 0)
14; CHECK-NEXT:    ret i32 [[TMP0]]
15; CHECK:       a:
16; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @f(i32 1)
17; CHECK-NEXT:    ret i32 [[TMP1]]
18;
19
20entry:
21  switch i32 %x, label %default [
22  i32 5, label %a
23  i32 6, label %a
24  i32 7, label %a
25  ]
26default:
27  %0 = call i32 @f(i32 0)
28  ret i32 %0
29a:
30  %1 = call i32 @f(i32 1)
31  ret i32 %1
32}
33
34
35define i32 @unreachable(i32 %x) {
36; CHECK-LABEL: @unreachable(
37; CHECK-NEXT:  entry:
38; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -5
39; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3
40; CHECK-NEXT:    br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]]
41; CHECK:       a:
42; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @f(i32 0)
43; CHECK-NEXT:    ret i32 [[TMP0]]
44; CHECK:       b:
45; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @f(i32 1)
46; CHECK-NEXT:    ret i32 [[TMP1]]
47;
48
49entry:
50  switch i32 %x, label %unreachable [
51  i32 5, label %a
52  i32 6, label %a
53  i32 7, label %a
54  i32 10, label %b
55  i32 20, label %b
56  i32 30, label %b
57  i32 40, label %b
58  ]
59unreachable:
60  unreachable
61a:
62  %0 = call i32 @f(i32 0)
63  ret i32 %0
64b:
65  %1 = call i32 @f(i32 1)
66  ret i32 %1
67}
68
69
70define i32 @unreachable2(i32 %x) {
71; CHECK-LABEL: @unreachable2(
72; CHECK-NEXT:  entry:
73; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -5
74; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3
75; CHECK-NEXT:    br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]]
76; CHECK:       a:
77; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @f(i32 0)
78; CHECK-NEXT:    ret i32 [[TMP0]]
79; CHECK:       b:
80; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @f(i32 1)
81; CHECK-NEXT:    ret i32 [[TMP1]]
82;
83
84entry:
85  ; Note: folding the most popular case destination into the default
86  ; would prevent switch-to-icmp here.
87  switch i32 %x, label %unreachable [
88  i32 5, label %a
89  i32 6, label %a
90  i32 7, label %a
91  i32 10, label %b
92  i32 20, label %b
93  ]
94unreachable:
95  unreachable
96a:
97  %0 = call i32 @f(i32 0)
98  ret i32 %0
99b:
100  %1 = call i32 @f(i32 1)
101  ret i32 %1
102}
103
104; This would crash because we did not clean up the
105; default block of the switch before removing the switch.
106
107define void @PR42737(i32* %a, i1 %c) {
108; CHECK-LABEL: @PR42737(
109; CHECK-NEXT:  entry:
110; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[C:%.*]], true
111; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
112; CHECK-NEXT:    unreachable
113;
114entry:
115  br i1 %c, label %switch, label %else
116
117else:
118  store i32 2, i32* %a
119  br label %switch
120
121switch:
122  %cleanup.dest1 = phi i32 [ 0, %else ], [ 3, %entry ]
123  switch i32 %cleanup.dest1, label %unreach1 [
124  i32 0, label %cleanup1
125  i32 3, label %cleanup2
126  ]
127
128cleanup1:
129  br label %unreach2
130
131cleanup2:
132  br label %unreach2
133
134unreach1:
135  %phi2 = phi i32 [ %cleanup.dest1, %switch ]
136  unreachable
137
138unreach2:
139  unreachable
140}
141