[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