[llvm] [CVP] Simplify minmax at use (PR #125341)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sat Feb 1 00:55:15 PST 2025


https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/125341

Address a regression caused by https://github.com/llvm/llvm-project/pull/121958.


>From bac08403c5aafd7f68899ecd0f60df7506887719 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 1 Feb 2025 16:45:00 +0800
Subject: [PATCH 1/2] [CVP] Add pre-commit tests. NFC.

---
 .../CorrelatedValuePropagation/min-max.ll     | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll b/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
index c9ee233b5a4612..601cdc65367f69 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
@@ -355,3 +355,28 @@ define i8 @test_umax_nneg(i8 %a, i8 %b) {
   %ret = call i8 @llvm.umax.i8(i8 %nneg_a, i8 %nneg_b)
   ret i8 %ret
 }
+
+define i64 @test_at_use2(i32 %x) {
+; CHECK-LABEL: @test_at_use2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 -1)
+; CHECK-NEXT:    br i1 [[COND]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[EXT:%.*]] = zext nneg i32 [[SMAX]] to i64
+; CHECK-NEXT:    ret i64 [[EXT]]
+; CHECK:       if.end:
+; CHECK-NEXT:    ret i64 0
+;
+entry:
+  %cond = icmp slt i32 %x, 0
+  %smax = call i32 @llvm.smax.i32(i32 %x, i32 -1)
+  br i1 %cond, label %if.end, label %if.then
+
+if.then:
+  %ext = zext nneg i32 %smax to i64
+  ret i64 %ext
+
+if.end:
+  ret i64 0
+}

>From d5d2f34faeb7045c0cceecfc9af3c291e8af7d75 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 1 Feb 2025 16:52:56 +0800
Subject: [PATCH 2/2] [CVP] Simplify minmax at use

---
 .../Scalar/CorrelatedValuePropagation.cpp     | 73 +++++++++++++------
 .../CorrelatedValuePropagation/min-max.ll     |  3 +-
 2 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index 8e74b8645fad9a..c6faabda0e9231 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -579,38 +579,63 @@ static bool processCmpIntrinsic(CmpIntrinsic *CI, LazyValueInfo *LVI) {
 // See if this min/max intrinsic always picks it's one specific operand.
 // If not, check whether we can canonicalize signed minmax into unsigned version
 static bool processMinMaxIntrinsic(MinMaxIntrinsic *MM, LazyValueInfo *LVI) {
+  bool Changed = false;
   CmpInst::Predicate Pred = CmpInst::getNonStrictPredicate(MM->getPredicate());
-  ConstantRange LHS_CR = LVI->getConstantRangeAtUse(MM->getOperandUse(0),
-                                                    /*UndefAllowed*/ false);
-  ConstantRange RHS_CR = LVI->getConstantRangeAtUse(MM->getOperandUse(1),
-                                                    /*UndefAllowed*/ false);
-  if (LHS_CR.icmp(Pred, RHS_CR)) {
-    ++NumMinMax;
-    MM->replaceAllUsesWith(MM->getLHS());
-    MM->eraseFromParent();
-    return true;
+  for (Use &U : make_early_inc_range(MM->uses())) {
+    ConstantRange LHS_CR =
+        ConstantRange::getEmpty(MM->getType()->getScalarSizeInBits());
+    ConstantRange RHS_CR = LHS_CR;
+    auto *CxtI = cast<Instruction>(U.getUser());
+    if (auto *PN = dyn_cast<PHINode>(CxtI)) {
+      BasicBlock *FromBB = PN->getIncomingBlock(U);
+      LHS_CR = LVI->getConstantRangeOnEdge(MM->getOperand(0), FromBB,
+                                           CxtI->getParent(), CxtI);
+      RHS_CR = LVI->getConstantRangeOnEdge(MM->getOperand(1), FromBB,
+                                           CxtI->getParent(), CxtI);
+    } else {
+      LHS_CR = LVI->getConstantRange(MM->getOperand(0), CxtI,
+                                     /*UndefAllowed=*/false);
+      RHS_CR = LVI->getConstantRange(MM->getOperand(1), CxtI,
+                                     /*UndefAllowed=*/false);
+    }
+    if (LHS_CR.icmp(Pred, RHS_CR)) {
+      Changed = true;
+      ++NumMinMax;
+      U.set(MM->getLHS());
+      continue;
+    }
+    if (RHS_CR.icmp(Pred, LHS_CR)) {
+      Changed = true;
+      ++NumMinMax;
+      U.set(MM->getRHS());
+      continue;
+    }
   }
-  if (RHS_CR.icmp(Pred, LHS_CR)) {
-    ++NumMinMax;
-    MM->replaceAllUsesWith(MM->getRHS());
+
+  if (MM->use_empty()) {
     MM->eraseFromParent();
     return true;
   }
 
-  if (MM->isSigned() &&
-      ConstantRange::areInsensitiveToSignednessOfICmpPredicate(LHS_CR,
-                                                               RHS_CR)) {
-    ++NumSMinMax;
-    IRBuilder<> B(MM);
-    MM->replaceAllUsesWith(B.CreateBinaryIntrinsic(
-        MM->getIntrinsicID() == Intrinsic::smin ? Intrinsic::umin
-                                                : Intrinsic::umax,
-        MM->getLHS(), MM->getRHS()));
-    MM->eraseFromParent();
-    return true;
+  if (MM->isSigned()) {
+    ConstantRange LHS_CR = LVI->getConstantRangeAtUse(MM->getOperandUse(0),
+                                                      /*UndefAllowed=*/false);
+    ConstantRange RHS_CR = LVI->getConstantRangeAtUse(MM->getOperandUse(1),
+                                                      /*UndefAllowed=*/false);
+    if (ConstantRange::areInsensitiveToSignednessOfICmpPredicate(LHS_CR,
+                                                                 RHS_CR)) {
+      ++NumSMinMax;
+      IRBuilder<> B(MM);
+      MM->replaceAllUsesWith(B.CreateBinaryIntrinsic(
+          MM->getIntrinsicID() == Intrinsic::smin ? Intrinsic::umin
+                                                  : Intrinsic::umax,
+          MM->getLHS(), MM->getRHS()));
+      MM->eraseFromParent();
+      return true;
+    }
   }
 
-  return false;
+  return Changed;
 }
 
 // Rewrite this with.overflow intrinsic as non-overflowing.
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll b/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
index 601cdc65367f69..563c813336705b 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
@@ -360,10 +360,9 @@ define i64 @test_at_use2(i32 %x) {
 ; CHECK-LABEL: @test_at_use2(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[X:%.*]], 0
-; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 -1)
 ; CHECK-NEXT:    br i1 [[COND]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    [[EXT:%.*]] = zext nneg i32 [[SMAX]] to i64
+; CHECK-NEXT:    [[EXT:%.*]] = zext nneg i32 [[X]] to i64
 ; CHECK-NEXT:    ret i64 [[EXT]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    ret i64 0



More information about the llvm-commits mailing list