[llvm] [InstCombine] Fold zext(X) + C2 pred C -> X + C3 pred C4 (PR #110511)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 16 18:13:55 PDT 2024


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

>From ef2ca06d64756e7c206521dc1118a09e8df09b36 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 30 Sep 2024 20:52:05 +0800
Subject: [PATCH 1/3] [InstCombine] Add pre-commit tests. NFC.

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

diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 0c141d4b8e73aa..61d1b4a3b29264 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -3183,3 +3183,99 @@ define i1 @icmp_of_ucmp_plus_const_with_const(i32 %x, i32 %y) {
   %cmp2 = icmp ult i8 %add, 2
   ret i1 %cmp2
 }
+
+define i1 @zext_range_check_ult(i8 %x) {
+; CHECK-LABEL: @zext_range_check_ult(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], 3
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %conv = zext i8 %x to i32
+  %add = add i32 %conv, -4
+  %cmp = icmp ult i32 %add, 3
+  ret i1 %cmp
+}
+
+; TODO: should be canonicalized to (x - 4) u> 2
+define i1 @zext_range_check_ugt(i8 %x) {
+; CHECK-LABEL: @zext_range_check_ugt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[CONV]], -7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP0]], -3
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %conv = zext i8 %x to i32
+  %add = add i32 %conv, -4
+  %cmp = icmp ugt i32 %add, 2
+  ret i1 %cmp
+}
+
+; TODO: should be canonicalized to (x - 4) u> 2
+define i1 @zext_range_check_ult_alter(i8 %x) {
+; CHECK-LABEL: @zext_range_check_ult_alter(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], -3
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %conv = zext i8 %x to i32
+  %add = add i32 %conv, -7
+  %cmp = icmp ult i32 %add, -3
+  ret i1 %cmp
+}
+
+define i1 @zext_range_check_mergable(i8 %x) {
+; CHECK-LABEL: @zext_range_check_mergable(
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -4
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[ADD]], 3
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[X]], 4
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP1]]
+; CHECK-NEXT:    ret i1 [[COND]]
+;
+  %conv = zext i8 %x to i32
+  %add = add nsw i32 %conv, -4
+  %cmp1 = icmp ult i32 %add, 3
+  %cmp2 = icmp slt i8 %x, 4
+  %cond = select i1 %cmp2, i1 true, i1 %cmp1
+  ret i1 %cond
+}
+
+; Negative tests
+
+define i1 @sext_range_check_ult(i8 %x) {
+; CHECK-LABEL: @sext_range_check_ult(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], 3
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %conv = sext i8 %x to i32
+  %add = add i32 %conv, -4
+  %cmp = icmp ult i32 %add, 3
+  ret i1 %cmp
+}
+
+define i1 @zext_range_check_ult_illegal_type(i7 %x) {
+; CHECK-LABEL: @zext_range_check_ult_illegal_type(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV:%.*]] = zext i7 [[X:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], 3
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %conv = zext i7 %x to i32
+  %add = add i32 %conv, -4
+  %cmp = icmp ult i32 %add, 3
+  ret i1 %cmp
+}

>From 3688da5a637d08b11425779c05582187a41477e7 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 30 Sep 2024 21:31:02 +0800
Subject: [PATCH 2/3] [InstCombine] Fold `zext(X) + C2 u< C -> X + trunc(C2) u<
 trunc(C)`

---
 .../InstCombine/InstCombineCompares.cpp       | 20 +++++++++++++++++++
 llvm/test/Transforms/InstCombine/icmp-add.ll  | 11 +++-------
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 18a6fdcec1728e..949b8349c121a9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3169,6 +3169,26 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
                         Builder.CreateAdd(X, ConstantInt::get(Ty, *C2 - C - 1)),
                         ConstantInt::get(Ty, ~C));
 
+  // zext(V) + C2 <u C -> V + trunc(C2) <u trunc(C) iff C2 s<0 && C s>0
+  Value *V;
+  if (Pred == ICmpInst::ICMP_ULT && match(X, m_ZExt(m_Value(V)))) {
+    Type *NewCmpTy = V->getType();
+    unsigned NewCmpBW = NewCmpTy->getScalarSizeInBits();
+    if (shouldChangeType(Ty, NewCmpTy) &&
+        C2->getSignificantBits() <= NewCmpBW &&
+        C.getSignificantBits() <= NewCmpBW) {
+      APInt TruncatedOffset = C2->trunc(NewCmpBW);
+      APInt TruncatedRHS = C.trunc(NewCmpBW);
+      if (TruncatedOffset.isNegative() && TruncatedRHS.isNonNegative()) {
+        Value *TruncatedOffsetV = ConstantInt::get(NewCmpTy, TruncatedOffset);
+        Value *TruncatedRV = ConstantInt::get(NewCmpTy, TruncatedRHS);
+        return new ICmpInst(ICmpInst::ICMP_ULT,
+                            Builder.CreateAdd(V, TruncatedOffsetV),
+                            TruncatedRV);
+      }
+    }
+  }
+
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 61d1b4a3b29264..2239e48468ee04 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -3187,9 +3187,8 @@ define i1 @icmp_of_ucmp_plus_const_with_const(i32 %x, i32 %y) {
 define i1 @zext_range_check_ult(i8 %x) {
 ; CHECK-LABEL: @zext_range_check_ult(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -4
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], 3
+; CHECK-NEXT:    [[TMP0:%.*]] = add i8 [[X:%.*]], -4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[TMP0]], 3
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
 entry:
@@ -3233,11 +3232,7 @@ entry:
 
 define i1 @zext_range_check_mergable(i8 %x) {
 ; CHECK-LABEL: @zext_range_check_mergable(
-; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -4
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[ADD]], 3
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[X]], 4
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP1]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i8 [[X:%.*]], 7
 ; CHECK-NEXT:    ret i1 [[COND]]
 ;
   %conv = zext i8 %x to i32

>From 56c7d9d569a154e866e201a00272e3c6da472b5a Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 6 Oct 2024 15:26:31 +0800
Subject: [PATCH 3/3] [InstCombine] Convert to using ConstantRange API

---
 .../InstCombine/InstCombineCompares.cpp       | 31 +++++++++++--------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 949b8349c121a9..fa7f63dc3ac1d7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3169,22 +3169,27 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
                         Builder.CreateAdd(X, ConstantInt::get(Ty, *C2 - C - 1)),
                         ConstantInt::get(Ty, ~C));
 
-  // zext(V) + C2 <u C -> V + trunc(C2) <u trunc(C) iff C2 s<0 && C s>0
+  // zext(V) + C2 pred C -> V + C3 pred' C4
   Value *V;
-  if (Pred == ICmpInst::ICMP_ULT && match(X, m_ZExt(m_Value(V)))) {
+  if (match(X, m_ZExt(m_Value(V)))) {
     Type *NewCmpTy = V->getType();
+    unsigned CmpBW = Ty->getScalarSizeInBits();
     unsigned NewCmpBW = NewCmpTy->getScalarSizeInBits();
-    if (shouldChangeType(Ty, NewCmpTy) &&
-        C2->getSignificantBits() <= NewCmpBW &&
-        C.getSignificantBits() <= NewCmpBW) {
-      APInt TruncatedOffset = C2->trunc(NewCmpBW);
-      APInt TruncatedRHS = C.trunc(NewCmpBW);
-      if (TruncatedOffset.isNegative() && TruncatedRHS.isNonNegative()) {
-        Value *TruncatedOffsetV = ConstantInt::get(NewCmpTy, TruncatedOffset);
-        Value *TruncatedRV = ConstantInt::get(NewCmpTy, TruncatedRHS);
-        return new ICmpInst(ICmpInst::ICMP_ULT,
-                            Builder.CreateAdd(V, TruncatedOffsetV),
-                            TruncatedRV);
+    if (shouldChangeType(Ty, NewCmpTy)) {
+      if (auto ZExtCR = CR.exactIntersectWith(ConstantRange(
+              APInt::getZero(CmpBW), APInt::getOneBitSet(CmpBW, NewCmpBW)))) {
+        ConstantRange SrcCR = ZExtCR->truncate(NewCmpBW);
+        CmpInst::Predicate EquivPred;
+        APInt EquivInt;
+        APInt EquivOffset;
+
+        SrcCR.getEquivalentICmp(EquivPred, EquivInt, EquivOffset);
+        return new ICmpInst(
+            EquivPred,
+            EquivOffset.isZero()
+                ? V
+                : Builder.CreateAdd(V, ConstantInt::get(NewCmpTy, EquivOffset)),
+            ConstantInt::get(NewCmpTy, EquivInt));
       }
     }
   }



More information about the llvm-commits mailing list