[llvm] [DAG] Propagate OrZero and DemandedElts for min/max in isKnownToBeAPowerOfTwo (PR #182369)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 2 04:05:34 PDT 2026


https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/182369

>From 50912cb85d2e740c73813e1fd4767292728467d1 Mon Sep 17 00:00:00 2001
From: Dibri Nsofor <dibrinsofor at gmail.com>
Date: Thu, 19 Feb 2026 13:32:34 -0700
Subject: [PATCH 1/6] [SelectionDAG] Propagate OrZero and DemandedElts for
 min/max in isKnownToBeAPowerOfTwo

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  4 +-
 .../AArch64/AArch64SelectionDAGTest.cpp       | 60 +++++++++++++++++++
 2 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 351eb54357a52..d08687a3cff51 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4821,9 +4821,9 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val,
   case ISD::SMAX:
   case ISD::UMIN:
   case ISD::UMAX:
-    return isKnownToBeAPowerOfTwo(Val.getOperand(1), /*OrZero=*/false,
+    return isKnownToBeAPowerOfTwo(Val.getOperand(1), DemandedElts, OrZero,
                                   Depth + 1) &&
-           isKnownToBeAPowerOfTwo(Val.getOperand(0), /*OrZero=*/false,
+           isKnownToBeAPowerOfTwo(Val.getOperand(0), DemandedElts, OrZero,
                                   Depth + 1);
 
   case ISD::SELECT:
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index 12b7763274f6c..7e1a5b1a86113 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -1025,6 +1025,66 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Select) {
       DAG->isKnownToBeAPowerOfTwo(VSelect444Big, DemandAll, /*OrZero=*/true));
 }
 
+TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxOrZero) {
+  SDLoc Loc;
+  auto Cst0 = DAG->getConstant(0, Loc, MVT::i32);
+  auto Cst4 = DAG->getConstant(4, Loc, MVT::i32);
+  auto Cst16 = DAG->getConstant(16, Loc, MVT::i32);
+
+  auto Cond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 1, MVT::i1);
+  auto Select40 = DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst4, Cst0);
+
+  auto UMinSelect16 = DAG->getNode(ISD::UMIN, Loc, MVT::i32, Select40, Cst16);
+  auto SMinSelect16 = DAG->getNode(ISD::SMIN, Loc, MVT::i32, Select40, Cst16);
+
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(Select40, /*OrZero=*/true));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMinSelect16, /*OrZero=*/true));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMinSelect16, /*OrZero=*/true));
+
+  auto VecVT = MVT::v2i16;
+  auto CstVec16 = DAG->getConstant(16, Loc, VecVT);
+  auto Vec04 = DAG->getBuildVector(VecVT, Loc, {Cst0, Cst4});
+  auto Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
+  auto VecCond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 2, MVT::v2i1);
+  auto VSelect0444 =
+      DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec04, Vec44);
+  auto VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, VSelect0444, CstVec16);
+  auto VSMin = DAG->getNode(ISD::SMIN, Loc, VecVT, VSelect0444, CstVec16);
+
+  APInt DemandLo(2, 1);
+  EXPECT_TRUE(
+      DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandLo, /*OrZero=*/true));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandLo, /*OrZero=*/true));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSMin, DemandLo, /*OrZero=*/true));
+}
+
+TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxPositive) {
+  SDLoc Loc;
+  auto Cst4 = DAG->getConstant(4, Loc, MVT::i32);
+  auto Cst8 = DAG->getConstant(8, Loc, MVT::i32);
+  auto Cst16 = DAG->getConstant(16, Loc, MVT::i32);
+
+  auto UMin84 = DAG->getNode(ISD::UMIN, Loc, MVT::i32, Cst8, Cst4);
+  auto SMin168 = DAG->getNode(ISD::SMIN, Loc, MVT::i32, Cst16, Cst8);
+  auto UMax84 = DAG->getNode(ISD::UMAX, Loc, MVT::i32, Cst8, Cst4);
+  auto SMax168 = DAG->getNode(ISD::SMAX, Loc, MVT::i32, Cst16, Cst8);
+
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMin84));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMin168));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMax84));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMax168));
+
+  auto VecVT = MVT::v2i16;
+  auto Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
+  auto Vec88 = DAG->getBuildVector(VecVT, Loc, {Cst8, Cst8});
+  auto VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, Vec44, Vec88);
+  auto VSMax = DAG->getNode(ISD::SMAX, Loc, VecVT, Vec44, Vec88);
+
+  APInt DemandAll(2, 3);
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandAll));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSMax, DemandAll));
+}
+
 TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_BUILD_VECTOR) {
   TargetLowering TL(*TM, *STI);
 

>From 77579b5980bde6d9573fa8f51d21871d70834738 Mon Sep 17 00:00:00 2001
From: Dibri Nsofor <dibrinsofor at gmail.com>
Date: Thu, 19 Feb 2026 14:23:27 -0700
Subject: [PATCH 2/6] [SelectionDAG] Add AArch64 lit regression and remove auto
 in new tests

---
 .../issue-181643-minmax-pow2-or-zero.ll       | 19 +++++++
 .../AArch64/AArch64SelectionDAGTest.cpp       | 56 ++++++++++---------
 2 files changed, 48 insertions(+), 27 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/issue-181643-minmax-pow2-or-zero.ll

diff --git a/llvm/test/CodeGen/AArch64/issue-181643-minmax-pow2-or-zero.ll b/llvm/test/CodeGen/AArch64/issue-181643-minmax-pow2-or-zero.ll
new file mode 100644
index 0000000000000..01a961a6ffbfc
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/issue-181643-minmax-pow2-or-zero.ll
@@ -0,0 +1,19 @@
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 %s -o - | FileCheck %s
+
+declare i32 @llvm.umin.i32(i32, i32)
+
+define i32 @f(i1 %c0, i1 %c1, i32 %x) {
+; CHECK-LABEL: f:
+; CHECK: bic w0, w{{[0-9]+}}, w2
+; CHECK-NOT: add w{{[0-9]+}}, w2, w{{[0-9]+}}
+; CHECK-NOT: and w0, w{{[0-9]+}}, w{{[0-9]+}}
+; CHECK: ret
+entry:
+  %a = select i1 %c0, i32 4, i32 0
+  %e = zext i1 %c1 to i32
+  %b = shl i32 1, %e
+  %y = call i32 @llvm.umin.i32(i32 %a, i32 %b)
+  %sum = add i32 %x, %y
+  %r = and i32 %y, %sum
+  ret i32 %r
+}
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index 7e1a5b1a86113..e0a4aad048cdd 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -1027,29 +1027,31 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Select) {
 
 TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxOrZero) {
   SDLoc Loc;
-  auto Cst0 = DAG->getConstant(0, Loc, MVT::i32);
-  auto Cst4 = DAG->getConstant(4, Loc, MVT::i32);
-  auto Cst16 = DAG->getConstant(16, Loc, MVT::i32);
+  SDValue Cst0 = DAG->getConstant(0, Loc, MVT::i32);
+  SDValue Cst4 = DAG->getConstant(4, Loc, MVT::i32);
+  SDValue Cst16 = DAG->getConstant(16, Loc, MVT::i32);
 
-  auto Cond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 1, MVT::i1);
-  auto Select40 = DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst4, Cst0);
+  SDValue Cond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 1, MVT::i1);
+  SDValue Select40 = DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst4, Cst0);
 
-  auto UMinSelect16 = DAG->getNode(ISD::UMIN, Loc, MVT::i32, Select40, Cst16);
-  auto SMinSelect16 = DAG->getNode(ISD::SMIN, Loc, MVT::i32, Select40, Cst16);
+  SDValue UMinSelect16 =
+      DAG->getNode(ISD::UMIN, Loc, MVT::i32, Select40, Cst16);
+  SDValue SMinSelect16 =
+      DAG->getNode(ISD::SMIN, Loc, MVT::i32, Select40, Cst16);
 
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(Select40, /*OrZero=*/true));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMinSelect16, /*OrZero=*/true));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMinSelect16, /*OrZero=*/true));
 
-  auto VecVT = MVT::v2i16;
-  auto CstVec16 = DAG->getConstant(16, Loc, VecVT);
-  auto Vec04 = DAG->getBuildVector(VecVT, Loc, {Cst0, Cst4});
-  auto Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
-  auto VecCond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 2, MVT::v2i1);
-  auto VSelect0444 =
+  EVT VecVT = MVT::v2i16;
+  SDValue CstVec16 = DAG->getConstant(16, Loc, VecVT);
+  SDValue Vec04 = DAG->getBuildVector(VecVT, Loc, {Cst0, Cst4});
+  SDValue Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
+  SDValue VecCond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 2, MVT::v2i1);
+  SDValue VSelect0444 =
       DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec04, Vec44);
-  auto VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, VSelect0444, CstVec16);
-  auto VSMin = DAG->getNode(ISD::SMIN, Loc, VecVT, VSelect0444, CstVec16);
+  SDValue VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, VSelect0444, CstVec16);
+  SDValue VSMin = DAG->getNode(ISD::SMIN, Loc, VecVT, VSelect0444, CstVec16);
 
   APInt DemandLo(2, 1);
   EXPECT_TRUE(
@@ -1060,25 +1062,25 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxOrZero) {
 
 TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxPositive) {
   SDLoc Loc;
-  auto Cst4 = DAG->getConstant(4, Loc, MVT::i32);
-  auto Cst8 = DAG->getConstant(8, Loc, MVT::i32);
-  auto Cst16 = DAG->getConstant(16, Loc, MVT::i32);
+  SDValue Cst4 = DAG->getConstant(4, Loc, MVT::i32);
+  SDValue Cst8 = DAG->getConstant(8, Loc, MVT::i32);
+  SDValue Cst16 = DAG->getConstant(16, Loc, MVT::i32);
 
-  auto UMin84 = DAG->getNode(ISD::UMIN, Loc, MVT::i32, Cst8, Cst4);
-  auto SMin168 = DAG->getNode(ISD::SMIN, Loc, MVT::i32, Cst16, Cst8);
-  auto UMax84 = DAG->getNode(ISD::UMAX, Loc, MVT::i32, Cst8, Cst4);
-  auto SMax168 = DAG->getNode(ISD::SMAX, Loc, MVT::i32, Cst16, Cst8);
+  SDValue UMin84 = DAG->getNode(ISD::UMIN, Loc, MVT::i32, Cst8, Cst4);
+  SDValue SMin168 = DAG->getNode(ISD::SMIN, Loc, MVT::i32, Cst16, Cst8);
+  SDValue UMax84 = DAG->getNode(ISD::UMAX, Loc, MVT::i32, Cst8, Cst4);
+  SDValue SMax168 = DAG->getNode(ISD::SMAX, Loc, MVT::i32, Cst16, Cst8);
 
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMin84));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMin168));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMax84));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMax168));
 
-  auto VecVT = MVT::v2i16;
-  auto Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
-  auto Vec88 = DAG->getBuildVector(VecVT, Loc, {Cst8, Cst8});
-  auto VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, Vec44, Vec88);
-  auto VSMax = DAG->getNode(ISD::SMAX, Loc, VecVT, Vec44, Vec88);
+  EVT VecVT = MVT::v2i16;
+  SDValue Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
+  SDValue Vec88 = DAG->getBuildVector(VecVT, Loc, {Cst8, Cst8});
+  SDValue VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, Vec44, Vec88);
+  SDValue VSMax = DAG->getNode(ISD::SMAX, Loc, VecVT, Vec44, Vec88);
 
   APInt DemandAll(2, 3);
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandAll));

>From 0070a79da9232242d8d5cd425d31d37c13e9fcff Mon Sep 17 00:00:00 2001
From: Dibri Nsofor <dibrinsofor at gmail.com>
Date: Wed, 25 Feb 2026 12:16:17 -0700
Subject: [PATCH 3/6] preventing const fold with select nodes, pr issues

Signed-off-by: Dibri Nsofor <dibrinsofor at gmail.com>
---
 .../AArch64/AArch64SelectionDAGTest.cpp       | 43 +++++++++++++------
 1 file changed, 31 insertions(+), 12 deletions(-)

diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index e0a4aad048cdd..dba3a1f701688 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -1039,8 +1039,14 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxOrZero) {
   SDValue SMinSelect16 =
       DAG->getNode(ISD::SMIN, Loc, MVT::i32, Select40, Cst16);
 
+  // Select40 can be 0 or 4: not strict pow2, but pow2-or-zero
+  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(Select40, /*OrZero=*/false));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(Select40, /*OrZero=*/true));
+
+  // UMIN/SMIN of pow2-or-zero with pow2 constant: still pow2-or-zero
+  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(UMinSelect16, /*OrZero=*/false));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMinSelect16, /*OrZero=*/true));
+  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SMinSelect16, /*OrZero=*/false));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMinSelect16, /*OrZero=*/true));
 
   EVT VecVT = MVT::v2i16;
@@ -1053,10 +1059,13 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxOrZero) {
   SDValue VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, VSelect0444, CstVec16);
   SDValue VSMin = DAG->getNode(ISD::SMIN, Loc, VecVT, VSelect0444, CstVec16);
 
+  // DemandLo only checks lane 0, which can be 0 or 4
   APInt DemandLo(2, 1);
-  EXPECT_TRUE(
-      DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandLo, /*OrZero=*/true));
+  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandLo, /*OrZero=*/false));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandLo, /*OrZero=*/true));
+  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandLo, /*OrZero=*/false));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandLo, /*OrZero=*/true));
+  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSMin, DemandLo, /*OrZero=*/false));
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSMin, DemandLo, /*OrZero=*/true));
 }
 
@@ -1066,21 +1075,31 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxPositive) {
   SDValue Cst8 = DAG->getConstant(8, Loc, MVT::i32);
   SDValue Cst16 = DAG->getConstant(16, Loc, MVT::i32);
 
-  SDValue UMin84 = DAG->getNode(ISD::UMIN, Loc, MVT::i32, Cst8, Cst4);
-  SDValue SMin168 = DAG->getNode(ISD::SMIN, Loc, MVT::i32, Cst16, Cst8);
-  SDValue UMax84 = DAG->getNode(ISD::UMAX, Loc, MVT::i32, Cst8, Cst4);
-  SDValue SMax168 = DAG->getNode(ISD::SMAX, Loc, MVT::i32, Cst16, Cst8);
+  // Use SELECT with unknown condition to prevent constant folding
+  SDValue Cond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 1, MVT::i1);
+  SDValue Select48 = DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst4, Cst8);
+  SDValue Select816 =
+      DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst8, Cst16);
+
+  SDValue UMin = DAG->getNode(ISD::UMIN, Loc, MVT::i32, Select48, Cst16);
+  SDValue SMin = DAG->getNode(ISD::SMIN, Loc, MVT::i32, Select816, Cst4);
+  SDValue UMax = DAG->getNode(ISD::UMAX, Loc, MVT::i32, Select48, Cst16);
+  SDValue SMax = DAG->getNode(ISD::SMAX, Loc, MVT::i32, Select816, Cst4);
 
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMin84));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMin168));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMax84));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMax168));
+  // All operands are non-zero powers of two, so OrZero=false should work
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMin));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMin));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMax));
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMax));
 
   EVT VecVT = MVT::v2i16;
   SDValue Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
   SDValue Vec88 = DAG->getBuildVector(VecVT, Loc, {Cst8, Cst8});
-  SDValue VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, Vec44, Vec88);
-  SDValue VSMax = DAG->getNode(ISD::SMAX, Loc, VecVT, Vec44, Vec88);
+  SDValue VecCond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 2, MVT::v2i1);
+  SDValue VSelect =
+      DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec44, Vec88);
+  SDValue VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, VSelect, Vec88);
+  SDValue VSMax = DAG->getNode(ISD::SMAX, Loc, VecVT, VSelect, Vec44);
 
   APInt DemandAll(2, 3);
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandAll));

>From fad4f19c8a8f3d1b0055730f6ca73b0ce2c4912f Mon Sep 17 00:00:00 2001
From: Dibri Nsofor <dibrinsofor at gmail.com>
Date: Wed, 25 Feb 2026 12:34:02 -0700
Subject: [PATCH 4/6] Remove old test file with CHECK-NOT assertions

---
 .../issue-181643-minmax-pow2-or-zero.ll       | 19 -------------------
 1 file changed, 19 deletions(-)
 delete mode 100644 llvm/test/CodeGen/AArch64/issue-181643-minmax-pow2-or-zero.ll

diff --git a/llvm/test/CodeGen/AArch64/issue-181643-minmax-pow2-or-zero.ll b/llvm/test/CodeGen/AArch64/issue-181643-minmax-pow2-or-zero.ll
deleted file mode 100644
index 01a961a6ffbfc..0000000000000
--- a/llvm/test/CodeGen/AArch64/issue-181643-minmax-pow2-or-zero.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 %s -o - | FileCheck %s
-
-declare i32 @llvm.umin.i32(i32, i32)
-
-define i32 @f(i1 %c0, i1 %c1, i32 %x) {
-; CHECK-LABEL: f:
-; CHECK: bic w0, w{{[0-9]+}}, w2
-; CHECK-NOT: add w{{[0-9]+}}, w2, w{{[0-9]+}}
-; CHECK-NOT: and w0, w{{[0-9]+}}, w{{[0-9]+}}
-; CHECK: ret
-entry:
-  %a = select i1 %c0, i32 4, i32 0
-  %e = zext i1 %c1 to i32
-  %b = shl i32 1, %e
-  %y = call i32 @llvm.umin.i32(i32 %a, i32 %b)
-  %sum = add i32 %x, %y
-  %r = and i32 %y, %sum
-  ret i32 %r
-}

>From 4d74f1958454f37daa056b44f7f4e467321486a9 Mon Sep 17 00:00:00 2001
From: Dibri Nsofor <dibrinsofor at gmail.com>
Date: Wed, 1 Apr 2026 19:02:20 -0600
Subject: [PATCH 5/6] removed unit tests

Signed-off-by: Dibri Nsofor <dibrinsofor at gmail.com>
---
 .../AArch64/AArch64SelectionDAGTest.cpp       | 81 -------------------
 1 file changed, 81 deletions(-)

diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index dba3a1f701688..12b7763274f6c 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -1025,87 +1025,6 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Select) {
       DAG->isKnownToBeAPowerOfTwo(VSelect444Big, DemandAll, /*OrZero=*/true));
 }
 
-TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxOrZero) {
-  SDLoc Loc;
-  SDValue Cst0 = DAG->getConstant(0, Loc, MVT::i32);
-  SDValue Cst4 = DAG->getConstant(4, Loc, MVT::i32);
-  SDValue Cst16 = DAG->getConstant(16, Loc, MVT::i32);
-
-  SDValue Cond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 1, MVT::i1);
-  SDValue Select40 = DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst4, Cst0);
-
-  SDValue UMinSelect16 =
-      DAG->getNode(ISD::UMIN, Loc, MVT::i32, Select40, Cst16);
-  SDValue SMinSelect16 =
-      DAG->getNode(ISD::SMIN, Loc, MVT::i32, Select40, Cst16);
-
-  // Select40 can be 0 or 4: not strict pow2, but pow2-or-zero
-  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(Select40, /*OrZero=*/false));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(Select40, /*OrZero=*/true));
-
-  // UMIN/SMIN of pow2-or-zero with pow2 constant: still pow2-or-zero
-  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(UMinSelect16, /*OrZero=*/false));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMinSelect16, /*OrZero=*/true));
-  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SMinSelect16, /*OrZero=*/false));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMinSelect16, /*OrZero=*/true));
-
-  EVT VecVT = MVT::v2i16;
-  SDValue CstVec16 = DAG->getConstant(16, Loc, VecVT);
-  SDValue Vec04 = DAG->getBuildVector(VecVT, Loc, {Cst0, Cst4});
-  SDValue Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
-  SDValue VecCond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 2, MVT::v2i1);
-  SDValue VSelect0444 =
-      DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec04, Vec44);
-  SDValue VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, VSelect0444, CstVec16);
-  SDValue VSMin = DAG->getNode(ISD::SMIN, Loc, VecVT, VSelect0444, CstVec16);
-
-  // DemandLo only checks lane 0, which can be 0 or 4
-  APInt DemandLo(2, 1);
-  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandLo, /*OrZero=*/false));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandLo, /*OrZero=*/true));
-  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandLo, /*OrZero=*/false));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandLo, /*OrZero=*/true));
-  EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSMin, DemandLo, /*OrZero=*/false));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSMin, DemandLo, /*OrZero=*/true));
-}
-
-TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_MinMaxPositive) {
-  SDLoc Loc;
-  SDValue Cst4 = DAG->getConstant(4, Loc, MVT::i32);
-  SDValue Cst8 = DAG->getConstant(8, Loc, MVT::i32);
-  SDValue Cst16 = DAG->getConstant(16, Loc, MVT::i32);
-
-  // Use SELECT with unknown condition to prevent constant folding
-  SDValue Cond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 1, MVT::i1);
-  SDValue Select48 = DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst4, Cst8);
-  SDValue Select816 =
-      DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst8, Cst16);
-
-  SDValue UMin = DAG->getNode(ISD::UMIN, Loc, MVT::i32, Select48, Cst16);
-  SDValue SMin = DAG->getNode(ISD::SMIN, Loc, MVT::i32, Select816, Cst4);
-  SDValue UMax = DAG->getNode(ISD::UMAX, Loc, MVT::i32, Select48, Cst16);
-  SDValue SMax = DAG->getNode(ISD::SMAX, Loc, MVT::i32, Select816, Cst4);
-
-  // All operands are non-zero powers of two, so OrZero=false should work
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMin));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMin));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(UMax));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SMax));
-
-  EVT VecVT = MVT::v2i16;
-  SDValue Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
-  SDValue Vec88 = DAG->getBuildVector(VecVT, Loc, {Cst8, Cst8});
-  SDValue VecCond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 2, MVT::v2i1);
-  SDValue VSelect =
-      DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec44, Vec88);
-  SDValue VUMin = DAG->getNode(ISD::UMIN, Loc, VecVT, VSelect, Vec88);
-  SDValue VSMax = DAG->getNode(ISD::SMAX, Loc, VecVT, VSelect, Vec44);
-
-  APInt DemandAll(2, 3);
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VUMin, DemandAll));
-  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSMax, DemandAll));
-}
-
 TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_BUILD_VECTOR) {
   TargetLowering TL(*TM, *STI);
 

>From 2128018c190e1dfd8673f683d7c985fb1a57bfcb Mon Sep 17 00:00:00 2001
From: Dibri Nsofor <dibrinsofor at gmail.com>
Date: Wed, 1 Apr 2026 19:29:36 -0600
Subject: [PATCH 6/6] regenerate ll file with new opts

Signed-off-by: Dibri Nsofor <dibrinsofor at gmail.com>
---
 llvm/test/CodeGen/X86/known-pow2.ll | 32 +++++++++++------------------
 1 file changed, 12 insertions(+), 20 deletions(-)

diff --git a/llvm/test/CodeGen/X86/known-pow2.ll b/llvm/test/CodeGen/X86/known-pow2.ll
index 5c395ec423505..629d7d9e4ae65 100644
--- a/llvm/test/CodeGen/X86/known-pow2.ll
+++ b/llvm/test/CodeGen/X86/known-pow2.ll
@@ -352,7 +352,6 @@ define i1 @pow2_umin(i32 %x, i32 %y) {
 define i32 @pow2_umin_vec(<4 x i32> %x, <4 x i32> %y, i32 %z, ptr %p) {
 ; CHECK-LABEL: pow2_umin_vec:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %edi, %eax
 ; CHECK-NEXT:    pslld $23, %xmm0
 ; CHECK-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
 ; CHECK-NEXT:    cvttps2dq %xmm0, %xmm0
@@ -371,10 +370,9 @@ define i32 @pow2_umin_vec(<4 x i32> %x, <4 x i32> %y, i32 %z, ptr %p) {
 ; CHECK-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
 ; CHECK-NEXT:    por %xmm2, %xmm1
 ; CHECK-NEXT:    movdqa %xmm1, (%rsi)
-; CHECK-NEXT:    movd %xmm1, %ecx
-; CHECK-NEXT:    xorl %edx, %edx
-; CHECK-NEXT:    divl %ecx
-; CHECK-NEXT:    movl %edx, %eax
+; CHECK-NEXT:    movd %xmm1, %eax
+; CHECK-NEXT:    decl %eax
+; CHECK-NEXT:    andl %edi, %eax
 ; CHECK-NEXT:    retq
   %yy = shl <4 x i32> <i32 1, i32 -1, i32 -1, i32 -1>, %x
   %d = call <4 x i32> @llvm.umin.v4i32(<4 x i32> %yy, <4 x i32> splat (i32 256))
@@ -452,7 +450,6 @@ define i1 @pow2_umax(i32 %x, i32 %y, i32 %z) {
 define i32 @pow2_umax_vec(<4 x i32> %x, <4 x i32> %y, i32 %z, ptr %p) {
 ; CHECK-LABEL: pow2_umax_vec:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %edi, %eax
 ; CHECK-NEXT:    pshuflw {{.*#+}} xmm1 = xmm0[2,3,3,3,4,5,6,7]
 ; CHECK-NEXT:    movdqa {{.*#+}} xmm2 = [4096,4294967295,4294967295,4294967295]
 ; CHECK-NEXT:    movdqa %xmm2, %xmm3
@@ -476,10 +473,9 @@ define i32 @pow2_umax_vec(<4 x i32> %x, <4 x i32> %y, i32 %z, ptr %p) {
 ; CHECK-NEXT:    andnps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
 ; CHECK-NEXT:    orps %xmm4, %xmm0
 ; CHECK-NEXT:    movaps %xmm0, (%rsi)
-; CHECK-NEXT:    movd %xmm0, %ecx
-; CHECK-NEXT:    xorl %edx, %edx
-; CHECK-NEXT:    divl %ecx
-; CHECK-NEXT:    movl %edx, %eax
+; CHECK-NEXT:    movd %xmm0, %eax
+; CHECK-NEXT:    decl %eax
+; CHECK-NEXT:    andl %edi, %eax
 ; CHECK-NEXT:    retq
   %yy = lshr <4 x i32> <i32 4096, i32 -1, i32 -1, i32 -1>, %x
   %d = call <4 x i32> @llvm.umax.v4i32(<4 x i32> %yy, <4 x i32> splat (i32 256))
@@ -560,7 +556,6 @@ define i1 @pow2_smin(i32 %x, i32 %y) {
 define i32 @pow2_smin_vec(<4 x i32> %x, <4 x i32> %y, i32 %z, ptr %p) {
 ; CHECK-LABEL: pow2_smin_vec:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %edi, %eax
 ; CHECK-NEXT:    pslld $23, %xmm0
 ; CHECK-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
 ; CHECK-NEXT:    cvttps2dq %xmm0, %xmm0
@@ -578,10 +573,9 @@ define i32 @pow2_smin_vec(<4 x i32> %x, <4 x i32> %y, i32 %z, ptr %p) {
 ; CHECK-NEXT:    pandn %xmm1, %xmm2
 ; CHECK-NEXT:    por %xmm0, %xmm2
 ; CHECK-NEXT:    movdqa %xmm2, (%rsi)
-; CHECK-NEXT:    movd %xmm2, %ecx
-; CHECK-NEXT:    xorl %edx, %edx
-; CHECK-NEXT:    divl %ecx
-; CHECK-NEXT:    movl %edx, %eax
+; CHECK-NEXT:    movd %xmm2, %eax
+; CHECK-NEXT:    decl %eax
+; CHECK-NEXT:    andl %edi, %eax
 ; CHECK-NEXT:    retq
   %yy = shl <4 x i32> <i32 1, i32 -1, i32 -1, i32 -1>, %x
   %d = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %yy, <4 x i32> splat (i32 256))
@@ -659,7 +653,6 @@ define i1 @pow2_smax(i32 %x, i32 %y, i32 %z) {
 define i32 @pow2_smax_vec(<4 x i32> %x, <4 x i32> %y, i32 %z, ptr %p) {
 ; CHECK-LABEL: pow2_smax_vec:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %edi, %eax
 ; CHECK-NEXT:    pshuflw {{.*#+}} xmm1 = xmm0[2,3,3,3,4,5,6,7]
 ; CHECK-NEXT:    movdqa {{.*#+}} xmm2 = [4096,4294967295,4294967295,4294967295]
 ; CHECK-NEXT:    movdqa %xmm2, %xmm3
@@ -683,10 +676,9 @@ define i32 @pow2_smax_vec(<4 x i32> %x, <4 x i32> %y, i32 %z, ptr %p) {
 ; CHECK-NEXT:    pandn %xmm0, %xmm1
 ; CHECK-NEXT:    por %xmm4, %xmm1
 ; CHECK-NEXT:    movdqa %xmm1, (%rsi)
-; CHECK-NEXT:    movd %xmm1, %ecx
-; CHECK-NEXT:    xorl %edx, %edx
-; CHECK-NEXT:    divl %ecx
-; CHECK-NEXT:    movl %edx, %eax
+; CHECK-NEXT:    movd %xmm1, %eax
+; CHECK-NEXT:    decl %eax
+; CHECK-NEXT:    andl %edi, %eax
 ; CHECK-NEXT:    retq
   %yy = lshr <4 x i32> <i32 4096, i32 -1, i32 -1, i32 -1>, %x
   %d = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %yy, <4 x i32> splat (i32 256))



More information about the llvm-commits mailing list