xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/or.ll (revision 0f0c0c36e3e90b4cb04004ed9c930f3863a36422)
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 @use(i1)
5
6define void @test_or_ule(i4 %x, i4 %y, i4 %z, i4 %a) {
7; CHECK-LABEL: @test_or_ule(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
10; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
11; CHECK-NEXT:    [[OR:%.*]] = or i1 [[C_1]], [[C_2]]
12; CHECK-NEXT:    br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
13; CHECK:       bb1:
14; CHECK-NEXT:    [[C_3:%.*]] = icmp ule i4 [[X]], [[Z]]
15; CHECK-NEXT:    call void @use(i1 [[C_3]])
16; CHECK-NEXT:    [[C_4:%.*]] = icmp ule i4 [[X]], [[A:%.*]]
17; CHECK-NEXT:    call void @use(i1 [[C_4]])
18; CHECK-NEXT:    ret void
19; CHECK:       exit:
20; CHECK-NEXT:    call void @use(i1 false)
21; CHECK-NEXT:    [[C_5:%.*]] = icmp ule i4 [[X]], [[A]]
22; CHECK-NEXT:    call void @use(i1 [[C_5]])
23; CHECK-NEXT:    call void @use(i1 true)
24; CHECK-NEXT:    call void @use(i1 true)
25; CHECK-NEXT:    call void @use(i1 true)
26; CHECK-NEXT:    ret void
27;
28entry:
29  %c.1 = icmp ule i4 %x, %y
30  %c.2 = icmp ule i4 %y, %z
31  %or = or i1 %c.1, %c.2
32  br i1 %or, label %bb1, label %exit
33
34bb1:
35  %c.3 = icmp ule i4 %x, %z
36  call void @use(i1 %c.3)
37
38  %c.4 = icmp ule i4 %x, %a
39  call void @use(i1 %c.4)
40
41  ret void
42
43exit:
44  %f.1 = icmp ule i4 %x, %z
45  call void @use(i1 %f.1)
46
47  %c.5 = icmp ule i4 %x, %a
48  call void @use(i1 %c.5)
49
50  %t.1 = icmp ugt i4 %y, %z
51  call void @use(i1 %t.1)
52
53  %t.2 = icmp ugt i4 %x, %y
54  call void @use(i1 %t.2)
55
56  %t.3 = icmp ugt i4 %x, %z
57  call void @use(i1 %t.3)
58
59  ret void
60}
61
62; The result of test_or_ule and test_or_select_ule should be same
63define void @test_or_select_ule(i4 %x, i4 %y, i4 %z, i4 %a) {
64; CHECK-LABEL: @test_or_select_ule(
65; CHECK-NEXT:  entry:
66; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
67; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
68; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C_1]], i1 true, i1 [[C_2]]
69; CHECK-NEXT:    br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
70; CHECK:       bb1:
71; CHECK-NEXT:    [[C_3:%.*]] = icmp ule i4 [[X]], [[Z]]
72; CHECK-NEXT:    call void @use(i1 [[C_3]])
73; CHECK-NEXT:    [[C_4:%.*]] = icmp ule i4 [[X]], [[A:%.*]]
74; CHECK-NEXT:    call void @use(i1 [[C_4]])
75; CHECK-NEXT:    ret void
76; CHECK:       exit:
77; CHECK-NEXT:    call void @use(i1 false)
78; CHECK-NEXT:    [[C_5:%.*]] = icmp ule i4 [[X]], [[A]]
79; CHECK-NEXT:    call void @use(i1 [[C_5]])
80; CHECK-NEXT:    call void @use(i1 true)
81; CHECK-NEXT:    call void @use(i1 true)
82; CHECK-NEXT:    call void @use(i1 true)
83; CHECK-NEXT:    ret void
84;
85entry:
86  %c.1 = icmp ule i4 %x, %y
87  %c.2 = icmp ule i4 %y, %z
88  %or = select i1 %c.1, i1 true, i1 %c.2
89  br i1 %or, label %bb1, label %exit
90
91bb1:
92  %c.3 = icmp ule i4 %x, %z
93  call void @use(i1 %c.3)
94
95  %c.4 = icmp ule i4 %x, %a
96  call void @use(i1 %c.4)
97
98  ret void
99
100exit:
101  %f.1 = icmp ule i4 %x, %z
102  call void @use(i1 %f.1)
103
104  %c.5 = icmp ule i4 %x, %a
105  call void @use(i1 %c.5)
106
107  %t.1 = icmp ugt i4 %y, %z
108  call void @use(i1 %t.1)
109
110  %t.2 = icmp ugt i4 %x, %y
111  call void @use(i1 %t.2)
112
113  %t.3 = icmp ugt i4 %x, %z
114  call void @use(i1 %t.3)
115
116  ret void
117}
118
119define i1 @test_or_chain_ule_1(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) {
120; CHECK-LABEL: @test_or_chain_ule_1(
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
123; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
124; CHECK-NEXT:    [[C_3:%.*]] = icmp ule i4 2, [[X]]
125; CHECK-NEXT:    [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]]
126; CHECK-NEXT:    [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]]
127; CHECK-NEXT:    [[OR_2:%.*]] = or i1 [[OR_1]], true
128; CHECK-NEXT:    [[OR_3:%.*]] = or i1 [[C_4]], [[OR_2]]
129; CHECK-NEXT:    br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]]
130; CHECK:       bb1:
131; CHECK-NEXT:    [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]]
132; CHECK-NEXT:    [[C_6:%.*]] = icmp ule i4 [[X]], [[A]]
133; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]]
134; CHECK-NEXT:    [[C_7:%.*]] = icmp ule i4 2, [[X]]
135; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]]
136; CHECK-NEXT:    ret i1 [[RES_2]]
137; CHECK:       exit:
138; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 true, true
139; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], true
140; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_4]], true
141; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], true
142; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], true
143; CHECK-NEXT:    [[RES_8:%.*]] = xor i1 [[RES_7]], true
144; CHECK-NEXT:    [[RES_9:%.*]] = xor i1 [[RES_8]], true
145; CHECK-NEXT:    ret i1 [[RES_9]]
146;
147entry:
148  %c.1 = icmp ule i4 %x, %y
149  %c.2 = icmp ule i4 %y, %z
150  %c.3 = icmp ule i4 2, %x
151  %c.4 = icmp ule i4 2, %a
152  %or.1 = or i1 %c.1, %c.2
153  %or.2 = or i1 %or.1, %c.3
154  %or.3 = or i1 %c.4, %or.2
155  br i1 %or.3, label %bb1, label %exit
156
157bb1:
158  %c.5 = icmp ule i4 %x, %z
159  %c.6 = icmp ule i4 %x, %a
160  %res.1 = xor i1 %c.5, %c.6
161  %c.7 = icmp ule i4 2, %x
162  %res.2 = xor i1 %res.1, %c.7
163  ret i1 %res.2
164
165exit:
166  %f.1 = icmp ule i4 %x, %z
167  %f.2 = icmp ule i4 2, %x
168  %res.3 = xor i1 %f.1, %f.2
169
170  %t.1 = icmp ugt i4 %y, %z
171  %res.4 = xor i1 %res.3, %t.1
172
173  %t.2 = icmp ugt i4 %x, %y
174  %res.5 = xor i1 %res.4, %t.2
175
176  %t.3 = icmp ugt i4 %x, %z
177  %res.6 = xor i1 %res.5, %t.3
178
179  %t.4 = icmp ugt i4 2, %a
180  %res.7 = xor i1 %res.6, %t.4
181
182  %c.8 = icmp ule i4 %x, %a
183  %res.8 = xor i1 %res.7, %c.8
184
185  %c.9 = icmp ule i4 %x, %b
186  %res.9 = xor i1 %res.8, %c.9
187
188  ret i1 %res.9
189}
190
191; Same as @test_or_chain_ule_1, but with the `or`s ordered differently.
192define i1 @test_or_chain_ule_2(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) {
193; CHECK-LABEL: @test_or_chain_ule_2(
194; CHECK-NEXT:  entry:
195; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
196; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
197; CHECK-NEXT:    [[C_3:%.*]] = icmp ule i4 2, [[X]]
198; CHECK-NEXT:    [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]]
199; CHECK-NEXT:    [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]]
200; CHECK-NEXT:    [[OR_2:%.*]] = or i1 [[C_3]], [[C_4]]
201; CHECK-NEXT:    [[OR_3:%.*]] = or i1 [[OR_1]], [[OR_2]]
202; CHECK-NEXT:    br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]]
203; CHECK:       bb1:
204; CHECK-NEXT:    [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]]
205; CHECK-NEXT:    [[C_6:%.*]] = icmp ule i4 [[X]], [[A]]
206; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]]
207; CHECK-NEXT:    [[C_7:%.*]] = icmp ule i4 2, [[X]]
208; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]]
209; CHECK-NEXT:    ret i1 [[RES_2]]
210; CHECK:       exit:
211; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 true, true
212; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], true
213; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_4]], true
214; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], true
215; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], true
216; CHECK-NEXT:    [[RES_8:%.*]] = xor i1 [[RES_7]], true
217; CHECK-NEXT:    [[RES_9:%.*]] = xor i1 [[RES_8]], true
218; CHECK-NEXT:    ret i1 [[RES_9]]
219;
220entry:
221  %c.1 = icmp ule i4 %x, %y
222  %c.2 = icmp ule i4 %y, %z
223  %c.3 = icmp ule i4 2, %x
224  %c.4 = icmp ule i4 2, %a
225  %or.1 = or i1 %c.1, %c.2
226  %or.2 = or i1 %c.3, %c.4
227  %or.3 = or i1 %or.1, %or.2
228  br i1 %or.3, label %bb1, label %exit
229
230bb1:
231  %c.5 = icmp ule i4 %x, %z
232  %c.6 = icmp ule i4 %x, %a
233  %res.1 = xor i1 %c.5, %c.6
234  %c.7 = icmp ule i4 2, %x
235  %res.2 = xor i1 %res.1, %c.7
236  ret i1 %res.2
237
238exit:
239  %f.1 = icmp ule i4 %x, %z
240  %f.2 = icmp ule i4 2, %x
241  %res.3 = xor i1 %f.1, %f.2
242
243  %t.1 = icmp ugt i4 %y, %z
244  %res.4 = xor i1 %res.3, %t.1
245
246  %t.2 = icmp ugt i4 %x, %y
247  %res.5 = xor i1 %res.4, %t.2
248
249  %t.3 = icmp ugt i4 %x, %z
250  %res.6 = xor i1 %res.5, %t.3
251
252  %t.4 = icmp ugt i4 2, %a
253  %res.7 = xor i1 %res.6, %t.4
254
255  %c.8 = icmp ule i4 %x, %a
256  %res.8 = xor i1 %res.7, %c.8
257
258  %c.9 = icmp ule i4 %x, %b
259  %res.9 = xor i1 %res.8, %c.9
260
261  ret i1 %res.9
262}
263
264declare i1 @cond() readnone
265
266; Test with `or` chain that also contains instructions other than `or` and `icmp`.
267define i1 @test_or_chain_with_other_conds_ule(i4 %x, i4 %y, i4 %z, i4 %a, i1 %arg.c) {
268; CHECK-LABEL: @test_or_chain_with_other_conds_ule(
269; CHECK-NEXT:  entry:
270; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
271; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
272; CHECK-NEXT:    [[C_3:%.*]] = call i1 @cond()
273; CHECK-NEXT:    [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]]
274; CHECK-NEXT:    [[OR_2:%.*]] = or i1 [[C_3]], [[OR_1]]
275; CHECK-NEXT:    [[OR_3:%.*]] = or i1 [[OR_2]], [[ARG_C:%.*]]
276; CHECK-NEXT:    br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]]
277; CHECK:       bb1:
278; CHECK-NEXT:    [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]]
279; CHECK-NEXT:    [[C_6:%.*]] = icmp ule i4 [[X]], [[A:%.*]]
280; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]]
281; CHECK-NEXT:    [[C_7:%.*]] = icmp ule i4 2, [[X]]
282; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]]
283; CHECK-NEXT:    ret i1 [[RES_2]]
284; CHECK:       exit:
285; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 false, true
286; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], true
287; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_4]], true
288; CHECK-NEXT:    [[C_8:%.*]] = icmp ule i4 [[X]], [[A]]
289; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], [[C_8]]
290; CHECK-NEXT:    ret i1 [[RES_6]]
291;
292entry:
293  %c.1 = icmp ule i4 %x, %y
294  %c.2 = icmp ule i4 %y, %z
295  %c.3 = call i1 @cond()
296  %or.1 = or i1 %c.1, %c.2
297  %or.2 = or i1 %c.3, %or.1
298  %or.3 = or i1 %or.2, %arg.c
299  br i1 %or.3, label %bb1, label %exit
300
301bb1:
302  %c.5 = icmp ule i4 %x, %z
303  %c.6 = icmp ule i4 %x, %a
304  %res.1 = xor i1 %c.5, %c.6
305  %c.7 = icmp ule i4 2, %x
306  %res.2 = xor i1 %res.1, %c.7
307  ret i1 %res.2
308
309exit:
310  %f.1 = icmp ule i4 %x, %z
311
312  %t.1 = icmp ugt i4 %y, %z
313  %res.3 = xor i1 %f.1, %t.1
314
315  %t.2 = icmp ugt i4 %x, %y
316  %res.4 = xor i1 %res.3, %t.2
317
318  %t.3 = icmp ugt i4 %x, %z
319  %res.5 = xor i1 %res.4, %t.3
320
321  %c.8 = icmp ule i4 %x, %a
322  %res.6 = xor i1 %res.5, %c.8
323
324  ret i1 %res.6
325}
326
327define i1 @test_or_chain_with_and_ule(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) {
328; CHECK-LABEL: @test_or_chain_with_and_ule(
329; CHECK-NEXT:  entry:
330; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
331; CHECK-NEXT:    [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
332; CHECK-NEXT:    [[C_3:%.*]] = icmp ule i4 2, [[X]]
333; CHECK-NEXT:    [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]]
334; CHECK-NEXT:    [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]]
335; CHECK-NEXT:    [[AND_2:%.*]] = and i1 [[C_3]], [[C_4]]
336; CHECK-NEXT:    [[OR_3:%.*]] = or i1 [[OR_1]], [[AND_2]]
337; CHECK-NEXT:    br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]]
338; CHECK:       bb1:
339; CHECK-NEXT:    [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]]
340; CHECK-NEXT:    [[C_6:%.*]] = icmp ule i4 [[X]], [[A]]
341; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]]
342; CHECK-NEXT:    [[C_7:%.*]] = icmp ule i4 2, [[X]]
343; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]]
344; CHECK-NEXT:    ret i1 [[RES_2]]
345; CHECK:       exit:
346; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 false, true
347; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], true
348; CHECK-NEXT:    [[RES_5:%.*]] = xor i1 [[RES_4]], true
349; CHECK-NEXT:    [[C_8:%.*]] = icmp ule i4 [[X]], [[A]]
350; CHECK-NEXT:    [[RES_6:%.*]] = xor i1 [[RES_5]], [[C_8]]
351; CHECK-NEXT:    [[C_9:%.*]] = icmp ule i4 [[X]], [[B:%.*]]
352; CHECK-NEXT:    [[RES_7:%.*]] = xor i1 [[RES_6]], [[C_9]]
353; CHECK-NEXT:    [[RES_8:%.*]] = xor i1 [[RES_7]], true
354; CHECK-NEXT:    [[C_11:%.*]] = icmp ugt i4 2, [[A]]
355; CHECK-NEXT:    [[RES_9:%.*]] = xor i1 [[RES_8]], [[C_11]]
356; CHECK-NEXT:    ret i1 [[RES_9]]
357;
358entry:
359  %c.1 = icmp ule i4 %x, %y
360  %c.2 = icmp ule i4 %y, %z
361  %c.3 = icmp ule i4 2, %x
362  %c.4 = icmp ule i4 2, %a
363  %or.1 = or i1 %c.1, %c.2
364  %and.2 = and i1 %c.3, %c.4
365  %or.3 = or i1 %or.1, %and.2
366  br i1 %or.3, label %bb1, label %exit
367
368bb1:
369  %c.5 = icmp ule i4 %x, %z
370  %c.6 = icmp ule i4 %x, %a
371  %res.1 = xor i1 %c.5, %c.6
372  %c.7 = icmp ule i4 2, %x
373  %res.2 = xor i1 %res.1, %c.7
374  ret i1 %res.2
375
376exit:
377  %f.1 = icmp ule i4 %x, %z
378  %t.1 = icmp ugt i4 %y, %z
379  %res.3 = xor i1 %f.1, %t.1
380
381  %t.2 = icmp ugt i4 %x, %y
382  %res.4 = xor i1 %res.3, %t.2
383
384  %t.3 = icmp ugt i4 %x, %z
385  %res.5 = xor i1 %res.4, %t.3
386
387  %c.8 = icmp ule i4 %x, %a
388  %res.6 = xor i1 %res.5, %c.8
389
390  %c.9 = icmp ule i4 %x, %b
391  %res.7 = xor i1 %res.6, %c.9
392
393  %c.10 = icmp ule i4 2, %x
394  %res.8 = xor i1 %res.7, %c.10
395
396  %c.11 = icmp ugt i4 2, %a
397  %res.9 = xor i1 %res.8, %c.11
398
399  ret i1 %res.9
400}
401
402define void @test_or_as_add_ult(i8 %init_val, i8 %high) {
403; CHECK-LABEL: @test_or_as_add_ult(
404; CHECK-NEXT:  entry:
405; CHECK-NEXT:    [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2
406; CHECK-NEXT:    [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3
407; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
408; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
409; CHECK:       then:
410; CHECK-NEXT:    [[F_0:%.*]] = icmp ult i8 [[START]], [[HIGH]]
411; CHECK-NEXT:    call void @use(i1 [[F_0]])
412; CHECK-NEXT:    [[I_1:%.*]] = or disjoint i8 [[START]], 1
413; CHECK-NEXT:    [[F_1:%.*]] = icmp ult i8 [[I_1]], [[HIGH]]
414; CHECK-NEXT:    call void @use(i1 [[F_1]])
415; CHECK-NEXT:    [[I_2:%.*]] = or disjoint i8 [[START]], 2
416; CHECK-NEXT:    [[F_2:%.*]] = icmp ult i8 [[I_2]], [[HIGH]]
417; CHECK-NEXT:    call void @use(i1 [[F_2]])
418; CHECK-NEXT:    ret void
419; CHECK:       end:
420; CHECK-NEXT:    call void @use(i1 true)
421; CHECK-NEXT:    [[START_1:%.*]] = or disjoint i8 [[START]], 1
422; CHECK-NEXT:    call void @use(i1 true)
423; CHECK-NEXT:    [[START_2:%.*]] = or disjoint i8 [[START]], 2
424; CHECK-NEXT:    call void @use(i1 true)
425; CHECK-NEXT:    [[START_3:%.*]] = or disjoint i8 [[START]], 3
426; CHECK-NEXT:    call void @use(i1 true)
427; CHECK-NEXT:    [[START_4:%.*]] = or i8 [[START]], 4
428; CHECK-NEXT:    [[C_4:%.*]] = icmp ult i8 [[START_4]], [[HIGH]]
429; CHECK-NEXT:    call void @use(i1 [[C_4]])
430; CHECK-NEXT:    ret void
431;
432entry:
433  %start = shl nuw nsw i8 %init_val, 2
434  %start.plus.3 = add nuw i8 %start, 3
435  %c.1 = icmp uge i8 %start.plus.3, %high
436  br i1 %c.1, label %then, label %end
437
438then:                                          ; preds = %entry
439  %f.0 = icmp ult i8 %start, %high
440  call void @use(i1 %f.0)
441  %i.1 = or disjoint i8 %start, 1
442  %f.1 = icmp ult i8 %i.1, %high
443  call void @use(i1 %f.1)
444  %i.2 = or disjoint i8 %start, 2
445  %f.2 = icmp ult i8 %i.2, %high
446  call void @use(i1 %f.2)
447  ret void
448
449end:                                           ; preds = %entry
450  %t.0 = icmp ult i8 %start, %high
451  call void @use(i1 %t.0)
452  %start.1 = or disjoint i8 %start, 1
453  %t.1 = icmp ult i8 %start.1, %high
454  call void @use(i1 %t.1)
455  %start.2 = or disjoint i8 %start, 2
456  %t.2 = icmp ult i8 %start.2, %high
457  call void @use(i1 %t.2)
458  %start.3 = or disjoint i8 %start, 3
459  %t.3 = icmp ult i8 %start.3, %high
460  call void @use(i1 %t.3)
461  %start.4 = or i8 %start, 4
462  %c.4 = icmp ult i8 %start.4, %high
463  call void @use(i1 %c.4)
464  ret void
465}
466
467define void @test_or_as_add_ule(i8 %init_val, i8 %high) {
468; CHECK-LABEL: @test_or_as_add_ule(
469; CHECK-NEXT:  entry:
470; CHECK-NEXT:    [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2
471; CHECK-NEXT:    [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3
472; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
473; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
474; CHECK:       then:
475; CHECK-NEXT:    [[F_0:%.*]] = icmp ule i8 [[START]], [[HIGH]]
476; CHECK-NEXT:    call void @use(i1 [[F_0]])
477; CHECK-NEXT:    [[I_1:%.*]] = or disjoint i8 [[START]], 1
478; CHECK-NEXT:    [[F_1:%.*]] = icmp ule i8 [[I_1]], [[HIGH]]
479; CHECK-NEXT:    call void @use(i1 [[F_1]])
480; CHECK-NEXT:    [[I_2:%.*]] = or disjoint i8 [[START]], 2
481; CHECK-NEXT:    [[F_2:%.*]] = icmp ule i8 [[I_2]], [[HIGH]]
482; CHECK-NEXT:    call void @use(i1 [[F_2]])
483; CHECK-NEXT:    ret void
484; CHECK:       end:
485; CHECK-NEXT:    call void @use(i1 true)
486; CHECK-NEXT:    [[START_1:%.*]] = or disjoint i8 [[START]], 1
487; CHECK-NEXT:    call void @use(i1 true)
488; CHECK-NEXT:    [[START_2:%.*]] = or disjoint i8 [[START]], 2
489; CHECK-NEXT:    call void @use(i1 true)
490; CHECK-NEXT:    [[START_3:%.*]] = or disjoint i8 [[START]], 3
491; CHECK-NEXT:    call void @use(i1 true)
492; CHECK-NEXT:    [[START_4:%.*]] = or i8 [[START]], 4
493; CHECK-NEXT:    [[T_4:%.*]] = icmp ule i8 [[START_4]], [[HIGH]]
494; CHECK-NEXT:    call void @use(i1 [[T_4]])
495; CHECK-NEXT:    [[START_5:%.*]] = or i8 [[START]], 5
496; CHECK-NEXT:    [[C_5:%.*]] = icmp ule i8 [[START_5]], [[HIGH]]
497; CHECK-NEXT:    call void @use(i1 [[C_5]])
498; CHECK-NEXT:    ret void
499;
500entry:
501  %start = shl nuw nsw i8 %init_val, 2
502  %start.plus.3 = add nuw i8 %start, 3
503  %c.1 = icmp uge i8 %start.plus.3, %high
504  br i1 %c.1, label %then, label %end
505
506then:                                          ; preds = %entry
507  %f.0 = icmp ule i8 %start, %high
508  call void @use(i1 %f.0)
509  %i.1 = or disjoint i8 %start, 1
510  %f.1 = icmp ule i8 %i.1, %high
511  call void @use(i1 %f.1)
512  %i.2 = or disjoint i8 %start, 2
513  %f.2 = icmp ule i8 %i.2, %high
514  call void @use(i1 %f.2)
515  ret void
516
517end:                                           ; preds = %entry
518  %t.0 = icmp ule i8 %start, %high
519  call void @use(i1 %t.0)
520  %start.1 = or disjoint i8 %start, 1
521  %t.1 = icmp ule i8 %start.1, %high
522  call void @use(i1 %t.1)
523  %start.2 = or disjoint i8 %start, 2
524  %t.2 = icmp ule i8 %start.2, %high
525  call void @use(i1 %t.2)
526  %start.3 = or disjoint i8 %start, 3
527  %t.3 = icmp ule i8 %start.3, %high
528  call void @use(i1 %t.3)
529  %start.4 = or i8 %start, 4
530  %t.4 = icmp ule i8 %start.4, %high
531  call void @use(i1 %t.4)
532  %start.5 = or i8 %start, 5
533  %c.5 = icmp ule i8 %start.5, %high
534  call void @use(i1 %c.5)
535
536  ret void
537}
538
539define void @test_or_as_add_ugt(i8 %init_val, i8 %high) {
540; CHECK-LABEL: @test_or_as_add_ugt(
541; CHECK-NEXT:  entry:
542; CHECK-NEXT:    [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2
543; CHECK-NEXT:    [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3
544; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
545; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
546; CHECK:       then:
547; CHECK-NEXT:    [[T_0:%.*]] = icmp ugt i8 [[START]], [[HIGH]]
548; CHECK-NEXT:    call void @use(i1 [[T_0]])
549; CHECK-NEXT:    [[I_1:%.*]] = or disjoint i8 [[START]], 1
550; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[I_1]], [[HIGH]]
551; CHECK-NEXT:    call void @use(i1 [[T_1]])
552; CHECK-NEXT:    [[I_2:%.*]] = or disjoint i8 [[START]], 2
553; CHECK-NEXT:    [[T_2:%.*]] = icmp ugt i8 [[I_2]], [[HIGH]]
554; CHECK-NEXT:    call void @use(i1 [[T_2]])
555; CHECK-NEXT:    ret void
556; CHECK:       end:
557; CHECK-NEXT:    call void @use(i1 false)
558; CHECK-NEXT:    [[START_1:%.*]] = or disjoint i8 [[START]], 1
559; CHECK-NEXT:    call void @use(i1 false)
560; CHECK-NEXT:    [[START_2:%.*]] = or disjoint i8 [[START]], 2
561; CHECK-NEXT:    call void @use(i1 false)
562; CHECK-NEXT:    [[START_3:%.*]] = or disjoint i8 [[START]], 3
563; CHECK-NEXT:    call void @use(i1 false)
564; CHECK-NEXT:    [[START_4:%.*]] = or i8 [[START]], 4
565; CHECK-NEXT:    [[F_4:%.*]] = icmp ugt i8 [[START_4]], [[HIGH]]
566; CHECK-NEXT:    call void @use(i1 [[F_4]])
567; CHECK-NEXT:    [[START_5:%.*]] = or i8 [[START]], 5
568; CHECK-NEXT:    [[C_5:%.*]] = icmp ugt i8 [[START_5]], [[HIGH]]
569; CHECK-NEXT:    call void @use(i1 [[C_5]])
570; CHECK-NEXT:    ret void
571;
572entry:
573  %start = shl nuw nsw i8 %init_val, 2
574  %start.plus.3 = add nuw i8 %start, 3
575  %c.1 = icmp uge i8 %start.plus.3, %high
576  br i1 %c.1, label %then, label %end
577
578then:                                          ; preds = %entry
579  %t.0 = icmp ugt i8 %start, %high
580  call void @use(i1 %t.0)
581  %i.1 = or disjoint i8 %start, 1
582  %t.1 = icmp ugt i8 %i.1, %high
583  call void @use(i1 %t.1)
584  %i.2 = or disjoint i8 %start, 2
585  %t.2 = icmp ugt i8 %i.2, %high
586  call void @use(i1 %t.2)
587  ret void
588
589end:                                           ; preds = %entry
590  %f.0 = icmp ugt i8 %start, %high
591  call void @use(i1 %f.0)
592  %start.1 = or disjoint i8 %start, 1
593  %f.1 = icmp ugt i8 %start.1, %high
594  call void @use(i1 %f.1)
595  %start.2 = or disjoint i8 %start, 2
596  %f.2 = icmp ugt i8 %start.2, %high
597  call void @use(i1 %f.2)
598  %start.3 = or disjoint i8 %start, 3
599  %f.3 = icmp ugt i8 %start.3, %high
600  call void @use(i1 %f.3)
601  %start.4 = or i8 %start, 4
602  %f.4 = icmp ugt i8 %start.4, %high
603  call void @use(i1 %f.4)
604  %start.5 = or i8 %start, 5
605  %c.5 = icmp ugt i8 %start.5, %high
606  call void @use(i1 %c.5)
607  ret void
608}
609
610define void @test_or_as_add_uge(i8 %init_val, i8 %high) {
611; CHECK-LABEL: @test_or_as_add_uge(
612; CHECK-NEXT:  entry:
613; CHECK-NEXT:    [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2
614; CHECK-NEXT:    [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3
615; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
616; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
617; CHECK:       then:
618; CHECK-NEXT:    [[T_0:%.*]] = icmp ugt i8 [[START]], [[HIGH]]
619; CHECK-NEXT:    call void @use(i1 [[T_0]])
620; CHECK-NEXT:    [[I_1:%.*]] = or disjoint i8 [[START]], 1
621; CHECK-NEXT:    [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]]
622; CHECK-NEXT:    call void @use(i1 [[T_1]])
623; CHECK-NEXT:    [[I_2:%.*]] = or disjoint i8 [[START]], 2
624; CHECK-NEXT:    [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]]
625; CHECK-NEXT:    call void @use(i1 [[T_2]])
626; CHECK-NEXT:    ret void
627; CHECK:       end:
628; CHECK-NEXT:    call void @use(i1 false)
629; CHECK-NEXT:    [[START_1:%.*]] = or disjoint i8 [[START]], 1
630; CHECK-NEXT:    call void @use(i1 false)
631; CHECK-NEXT:    [[START_2:%.*]] = or disjoint i8 [[START]], 2
632; CHECK-NEXT:    call void @use(i1 false)
633; CHECK-NEXT:    [[START_3:%.*]] = or disjoint i8 [[START]], 3
634; CHECK-NEXT:    call void @use(i1 false)
635; CHECK-NEXT:    [[START_4:%.*]] = or i8 [[START]], 4
636; CHECK-NEXT:    [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]]
637; CHECK-NEXT:    call void @use(i1 [[C_4]])
638; CHECK-NEXT:    [[START_5:%.*]] = or i8 [[START]], 5
639; CHECK-NEXT:    [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]]
640; CHECK-NEXT:    call void @use(i1 [[C_5]])
641; CHECK-NEXT:    ret void
642;
643entry:
644  %start = shl nuw nsw i8 %init_val, 2
645  %start.plus.3 = add nuw i8 %start, 3
646  %c.1 = icmp uge i8 %start.plus.3, %high
647  br i1 %c.1, label %then, label %end
648
649then:                                          ; preds = %entry
650  %t.0 = icmp ugt i8 %start, %high
651  call void @use(i1 %t.0)
652  %i.1 = or disjoint i8 %start, 1
653  %t.1 = icmp uge i8 %i.1, %high
654  call void @use(i1 %t.1)
655  %i.2 = or disjoint i8 %start, 2
656  %t.2 = icmp uge i8 %i.2, %high
657  call void @use(i1 %t.2)
658  ret void
659
660end:                                           ; preds = %entry
661  %f.0 = icmp ugt i8 %start, %high
662  call void @use(i1 %f.0)
663  %start.1 = or disjoint i8 %start, 1
664  %f.1 = icmp uge i8 %start.1, %high
665  call void @use(i1 %f.1)
666  %start.2 = or disjoint i8 %start, 2
667  %f.2 = icmp uge i8 %start.2, %high
668  call void @use(i1 %f.2)
669  %start.3 = or disjoint i8 %start, 3
670  %f.3 = icmp uge i8 %start.3, %high
671  call void @use(i1 %f.3)
672  %start.4 = or i8 %start, 4
673  %c.4 = icmp uge i8 %start.4, %high
674  call void @use(i1 %c.4)
675  %start.5 = or i8 %start, 5
676  %c.5 = icmp uge i8 %start.5, %high
677  call void @use(i1 %c.5)
678  ret void
679}
680
681define void @test_not_decompose(i8 %start, i8 %high) {
682; CHECK-LABEL: @test_not_decompose(
683; CHECK-NEXT:  entry:
684; CHECK-NEXT:    [[START_PLUS_3:%.*]] = add nuw i8 [[START:%.*]], 3
685; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
686; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
687; CHECK:       then:
688; CHECK-NEXT:    [[I_1:%.*]] = or i8 [[START]], 1
689; CHECK-NEXT:    [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]]
690; CHECK-NEXT:    call void @use(i1 [[T_1]])
691; CHECK-NEXT:    [[I_2:%.*]] = or i8 [[START]], 2
692; CHECK-NEXT:    [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]]
693; CHECK-NEXT:    call void @use(i1 [[T_2]])
694; CHECK-NEXT:    ret void
695; CHECK:       end:
696; CHECK-NEXT:    [[START_1:%.*]] = or i8 [[START]], 1
697; CHECK-NEXT:    [[F_1:%.*]] = icmp uge i8 [[START_1]], [[HIGH]]
698; CHECK-NEXT:    call void @use(i1 [[F_1]])
699; CHECK-NEXT:    [[START_2:%.*]] = or i8 [[START]], 2
700; CHECK-NEXT:    [[F_2:%.*]] = icmp uge i8 [[START_2]], [[HIGH]]
701; CHECK-NEXT:    call void @use(i1 [[F_2]])
702; CHECK-NEXT:    [[START_3:%.*]] = or i8 [[START]], 3
703; CHECK-NEXT:    [[F_3:%.*]] = icmp uge i8 [[START_3]], [[HIGH]]
704; CHECK-NEXT:    call void @use(i1 [[F_3]])
705; CHECK-NEXT:    [[START_4:%.*]] = or i8 [[START]], 4
706; CHECK-NEXT:    [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]]
707; CHECK-NEXT:    call void @use(i1 [[C_4]])
708; CHECK-NEXT:    [[START_5:%.*]] = or i8 [[START]], 5
709; CHECK-NEXT:    [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]]
710; CHECK-NEXT:    call void @use(i1 [[C_5]])
711; CHECK-NEXT:    ret void
712;
713entry:
714  %start.plus.3 = add nuw i8 %start, 3
715  %c.1 = icmp uge i8 %start.plus.3, %high
716  br i1 %c.1, label %then, label %end
717
718then:                                          ; preds = %entry
719  %i.1 = or i8 %start, 1
720  %t.1 = icmp uge i8 %i.1, %high
721  call void @use(i1 %t.1)
722  %i.2 = or i8 %start, 2
723  %t.2 = icmp uge i8 %i.2, %high
724  call void @use(i1 %t.2)
725  ret void
726
727end:                                           ; preds = %entry
728  %start.1 = or i8 %start, 1
729  %f.1 = icmp uge i8 %start.1, %high
730  call void @use(i1 %f.1)
731  %start.2 = or i8 %start, 2
732  %f.2 = icmp uge i8 %start.2, %high
733  call void @use(i1 %f.2)
734  %start.3 = or i8 %start, 3
735  %f.3 = icmp uge i8 %start.3, %high
736  call void @use(i1 %f.3)
737  %start.4 = or i8 %start, 4
738  %c.4 = icmp uge i8 %start.4, %high
739  call void @use(i1 %c.4)
740  %start.5 = or i8 %start, 5
741  %c.5 = icmp uge i8 %start.5, %high
742  call void @use(i1 %c.5)
743
744  ret void
745}
746
747; Nothing in the IR implies the disjoint flag, but we can still use it
748; to decompose into an add.
749define void @test_decompose_explicit_disjoint(i8 %start, i8 %high) {
750; CHECK-LABEL: @test_decompose_explicit_disjoint(
751; CHECK-NEXT:  entry:
752; CHECK-NEXT:    [[START_PLUS_3:%.*]] = add nuw i8 [[START:%.*]], 3
753; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
754; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
755; CHECK:       then:
756; CHECK-NEXT:    [[I_1:%.*]] = or disjoint i8 [[START]], 1
757; CHECK-NEXT:    [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]]
758; CHECK-NEXT:    call void @use(i1 [[T_1]])
759; CHECK-NEXT:    [[I_2:%.*]] = or disjoint i8 [[START]], 2
760; CHECK-NEXT:    [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]]
761; CHECK-NEXT:    call void @use(i1 [[T_2]])
762; CHECK-NEXT:    ret void
763; CHECK:       end:
764; CHECK-NEXT:    [[START_1:%.*]] = or disjoint i8 [[START]], 1
765; CHECK-NEXT:    call void @use(i1 false)
766; CHECK-NEXT:    [[START_2:%.*]] = or disjoint i8 [[START]], 2
767; CHECK-NEXT:    call void @use(i1 false)
768; CHECK-NEXT:    [[START_3:%.*]] = or disjoint i8 [[START]], 3
769; CHECK-NEXT:    call void @use(i1 false)
770; CHECK-NEXT:    [[START_4:%.*]] = or disjoint i8 [[START]], 4
771; CHECK-NEXT:    [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]]
772; CHECK-NEXT:    call void @use(i1 [[C_4]])
773; CHECK-NEXT:    [[START_5:%.*]] = or disjoint i8 [[START]], 5
774; CHECK-NEXT:    [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]]
775; CHECK-NEXT:    call void @use(i1 [[C_5]])
776; CHECK-NEXT:    ret void
777;
778entry:
779  %start.plus.3 = add nuw i8 %start, 3
780  %c.1 = icmp uge i8 %start.plus.3, %high
781  br i1 %c.1, label %then, label %end
782
783then:                                          ; preds = %entry
784  %i.1 = or disjoint i8 %start, 1
785  %t.1 = icmp uge i8 %i.1, %high
786  call void @use(i1 %t.1)
787  %i.2 = or disjoint i8 %start, 2
788  %t.2 = icmp uge i8 %i.2, %high
789  call void @use(i1 %t.2)
790  ret void
791
792end:                                           ; preds = %entry
793  %start.1 = or disjoint i8 %start, 1
794  %f.1 = icmp uge i8 %start.1, %high
795  call void @use(i1 %f.1)
796  %start.2 = or disjoint i8 %start, 2
797  %f.2 = icmp uge i8 %start.2, %high
798  call void @use(i1 %f.2)
799  %start.3 = or disjoint i8 %start, 3
800  %f.3 = icmp uge i8 %start.3, %high
801  call void @use(i1 %f.3)
802  %start.4 = or disjoint i8 %start, 4
803  %c.4 = icmp uge i8 %start.4, %high
804  call void @use(i1 %c.4)
805  %start.5 = or disjoint i8 %start, 5
806  %c.5 = icmp uge i8 %start.5, %high
807  call void @use(i1 %c.5)
808
809  ret void
810}
811