[llvm] [InstCombine] Try the flipped strictness of predicate in `foldICmpShlConstant` (PR #92773)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Mon May 20 10:26:43 PDT 2024


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/92773

>From fa36954024e7708a7d99d65fe3669bba5926175b Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 20 May 2024 23:00:01 +0800
Subject: [PATCH 1/4] [InstCombine] Add pre-commit tests. NFC.

---
 llvm/test/Transforms/InstCombine/icmp.ll | 78 ++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 2d786c8f48833..6e1a8c2a289f7 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -5198,3 +5198,81 @@ 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:    [[SHL:%.*]] = shl i64 [[X:%.*]], 32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934593
+; 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:    [[SHL:%.*]] = shl nsw i64 [[X:%.*]], 32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934593
+; 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:    [[SHL:%.*]] = shl <2 x i64> [[X:%.*]], <i64 32, i64 32>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i64> [[SHL]], <i64 8589934593, i64 8589934593>
+; 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
+}

>From 91faa84c4ce2fae976e48116805cba27434db2d8 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 20 May 2024 23:04:22 +0800
Subject: [PATCH 2/4] [InstCombine] Try the flipped strictness of predicate in
 `foldICmpShlConstant`.

---
 .../InstCombine/InstCombineCompares.cpp       | 39 +++++++++++++++----
 llvm/test/Transforms/InstCombine/icmp.ll      | 11 +++---
 2 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 542a1c82b127a..f5952362f56bd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2414,14 +2414,37 @@ 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 && DL.isLegalInteger(TypeBits - Amt)) {
+    auto FoldICmpShlToICmpTrunc = [&](ICmpInst::Predicate Pred,
+                                      const APInt &C) -> Instruction * {
+      if (C.countr_zero() < Amt)
+        return nullptr;
+      Type *TruncTy = ShType->getWithNewBitWidth(TypeBits - Amt);
+      Constant *NewC =
+          ConstantInt::get(TruncTy, C.ashr(*ShiftAmt).trunc(TypeBits - Amt));
+      return new ICmpInst(
+          Pred, Builder.CreateTrunc(X, TruncTy, "", Shl->hasNoSignedWrap()),
+          NewC);
+    };
+
+    if (Instruction *Res = FoldICmpShlToICmpTrunc(Pred, C))
+      return Res;
+
+    // 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))) {
+      ICmpInst::Predicate NewPred = FlippedStrictness->first;
+      const APInt &NewC =
+          cast<ConstantInt>(FlippedStrictness->second)->getValue();
+      if (Instruction *Res = FoldICmpShlToICmpTrunc(NewPred, NewC))
+        return Res;
+    }
   }
 
   return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 6e1a8c2a289f7..319e13235ccd6 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -5201,8 +5201,8 @@ define i1 @icmp_freeze_sext(i16 %x, i16 %y) {
 
 define i1 @test_icmp_shl(i64 %x) {
 ; CHECK-LABEL: @test_icmp_shl(
-; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[X:%.*]], 32
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934593
+; 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
@@ -5257,8 +5257,7 @@ define i1 @test_icmp_shl_nuw(i64 %x) {
 
 define i1 @test_icmp_shl_nsw(i64 %x) {
 ; CHECK-LABEL: @test_icmp_shl_nsw(
-; CHECK-NEXT:    [[SHL:%.*]] = shl nsw i64 [[X:%.*]], 32
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[SHL]], 8589934593
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[X:%.*]], 3
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %shl = shl nsw i64 %x, 32
@@ -5268,8 +5267,8 @@ define i1 @test_icmp_shl_nsw(i64 %x) {
 
 define <2 x i1> @test_icmp_shl_vec(<2 x i64> %x) {
 ; CHECK-LABEL: @test_icmp_shl_vec(
-; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i64> [[X:%.*]], <i64 32, i64 32>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i64> [[SHL]], <i64 8589934593, i64 8589934593>
+; 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)

>From bba9b3825bbe503cb51383055fb4dca1ab18304f Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Tue, 21 May 2024 01:00:29 +0800
Subject: [PATCH 3/4] [InstCombine] Address review comments.

---
 .../InstCombine/InstCombineCompares.cpp       | 33 ++++++++++---------
 llvm/test/Transforms/InstCombine/icmp.ll      | 20 +++++++++++
 2 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index f5952362f56bd..3b2521db9622d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2414,7 +2414,8 @@ 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 && DL.isLegalInteger(TypeBits - Amt)) {
+  if (Shl->hasOneUse() && Amt != 0 &&
+      shouldChangeType(ShType->getScalarSizeInBits(), TypeBits - Amt)) {
     auto FoldICmpShlToICmpTrunc = [&](ICmpInst::Predicate Pred,
                                       const APInt &C) -> Instruction * {
       if (C.countr_zero() < Amt)
@@ -2430,20 +2431,22 @@ Instruction *InstCombinerImpl::foldICmpShlConstant(ICmpInst &Cmp,
     if (Instruction *Res = FoldICmpShlToICmpTrunc(Pred, C))
       return Res;
 
-    // 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))) {
-      ICmpInst::Predicate NewPred = FlippedStrictness->first;
-      const APInt &NewC =
-          cast<ConstantInt>(FlippedStrictness->second)->getValue();
-      if (Instruction *Res = FoldICmpShlToICmpTrunc(NewPred, NewC))
-        return Res;
+    if (ICmpInst::isStrictPredicate(Pred)) {
+      // 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))) {
+        ICmpInst::Predicate NewPred = FlippedStrictness->first;
+        const APInt &NewC =
+            cast<ConstantInt>(FlippedStrictness->second)->getValue();
+        if (Instruction *Res = FoldICmpShlToICmpTrunc(NewPred, NewC))
+          return Res;
+      }
     }
   }
 
diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 319e13235ccd6..4dbe2fc88ff71 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -5275,3 +5275,23 @@ define <2 x i1> @test_icmp_shl_vec(<2 x i64> %x) {
   %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
+}

>From c28db82e97c633f9cb70d9c34ab6eef94ffcf10d Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Tue, 21 May 2024 01:26:10 +0800
Subject: [PATCH 4/4] [InstCombine] Simplify code. NFC.

---
 .../InstCombine/InstCombineCompares.cpp       | 34 ++++++++-----------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 3b2521db9622d..49200d02ef339 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2416,22 +2416,10 @@ Instruction *InstCombinerImpl::foldICmpShlConstant(ICmpInst &Cmp,
   unsigned Amt = ShiftAmt->getLimitedValue(TypeBits - 1);
   if (Shl->hasOneUse() && Amt != 0 &&
       shouldChangeType(ShType->getScalarSizeInBits(), TypeBits - Amt)) {
-    auto FoldICmpShlToICmpTrunc = [&](ICmpInst::Predicate Pred,
-                                      const APInt &C) -> Instruction * {
-      if (C.countr_zero() < Amt)
-        return nullptr;
-      Type *TruncTy = ShType->getWithNewBitWidth(TypeBits - Amt);
-      Constant *NewC =
-          ConstantInt::get(TruncTy, C.ashr(*ShiftAmt).trunc(TypeBits - Amt));
-      return new ICmpInst(
-          Pred, Builder.CreateTrunc(X, TruncTy, "", Shl->hasNoSignedWrap()),
-          NewC);
-    };
-
-    if (Instruction *Res = FoldICmpShlToICmpTrunc(Pred, C))
-      return Res;
+    ICmpInst::Predicate CmpPred = Pred;
+    APInt RHSC = C;
 
-    if (ICmpInst::isStrictPredicate(Pred)) {
+    if (RHSC.countr_zero() < Amt && ICmpInst::isStrictPredicate(CmpPred)) {
       // Try the flipped strictness predicate.
       // e.g.:
       // icmp ult i64 (shl X, 32), 8589934593 ->
@@ -2441,13 +2429,19 @@ Instruction *InstCombinerImpl::foldICmpShlConstant(ICmpInst &Cmp,
       if (auto FlippedStrictness =
               InstCombiner::getFlippedStrictnessPredicateAndConstant(
                   Pred, ConstantInt::get(ShType->getContext(), C))) {
-        ICmpInst::Predicate NewPred = FlippedStrictness->first;
-        const APInt &NewC =
-            cast<ConstantInt>(FlippedStrictness->second)->getValue();
-        if (Instruction *Res = FoldICmpShlToICmpTrunc(NewPred, NewC))
-          return Res;
+        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;



More information about the llvm-commits mailing list