[llvm] [CVP]: Fold `icmp eq X, C` to `trunc X to i1` if C=2k+1 and X in [2k, 2k+1] (PR #83829)

via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 9 05:01:42 PST 2024


https://github.com/YanWQ-monad updated https://github.com/llvm/llvm-project/pull/83829

>From 411ab902867d158304ababe1f645d85ba120ca19 Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Mon, 4 Mar 2024 19:23:02 +0800
Subject: [PATCH 1/5] [CVP]: Add tests from rust-lang/rust#121673

---
 .../CorrelatedValuePropagation/icmp.ll        | 60 +++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
index 101820a4c65f23..2dde67e274884e 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
@@ -1455,3 +1455,63 @@ entry:
   %select = select i1 %cmp1, i1 %cmp2, i1 false
   ret i1 %select
 }
+
+define i1 @test_icmp_eq_on_valid_bool_range(i8 %x) {
+; CHECK-LABEL: @test_icmp_eq_on_valid_bool_range(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 2
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call i1 @get_bool()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i1 [ [[TMP3]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
+; CHECK-NEXT:    ret i1 [[TMP4]]
+;
+  %1 = icmp ult i8 %x, 2
+  br i1 %1, label %bb1, label %bb2
+
+bb2:
+  %2 = tail call i1 @get_bool()
+  br label %bb3
+
+bb1:
+  %3 = icmp eq i8 %x, 1
+  br label %bb3
+
+bb3:
+  %4 = phi i1 [ %3, %bb1 ], [ %2, %bb2 ]
+  ret i1 %4
+}
+
+define i1 @test_icmp_ne_on_valid_bool_range(i8 %x) {
+; CHECK-LABEL: @test_icmp_ne_on_valid_bool_range(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 2
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call i1 @get_bool()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[X]], 0
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i1 [ [[TMP3]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
+; CHECK-NEXT:    ret i1 [[TMP4]]
+;
+  %1 = icmp ult i8 %x, 2
+  br i1 %1, label %bb1, label %bb2
+
+bb2:
+  %2 = tail call i1 @get_bool()
+  br label %bb3
+
+bb1:
+  %3 = icmp ne i8 %x, 0
+  br label %bb3
+
+bb3:
+  %4 = phi i1 [ %3, %bb1 ], [ %2, %bb2 ]
+  ret i1 %4
+}

>From 2aea11f5bb6490099af4ee630d287e61c763b4a1 Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Mon, 4 Mar 2024 19:30:14 +0800
Subject: [PATCH 2/5] [CVP]: Fold `icmp eq X, C` to `trunc X to i1` if C=2k+1
 and X in [2k, 2k+1]

---
 .../Scalar/CorrelatedValuePropagation.cpp     | 36 +++++++++++++++++++
 .../CorrelatedValuePropagation/icmp.ll        |  8 ++---
 llvm/test/Transforms/JumpThreading/pr33917.ll |  8 ++---
 3 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index 490cb7e528eb6f..73be5f0b016603 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -332,6 +332,39 @@ static bool constantFoldCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
   return true;
 }
 
+/// Given an icmp `icmp eq X, C`,
+/// if we already know that C is 2k+1 and X is in [2k, 2k+1],
+/// then we can fold it to `trunc X to i1`.
+static bool processEqualityICmp(CmpInst *Cmp, LazyValueInfo *LVI) {
+  if (Cmp->getType()->isVectorTy() ||
+      !Cmp->getOperand(0)->getType()->isIntegerTy() || !Cmp->isEquality())
+    return false;
+
+  Value *Op0 = Cmp->getOperand(0);
+  Value *Op1 = Cmp->getOperand(1);
+  ConstantInt *CI = dyn_cast<ConstantInt>(Op1);
+  if (!CI)
+    return false;
+
+  ConstantRange Range =
+      LVI->getConstantRangeAtUse(Cmp->getOperandUse(0), /*UndefAllowed*/ true);
+  APInt RangeSize = Range.getUpper() - Range.getLower();
+  APInt Value = CI->getValue();
+  if (RangeSize != 2 || !Range.contains(Value))
+    return false;
+
+  bool ShouldBeOdd = Cmp->getPredicate() == ICmpInst::Predicate::ICMP_EQ;
+  if ((CI->getValue() & 1) == ShouldBeOdd) {
+    IRBuilder<> B{Cmp};
+    auto *Trunc = B.CreateTruncOrBitCast(Op0, Cmp->getType());
+    Cmp->replaceAllUsesWith(Trunc);
+    Cmp->eraseFromParent();
+    return true;
+  }
+
+  return false;
+}
+
 static bool processCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
   if (constantFoldCmp(Cmp, LVI))
     return true;
@@ -340,6 +373,9 @@ static bool processCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
     if (processICmp(ICmp, LVI))
       return true;
 
+  if (processEqualityICmp(Cmp, LVI))
+      return true;
+
   return false;
 }
 
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
index 2dde67e274884e..ccfbc274d570ce 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
@@ -594,10 +594,10 @@ define void @test_cmp_phi(i8 %a) {
 ; CHECK-NEXT:    br i1 [[C0]], label [[LOOP:%.*]], label [[EXIT:%.*]]
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[P:%.*]] = phi i8 [ [[A]], [[ENTRY:%.*]] ], [ [[B:%.*]], [[LOOP]] ]
-; CHECK-NEXT:    [[C1:%.*]] = icmp ne i8 [[P]], 0
+; CHECK-NEXT:    [[TMP0:%.*]] = trunc i8 [[P]] to i1
 ; CHECK-NEXT:    [[C4:%.*]] = call i1 @get_bool()
 ; CHECK-NEXT:    [[B]] = zext i1 [[C4]] to i8
-; CHECK-NEXT:    br i1 [[C1]], label [[LOOP]], label [[EXIT]]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ;
@@ -1464,7 +1464,7 @@ define i1 @test_icmp_eq_on_valid_bool_range(i8 %x) {
 ; CHECK-NEXT:    [[TMP2:%.*]] = tail call i1 @get_bool()
 ; CHECK-NEXT:    br label [[BB3:%.*]]
 ; CHECK:       bb1:
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i8 [[X]], 1
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i8 [[X]] to i1
 ; CHECK-NEXT:    br label [[BB3]]
 ; CHECK:       bb3:
 ; CHECK-NEXT:    [[TMP4:%.*]] = phi i1 [ [[TMP3]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
@@ -1494,7 +1494,7 @@ define i1 @test_icmp_ne_on_valid_bool_range(i8 %x) {
 ; CHECK-NEXT:    [[TMP2:%.*]] = tail call i1 @get_bool()
 ; CHECK-NEXT:    br label [[BB3:%.*]]
 ; CHECK:       bb1:
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[X]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i8 [[X]] to i1
 ; CHECK-NEXT:    br label [[BB3]]
 ; CHECK:       bb3:
 ; CHECK-NEXT:    [[TMP4:%.*]] = phi i1 [ [[TMP3]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
diff --git a/llvm/test/Transforms/JumpThreading/pr33917.ll b/llvm/test/Transforms/JumpThreading/pr33917.ll
index 7d21a4e1781519..20380c769bf173 100644
--- a/llvm/test/Transforms/JumpThreading/pr33917.ll
+++ b/llvm/test/Transforms/JumpThreading/pr33917.ll
@@ -15,16 +15,16 @@ define void @patatino() personality ptr @rust_eh_personality {
 ; CHECK-LABEL: @patatino(
 ; CHECK-NEXT:  bb9:
 ; CHECK-NEXT:    [[T9:%.*]] = invoke ptr @foo()
-; CHECK-NEXT:    to label [[GOOD:%.*]] unwind label [[BAD:%.*]]
+; CHECK-NEXT:            to label [[GOOD:%.*]] unwind label [[BAD:%.*]]
 ; CHECK:       bad:
 ; CHECK-NEXT:    [[T10:%.*]] = landingpad { ptr, i32 }
-; CHECK-NEXT:    cleanup
+; CHECK-NEXT:            cleanup
 ; CHECK-NEXT:    resume { ptr, i32 } [[T10]]
 ; CHECK:       good:
 ; CHECK-NEXT:    [[T11:%.*]] = icmp ne ptr [[T9]], null
 ; CHECK-NEXT:    [[T12:%.*]] = zext i1 [[T11]] to i64
-; CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[T12]], 1
-; CHECK-NEXT:    br i1 [[COND]], label [[IF_TRUE:%.*]], label [[DONE:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[T12]] to i1
+; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_TRUE:%.*]], label [[DONE:%.*]]
 ; CHECK:       if_true:
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[T11]])
 ; CHECK-NEXT:    br label [[DONE]]

>From bf8d241f6a066d2a8b28ae5a3cf8fa6ea0f19b5f Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Mon, 4 Mar 2024 19:44:54 +0800
Subject: [PATCH 3/5] Fix format

---
 llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index 73be5f0b016603..a3c078d82ee3dc 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -374,7 +374,7 @@ static bool processCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
       return true;
 
   if (processEqualityICmp(Cmp, LVI))
-      return true;
+    return true;
 
   return false;
 }

>From bc03a0809b3649f21f78b8294c2a783b93cb6ac6 Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Mon, 4 Mar 2024 20:28:19 +0800
Subject: [PATCH 4/5] Refactor the code based on review

---
 .../Scalar/CorrelatedValuePropagation.cpp     | 72 +++++++++----------
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index a3c078d82ee3dc..db6309d8b82cd3 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -34,6 +34,7 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Operator.h"
 #include "llvm/IR/PassManager.h"
+#include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Support/Casting.h"
@@ -44,6 +45,7 @@
 #include <utility>
 
 using namespace llvm;
+using namespace llvm::PatternMatch;
 
 #define DEBUG_TYPE "correlated-value-propagation"
 
@@ -285,7 +287,41 @@ static bool processPHI(PHINode *P, LazyValueInfo *LVI, DominatorTree *DT,
   return Changed;
 }
 
+/// Given an icmp `icmp eq X, C`,
+/// if we already know that C is 2k+1 and X is in [2k, 2k+1],
+/// then we can fold it to `trunc X to i1`.
+static bool processEqualityICmp(ICmpInst *Cmp, LazyValueInfo *LVI) {
+  if (Cmp->getType()->isVectorTy() ||
+      !Cmp->getOperand(0)->getType()->isIntegerTy() || !Cmp->isEquality())
+    return false;
+
+  Value *Op0 = Cmp->getOperand(0);
+  const APInt *RHSC;
+  if (!match(Cmp->getOperand(1), m_APInt(RHSC)))
+    return false;
+
+  ConstantRange Range =
+      LVI->getConstantRangeAtUse(Cmp->getOperandUse(0), /*UndefAllowed*/ true);
+  APInt RangeSize = Range.getUpper() - Range.getLower();
+  if (RangeSize != 2 || !Range.contains(*RHSC))
+    return false;
+
+  bool ShouldBeOdd = Cmp->getPredicate() == ICmpInst::Predicate::ICMP_EQ;
+  if ((*RHSC)[0] == ShouldBeOdd) {
+    IRBuilder<> B{Cmp};
+    Value *Trunc = B.CreateTrunc(Op0, Cmp->getType());
+    Cmp->replaceAllUsesWith(Trunc);
+    Cmp->eraseFromParent();
+    return true;
+  }
+
+  return false;
+}
+
 static bool processICmp(ICmpInst *Cmp, LazyValueInfo *LVI) {
+  if (processEqualityICmp(Cmp, LVI))
+    return true;
+
   // Only for signed relational comparisons of scalar integers.
   if (Cmp->getType()->isVectorTy() ||
       !Cmp->getOperand(0)->getType()->isIntegerTy())
@@ -332,39 +368,6 @@ static bool constantFoldCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
   return true;
 }
 
-/// Given an icmp `icmp eq X, C`,
-/// if we already know that C is 2k+1 and X is in [2k, 2k+1],
-/// then we can fold it to `trunc X to i1`.
-static bool processEqualityICmp(CmpInst *Cmp, LazyValueInfo *LVI) {
-  if (Cmp->getType()->isVectorTy() ||
-      !Cmp->getOperand(0)->getType()->isIntegerTy() || !Cmp->isEquality())
-    return false;
-
-  Value *Op0 = Cmp->getOperand(0);
-  Value *Op1 = Cmp->getOperand(1);
-  ConstantInt *CI = dyn_cast<ConstantInt>(Op1);
-  if (!CI)
-    return false;
-
-  ConstantRange Range =
-      LVI->getConstantRangeAtUse(Cmp->getOperandUse(0), /*UndefAllowed*/ true);
-  APInt RangeSize = Range.getUpper() - Range.getLower();
-  APInt Value = CI->getValue();
-  if (RangeSize != 2 || !Range.contains(Value))
-    return false;
-
-  bool ShouldBeOdd = Cmp->getPredicate() == ICmpInst::Predicate::ICMP_EQ;
-  if ((CI->getValue() & 1) == ShouldBeOdd) {
-    IRBuilder<> B{Cmp};
-    auto *Trunc = B.CreateTruncOrBitCast(Op0, Cmp->getType());
-    Cmp->replaceAllUsesWith(Trunc);
-    Cmp->eraseFromParent();
-    return true;
-  }
-
-  return false;
-}
-
 static bool processCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
   if (constantFoldCmp(Cmp, LVI))
     return true;
@@ -373,9 +376,6 @@ static bool processCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
     if (processICmp(ICmp, LVI))
       return true;
 
-  if (processEqualityICmp(Cmp, LVI))
-    return true;
-
   return false;
 }
 

>From ed9cd596e886605a79a820afb8087f79e151e6b8 Mon Sep 17 00:00:00 2001
From: YanWQ-monad <YanWQmonad at gmail.com>
Date: Mon, 4 Mar 2024 20:28:55 +0800
Subject: [PATCH 5/5] Add a test on wrapped set

---
 .../CorrelatedValuePropagation/icmp.ll        | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
index ccfbc274d570ce..47d23d4de6db43 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
@@ -1515,3 +1515,37 @@ bb3:
   %4 = phi i1 [ %3, %bb1 ], [ %2, %bb2 ]
   ret i1 %4
 }
+
+define i1 @test_icmp_ne_on_wrapped_set(i8 %x) {
+; CHECK-LABEL: @test_icmp_ne_on_wrapped_set(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sle i8 [[X:%.*]], -128
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sge i8 [[X]], 127
+; CHECK-NEXT:    [[TMP3:%.*]] = or i1 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    br i1 [[TMP3]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call i1 @get_bool()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i8 [[X]] to i1
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP6:%.*]] = phi i1 [ [[TMP5]], [[BB1]] ], [ [[TMP4]], [[BB2]] ]
+; CHECK-NEXT:    ret i1 [[TMP6]]
+;
+  %1 = icmp sle i8 %x, -128
+  %2 = icmp sge i8 %x, 127
+  %3 = or i1 %1, %2
+  br i1 %3, label %bb1, label %bb2
+
+bb2:
+  %4 = tail call i1 @get_bool()
+  br label %bb3
+
+bb1:
+  %5 = icmp eq i8 %x, 127
+  br label %bb3
+
+bb3:
+  %6 = phi i1 [ %5, %bb1 ], [ %4, %bb2 ]
+  ret i1 %6
+}



More information about the llvm-commits mailing list