Skip to content

Commit 3be8e2c

Browse files
authored
[InstCombine] Prefer to keep power-of-2 constants when combining ashr exact and slt/ult of a constant (#86111)
We have flexibility in what constant to use when combining an `ashr exact` with a slt or ult of a constant, and it's not possible to revisit this decision later in the compilation pipeline after the `ashr exact` is removed. Keeping a constant close to power-of-2 (pow2val + 1) should be no worse than neutral, and in some cases may allow better codegen later on for targets that can more cheaply generate power of 2 (which may be selectable if converting back to setle/setge) or near power of 2 constants. Alive2 proofs: <https://alive2.llvm.org/ce/z/2BmPnq> and <https://alive2.llvm.org/ce/z/DtuhnR>
1 parent 452f439 commit 3be8e2c

File tree

2 files changed

+14
-6
lines changed

2 files changed

+14
-6
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2479,6 +2479,16 @@ Instruction *InstCombinerImpl::foldICmpShrConstant(ICmpInst &Cmp,
24792479
// those conditions rather than checking them. This is difficult because of
24802480
// undef/poison (PR34838).
24812481
if (IsAShr && Shr->hasOneUse()) {
2482+
if (IsExact && (Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_ULT) &&
2483+
(C - 1).isPowerOf2() && C.countLeadingZeros() > ShAmtVal) {
2484+
// When C - 1 is a power of two and the transform can be legally
2485+
// performed, prefer this form so the produced constant is close to a
2486+
// power of two.
2487+
// icmp slt/ult (ashr exact X, ShAmtC), C
2488+
// --> icmp slt/ult X, (C - 1) << ShAmtC) + 1
2489+
APInt ShiftedC = (C - 1).shl(ShAmtVal) + 1;
2490+
return new ICmpInst(Pred, X, ConstantInt::get(ShrTy, ShiftedC));
2491+
}
24822492
if (IsExact || Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_ULT) {
24832493
// When ShAmtC can be shifted losslessly:
24842494
// icmp PRED (ashr exact X, ShAmtC), C --> icmp PRED X, (C << ShAmtC)

llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3379,7 +3379,7 @@ define i1 @ashrslt_01_01_exact(i4 %x) {
33793379

33803380
define i1 @ashrslt_01_02_exact(i4 %x) {
33813381
; CHECK-LABEL: @ashrslt_01_02_exact(
3382-
; CHECK-NEXT: [[C:%.*]] = icmp slt i4 [[X:%.*]], 4
3382+
; CHECK-NEXT: [[C:%.*]] = icmp slt i4 [[X:%.*]], 3
33833383
; CHECK-NEXT: ret i1 [[C]]
33843384
;
33853385
%s = ashr exact i4 %x, 1
@@ -3389,7 +3389,7 @@ define i1 @ashrslt_01_02_exact(i4 %x) {
33893389

33903390
define i1 @ashrslt_01_03_exact(i4 %x) {
33913391
; CHECK-LABEL: @ashrslt_01_03_exact(
3392-
; CHECK-NEXT: [[C:%.*]] = icmp slt i4 [[X:%.*]], 6
3392+
; CHECK-NEXT: [[C:%.*]] = icmp slt i4 [[X:%.*]], 5
33933393
; CHECK-NEXT: ret i1 [[C]]
33943394
;
33953395
%s = ashr exact i4 %x, 1
@@ -3800,11 +3800,9 @@ define i1 @ashrslt_03_15_exact(i4 %x) {
38003800
ret i1 %c
38013801
}
38023802

3803-
; TODO: The resulting compared constant can be safely replaced with one that
3804-
; is closer to a power of two.
38053803
define i1 @ashr_slt_exact_near_pow2_cmpval(i8 %x) {
38063804
; CHECK-LABEL: @ashr_slt_exact_near_pow2_cmpval(
3807-
; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X:%.*]], 10
3805+
; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X:%.*]], 9
38083806
; CHECK-NEXT: ret i1 [[C]]
38093807
;
38103808
%s = ashr exact i8 %x, 1
@@ -3814,7 +3812,7 @@ define i1 @ashr_slt_exact_near_pow2_cmpval(i8 %x) {
38143812

38153813
define i1 @ashr_ult_exact_near_pow2_cmpval(i8 %x) {
38163814
; CHECK-LABEL: @ashr_ult_exact_near_pow2_cmpval(
3817-
; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[X:%.*]], 10
3815+
; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[X:%.*]], 9
38183816
; CHECK-NEXT: ret i1 [[C]]
38193817
;
38203818
%s = ashr exact i8 %x, 1

0 commit comments

Comments
 (0)