[DAG] isKnownToBeAPowerOfTwo - add DemandedElts + OrZero handling to ISD::SELECT/VSELECT cases (#181753)

Pass DemandedElts and OrZero arguments through SELECT/VSELECT nodes when
checking if values are power-of-two.

Add unit tests for scalar SELECT (OrZero) and vector VSELECT
(DemandedElts + OrZero).

Resolves #181645
This commit is contained in:
Fedor Nikolaev 2026-02-17 14:05:28 +01:00 committed by GitHub
parent 47a969ef88
commit 900778e40d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 2 deletions

View File

@ -4747,9 +4747,9 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val,
case ISD::SELECT:
case ISD::VSELECT:
return isKnownToBeAPowerOfTwo(Val.getOperand(2), /*OrZero=*/false,
return isKnownToBeAPowerOfTwo(Val.getOperand(2), DemandedElts, OrZero,
Depth + 1) &&
isKnownToBeAPowerOfTwo(Val.getOperand(1), /*OrZero=*/false,
isKnownToBeAPowerOfTwo(Val.getOperand(1), DemandedElts, OrZero,
Depth + 1);
case ISD::ZERO_EXTEND:

View File

@ -914,6 +914,63 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Constants) {
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SplatBig, /*OrZero=*/true));
}
TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Select) {
SDLoc Loc;
auto Cst0 = DAG->getConstant(0, Loc, MVT::i32);
auto Cst3 = DAG->getConstant(3, Loc, MVT::i32);
auto Cst4 = DAG->getConstant(4, Loc, MVT::i32);
auto CstBig = DAG->getConstant(2 << 17, 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 Select43 = DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst4, Cst3);
auto Select4Big =
DAG->getNode(ISD::SELECT, Loc, MVT::i32, Cond, Cst4, CstBig);
EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(Select40));
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(Select40, /*OrZero=*/true));
EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(Select43));
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(Select4Big));
auto VecVT = MVT::v2i16;
auto Vec04 = DAG->getBuildVector(VecVT, Loc, {Cst0, Cst4});
auto Vec44 = DAG->getBuildVector(VecVT, Loc, {Cst4, Cst4});
auto Vec4Big = DAG->getBuildVector(VecVT, Loc, {Cst4, CstBig});
auto Vec0Big = DAG->getBuildVector(VecVT, Loc, {Cst0, CstBig});
auto VecCond = DAG->getCopyFromReg(DAG->getEntryNode(), Loc, 2, MVT::v2i1);
auto VSelect0444 =
DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec04, Vec44);
auto VSelect4444 =
DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec44, Vec44);
auto VSelect040Big =
DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec04, Vec0Big);
auto VSelect444Big =
DAG->getNode(ISD::VSELECT, Loc, VecVT, VecCond, Vec44, Vec4Big);
APInt DemandLo(2, 1);
EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandLo));
EXPECT_TRUE(
DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandLo, /*OrZero=*/true));
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSelect444Big, DemandLo));
APInt DemandHi(2, 2);
EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSelect444Big, DemandHi));
EXPECT_TRUE(
DAG->isKnownToBeAPowerOfTwo(VSelect444Big, DemandHi, /*OrZero=*/true));
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandHi));
APInt DemandAll(2, 3);
EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSelect0444, DemandAll));
EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSelect040Big, DemandAll));
EXPECT_FALSE(DAG->isKnownToBeAPowerOfTwo(VSelect444Big, DemandAll));
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(VSelect4444, DemandAll));
EXPECT_TRUE(
DAG->isKnownToBeAPowerOfTwo(VSelect040Big, DemandAll, /*OrZero=*/true));
EXPECT_TRUE(
DAG->isKnownToBeAPowerOfTwo(VSelect444Big, DemandAll, /*OrZero=*/true));
}
TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_BUILD_VECTOR) {
TargetLowering TL(*TM, *STI);