[llvm] Improved ISD::SRL handling in isKnownToBeAPowerOfTwo (PR #182562)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 20 10:26:44 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-selectiondag
Author: None (Iasonaskrpr)
<details>
<summary>Changes</summary>
Fixes #<!-- -->181651
Added DemandedElts argument to isConstOrConstSplat and to isKnowTobePowerOfTwo calls and OrZero || isKnownNeverZero(Val, Depth) is checked before isKnowTobePowerOfTwo. Also added unit tests.
---
Full diff: https://github.com/llvm/llvm-project/pull/182562.diff
2 Files Affected:
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (+4-4)
- (modified) llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp (+74)
``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 581553d41cb6d..35a1b89448f59 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4723,12 +4723,12 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val,
case ISD::SRL: {
// A logical right-shift of a constant sign-bit will have exactly
// one bit set.
- auto *C = isConstOrConstSplat(Val.getOperand(0));
+ auto *C = isConstOrConstSplat(Val.getOperand(0), DemandedElts);
if (C && C->getAPIntValue().isSignMask())
return true;
- return isKnownToBeAPowerOfTwo(Val.getOperand(0), /*OrZero=*/false,
- Depth + 1) &&
- isKnownNeverZero(Val, Depth);
+ return (OrZero || isKnownNeverZero(Val, Depth)) &&
+ isKnownToBeAPowerOfTwo(Val.getOperand(0), DemandedElts, OrZero,
+ Depth + 1);
}
case ISD::ROTL:
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index b2b8dfb0c21fc..705b370206529 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -971,6 +971,80 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Select) {
DAG->isKnownToBeAPowerOfTwo(VSelect444Big, DemandAll, /*OrZero=*/true));
}
+TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_ISD_SRL) {
+ SDLoc Loc;
+ auto Cst0 = DAG->getConstant(0, Loc, MVT::i32);
+ auto Cst1 = DAG->getConstant(1, Loc, MVT::i32);
+ auto Cst4 = DAG->getConstant(4, Loc, MVT::i32);
+ auto Cst7 = DAG->getConstant(7, Loc, MVT::i32);
+ auto CstBig = DAG->getConstant(2 << 17, Loc, MVT::i32);
+
+ auto SRL40 = DAG->getNode(ISD::SRL, Loc, MVT::i32, Cst4, Cst0);
+ auto SRL41 = DAG->getNode(ISD::SRL, Loc, MVT::i32, Cst4, Cst1);
+ auto SRL44 = DAG->getNode(ISD::SRL, Loc, MVT::i32, Cst4, Cst4);
+ auto SRL71 = DAG->getNode(ISD::SRL, Loc, MVT::i32, Cst7, Cst1);
+ auto SRLBig4 = DAG->getNode(ISD::SRL, Loc, MVT::i32, CstBig, Cst4);
+
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRL40));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRL41));
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRL44));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRL44, /*OrZero=*/true));
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRL71));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRLBig4));
+
+ auto VecVT = MVT::v2i16;
+ auto Vec00 = DAG->getBuildVector(VecVT, Loc, {Cst0, Cst0});
+ auto Vec04 = DAG->getBuildVector(VecVT, Loc, {Cst0, Cst4});
+ auto Vec11 = DAG->getBuildVector(VecVT, Loc, {Cst1, Cst1});
+ auto Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
+ auto Vec74 = DAG->getBuildVector(VecVT, Loc, {Cst7, Cst4});
+ auto Vec4Big = DAG->getBuildVector(VecVT, Loc, {Cst4, CstBig});
+
+ auto SRL4404 = DAG->getNode(ISD::SRL, Loc, VecVT, Vec44, Vec04);
+ auto SRL7411 = DAG->getNode(ISD::SRL, Loc, VecVT, Vec74, Vec11);
+ auto SRL4Big04 = DAG->getNode(ISD::SRL, Loc, VecVT, Vec4Big, Vec04);
+ auto SRL4Big00 = DAG->getNode(ISD::SRL, Loc, VecVT, Vec4Big, Vec00);
+
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRL4404));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRL4404, /*OrZero=*/true));
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRL7411));
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRL7411, /*OrZero=*/true));
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRL4Big00));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRL4Big00, /*OrZero=*/true));
+
+ APInt DemandLo(2, 1);
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRL7411, DemandLo));
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRL7411, DemandLo, /*OrZero=*/true));
+
+ APInt DemandHi(2, 2);
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRL7411, DemandHi));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRL7411, DemandHi, /*OrZero=*/true));
+
+ APInt DemandAll(2, 3);
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRL4Big04, DemandHi));
+ EXPECT_TRUE(
+ DAG->isKnownToBeAPowerOfTwo(SRL4Big04, DemandHi, /*OrZero=*/true));
+
+ auto SplatVT = MVT::nxv2i16;
+ auto Splat0 = DAG->getSplat(SplatVT, Loc, Cst0);
+ auto Splat4 = DAG->getSplat(SplatVT, Loc, Cst4);
+ auto SplatBig = DAG->getSplat(SplatVT, Loc, CstBig);
+
+ auto SRLSplatBig0 = DAG->getNode(ISD::SRL, Loc, VecVT, SplatBig, Splat0);
+ auto SRLSplatBig4 = DAG->getNode(ISD::SRL, Loc, VecVT, SplatBig, Splat4);
+ auto SRLSplat44 = DAG->getNode(ISD::SRL, Loc, VecVT, Splat4, Splat4);
+ auto SRLSplat40 = DAG->getNode(ISD::SRL, Loc, VecVT, Splat4, Splat0);
+
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRLSplatBig0));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRLSplatBig0, /*OrZero=*/true));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRLSplatBig4));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRLSplatBig4, /*OrZero=*/true));
+ EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(SRLSplat44));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRLSplat44, /*OrZero=*/true));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRLSplat40));
+ EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SRLSplat40, /*OrZero=*/true));
+}
+
TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_BUILD_VECTOR) {
TargetLowering TL(*TM, *STI);
``````````
</details>
https://github.com/llvm/llvm-project/pull/182562
More information about the llvm-commits
mailing list