1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
7 declare void @llvm.assume(i1)
9 define i1 @t0(i8 %base, i8 %offset) {
11 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
12 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
13 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
14 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
15 ; CHECK-NEXT: ret i1 [[TMP2]]
17 %adjusted = add i8 %base, %offset
18 call void @use8(i8 %adjusted)
19 %not_null = icmp ne i8 %adjusted, 0
20 %no_underflow = icmp ule i8 %adjusted, %base
21 %r = and i1 %not_null, %no_underflow
25 define i1 @t0_logical(i8 %base, i8 %offset) {
26 ; CHECK-LABEL: @t0_logical(
27 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
28 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
29 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
30 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
31 ; CHECK-NEXT: ret i1 [[TMP2]]
33 %adjusted = add i8 %base, %offset
34 call void @use8(i8 %adjusted)
35 %not_null = icmp ne i8 %adjusted, 0
36 %no_underflow = icmp ule i8 %adjusted, %base
37 %r = select i1 %not_null, i1 %no_underflow, i1 false
41 ; We need to produce extra instruction, so one of icmp's must go away.
42 define i1 @t1_oneuse0(i8 %base, i8 %offset) {
43 ; CHECK-LABEL: @t1_oneuse0(
44 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
45 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
46 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
47 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])
48 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
49 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
50 ; CHECK-NEXT: ret i1 [[TMP2]]
52 %adjusted = add i8 %base, %offset
53 call void @use8(i8 %adjusted)
54 %not_null = icmp ne i8 %adjusted, 0
55 call void @use1(i1 %not_null)
56 %no_underflow = icmp ule i8 %adjusted, %base
57 %r = and i1 %not_null, %no_underflow
61 define i1 @t1_oneuse0_logical(i8 %base, i8 %offset) {
62 ; CHECK-LABEL: @t1_oneuse0_logical(
63 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
64 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
65 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
66 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])
67 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
68 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
69 ; CHECK-NEXT: ret i1 [[TMP2]]
71 %adjusted = add i8 %base, %offset
72 call void @use8(i8 %adjusted)
73 %not_null = icmp ne i8 %adjusted, 0
74 call void @use1(i1 %not_null)
75 %no_underflow = icmp ule i8 %adjusted, %base
76 %r = select i1 %not_null, i1 %no_underflow, i1 false
79 define i1 @t2_oneuse1(i8 %base, i8 %offset) {
80 ; CHECK-LABEL: @t2_oneuse1(
81 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
82 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
83 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[ADJUSTED]], [[BASE]]
84 ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])
85 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
86 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
87 ; CHECK-NEXT: ret i1 [[TMP2]]
89 %adjusted = add i8 %base, %offset
90 call void @use8(i8 %adjusted)
91 %not_null = icmp ne i8 %adjusted, 0
92 %no_underflow = icmp ule i8 %adjusted, %base
93 call void @use1(i1 %no_underflow)
94 %r = and i1 %not_null, %no_underflow
98 define i1 @t2_oneuse1_logical(i8 %base, i8 %offset) {
99 ; CHECK-LABEL: @t2_oneuse1_logical(
100 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
101 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
102 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[ADJUSTED]], [[BASE]]
103 ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])
104 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
105 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
106 ; CHECK-NEXT: ret i1 [[TMP2]]
108 %adjusted = add i8 %base, %offset
109 call void @use8(i8 %adjusted)
110 %not_null = icmp ne i8 %adjusted, 0
111 %no_underflow = icmp ule i8 %adjusted, %base
112 call void @use1(i1 %no_underflow)
113 %r = select i1 %not_null, i1 %no_underflow, i1 false
116 define i1 @n3_oneuse2_bad(i8 %base, i8 %offset) {
117 ; CHECK-LABEL: @n3_oneuse2_bad(
118 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
119 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
120 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
121 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])
122 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[ADJUSTED]], [[BASE]]
123 ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])
124 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]
125 ; CHECK-NEXT: ret i1 [[R]]
127 %adjusted = add i8 %base, %offset
128 call void @use8(i8 %adjusted)
129 %not_null = icmp ne i8 %adjusted, 0
130 call void @use1(i1 %not_null)
131 %no_underflow = icmp ule i8 %adjusted, %base
132 call void @use1(i1 %no_underflow)
133 %r = and i1 %not_null, %no_underflow
137 define i1 @n3_oneuse2_bad_logical(i8 %base, i8 %offset) {
138 ; CHECK-LABEL: @n3_oneuse2_bad_logical(
139 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
140 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
141 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
142 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])
143 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[ADJUSTED]], [[BASE]]
144 ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])
145 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]
146 ; CHECK-NEXT: ret i1 [[R]]
148 %adjusted = add i8 %base, %offset
149 call void @use8(i8 %adjusted)
150 %not_null = icmp ne i8 %adjusted, 0
151 call void @use1(i1 %not_null)
152 %no_underflow = icmp ule i8 %adjusted, %base
153 call void @use1(i1 %no_underflow)
154 %r = select i1 %not_null, i1 %no_underflow, i1 false
158 define i1 @t4_commutativity0(i8 %base, i8 %offset) {
159 ; CHECK-LABEL: @t4_commutativity0(
160 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
161 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
162 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
163 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
164 ; CHECK-NEXT: ret i1 [[TMP2]]
166 %adjusted = add i8 %base, %offset
167 call void @use8(i8 %adjusted)
168 %not_null = icmp ne i8 %adjusted, 0
169 %no_underflow = icmp ule i8 %adjusted, %base
170 %r = and i1 %no_underflow, %not_null ; swapped
174 define i1 @t4_commutativity0_logical(i8 %base, i8 %offset) {
175 ; CHECK-LABEL: @t4_commutativity0_logical(
176 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
177 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
178 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
179 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
180 ; CHECK-NEXT: ret i1 [[TMP2]]
182 %adjusted = add i8 %base, %offset
183 call void @use8(i8 %adjusted)
184 %not_null = icmp ne i8 %adjusted, 0
185 %no_underflow = icmp ule i8 %adjusted, %base
186 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped
189 define i1 @t5_commutativity1(i8 %base, i8 %offset) {
190 ; CHECK-LABEL: @t5_commutativity1(
191 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
192 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
193 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
194 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
195 ; CHECK-NEXT: ret i1 [[TMP2]]
197 %adjusted = add i8 %base, %offset
198 call void @use8(i8 %adjusted)
199 %not_null = icmp ne i8 %adjusted, 0
200 %no_underflow = icmp uge i8 %base, %adjusted ; swapped
201 %r = and i1 %not_null, %no_underflow
205 define i1 @t5_commutativity1_logical(i8 %base, i8 %offset) {
206 ; CHECK-LABEL: @t5_commutativity1_logical(
207 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
208 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
209 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
210 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
211 ; CHECK-NEXT: ret i1 [[TMP2]]
213 %adjusted = add i8 %base, %offset
214 call void @use8(i8 %adjusted)
215 %not_null = icmp ne i8 %adjusted, 0
216 %no_underflow = icmp uge i8 %base, %adjusted ; swapped
217 %r = select i1 %not_null, i1 %no_underflow, i1 false
220 define i1 @t6_commutativity3(i8 %base, i8 %offset) {
221 ; CHECK-LABEL: @t6_commutativity3(
222 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
223 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
224 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
225 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
226 ; CHECK-NEXT: ret i1 [[TMP2]]
228 %adjusted = add i8 %base, %offset
229 call void @use8(i8 %adjusted)
230 %not_null = icmp ne i8 %adjusted, 0
231 %no_underflow = icmp uge i8 %base, %adjusted ; swapped
232 %r = and i1 %no_underflow, %not_null ; swapped
236 define i1 @t6_commutativity3_logical(i8 %base, i8 %offset) {
237 ; CHECK-LABEL: @t6_commutativity3_logical(
238 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
239 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
240 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
241 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
242 ; CHECK-NEXT: ret i1 [[TMP2]]
244 %adjusted = add i8 %base, %offset
245 call void @use8(i8 %adjusted)
246 %not_null = icmp ne i8 %adjusted, 0
247 %no_underflow = icmp uge i8 %base, %adjusted ; swapped
248 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped
252 ; We could have the opposite question, did we get null or overflow happened?
253 define i1 @t7(i8 %base, i8 %offset) {
255 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
256 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
257 ; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[ADJUSTED]], -1
258 ; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[BASE]]
259 ; CHECK-NEXT: ret i1 [[TMP2]]
261 %adjusted = add i8 %base, %offset
262 call void @use8(i8 %adjusted)
263 %not_null = icmp eq i8 %adjusted, 0
264 %no_underflow = icmp ugt i8 %adjusted, %base
265 %r = or i1 %not_null, %no_underflow
269 define i1 @t7_logical(i8 %base, i8 %offset) {
270 ; CHECK-LABEL: @t7_logical(
271 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
272 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
273 ; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[ADJUSTED]], -1
274 ; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[BASE]]
275 ; CHECK-NEXT: ret i1 [[TMP2]]
277 %adjusted = add i8 %base, %offset
278 call void @use8(i8 %adjusted)
279 %not_null = icmp eq i8 %adjusted, 0
280 %no_underflow = icmp ugt i8 %adjusted, %base
281 %r = select i1 %not_null, i1 true, i1 %no_underflow
285 ; The comparison can be with any of the values being added.
286 define i1 @t8(i8 %base, i8 %offset) {
288 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
289 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
290 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
291 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
292 ; CHECK-NEXT: ret i1 [[TMP2]]
294 %adjusted = add i8 %base, %offset
295 call void @use8(i8 %adjusted)
296 %not_null = icmp ne i8 %adjusted, 0
297 %no_underflow = icmp ule i8 %adjusted, %offset
298 %r = and i1 %not_null, %no_underflow
302 define i1 @t8_logical(i8 %base, i8 %offset) {
303 ; CHECK-LABEL: @t8_logical(
304 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
305 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
306 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
307 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
308 ; CHECK-NEXT: ret i1 [[TMP2]]
310 %adjusted = add i8 %base, %offset
311 call void @use8(i8 %adjusted)
312 %not_null = icmp ne i8 %adjusted, 0
313 %no_underflow = icmp ule i8 %adjusted, %offset
314 %r = select i1 %not_null, i1 %no_underflow, i1 false