@@ -375,3 +375,116 @@ 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:%.*]] = udiv i32 [[X:%.*]], 13
385
+ ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[V]], [[X]]
386
+ ; CHECK-NEXT: ret i1 [[TMP1]]
387
+ ;
388
+ %v = udiv 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 2, i32 3, i32 2, i32 4>
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 2 , i32 3 , i32 2 , i32 4 >
424
+ %r = icmp sle <4 x i32 > %v , %x
425
+ ret <4 x i1 > %r
426
+ }
427
+
428
+ define i1 @lshr_by_const_cmp_ule_value (i32 %x ) {
429
+ ; CHECK-LABEL: @lshr_by_const_cmp_ule_value(
430
+ ; CHECK-NEXT: ret i1 true
431
+ ;
432
+ %v = lshr i32 %x , 3
433
+ %r = icmp ule i32 %v , %x
434
+ ret i1 %r
435
+ }
436
+
437
+ ; Negative test - constant is 1
438
+
439
+ define i1 @udiv_by_const_cmp_eq_value_neg (i32 %x ) {
440
+ ; CHECK-LABEL: @udiv_by_const_cmp_eq_value_neg(
441
+ ; CHECK-NEXT: ret i1 true
442
+ ;
443
+ %v = udiv i32 %x , 1
444
+ %r = icmp eq i32 %v , %x
445
+ ret i1 %r
446
+ }
447
+
448
+ define i1 @sdiv_by_const_cmp_eq_value_neg (i32 %x ) {
449
+ ; CHECK-LABEL: @sdiv_by_const_cmp_eq_value_neg(
450
+ ; CHECK-NEXT: ret i1 true
451
+ ;
452
+ %v = sdiv i32 %x , 1
453
+ %r = icmp eq i32 %v , %x
454
+ ret i1 %r
455
+ }
456
+
457
+ ; Negative test - constant is 0
458
+
459
+ define i1 @lshr_by_const_cmp_slt_value_neg (i32 %x ) {
460
+ ; CHECK-LABEL: @lshr_by_const_cmp_slt_value_neg(
461
+ ; CHECK-NEXT: ret i1 false
462
+ ;
463
+ %v = lshr i32 %x , 0
464
+ %r = icmp slt i32 %v , %x
465
+ ret i1 %r
466
+ }
467
+
468
+ ; Negative test - unsigned predicate with sdiv
469
+
470
+ define i1 @sdiv_by_const_cmp_ult_value_neg (i32 %x ) {
471
+ ; CHECK-LABEL: @sdiv_by_const_cmp_ult_value_neg(
472
+ ; CHECK-NEXT: ret i1 false
473
+ ;
474
+ %v = sdiv i32 %x , 1
475
+ %r = icmp ult i32 %v , %x
476
+ ret i1 %r
477
+ }
478
+
479
+ ; Negative case - one of the components of a vector is 1
480
+
481
+ define <4 x i1 > @sdiv_by_const_cmp_sgt_value_neg (<4 x i32 > %x ) {
482
+ ; CHECK-LABEL: @sdiv_by_const_cmp_sgt_value_neg(
483
+ ; CHECK-NEXT: [[V:%.*]] = sdiv <4 x i32> [[X:%.*]], <i32 1, i32 2, i32 3, i32 4>
484
+ ; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[V]], [[X]]
485
+ ; CHECK-NEXT: ret <4 x i1> [[R]]
486
+ ;
487
+ %v = sdiv <4 x i32 > %x , <i32 1 , i32 2 , i32 3 , i32 4 >
488
+ %r = icmp sgt <4 x i32 > %v , %x
489
+ ret <4 x i1 > %r
490
+ }
0 commit comments