@@ -375,3 +375,150 @@ define i1 @sdiv_eq_smin_use(i32 %x, i32 %y) {
375
375
%r = icmp eq i32 %d , -2147483648
376
376
ret i1 %r
377
377
}
378
+
379
+ ; Fold (X / C) cmp X into X ~cmp 0 (~cmp is the inverse predicate of cmp), for some C != 1
380
+ ; Alternative form of this fold is when division is replaced with logic right shift
381
+
382
+ define i1 @sdiv_x_by_const_cmp_x (i32 %x ) {
383
+ ; CHECK-LABEL: @sdiv_x_by_const_cmp_x(
384
+ ; CHECK-NEXT: [[V:%.*]] = sdiv i32 [[X:%.*]], 13
385
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[V]], [[X]]
386
+ ; CHECK-NEXT: ret i1 [[TMP1]]
387
+ ;
388
+ %v = sdiv i32 %x , 13
389
+ %r = icmp eq i32 %v , %x
390
+ ret i1 %r
391
+ }
392
+
393
+ define i1 @udiv_x_by_const_cmp_x (i32 %x ) {
394
+ ; CHECK-LABEL: @udiv_x_by_const_cmp_x(
395
+ ; CHECK-NEXT: [[TMP2:%.*]] = udiv i32 [[X:%.*]], 123
396
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP2]], [[X]]
397
+ ; CHECK-NEXT: ret i1 [[TMP1]]
398
+ ;
399
+ %1 = udiv i32 %x , 123
400
+ %2 = icmp slt i32 %1 , %x
401
+ ret i1 %2
402
+ }
403
+
404
+ ; Same as above but with right shift instead of division (C != 0)
405
+
406
+ define i1 @lshr_x_by_const_cmp_x (i32 %x ) {
407
+ ; CHECK-LABEL: @lshr_x_by_const_cmp_x(
408
+ ; CHECK-NEXT: [[V:%.*]] = lshr i32 [[X:%.*]], 1
409
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[V]], [[X]]
410
+ ; CHECK-NEXT: ret i1 [[TMP1]]
411
+ ;
412
+ %v = lshr i32 %x , 1
413
+ %r = icmp eq i32 %v , %x
414
+ ret i1 %r
415
+ }
416
+
417
+ define <4 x i1 > @lshr_by_const_cmp_sle_value (<4 x i32 > %x ) {
418
+ ; CHECK-LABEL: @lshr_by_const_cmp_sle_value(
419
+ ; CHECK-NEXT: [[V:%.*]] = lshr <4 x i32> [[X:%.*]], <i32 3, i32 3, i32 3, i32 3>
420
+ ; CHECK-NEXT: [[R:%.*]] = icmp sle <4 x i32> [[V]], [[X]]
421
+ ; CHECK-NEXT: ret <4 x i1> [[R]]
422
+ ;
423
+ %v = lshr <4 x i32 > %x , <i32 3 , i32 3 , i32 3 , i32 3 >
424
+ %r = icmp sle <4 x i32 > %v , %x
425
+ ret <4 x i1 > %r
426
+ }
427
+
428
+ define i1 @lshr_by_const_cmp_uge_value (i32 %x ) {
429
+ ; CHECK-LABEL: @lshr_by_const_cmp_uge_value(
430
+ ; CHECK-NEXT: [[V:%.*]] = lshr i32 [[X:%.*]], 3
431
+ ; CHECK-NEXT: [[R:%.*]] = icmp sle i32 [[V]], [[X]]
432
+ ; CHECK-NEXT: ret i1 [[R]]
433
+ ;
434
+ %v = lshr i32 %x , 3
435
+ %r = icmp sle i32 %v , %x
436
+ ret i1 %r
437
+ }
438
+
439
+ define i1 @ashr_x_by_const_cmp_sge_x (i32 %x ) {
440
+ ; CHECK-LABEL: @ashr_x_by_const_cmp_sge_x(
441
+ ; CHECK-NEXT: [[V:%.*]] = ashr i32 [[X:%.*]], 5
442
+ ; CHECK-NEXT: [[R:%.*]] = icmp sge i32 [[V]], [[X]]
443
+ ; CHECK-NEXT: ret i1 [[R]]
444
+ ;
445
+ %v = ashr i32 %x , 5
446
+ %r = icmp sge i32 %v , %x
447
+ ret i1 %r
448
+ }
449
+
450
+ ; Negative test - constant is 1
451
+
452
+ define <2 x i1 > @udiv_x_by_const_cmp_eq_value_neg (<2 x i32 > %x ) {
453
+ ; CHECK-LABEL: @udiv_x_by_const_cmp_eq_value_neg(
454
+ ; CHECK-NEXT: [[V:%.*]] = udiv <2 x i32> [[X:%.*]], <i32 1, i32 3>
455
+ ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i32> [[V]], [[X]]
456
+ ; CHECK-NEXT: ret <2 x i1> [[R]]
457
+ ;
458
+ %v = udiv <2 x i32 > %x , <i32 1 , i32 3 >
459
+ %r = icmp eq <2 x i32 > %v , %x
460
+ ret <2 x i1 > %r
461
+ }
462
+
463
+ define <2 x i1 > @sdiv_x_by_const_cmp_eq_value_neg (<2 x i32 > %x ) {
464
+ ; CHECK-LABEL: @sdiv_x_by_const_cmp_eq_value_neg(
465
+ ; CHECK-NEXT: [[V:%.*]] = sdiv <2 x i32> [[X:%.*]], <i32 1, i32 3>
466
+ ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i32> [[V]], [[X]]
467
+ ; CHECK-NEXT: ret <2 x i1> [[R]]
468
+ ;
469
+ %v = sdiv <2 x i32 > %x , <i32 1 , i32 3 >
470
+ %r = icmp eq <2 x i32 > %v , %x
471
+ ret <2 x i1 > %r
472
+ }
473
+
474
+ ; Negative test - constant is 0
475
+
476
+ define <2 x i1 > @lshr_x_by_const_cmp_slt_value_neg (<2 x i32 > %x ) {
477
+ ; CHECK-LABEL: @lshr_x_by_const_cmp_slt_value_neg(
478
+ ; CHECK-NEXT: [[V:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 0, i32 2>
479
+ ; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i32> [[V]], [[X]]
480
+ ; CHECK-NEXT: ret <2 x i1> [[R]]
481
+ ;
482
+ %v = lshr <2 x i32 > %x , <i32 0 , i32 2 >
483
+ %r = icmp slt <2 x i32 > %v , %x
484
+ ret <2 x i1 > %r
485
+ }
486
+
487
+ ; Negative test - unsigned predicate with sdiv
488
+
489
+ define i1 @sdiv_x_by_const_cmp_ult_value_neg (i32 %x ) {
490
+ ; CHECK-LABEL: @sdiv_x_by_const_cmp_ult_value_neg(
491
+ ; CHECK-NEXT: [[V:%.*]] = sdiv i32 [[X:%.*]], 3
492
+ ; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[V]], [[X]]
493
+ ; CHECK-NEXT: ret i1 [[R]]
494
+ ;
495
+ %v = sdiv i32 %x , 3
496
+ %r = icmp ult i32 %v , %x
497
+ ret i1 %r
498
+ }
499
+
500
+ ; Negative case - one of the components of a vector is 1
501
+
502
+ define <4 x i1 > @sdiv_x_by_const_cmp_sgt_value_neg (<4 x i32 > %x ) {
503
+ ; CHECK-LABEL: @sdiv_x_by_const_cmp_sgt_value_neg(
504
+ ; CHECK-NEXT: [[V:%.*]] = sdiv <4 x i32> [[X:%.*]], <i32 1, i32 2, i32 3, i32 4>
505
+ ; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[V]], [[X]]
506
+ ; CHECK-NEXT: ret <4 x i1> [[R]]
507
+ ;
508
+ %v = sdiv <4 x i32 > %x , <i32 1 , i32 2 , i32 3 , i32 4 >
509
+ %r = icmp sgt <4 x i32 > %v , %x
510
+ ret <4 x i1 > %r
511
+ }
512
+
513
+ ; Negative case - ashr only allows sge/slt predicates
514
+
515
+ define i1 @ashr_x_by_const_cmp_sle_value_neg (i32 %x ) {
516
+ ; CHECK-LABEL: @ashr_x_by_const_cmp_sle_value_neg(
517
+ ; CHECK-NEXT: [[V:%.*]] = ashr i32 [[X:%.*]], 3
518
+ ; CHECK-NEXT: [[R:%.*]] = icmp sle i32 [[V]], [[X]]
519
+ ; CHECK-NEXT: ret i1 [[R]]
520
+ ;
521
+ %v = ashr i32 %x , 3
522
+ %r = icmp sle i32 %v , %x
523
+ ret i1 %r
524
+ }
0 commit comments