xref: /llvm-project/llvm/test/CodeGen/AArch64/selectopt-cast.ll (revision c1f5937eb4bf4002b8205873189f900364868fd5)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -select-optimize -mtriple=arm64-apple-macosx -S %s | FileCheck %s
3; RUN: opt -passes='require<profile-summary>,function(select-optimize)' -mtriple=arm64-apple-macosx -S %s | FileCheck %s
4
5define void @test_add_zext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
6; CHECK-LABEL: @test_add_zext(
7; CHECK-NEXT:  entry:
8; CHECK-NEXT:    br label [[LOOP:%.*]]
9; CHECK:       loop:
10; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
11; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
12; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
13; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
14; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
15; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
16; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
17; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
18; CHECK-NEXT:    [[DEC:%.*]] = zext i1 [[CMP3]] to i64
19; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
20; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END]]
21; CHECK:       select.true.sink:
22; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[J]], 1
23; CHECK-NEXT:    br label [[SELECT_END]]
24; CHECK:       select.end:
25; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[TMP0]], [[SELECT_TRUE_SINK]] ], [ [[J]], [[LOOP]] ]
26; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
27; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
28; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
29; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
30; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
31; CHECK:       exit:
32; CHECK-NEXT:    ret void
33;
34entry:
35  br label %loop
36
37loop:
38  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
39  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
40  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
41  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
42  %l.i = load ptr, ptr %gep.i, align 8
43  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
44  %l.j = load ptr, ptr %gep.j, align 8
45  %cmp3 = icmp ult ptr %l.i, %l.j
46  %dec = zext i1 %cmp3 to i64
47  %j.next = add nsw i64 %j, %dec
48  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
49  store i64 %j.next, ptr %gep.dst, align 8
50  %iv.next = add i64 %iv, 1
51  %ec = icmp eq i64 %iv, %j.start
52  br i1 %ec, label %exit, label %loop
53
54exit:
55  ret void
56}
57
58define void @test_add_zext_first_op(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
59; CHECK-LABEL: @test_add_zext_first_op(
60; CHECK-NEXT:  entry:
61; CHECK-NEXT:    br label [[LOOP:%.*]]
62; CHECK:       loop:
63; CHECK-NEXT:    [[IV1:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
64; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[J_START:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
65; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
66; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
67; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_DST]], align 8
68; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[DST]], i64 [[J]]
69; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
70; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
71; CHECK-NEXT:    [[DEC:%.*]] = zext i1 [[CMP3]] to i64
72; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
73; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END]]
74; CHECK:       select.true.sink:
75; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 1, [[J]]
76; CHECK-NEXT:    br label [[SELECT_END]]
77; CHECK:       select.end:
78; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[TMP0]], [[SELECT_TRUE_SINK]] ], [ [[J]], [[LOOP]] ]
79; CHECK-NEXT:    [[GEP_DST1:%.*]] = getelementptr inbounds ptr, ptr [[DST1:%.*]], i64 [[IV1]]
80; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST1]], align 8
81; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV1]], 1
82; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV1]], [[J_START]]
83; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
84; CHECK:       exit:
85; CHECK-NEXT:    ret void
86;
87entry:
88  br label %loop
89
90loop:
91  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
92  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
93  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
94  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
95  %l.i = load ptr, ptr %gep.i, align 8
96  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
97  %l.j = load ptr, ptr %gep.j, align 8
98  %cmp3 = icmp ult ptr %l.i, %l.j
99  %dec = zext i1 %cmp3 to i64
100  %j.next = add nsw i64 %dec, %j
101  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
102  store i64 %j.next, ptr %gep.dst, align 8
103  %iv.next = add i64 %iv, 1
104  %ec = icmp eq i64 %iv, %j.start
105  br i1 %ec, label %exit, label %loop
106
107exit:
108  ret void
109}
110
111define void @test_add_zext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
112; CHECK-LABEL: @test_add_zext_not(
113; CHECK-NEXT:  entry:
114; CHECK-NEXT:    br label [[LOOP:%.*]]
115; CHECK:       loop:
116; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
117; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[J_START:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
118; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
119; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
120; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
121; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
122; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
123; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
124; CHECK-NEXT:    [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
125; CHECK-NEXT:    [[DEC:%.*]] = zext i1 [[NOT_CMP3]] to i64
126; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
127; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE_SINK:%.*]]
128; CHECK:       select.false.sink:
129; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[J]], 1
130; CHECK-NEXT:    br label [[SELECT_END]]
131; CHECK:       select.end:
132; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE_SINK]] ]
133; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
134; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
135; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
136; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV]], [[J_START]]
137; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
138; CHECK:       exit:
139; CHECK-NEXT:    ret void
140;
141entry:
142  br label %loop
143
144loop:
145  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
146  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
147  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
148  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
149  %l.i = load ptr, ptr %gep.i, align 8
150  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
151  %l.j = load ptr, ptr %gep.j, align 8
152  %cmp3 = icmp ult ptr %l.i, %l.j
153  %not.cmp3 = xor i1 %cmp3, true
154  %dec = zext i1 %not.cmp3 to i64
155  %j.next = add nsw i64 %j, %dec
156  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
157  store i64 %j.next, ptr %gep.dst, align 8
158  %iv.next = add i64 %iv, 1
159  %ec = icmp eq i64 %iv, %j.start
160  br i1 %ec, label %exit, label %loop
161
162exit:
163  ret void
164}
165
166define void @test_add_sext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
167; CHECK-LABEL: @test_add_sext(
168; CHECK-NEXT:  entry:
169; CHECK-NEXT:    br label [[LOOP:%.*]]
170; CHECK:       loop:
171; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
172; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
173; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
174; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
175; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
176; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
177; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
178; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
179; CHECK-NEXT:    [[DEC:%.*]] = sext i1 [[CMP3]] to i64
180; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
181; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END]]
182; CHECK:       select.true.sink:
183; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[J]], -1
184; CHECK-NEXT:    br label [[SELECT_END]]
185; CHECK:       select.end:
186; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[TMP0]], [[SELECT_TRUE_SINK]] ], [ [[J]], [[LOOP]] ]
187; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
188; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
189; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
190; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
191; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
192; CHECK:       exit:
193; CHECK-NEXT:    ret void
194;
195entry:
196  br label %loop
197
198loop:
199  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
200  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
201  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
202  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
203  %l.i = load ptr, ptr %gep.i, align 8
204  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
205  %l.j = load ptr, ptr %gep.j, align 8
206  %cmp3 = icmp ult ptr %l.i, %l.j
207  %dec = sext i1 %cmp3 to i64
208  %j.next = add nsw i64 %j, %dec
209  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
210  store i64 %j.next, ptr %gep.dst, align 8
211  %iv.next = add i64 %iv, 1
212  %ec = icmp eq i64 %iv, %j.start
213  br i1 %ec, label %exit, label %loop
214
215exit:
216  ret void
217}
218
219define void @test_add_sext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
220; CHECK-LABEL: @test_add_sext_not(
221; CHECK-NEXT:  entry:
222; CHECK-NEXT:    br label [[LOOP:%.*]]
223; CHECK:       loop:
224; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
225; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
226; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
227; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
228; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
229; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
230; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
231; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
232; CHECK-NEXT:    [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
233; CHECK-NEXT:    [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
234; CHECK-NEXT:    [[NOT_CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
235; CHECK-NEXT:    br i1 [[NOT_CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]]
236; CHECK:       select.false.sink:
237; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[J]], -1
238; CHECK-NEXT:    br label [[SELECT_END]]
239; CHECK:       select.end:
240; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE]] ]
241; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
242; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
243; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
244; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
245; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
246; CHECK:       exit:
247; CHECK-NEXT:    ret void
248;
249entry:
250  br label %loop
251
252loop:
253  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
254  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
255  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
256  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
257  %l.i = load ptr, ptr %gep.i, align 8
258  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
259  %l.j = load ptr, ptr %gep.j, align 8
260  %cmp3 = icmp ult ptr %l.i, %l.j
261  %not.cmp3 = xor i1 %cmp3, true
262  %dec = sext i1 %not.cmp3 to i64
263  %j.next = add nsw i64 %j, %dec
264  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
265  store i64 %j.next, ptr %gep.dst, align 8
266  %iv.next = add i64 %iv, 1
267  %ec = icmp eq i64 %iv, %j.start
268  br i1 %ec, label %exit, label %loop
269
270exit:
271  ret void
272}
273
274define void @test_add_sext_not_and_regular_select(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
275; CHECK-LABEL: @test_add_sext_not_and_regular_select(
276; CHECK-NEXT:  entry:
277; CHECK-NEXT:    br label [[LOOP:%.*]]
278; CHECK:       loop:
279; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ]
280; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ]
281; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ]
282; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
283; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
284; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
285; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
286; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
287; CHECK-NEXT:    [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
288; CHECK-NEXT:    [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
289; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
290; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE_SINK:%.*]]
291; CHECK:       select.false.sink:
292; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[J]], -1
293; CHECK-NEXT:    br label [[SELECT_END1]]
294; CHECK:       select.end:
295; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE_SINK]] ]
296; CHECK-NEXT:    [[SINK:%.*]] = phi ptr [ [[L_I]], [[LOOP]] ], [ [[L_J]], [[SELECT_FALSE_SINK]] ]
297; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
298; CHECK-NEXT:    store ptr [[SINK]], ptr [[GEP_DST]], align 8
299; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
300; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
301; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
302; CHECK:       exit:
303; CHECK-NEXT:    ret void
304;
305entry:
306  br label %loop
307
308loop:
309  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
310  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
311  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
312  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
313  %l.i = load ptr, ptr %gep.i, align 8
314  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
315  %l.j = load ptr, ptr %gep.j, align 8
316  %cmp3 = icmp ult ptr %l.i, %l.j
317  %not.cmp3 = xor i1 %cmp3, true
318  %dec = sext i1 %not.cmp3 to i64
319  %j.next = add nsw i64 %j, %dec
320  %sink = select i1 %cmp3, ptr %l.i, ptr %l.j
321  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
322  store ptr %sink, ptr %gep.dst, align 8
323  %iv.next = add i64 %iv, 1
324  %ec = icmp eq i64 %iv, %j.start
325  br i1 %ec, label %exit, label %loop
326
327exit:
328  ret void
329}
330
331define void @test_add_sext_not_and_regular_select2(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
332; CHECK-LABEL: @test_add_sext_not_and_regular_select2(
333; CHECK-NEXT:  entry:
334; CHECK-NEXT:    br label [[LOOP:%.*]]
335; CHECK:       loop:
336; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ]
337; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ]
338; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ]
339; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
340; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX1]], align 8
341; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
342; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[ARRAYIDX2]], align 8
343; CHECK-NEXT:    [[ARRAYIDX_I:%.*]] = getelementptr inbounds i64, ptr [[TMP0]], i64 [[P:%.*]]
344; CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr [[ARRAYIDX_I]], align 8
345; CHECK-NEXT:    [[ARRAYIDX1_I:%.*]] = getelementptr inbounds i64, ptr [[TMP1]], i64 [[P]]
346; CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr [[ARRAYIDX1_I]], align 8
347; CHECK-NEXT:    [[CMP3:%.*]] = icmp slt i64 [[TMP2]], [[TMP3]]
348; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
349; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE:%.*]]
350; CHECK:       select.false.sink:
351; CHECK-NEXT:    [[TMP5:%.*]] = add nsw i64 [[J]], -1
352; CHECK-NEXT:    br label [[SELECT_END1]]
353; CHECK:       select.end:
354; CHECK-NEXT:    [[DOTSINK:%.*]] = phi ptr [ [[TMP0]], [[LOOP]] ], [ [[TMP1]], [[SELECT_FALSE]] ]
355; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP5]], [[SELECT_FALSE]] ]
356; CHECK-NEXT:    [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
357; CHECK-NEXT:    [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
358; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
359; CHECK-NEXT:    store ptr [[DOTSINK]], ptr [[TMP4]], align 8
360; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
361; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
362; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
363; CHECK:       exit:
364; CHECK-NEXT:    ret void
365;
366entry:
367  br label %loop
368
369loop:
370  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
371  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
372  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
373  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
374  %l.gep.i = load ptr, ptr %gep.i, align 8
375  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
376  %l.gep.j = load ptr, ptr %gep.j, align 8
377  %gep.i.1 = getelementptr inbounds i64, ptr %l.gep.i, i64 %p
378  %2 = load i64, ptr %gep.i.1, align 8
379  %gep.j.1 = getelementptr inbounds i64, ptr %l.gep.j, i64 %p
380  %3 = load i64, ptr %gep.j.1, align 8
381  %cmp3 = icmp slt i64 %2, %3
382  %sel = select i1 %cmp3, ptr %l.gep.i, ptr %l.gep.j
383  %not.cmp3 = xor i1 %cmp3, true
384  %dec = sext i1 %not.cmp3 to i64
385  %j.next = add nsw i64 %j, %dec
386  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
387  store ptr %sel, ptr %gep.dst, align 8
388  %iv.next = add i64 %iv, 1
389  %ec = icmp eq i64 %iv, %j.start
390  br i1 %ec, label %exit, label %loop
391
392exit:
393  ret void
394}
395
396define void @test_sub_zext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
397; CHECK-LABEL: @test_sub_zext(
398; CHECK-NEXT:  entry:
399; CHECK-NEXT:    br label [[LOOP:%.*]]
400; CHECK:       loop:
401; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
402; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
403; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
404; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
405; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
406; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
407; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
408; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
409; CHECK-NEXT:    [[DEC:%.*]] = zext i1 [[CMP3]] to i64
410; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
411; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END]]
412; CHECK:       select.true.sink:
413; CHECK-NEXT:    [[TMP0:%.*]] = sub nsw i64 [[J]], 1
414; CHECK-NEXT:    br label [[SELECT_END]]
415; CHECK:       select.end:
416; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[TMP0]], [[SELECT_TRUE_SINK]] ], [ [[J]], [[LOOP]] ]
417; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
418; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
419; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
420; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
421; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
422; CHECK:       exit:
423; CHECK-NEXT:    ret void
424;
425entry:
426  br label %loop
427
428loop:
429  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
430  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
431  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
432  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
433  %l.i = load ptr, ptr %gep.i, align 8
434  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
435  %l.j = load ptr, ptr %gep.j, align 8
436  %cmp3 = icmp ult ptr %l.i, %l.j
437  %dec = zext i1 %cmp3 to i64
438  %j.next = sub nsw i64 %j, %dec
439  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
440  store i64 %j.next, ptr %gep.dst, align 8
441  %iv.next = add i64 %iv, 1
442  %ec = icmp eq i64 %iv, %j.start
443  br i1 %ec, label %exit, label %loop
444
445exit:
446  ret void
447}
448
449define void @test_sub_zext_first_op(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
450; CHECK-LABEL: @test_sub_zext_first_op(
451; CHECK-NEXT:  entry:
452; CHECK-NEXT:    br label [[LOOP:%.*]]
453; CHECK:       loop:
454; CHECK-NEXT:    [[IV1:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
455; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[J_START:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LOOP]] ]
456; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[LOOP]] ]
457; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
458; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_DST]], align 8
459; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[DST]], i64 [[J]]
460; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
461; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
462; CHECK-NEXT:    [[DEC:%.*]] = zext i1 [[CMP3]] to i64
463; CHECK-NEXT:    [[J_NEXT]] = sub nsw i64 [[DEC]], [[J]]
464; CHECK-NEXT:    [[GEP_DST1:%.*]] = getelementptr inbounds ptr, ptr [[DST1:%.*]], i64 [[IV1]]
465; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST1]], align 8
466; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV1]], 1
467; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV1]], [[J_START]]
468; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
469; CHECK:       exit:
470; CHECK-NEXT:    ret void
471;
472entry:
473  br label %loop
474
475loop:
476  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
477  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
478  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
479  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
480  %l.i = load ptr, ptr %gep.i, align 8
481  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
482  %l.j = load ptr, ptr %gep.j, align 8
483  %cmp3 = icmp ult ptr %l.i, %l.j
484  %dec = zext i1 %cmp3 to i64
485  %j.next = sub nsw i64 %dec, %j
486  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
487  store i64 %j.next, ptr %gep.dst, align 8
488  %iv.next = add i64 %iv, 1
489  %ec = icmp eq i64 %iv, %j.start
490  br i1 %ec, label %exit, label %loop
491
492exit:
493  ret void
494}
495
496define void @test_sub_zext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
497; CHECK-LABEL: @test_sub_zext_not(
498; CHECK-NEXT:  entry:
499; CHECK-NEXT:    br label [[LOOP:%.*]]
500; CHECK:       loop:
501; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
502; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[J_START:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
503; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
504; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
505; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
506; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
507; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
508; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
509; CHECK-NEXT:    [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
510; CHECK-NEXT:    [[DEC:%.*]] = zext i1 [[NOT_CMP3]] to i64
511; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
512; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE_SINK:%.*]]
513; CHECK:       select.false.sink:
514; CHECK-NEXT:    [[TMP0:%.*]] = sub nsw i64 [[J]], 1
515; CHECK-NEXT:    br label [[SELECT_END]]
516; CHECK:       select.end:
517; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE_SINK]] ]
518; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
519; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
520; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
521; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV]], [[J_START]]
522; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
523; CHECK:       exit:
524; CHECK-NEXT:    ret void
525;
526entry:
527  br label %loop
528
529loop:
530  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
531  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
532  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
533  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
534  %l.i = load ptr, ptr %gep.i, align 8
535  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
536  %l.j = load ptr, ptr %gep.j, align 8
537  %cmp3 = icmp ult ptr %l.i, %l.j
538  %not.cmp3 = xor i1 %cmp3, true
539  %dec = zext i1 %not.cmp3 to i64
540  %j.next = sub nsw i64 %j, %dec
541  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
542  store i64 %j.next, ptr %gep.dst, align 8
543  %iv.next = add i64 %iv, 1
544  %ec = icmp eq i64 %iv, %j.start
545  br i1 %ec, label %exit, label %loop
546
547exit:
548  ret void
549}
550
551define void @test_sub_sext(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
552; CHECK-LABEL: @test_sub_sext(
553; CHECK-NEXT:  entry:
554; CHECK-NEXT:    br label [[LOOP:%.*]]
555; CHECK:       loop:
556; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
557; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
558; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
559; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
560; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
561; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
562; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
563; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
564; CHECK-NEXT:    [[DEC:%.*]] = sext i1 [[CMP3]] to i64
565; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
566; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END]]
567; CHECK:       select.true.sink:
568; CHECK-NEXT:    [[TMP0:%.*]] = sub nsw i64 [[J]], -1
569; CHECK-NEXT:    br label [[SELECT_END]]
570; CHECK:       select.end:
571; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[TMP0]], [[SELECT_TRUE_SINK]] ], [ [[J]], [[LOOP]] ]
572; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
573; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
574; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
575; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
576; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
577; CHECK:       exit:
578; CHECK-NEXT:    ret void
579;
580entry:
581  br label %loop
582
583loop:
584  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
585  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
586  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
587  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
588  %l.i = load ptr, ptr %gep.i, align 8
589  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
590  %l.j = load ptr, ptr %gep.j, align 8
591  %cmp3 = icmp ult ptr %l.i, %l.j
592  %dec = sext i1 %cmp3 to i64
593  %j.next = sub nsw i64 %j, %dec
594  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
595  store i64 %j.next, ptr %gep.dst, align 8
596  %iv.next = add i64 %iv, 1
597  %ec = icmp eq i64 %iv, %j.start
598  br i1 %ec, label %exit, label %loop
599
600exit:
601  ret void
602}
603
604define void @test_sub_sext_not(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
605; CHECK-LABEL: @test_sub_sext_not(
606; CHECK-NEXT:  entry:
607; CHECK-NEXT:    br label [[LOOP:%.*]]
608; CHECK:       loop:
609; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
610; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
611; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END]] ]
612; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
613; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
614; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
615; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
616; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
617; CHECK-NEXT:    [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
618; CHECK-NEXT:    [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
619; CHECK-NEXT:    [[NOT_CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
620; CHECK-NEXT:    br i1 [[NOT_CMP3_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]]
621; CHECK:       select.false.sink:
622; CHECK-NEXT:    [[TMP0:%.*]] = sub nsw i64 [[J]], -1
623; CHECK-NEXT:    br label [[SELECT_END]]
624; CHECK:       select.end:
625; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE]] ]
626; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
627; CHECK-NEXT:    store i64 [[J_NEXT]], ptr [[GEP_DST]], align 8
628; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
629; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
630; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
631; CHECK:       exit:
632; CHECK-NEXT:    ret void
633;
634entry:
635  br label %loop
636
637loop:
638  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
639  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
640  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
641  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
642  %l.i = load ptr, ptr %gep.i, align 8
643  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
644  %l.j = load ptr, ptr %gep.j, align 8
645  %cmp3 = icmp ult ptr %l.i, %l.j
646  %not.cmp3 = xor i1 %cmp3, true
647  %dec = sext i1 %not.cmp3 to i64
648  %j.next = sub nsw i64 %j, %dec
649  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
650  store i64 %j.next, ptr %gep.dst, align 8
651  %iv.next = add i64 %iv, 1
652  %ec = icmp eq i64 %iv, %j.start
653  br i1 %ec, label %exit, label %loop
654
655exit:
656  ret void
657}
658
659define void @test_sub_sext_not_and_regular_select(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
660; CHECK-LABEL: @test_sub_sext_not_and_regular_select(
661; CHECK-NEXT:  entry:
662; CHECK-NEXT:    br label [[LOOP:%.*]]
663; CHECK:       loop:
664; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ]
665; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ]
666; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ]
667; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
668; CHECK-NEXT:    [[L_I:%.*]] = load ptr, ptr [[GEP_I]], align 8
669; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
670; CHECK-NEXT:    [[L_J:%.*]] = load ptr, ptr [[GEP_J]], align 8
671; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult ptr [[L_I]], [[L_J]]
672; CHECK-NEXT:    [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
673; CHECK-NEXT:    [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
674; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
675; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE_SINK:%.*]]
676; CHECK:       select.false.sink:
677; CHECK-NEXT:    [[TMP0:%.*]] = sub nsw i64 [[J]], -1
678; CHECK-NEXT:    br label [[SELECT_END1]]
679; CHECK:       select.end:
680; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP0]], [[SELECT_FALSE_SINK]] ]
681; CHECK-NEXT:    [[SINK:%.*]] = phi ptr [ [[L_I]], [[LOOP]] ], [ [[L_J]], [[SELECT_FALSE_SINK]] ]
682; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
683; CHECK-NEXT:    store ptr [[SINK]], ptr [[GEP_DST]], align 8
684; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
685; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
686; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
687; CHECK:       exit:
688; CHECK-NEXT:    ret void
689;
690entry:
691  br label %loop
692
693loop:
694  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
695  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
696  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
697  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
698  %l.i = load ptr, ptr %gep.i, align 8
699  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
700  %l.j = load ptr, ptr %gep.j, align 8
701  %cmp3 = icmp ult ptr %l.i, %l.j
702  %not.cmp3 = xor i1 %cmp3, true
703  %dec = sext i1 %not.cmp3 to i64
704  %j.next = sub nsw i64 %j, %dec
705  %sink = select i1 %cmp3, ptr %l.i, ptr %l.j
706  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
707  store ptr %sink, ptr %gep.dst, align 8
708  %iv.next = add i64 %iv, 1
709  %ec = icmp eq i64 %iv, %j.start
710  br i1 %ec, label %exit, label %loop
711
712exit:
713  ret void
714}
715
716define void @test_sub_sext_not_and_regular_select2(ptr %dst, ptr %src, i64 %j.start, i64 %p, i64 %i.start) {
717; CHECK-LABEL: @test_sub_sext_not_and_regular_select2(
718; CHECK-NEXT:  entry:
719; CHECK-NEXT:    br label [[LOOP:%.*]]
720; CHECK:       loop:
721; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END1:%.*]] ]
722; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[HIGH:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END1]] ]
723; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[J_NEXT]], [[SELECT_END1]] ]
724; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
725; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX1]], align 8
726; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[J]]
727; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[ARRAYIDX2]], align 8
728; CHECK-NEXT:    [[ARRAYIDX_I:%.*]] = getelementptr inbounds i64, ptr [[TMP0]], i64 [[P:%.*]]
729; CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr [[ARRAYIDX_I]], align 8
730; CHECK-NEXT:    [[ARRAYIDX1_I:%.*]] = getelementptr inbounds i64, ptr [[TMP1]], i64 [[P]]
731; CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr [[ARRAYIDX1_I]], align 8
732; CHECK-NEXT:    [[CMP3:%.*]] = icmp slt i64 [[TMP2]], [[TMP3]]
733; CHECK-NEXT:    [[CMP3_FROZEN:%.*]] = freeze i1 [[CMP3]]
734; CHECK-NEXT:    br i1 [[CMP3_FROZEN]], label [[SELECT_END1]], label [[SELECT_FALSE:%.*]]
735; CHECK:       select.false.sink:
736; CHECK-NEXT:    [[TMP5:%.*]] = sub nsw i64 [[J]], -1
737; CHECK-NEXT:    br label [[SELECT_END1]]
738; CHECK:       select.end:
739; CHECK-NEXT:    [[DOTSINK:%.*]] = phi ptr [ [[TMP0]], [[LOOP]] ], [ [[TMP1]], [[SELECT_FALSE]] ]
740; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[LOOP]] ], [ [[TMP5]], [[SELECT_FALSE]] ]
741; CHECK-NEXT:    [[NOT_CMP3:%.*]] = xor i1 [[CMP3]], true
742; CHECK-NEXT:    [[DEC:%.*]] = sext i1 [[NOT_CMP3]] to i64
743; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i64 [[IV]]
744; CHECK-NEXT:    store ptr [[DOTSINK]], ptr [[TMP4]], align 8
745; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
746; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], [[HIGH]]
747; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP]]
748; CHECK:       exit:
749; CHECK-NEXT:    ret void
750;
751entry:
752  br label %loop
753
754loop:
755  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
756  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
757  %i = phi i64 [ %i.start, %entry ], [ %j.next, %loop ]
758  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
759  %l.gep.i = load ptr, ptr %gep.i, align 8
760  %gep.j = getelementptr inbounds ptr, ptr %src, i64 %j
761  %l.gep.j = load ptr, ptr %gep.j, align 8
762  %gep.i.1 = getelementptr inbounds i64, ptr %l.gep.i, i64 %p
763  %2 = load i64, ptr %gep.i.1, align 8
764  %gep.j.1 = getelementptr inbounds i64, ptr %l.gep.j, i64 %p
765  %3 = load i64, ptr %gep.j.1, align 8
766  %cmp3 = icmp slt i64 %2, %3
767  %sel = select i1 %cmp3, ptr %l.gep.i, ptr %l.gep.j
768  %not.cmp3 = xor i1 %cmp3, true
769  %dec = sext i1 %not.cmp3 to i64
770  %j.next = sub nsw i64 %j, %dec
771  %gep.dst = getelementptr inbounds ptr, ptr %dst, i64 %iv
772  store ptr %sel, ptr %gep.dst, align 8
773  %iv.next = add i64 %iv, 1
774  %ec = icmp eq i64 %iv, %j.start
775  br i1 %ec, label %exit, label %loop
776
777exit:
778  ret void
779}
780
781define void @test_add_lshr_add_regular_select(ptr %dst, ptr %src, i64 %i.start, i64 %j.start) {
782; CHECK-LABEL: @test_add_lshr_add_regular_select(
783; CHECK-NEXT:  entry:
784; CHECK-NEXT:    br label [[LOOP:%.*]]
785; CHECK:       loop:
786; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 100000, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
787; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[I_NEXT:%.*]], [[SELECT_END]] ]
788; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[J_START:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
789; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
790; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[GEP_I]], align 8
791; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds i64, ptr [[TMP0]], i64 [[J]]
792; CHECK-NEXT:    [[TMP1:%.*]] = load i64, ptr [[GEP_J]], align 8
793; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[TMP1]], -1
794; CHECK-NEXT:    [[SHIFT:%.*]] = lshr i64 [[TMP1]], 63
795; CHECK-NEXT:    [[CMP_FROZEN:%.*]] = freeze i1 [[CMP]]
796; CHECK-NEXT:    br i1 [[CMP_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_FALSE_SINK:%.*]]
797; CHECK:       select.true.sink:
798; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i64 [[I]], 1
799; CHECK-NEXT:    br label [[SELECT_END]]
800; CHECK:       select.false.sink:
801; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i64 [[J]], 1
802; CHECK-NEXT:    br label [[SELECT_END]]
803; CHECK:       select.end:
804; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[SELECT_TRUE_SINK]] ], [ [[TMP3]], [[SELECT_FALSE_SINK]] ]
805; CHECK-NEXT:    [[I_NEXT]] = phi i64 [ [[TMP2]], [[SELECT_TRUE_SINK]] ], [ [[I]], [[SELECT_FALSE_SINK]] ]
806; CHECK-NEXT:    [[COND:%.*]] = phi i64 [ [[J]], [[SELECT_TRUE_SINK]] ], [ [[I]], [[SELECT_FALSE_SINK]] ]
807; CHECK-NEXT:    [[INC:%.*]] = zext i1 [[CMP]] to i64
808; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr i64, ptr [[DST:%.*]], i64 [[IV]]
809; CHECK-NEXT:    store i64 [[COND]], ptr [[GEP_DST]], align 8
810; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], -1
811; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 0
812; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
813; CHECK:       exit:
814; CHECK-NEXT:    ret void
815;
816entry:
817  br label %loop
818
819loop:
820  %iv = phi i64 [ 100000, %entry ], [ %iv.next, %loop ]
821  %i = phi i64 [ %i.start, %entry ], [ %i.next, %loop ]
822  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
823  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
824  %0 = load ptr, ptr %gep.i, align 8
825  %gep.j = getelementptr inbounds i64, ptr %0, i64 %j
826  %1 = load i64, ptr %gep.j, align 8
827  %cmp = icmp sgt i64 %1, -1
828  %shift = lshr i64 %1, 63
829  %j.next = add nsw i64 %j, %shift
830  %inc = zext i1 %cmp to i64
831  %i.next = add nsw i64 %i, %inc
832  %cond = select i1 %cmp, i64 %j, i64 %i
833  %gep.dst = getelementptr i64, ptr %dst, i64 %iv
834  store i64 %cond, ptr %gep.dst, align 8
835  %iv.next = add nsw i64 %iv, -1
836  %ec = icmp eq i64 %iv.next, 0
837  br i1 %ec, label %exit, label %loop
838
839exit:
840  ret void
841}
842
843define void @test_add_ashr_add_regular_select(ptr %dst, ptr %src, i64 %i.start, i64 %j.start) {
844; CHECK-LABEL: @test_add_ashr_add_regular_select(
845; CHECK-NEXT:  entry:
846; CHECK-NEXT:    br label [[LOOP:%.*]]
847; CHECK:       loop:
848; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 100000, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[SELECT_END:%.*]] ]
849; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_START:%.*]], [[ENTRY]] ], [ [[I_NEXT:%.*]], [[SELECT_END]] ]
850; CHECK-NEXT:    [[J:%.*]] = phi i64 [ [[J_START:%.*]], [[ENTRY]] ], [ [[J_NEXT:%.*]], [[SELECT_END]] ]
851; CHECK-NEXT:    [[GEP_I:%.*]] = getelementptr inbounds ptr, ptr [[SRC:%.*]], i64 [[I]]
852; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[GEP_I]], align 8
853; CHECK-NEXT:    [[GEP_J:%.*]] = getelementptr inbounds i64, ptr [[TMP0]], i64 [[J]]
854; CHECK-NEXT:    [[TMP1:%.*]] = load i64, ptr [[GEP_J]], align 8
855; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[TMP1]], -1
856; CHECK-NEXT:    [[SHIFT:%.*]] = ashr i64 [[TMP1]], 63
857; CHECK-NEXT:    [[CMP_FROZEN:%.*]] = freeze i1 [[CMP]]
858; CHECK-NEXT:    br i1 [[CMP_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_FALSE_SINK:%.*]]
859; CHECK:       select.true.sink:
860; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i64 [[I]], 1
861; CHECK-NEXT:    br label [[SELECT_END]]
862; CHECK:       select.false.sink:
863; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i64 [[J]], -1
864; CHECK-NEXT:    br label [[SELECT_END]]
865; CHECK:       select.end:
866; CHECK-NEXT:    [[J_NEXT]] = phi i64 [ [[J]], [[SELECT_TRUE_SINK]] ], [ [[TMP3]], [[SELECT_FALSE_SINK]] ]
867; CHECK-NEXT:    [[I_NEXT]] = phi i64 [ [[TMP2]], [[SELECT_TRUE_SINK]] ], [ [[I]], [[SELECT_FALSE_SINK]] ]
868; CHECK-NEXT:    [[COND:%.*]] = phi i64 [ [[J]], [[SELECT_TRUE_SINK]] ], [ [[I]], [[SELECT_FALSE_SINK]] ]
869; CHECK-NEXT:    [[INC:%.*]] = zext i1 [[CMP]] to i64
870; CHECK-NEXT:    [[GEP_DST:%.*]] = getelementptr i64, ptr [[DST:%.*]], i64 [[IV]]
871; CHECK-NEXT:    store i64 [[COND]], ptr [[GEP_DST]], align 8
872; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], -1
873; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 0
874; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
875; CHECK:       exit:
876; CHECK-NEXT:    ret void
877;
878entry:
879  br label %loop
880
881loop:
882  %iv = phi i64 [ 100000, %entry ], [ %iv.next, %loop ]
883  %i = phi i64 [ %i.start, %entry ], [ %i.next, %loop ]
884  %j = phi i64 [ %j.start, %entry ], [ %j.next, %loop ]
885  %gep.i = getelementptr inbounds ptr, ptr %src, i64 %i
886  %0 = load ptr, ptr %gep.i, align 8
887  %gep.j = getelementptr inbounds i64, ptr %0, i64 %j
888  %1 = load i64, ptr %gep.j, align 8
889  %cmp = icmp sgt i64 %1, -1
890  %shift = ashr i64 %1, 63
891  %j.next = add nsw i64 %j, %shift
892  %inc = zext i1 %cmp to i64
893  %i.next = add nsw i64 %i, %inc
894  %cond = select i1 %cmp, i64 %j, i64 %i
895  %gep.dst = getelementptr i64, ptr %dst, i64 %iv
896  store i64 %cond, ptr %gep.dst, align 8
897  %iv.next = add nsw i64 %iv, -1
898  %ec = icmp eq i64 %iv.next, 0
899  br i1 %ec, label %exit, label %loop
900
901exit:
902  ret void
903}
904