1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -aggressive-instcombine -S | FileCheck %s
4 define i32 @fshl(i32 %a, i32 %b, i32 %c) {
7 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
8 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
10 ; CHECK-NEXT: br label [[END]]
12 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[B:%.*]]
13 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[TMP0]], i32 [[C]])
14 ; CHECK-NEXT: ret i32 [[TMP1]]
17 %cmp = icmp eq i32 %c, 0
18 br i1 %cmp, label %end, label %fshbb
22 %shr = lshr i32 %b, %sub
24 %or = or i32 %shr, %shl
28 %cond = phi i32 [ %or, %fshbb ], [ %a, %entry ]
32 define i32 @fshl_commute_phi(i32 %a, i32 %b, i32 %c) {
33 ; CHECK-LABEL: @fshl_commute_phi(
35 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
36 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
38 ; CHECK-NEXT: br label [[END]]
40 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[B:%.*]]
41 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[TMP0]], i32 [[C]])
42 ; CHECK-NEXT: ret i32 [[TMP1]]
45 %cmp = icmp eq i32 %c, 0
46 br i1 %cmp, label %end, label %fshbb
50 %shr = lshr i32 %b, %sub
52 %or = or i32 %shr, %shl
56 %cond = phi i32 [ %a, %entry ], [ %or, %fshbb ]
60 define i32 @fshl_commute_or(i32 %a, i32 %b, i32 %c) {
61 ; CHECK-LABEL: @fshl_commute_or(
63 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
64 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
66 ; CHECK-NEXT: br label [[END]]
68 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[B:%.*]]
69 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[TMP0]], i32 [[C]])
70 ; CHECK-NEXT: ret i32 [[TMP1]]
73 %cmp = icmp eq i32 %c, 0
74 br i1 %cmp, label %end, label %fshbb
78 %shr = lshr i32 %b, %sub
80 %or = or i32 %shl, %shr
84 %cond = phi i32 [ %a, %entry ], [ %or, %fshbb ]
88 ; Verify that the intrinsic is inserted into a valid position.
90 define i32 @fshl_insert_valid_location(i32 %a, i32 %b, i32 %c) {
91 ; CHECK-LABEL: @fshl_insert_valid_location(
93 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
94 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
96 ; CHECK-NEXT: br label [[END]]
98 ; CHECK-NEXT: [[OTHER:%.*]] = phi i32 [ 1, [[FSHBB]] ], [ 2, [[ENTRY:%.*]] ]
99 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[B:%.*]]
100 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[TMP0]], i32 [[C]])
101 ; CHECK-NEXT: [[RES:%.*]] = or i32 [[TMP1]], [[OTHER]]
102 ; CHECK-NEXT: ret i32 [[RES]]
105 %cmp = icmp eq i32 %c, 0
106 br i1 %cmp, label %end, label %fshbb
109 %sub = sub i32 32, %c
110 %shr = lshr i32 %b, %sub
111 %shl = shl i32 %a, %c
112 %or = or i32 %shr, %shl
116 %cond = phi i32 [ %or, %fshbb ], [ %a, %entry ]
117 %other = phi i32 [ 1, %fshbb ], [ 2, %entry ]
118 %res = or i32 %cond, %other
122 define i32 @fshr(i32 %a, i32 %b, i32 %c) {
123 ; CHECK-LABEL: @fshr(
125 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
126 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
128 ; CHECK-NEXT: br label [[END]]
130 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[A:%.*]]
131 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP0]], i32 [[B:%.*]], i32 [[C]])
132 ; CHECK-NEXT: ret i32 [[TMP1]]
135 %cmp = icmp eq i32 %c, 0
136 br i1 %cmp, label %end, label %fshbb
139 %sub = sub i32 32, %c
140 %shl = shl i32 %a, %sub
141 %shr = lshr i32 %b, %c
142 %or = or i32 %shr, %shl
146 %cond = phi i32 [ %or, %fshbb ], [ %b, %entry ]
150 define i32 @fshr_commute_phi(i32 %a, i32 %b, i32 %c) {
151 ; CHECK-LABEL: @fshr_commute_phi(
153 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
154 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
156 ; CHECK-NEXT: br label [[END]]
158 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[A:%.*]]
159 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP0]], i32 [[B:%.*]], i32 [[C]])
160 ; CHECK-NEXT: ret i32 [[TMP1]]
163 %cmp = icmp eq i32 %c, 0
164 br i1 %cmp, label %end, label %fshbb
167 %sub = sub i32 32, %c
168 %shl = shl i32 %a, %sub
169 %shr = lshr i32 %b, %c
170 %or = or i32 %shr, %shl
174 %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
178 define i32 @fshr_commute_or(i32 %a, i32 %b, i32 %c) {
179 ; CHECK-LABEL: @fshr_commute_or(
181 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
182 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
184 ; CHECK-NEXT: br label [[END]]
186 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[A:%.*]]
187 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP0]], i32 [[B:%.*]], i32 [[C]])
188 ; CHECK-NEXT: ret i32 [[TMP1]]
191 %cmp = icmp eq i32 %c, 0
192 br i1 %cmp, label %end, label %fshbb
195 %sub = sub i32 32, %c
196 %shl = shl i32 %a, %sub
197 %shr = lshr i32 %b, %c
198 %or = or i32 %shl, %shr
202 %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
206 ; Negative test - non-power-of-2 might require urem expansion in the backend.
208 define i12 @could_be_fshr_weird_type(i12 %a, i12 %b, i12 %c) {
209 ; CHECK-LABEL: @could_be_fshr_weird_type(
211 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i12 [[C:%.*]], 0
212 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
214 ; CHECK-NEXT: [[SUB:%.*]] = sub i12 12, [[C]]
215 ; CHECK-NEXT: [[SHL:%.*]] = shl i12 [[A:%.*]], [[SUB]]
216 ; CHECK-NEXT: [[SHR:%.*]] = lshr i12 [[B:%.*]], [[C]]
217 ; CHECK-NEXT: [[OR:%.*]] = or i12 [[SHL]], [[SHR]]
218 ; CHECK-NEXT: br label [[END]]
220 ; CHECK-NEXT: [[COND:%.*]] = phi i12 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
221 ; CHECK-NEXT: ret i12 [[COND]]
224 %cmp = icmp eq i12 %c, 0
225 br i1 %cmp, label %end, label %fshbb
228 %sub = sub i12 12, %c
229 %shl = shl i12 %a, %sub
230 %shr = lshr i12 %b, %c
231 %or = or i12 %shl, %shr
235 %cond = phi i12 [ %b, %entry ], [ %or, %fshbb ]
239 ; Negative test - wrong phi ops.
241 define i32 @not_fshr_1(i32 %a, i32 %b, i32 %c) {
242 ; CHECK-LABEL: @not_fshr_1(
244 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
245 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
247 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[C]]
248 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
249 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
250 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
251 ; CHECK-NEXT: br label [[END]]
253 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[C]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
254 ; CHECK-NEXT: ret i32 [[COND]]
257 %cmp = icmp eq i32 %c, 0
258 br i1 %cmp, label %end, label %fshbb
261 %sub = sub i32 32, %c
262 %shl = shl i32 %a, %sub
263 %shr = lshr i32 %b, %c
264 %or = or i32 %shl, %shr
268 %cond = phi i32 [ %c, %entry ], [ %or, %fshbb ]
272 ; Negative test - too many phi ops.
274 define i32 @not_fshr_2(i32 %a, i32 %b, i32 %c, i32 %d) {
275 ; CHECK-LABEL: @not_fshr_2(
277 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
278 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
280 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[C]]
281 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
282 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
283 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
284 ; CHECK-NEXT: [[CMP42:%.*]] = icmp ugt i32 [[OR]], 42
285 ; CHECK-NEXT: br i1 [[CMP42]], label [[END]], label [[BOGUS:%.*]]
287 ; CHECK-NEXT: br label [[END]]
289 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ], [ [[D:%.*]], [[BOGUS]] ]
290 ; CHECK-NEXT: ret i32 [[COND]]
293 %cmp = icmp eq i32 %c, 0
294 br i1 %cmp, label %end, label %fshbb
297 %sub = sub i32 32, %c
298 %shl = shl i32 %a, %sub
299 %shr = lshr i32 %b, %c
300 %or = or i32 %shl, %shr
301 %cmp42 = icmp ugt i32 %or, 42
302 br i1 %cmp42, label %end, label %bogus
308 %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ], [ %d, %bogus ]
312 ; Negative test - wrong cmp (but this should match?).
314 define i32 @not_fshr_3(i32 %a, i32 %b, i32 %c) {
315 ; CHECK-LABEL: @not_fshr_3(
317 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[C:%.*]], 0
318 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
320 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[C]]
321 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
322 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
323 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
324 ; CHECK-NEXT: br label [[END]]
326 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
327 ; CHECK-NEXT: ret i32 [[COND]]
330 %cmp = icmp sle i32 %c, 0
331 br i1 %cmp, label %end, label %fshbb
334 %sub = sub i32 32, %c
335 %shl = shl i32 %a, %sub
336 %shr = lshr i32 %b, %c
337 %or = or i32 %shl, %shr
341 %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
345 ; Negative test - wrong shift.
347 define i32 @not_fshr_4(i32 %a, i32 %b, i32 %c) {
348 ; CHECK-LABEL: @not_fshr_4(
350 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
351 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
353 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[C]]
354 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
355 ; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[B:%.*]], [[C]]
356 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
357 ; CHECK-NEXT: br label [[END]]
359 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
360 ; CHECK-NEXT: ret i32 [[COND]]
363 %cmp = icmp eq i32 %c, 0
364 br i1 %cmp, label %end, label %fshbb
367 %sub = sub i32 32, %c
368 %shl = shl i32 %a, %sub
369 %shr = ashr i32 %b, %c
370 %or = or i32 %shl, %shr
374 %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
378 ; Negative test - wrong shift for rotate (but can be folded to a generic funnel shift).
380 define i32 @not_fshr_5(i32 %a, i32 %b, i32 %c) {
381 ; CHECK-LABEL: @not_fshr_5(
383 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
384 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
386 ; CHECK-NEXT: br label [[END]]
388 ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[C]]
389 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP0]], i32 [[B:%.*]], i32 [[C]])
390 ; CHECK-NEXT: ret i32 [[TMP1]]
393 %cmp = icmp eq i32 %c, 0
394 br i1 %cmp, label %end, label %fshbb
397 %sub = sub i32 32, %c
398 %shl = shl i32 %c, %sub
399 %shr = lshr i32 %b, %c
400 %or = or i32 %shl, %shr
404 %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
408 ; Negative test - wrong sub.
410 define i32 @not_fshr_6(i32 %a, i32 %b, i32 %c) {
411 ; CHECK-LABEL: @not_fshr_6(
413 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
414 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
416 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 8, [[C]]
417 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
418 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
419 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
420 ; CHECK-NEXT: br label [[END]]
422 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
423 ; CHECK-NEXT: ret i32 [[COND]]
426 %cmp = icmp eq i32 %c, 0
427 br i1 %cmp, label %end, label %fshbb
431 %shl = shl i32 %a, %sub
432 %shr = lshr i32 %b, %c
433 %or = or i32 %shl, %shr
437 %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
441 ; Negative test - extra use. Technically, we could transform this
442 ; because it doesn't increase the instruction count, but we're
443 ; being cautious not to cause a potential perf pessimization for
444 ; targets that do not have a fshate instruction.
446 define i32 @could_be_fshr(i32 %a, i32 %b, i32 %c, i32* %p) {
447 ; CHECK-LABEL: @could_be_fshr(
449 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
450 ; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
452 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[C]]
453 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
454 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
455 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
456 ; CHECK-NEXT: store i32 [[OR]], i32* [[P:%.*]], align 4
457 ; CHECK-NEXT: br label [[END]]
459 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
460 ; CHECK-NEXT: ret i32 [[COND]]
463 %cmp = icmp eq i32 %c, 0
464 br i1 %cmp, label %end, label %fshbb
467 %sub = sub i32 32, %c
468 %shl = shl i32 %a, %sub
469 %shr = lshr i32 %b, %c
470 %or = or i32 %shl, %shr
471 store i32 %or, i32* %p
475 %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
479 ; PR48068 - Ensure we don't fold a funnel shift that depends on a shift value that
480 ; can't be hoisted out of a basic block.
481 @a = global i32 0, align 4
485 define i32 @PR48068() {
486 ; CHECK-LABEL: @PR48068(
488 ; CHECK-NEXT: [[CALL:%.*]] = call i32 bitcast (i32 (...)* @i to i32 ()*)()
489 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
490 ; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP0]], 0
491 ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
493 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CALL]], [[TMP0]]
494 ; CHECK-NEXT: [[CALL_I:%.*]] = call i32 bitcast (i32 (...)* @f to i32 ()*)()
495 ; CHECK-NEXT: [[SUB_I:%.*]] = sub nsw i32 32, [[TMP0]]
496 ; CHECK-NEXT: [[SHR_I:%.*]] = lshr i32 [[CALL_I]], [[SUB_I]]
497 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR_I]]
498 ; CHECK-NEXT: br label [[IF_END]]
500 ; CHECK-NEXT: [[H_0:%.*]] = phi i32 [ [[OR]], [[IF_THEN]] ], [ [[CALL]], [[ENTRY:%.*]] ]
501 ; CHECK-NEXT: ret i32 [[H_0]]
504 %call = call i32 bitcast (i32 (...)* @i to i32 ()*)()
505 %0 = load i32, i32* @a, align 4
506 %tobool.not = icmp eq i32 %0, 0
507 br i1 %tobool.not, label %if.end, label %if.then
509 if.then: ; preds = %entry
510 %shl = shl i32 %call, %0
511 %call.i = call i32 bitcast (i32 (...)* @f to i32 ()*)()
512 %sub.i = sub nsw i32 32, %0
513 %shr.i = lshr i32 %call.i, %sub.i
514 %or = or i32 %shl, %shr.i
517 if.end: ; preds = %if.then, %entry
518 %h.0 = phi i32 [ %or, %if.then ], [ %call, %entry ]