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