Skip to content

Commit 5c7c1f6

Browse files
authored
[InstCombine] Try the flipped strictness of predicate in foldICmpShlConstant (#92773)
This patch extends the transform `(icmp pred iM (shl iM %v, N), C) -> (icmp pred i(M-N) (trunc %v iM to i(M-N)), (trunc (C>>N))` to handle icmps with the flipped strictness of predicate. See the following case: ``` icmp ult i64 (shl X, 32), 8589934593 -> icmp ule i64 (shl X, 32), 8589934592 -> icmp ule i32 (trunc X, i32), 2 -> icmp ult i32 (trunc X, i32), 3 ``` Fixes the regression introduced by #86111 (comment). Alive2 proofs: https://alive2.llvm.org/ce/z/-sp5n3 `nuw` cannot be propagated as we always use `ashr` here. I don't see the value of fixing this (see the test `test_icmp_shl_nuw`).
1 parent fcffea0 commit 5c7c1f6

File tree

2 files changed

+125
-8
lines changed

2 files changed

+125
-8
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,14 +2417,34 @@ Instruction *InstCombinerImpl::foldICmpShlConstant(ICmpInst &Cmp,
24172417
// free on the target. It has the additional benefit of comparing to a
24182418
// smaller constant that may be more target-friendly.
24192419
unsigned Amt = ShiftAmt->getLimitedValue(TypeBits - 1);
2420-
if (Shl->hasOneUse() && Amt != 0 && C.countr_zero() >= Amt &&
2421-
DL.isLegalInteger(TypeBits - Amt)) {
2422-
Type *TruncTy = IntegerType::get(Cmp.getContext(), TypeBits - Amt);
2423-
if (auto *ShVTy = dyn_cast<VectorType>(ShType))
2424-
TruncTy = VectorType::get(TruncTy, ShVTy->getElementCount());
2425-
Constant *NewC =
2426-
ConstantInt::get(TruncTy, C.ashr(*ShiftAmt).trunc(TypeBits - Amt));
2427-
return new ICmpInst(Pred, Builder.CreateTrunc(X, TruncTy), NewC);
2420+
if (Shl->hasOneUse() && Amt != 0 &&
2421+
shouldChangeType(ShType->getScalarSizeInBits(), TypeBits - Amt)) {
2422+
ICmpInst::Predicate CmpPred = Pred;
2423+
APInt RHSC = C;
2424+
2425+
if (RHSC.countr_zero() < Amt && ICmpInst::isStrictPredicate(CmpPred)) {
2426+
// Try the flipped strictness predicate.
2427+
// e.g.:
2428+
// icmp ult i64 (shl X, 32), 8589934593 ->
2429+
// icmp ule i64 (shl X, 32), 8589934592 ->
2430+
// icmp ule i32 (trunc X, i32), 2 ->
2431+
// icmp ult i32 (trunc X, i32), 3
2432+
if (auto FlippedStrictness =
2433+
InstCombiner::getFlippedStrictnessPredicateAndConstant(
2434+
Pred, ConstantInt::get(ShType->getContext(), C))) {
2435+
CmpPred = FlippedStrictness->first;
2436+
RHSC = cast<ConstantInt>(FlippedStrictness->second)->getValue();
2437+
}
2438+
}
2439+
2440+
if (RHSC.countr_zero() >= Amt) {
2441+
Type *TruncTy = ShType->getWithNewBitWidth(TypeBits - Amt);
2442+
Constant *NewC =
2443+
ConstantInt::get(TruncTy, RHSC.ashr(*ShiftAmt).trunc(TypeBits - Amt));
2444+
return new ICmpInst(
2445+
CmpPred, Builder.CreateTrunc(X, TruncTy, "", Shl->hasNoSignedWrap()),
2446+
NewC);
2447+
}
24282448
}
24292449

24302450
return nullptr;

llvm/test/Transforms/InstCombine/icmp.ll

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5198,3 +5198,100 @@ define i1 @icmp_freeze_sext(i16 %x, i16 %y) {
51985198
%cmp2 = icmp uge i16 %ext.fr, %y
51995199
ret i1 %cmp2
52005200
}
5201+
5202+
define i1 @test_icmp_shl(i64 %x) {
5203+
; CHECK-LABEL: @test_icmp_shl(
5204+
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
5205+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], 3
5206+
; CHECK-NEXT: ret i1 [[CMP]]
5207+
;
5208+
%shl = shl i64 %x, 32
5209+
%cmp = icmp ult i64 %shl, 8589934593
5210+
ret i1 %cmp
5211+
}
5212+
5213+
define i1 @test_icmp_shl_multiuse(i64 %x) {
5214+
; CHECK-LABEL: @test_icmp_shl_multiuse(
5215+
; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[X:%.*]], 32
5216+
; CHECK-NEXT: call void @use_i64(i64 [[SHL]])
5217+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934593
5218+
; CHECK-NEXT: ret i1 [[CMP]]
5219+
;
5220+
%shl = shl i64 %x, 32
5221+
call void @use_i64(i64 %shl)
5222+
%cmp = icmp ult i64 %shl, 8589934593
5223+
ret i1 %cmp
5224+
}
5225+
5226+
define i1 @test_icmp_shl_illegal_length(i64 %x) {
5227+
; CHECK-LABEL: @test_icmp_shl_illegal_length(
5228+
; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[X:%.*]], 31
5229+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934593
5230+
; CHECK-NEXT: ret i1 [[CMP]]
5231+
;
5232+
%shl = shl i64 %x, 31
5233+
%cmp = icmp ult i64 %shl, 8589934593
5234+
ret i1 %cmp
5235+
}
5236+
5237+
define i1 @test_icmp_shl_invalid_rhsc(i64 %x) {
5238+
; CHECK-LABEL: @test_icmp_shl_invalid_rhsc(
5239+
; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[X:%.*]], 32
5240+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934595
5241+
; CHECK-NEXT: ret i1 [[CMP]]
5242+
;
5243+
%shl = shl i64 %x, 32
5244+
%cmp = icmp ult i64 %shl, 8589934595
5245+
ret i1 %cmp
5246+
}
5247+
5248+
define i1 @test_icmp_shl_nuw(i64 %x) {
5249+
; CHECK-LABEL: @test_icmp_shl_nuw(
5250+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[X:%.*]], 3
5251+
; CHECK-NEXT: ret i1 [[CMP]]
5252+
;
5253+
%shl = shl nuw i64 %x, 32
5254+
%cmp = icmp ult i64 %shl, 8589934593
5255+
ret i1 %cmp
5256+
}
5257+
5258+
define i1 @test_icmp_shl_nsw(i64 %x) {
5259+
; CHECK-LABEL: @test_icmp_shl_nsw(
5260+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[X:%.*]], 3
5261+
; CHECK-NEXT: ret i1 [[CMP]]
5262+
;
5263+
%shl = shl nsw i64 %x, 32
5264+
%cmp = icmp ult i64 %shl, 8589934593
5265+
ret i1 %cmp
5266+
}
5267+
5268+
define <2 x i1> @test_icmp_shl_vec(<2 x i64> %x) {
5269+
; CHECK-LABEL: @test_icmp_shl_vec(
5270+
; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i64> [[X:%.*]] to <2 x i32>
5271+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 3, i32 3>
5272+
; CHECK-NEXT: ret <2 x i1> [[CMP]]
5273+
;
5274+
%shl = shl <2 x i64> %x, splat(i64 32)
5275+
%cmp = icmp ult <2 x i64> %shl, splat(i64 8589934593)
5276+
ret <2 x i1> %cmp
5277+
}
5278+
5279+
define i1 @test_icmp_shl_eq(i64 %x) {
5280+
; CHECK-LABEL: @test_icmp_shl_eq(
5281+
; CHECK-NEXT: ret i1 false
5282+
;
5283+
%shl = shl i64 %x, 32
5284+
%cmp = icmp eq i64 %shl, 8589934593
5285+
ret i1 %cmp
5286+
}
5287+
5288+
define i1 @test_icmp_shl_sgt(i64 %x) {
5289+
; CHECK-LABEL: @test_icmp_shl_sgt(
5290+
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
5291+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], 1
5292+
; CHECK-NEXT: ret i1 [[CMP]]
5293+
;
5294+
%shl = shl i64 %x, 32
5295+
%cmp = icmp sgt i64 %shl, 8589934591
5296+
ret i1 %cmp
5297+
}

0 commit comments

Comments
 (0)