xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/switch.ll (revision 39d7f700ce0103539fb00bd2841c5ca994c1a7f1)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4declare void @may_unwind()
5
6define i1 @test_switch_in_block_with_assume(i8 %x) {
7; CHECK-LABEL: @test_switch_in_block_with_assume(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    call void @may_unwind()
10; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[X:%.*]], 10
11; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
12; CHECK-NEXT:    switch i8 0, label [[EXIT_1:%.*]] [
13; CHECK-NEXT:    i8 1, label [[EXIT_2:%.*]]
14; CHECK-NEXT:    ]
15; CHECK:       exit.1:
16; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i8 [[X]], 9
17; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, [[C_2]]
18; CHECK-NEXT:    ret i1 [[RES_1]]
19; CHECK:       exit.2:
20; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i8 [[X]], 9
21; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 true, [[C_3]]
22; CHECK-NEXT:    ret i1 [[RES_2]]
23;
24entry:
25  call void @may_unwind()
26  %c.1 = icmp ult i8 %x, 10
27  call void @llvm.assume(i1 %c.1)
28  switch i8 0, label %exit.1 [
29  i8 1, label %exit.2
30  ]
31
32exit.1:
33  %t.1 = icmp ult i8 %x, 10
34  %c.2 = icmp ult i8 %x, 9
35  %res.1 = xor i1 %t.1, %c.2
36  ret i1 %res.1
37
38exit.2:
39  %t.2 = icmp ult i8 %x, 10
40  %c.3 = icmp ult i8 %x, 9
41  %res.2 = xor i1 %t.2, %c.3
42  ret i1 %res.2
43}
44
45declare void @llvm.assume(i1)
46
47define i1 @simplify_based_on_switch(i8 %x) {
48; CHECK-LABEL: @simplify_based_on_switch(
49; CHECK-NEXT:  entry:
50; CHECK-NEXT:    switch i8 [[X:%.*]], label [[EXIT_1:%.*]] [
51; CHECK-NEXT:    i8 6, label [[EXIT_2:%.*]]
52; CHECK-NEXT:    i8 10, label [[EXIT_3:%.*]]
53; CHECK-NEXT:    ]
54; CHECK:       exit.1:
55; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[X]], 7
56; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i8 [[X]], 6
57; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]]
58; CHECK-NEXT:    ret i1 [[RES_1]]
59; CHECK:       exit.2:
60; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 true, false
61; CHECK-NEXT:    ret i1 [[RES_2]]
62; CHECK:       exit.3:
63; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 true, false
64; CHECK-NEXT:    ret i1 [[RES_3]]
65;
66entry:
67  switch i8 %x, label %exit.1 [
68  i8 6, label %exit.2
69  i8 10, label %exit.3
70  ]
71
72exit.1:
73  %c.1 = icmp ult i8 %x, 7
74  %c.2 = icmp ult i8 %x, 6
75  %res.1 = xor i1 %c.1, %c.2
76  ret i1 %res.1
77
78exit.2:
79  %t.1 = icmp ult i8 %x, 7
80  %f.1 = icmp ult i8 %x, 6
81  %res.2 = xor i1 %t.1, %f.1
82  ret i1 %res.2
83
84exit.3:
85  %t.2 = icmp ult i8 %x, 11
86  %f.2 = icmp ult i8 %x, 10
87  %res.3 = xor i1 %t.2, %f.2
88  ret i1 %res.3
89}
90
91define i1 @simplify_based_on_switch_successor_branches(i8 %x) {
92; CHECK-LABEL: @simplify_based_on_switch_successor_branches(
93; CHECK-NEXT:  entry:
94; CHECK-NEXT:    switch i8 [[X:%.*]], label [[EXIT_1:%.*]] [
95; CHECK-NEXT:    i8 6, label [[EXIT_2:%.*]]
96; CHECK-NEXT:    i8 10, label [[EXIT_3:%.*]]
97; CHECK-NEXT:    ]
98; CHECK:       exit.1:
99; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[X]], 7
100; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i8 [[X]], 6
101; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]]
102; CHECK-NEXT:    ret i1 [[RES_1]]
103; CHECK:       exit.2:
104; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 true, false
105; CHECK-NEXT:    call void @use(i1 [[RES_2]])
106; CHECK-NEXT:    br label [[EXIT_3]]
107; CHECK:       exit.3:
108; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i8 [[X]], 11
109; CHECK-NEXT:    [[C_4:%.*]] = icmp ult i8 [[X]], 10
110; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[C_3]], [[C_4]]
111; CHECK-NEXT:    ret i1 [[RES_3]]
112;
113entry:
114  switch i8 %x, label %exit.1 [
115  i8 6, label %exit.2
116  i8 10, label %exit.3
117  ]
118
119exit.1:
120  %c.1 = icmp ult i8 %x, 7
121  %c.2 = icmp ult i8 %x, 6
122  %res.1 = xor i1 %c.1, %c.2
123  ret i1 %res.1
124
125exit.2:
126  %t.1 = icmp ult i8 %x, 7
127  %f.1 = icmp ult i8 %x, 6
128  %res.2 = xor i1 %t.1, %f.1
129  call void @use(i1 %res.2)
130  br label %exit.3
131
132exit.3:
133  %c.3 = icmp ult i8 %x, 11
134  %c.4 = icmp ult i8 %x, 10
135  %res.3 = xor i1 %c.3, %c.4
136  ret i1 %res.3
137}
138
139define i1 @switch_same_destination_for_different_cases(i8 %x) {
140; CHECK-LABEL: @switch_same_destination_for_different_cases(
141; CHECK-NEXT:  entry:
142; CHECK-NEXT:    switch i8 [[X:%.*]], label [[EXIT_1:%.*]] [
143; CHECK-NEXT:    i8 6, label [[EXIT_2:%.*]]
144; CHECK-NEXT:    i8 10, label [[EXIT_2]]
145; CHECK-NEXT:    ]
146; CHECK:       exit.1:
147; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[X]], 7
148; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i8 [[X]], 6
149; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]]
150; CHECK-NEXT:    ret i1 [[RES_1]]
151; CHECK:       exit.2:
152; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i8 [[X]], 7
153; CHECK-NEXT:    call void @use(i1 [[C_3]])
154; CHECK-NEXT:    [[C_4:%.*]] = icmp ult i8 [[X]], 6
155; CHECK-NEXT:    call void @use(i1 [[C_4]])
156; CHECK-NEXT:    [[C_5:%.*]] = icmp ult i8 [[X]], 11
157; CHECK-NEXT:    call void @use(i1 [[C_5]])
158; CHECK-NEXT:    [[C_6:%.*]] = icmp ult i8 [[X]], 10
159; CHECK-NEXT:    ret i1 [[C_6]]
160;
161entry:
162  switch i8 %x, label %exit.1 [
163  i8 6, label %exit.2
164  i8 10, label %exit.2
165  ]
166
167exit.1:
168  %c.1 = icmp ult i8 %x, 7
169  %c.2 = icmp ult i8 %x, 6
170  %res.1 = xor i1 %c.1, %c.2
171  ret i1 %res.1
172
173exit.2:
174  %c.3 = icmp ult i8 %x, 7
175  call void @use(i1 %c.3)
176  %c.4 = icmp ult i8 %x, 6
177  call void @use(i1 %c.4)
178  %c.5 = icmp ult i8 %x, 11
179  call void @use(i1 %c.5)
180  %c.6 = icmp ult i8 %x, 10
181  ret i1 %c.6
182}
183
184declare void @use(i1)
185