[llvm] 5c7c1f6 - [InstCombine] Try the flipped strictness of predicate in `foldICmpShlConstant` (#92773)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 27 21:47:30 PDT 2024
Author: Yingwei Zheng
Date: 2024-05-28T12:47:27+08:00
New Revision: 5c7c1f6aba467b1c5a51d58fc591314ecd7147ce
URL: https://github.com/llvm/llvm-project/commit/5c7c1f6aba467b1c5a51d58fc591314ecd7147ce
DIFF: https://github.com/llvm/llvm-project/commit/5c7c1f6aba467b1c5a51d58fc591314ecd7147ce.diff
LOG: [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
https://github.com/llvm/llvm-project/pull/86111#issuecomment-2098203152.
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`).
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/icmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 430f3e12fa5b8..c3272d97509f5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2417,14 +2417,34 @@ Instruction *InstCombinerImpl::foldICmpShlConstant(ICmpInst &Cmp,
// free on the target. It has the additional benefit of comparing to a
// smaller constant that may be more target-friendly.
unsigned Amt = ShiftAmt->getLimitedValue(TypeBits - 1);
- if (Shl->hasOneUse() && Amt != 0 && C.countr_zero() >= Amt &&
- DL.isLegalInteger(TypeBits - Amt)) {
- Type *TruncTy = IntegerType::get(Cmp.getContext(), TypeBits - Amt);
- if (auto *ShVTy = dyn_cast<VectorType>(ShType))
- TruncTy = VectorType::get(TruncTy, ShVTy->getElementCount());
- Constant *NewC =
- ConstantInt::get(TruncTy, C.ashr(*ShiftAmt).trunc(TypeBits - Amt));
- return new ICmpInst(Pred, Builder.CreateTrunc(X, TruncTy), NewC);
+ if (Shl->hasOneUse() && Amt != 0 &&
+ shouldChangeType(ShType->getScalarSizeInBits(), TypeBits - Amt)) {
+ ICmpInst::Predicate CmpPred = Pred;
+ APInt RHSC = C;
+
+ if (RHSC.countr_zero() < Amt && ICmpInst::isStrictPredicate(CmpPred)) {
+ // Try the flipped strictness predicate.
+ // e.g.:
+ // 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
+ if (auto FlippedStrictness =
+ InstCombiner::getFlippedStrictnessPredicateAndConstant(
+ Pred, ConstantInt::get(ShType->getContext(), C))) {
+ CmpPred = FlippedStrictness->first;
+ RHSC = cast<ConstantInt>(FlippedStrictness->second)->getValue();
+ }
+ }
+
+ if (RHSC.countr_zero() >= Amt) {
+ Type *TruncTy = ShType->getWithNewBitWidth(TypeBits - Amt);
+ Constant *NewC =
+ ConstantInt::get(TruncTy, RHSC.ashr(*ShiftAmt).trunc(TypeBits - Amt));
+ return new ICmpInst(
+ CmpPred, Builder.CreateTrunc(X, TruncTy, "", Shl->hasNoSignedWrap()),
+ NewC);
+ }
}
return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 2d786c8f48833..4dbe2fc88ff71 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -5198,3 +5198,100 @@ define i1 @icmp_freeze_sext(i16 %x, i16 %y) {
%cmp2 = icmp uge i16 %ext.fr, %y
ret i1 %cmp2
}
+
+define i1 @test_icmp_shl(i64 %x) {
+; CHECK-LABEL: @test_icmp_shl(
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], 3
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %shl = shl i64 %x, 32
+ %cmp = icmp ult i64 %shl, 8589934593
+ ret i1 %cmp
+}
+
+define i1 @test_icmp_shl_multiuse(i64 %x) {
+; CHECK-LABEL: @test_icmp_shl_multiuse(
+; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[X:%.*]], 32
+; CHECK-NEXT: call void @use_i64(i64 [[SHL]])
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934593
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %shl = shl i64 %x, 32
+ call void @use_i64(i64 %shl)
+ %cmp = icmp ult i64 %shl, 8589934593
+ ret i1 %cmp
+}
+
+define i1 @test_icmp_shl_illegal_length(i64 %x) {
+; CHECK-LABEL: @test_icmp_shl_illegal_length(
+; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[X:%.*]], 31
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934593
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %shl = shl i64 %x, 31
+ %cmp = icmp ult i64 %shl, 8589934593
+ ret i1 %cmp
+}
+
+define i1 @test_icmp_shl_invalid_rhsc(i64 %x) {
+; CHECK-LABEL: @test_icmp_shl_invalid_rhsc(
+; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[X:%.*]], 32
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934595
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %shl = shl i64 %x, 32
+ %cmp = icmp ult i64 %shl, 8589934595
+ ret i1 %cmp
+}
+
+define i1 @test_icmp_shl_nuw(i64 %x) {
+; CHECK-LABEL: @test_icmp_shl_nuw(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[X:%.*]], 3
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %shl = shl nuw i64 %x, 32
+ %cmp = icmp ult i64 %shl, 8589934593
+ ret i1 %cmp
+}
+
+define i1 @test_icmp_shl_nsw(i64 %x) {
+; CHECK-LABEL: @test_icmp_shl_nsw(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[X:%.*]], 3
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %shl = shl nsw i64 %x, 32
+ %cmp = icmp ult i64 %shl, 8589934593
+ ret i1 %cmp
+}
+
+define <2 x i1> @test_icmp_shl_vec(<2 x i64> %x) {
+; CHECK-LABEL: @test_icmp_shl_vec(
+; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i64> [[X:%.*]] to <2 x i32>
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 3, i32 3>
+; CHECK-NEXT: ret <2 x i1> [[CMP]]
+;
+ %shl = shl <2 x i64> %x, splat(i64 32)
+ %cmp = icmp ult <2 x i64> %shl, splat(i64 8589934593)
+ ret <2 x i1> %cmp
+}
+
+define i1 @test_icmp_shl_eq(i64 %x) {
+; CHECK-LABEL: @test_icmp_shl_eq(
+; CHECK-NEXT: ret i1 false
+;
+ %shl = shl i64 %x, 32
+ %cmp = icmp eq i64 %shl, 8589934593
+ ret i1 %cmp
+}
+
+define i1 @test_icmp_shl_sgt(i64 %x) {
+; CHECK-LABEL: @test_icmp_shl_sgt(
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], 1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %shl = shl i64 %x, 32
+ %cmp = icmp sgt i64 %shl, 8589934591
+ ret i1 %cmp
+}
More information about the llvm-commits
mailing list