Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2619,6 +2619,32 @@ void AArch64TargetLowering::computeKnownBitsForTargetNode(
<< Op->getConstantOperandVal(1)));
break;
}
case AArch64ISD::MOVImsl: {
Known = KnownBits::makeConstant(
APInt(Known.getBitWidth(), ~(~Op->getConstantOperandVal(0)
<< Op->getConstantOperandVal(1))));
break;
}
case AArch64ISD::MOVIedit: {
Known = KnownBits::makeConstant(APInt(
Known.getBitWidth(),
AArch64_AM::decodeAdvSIMDModImmType10(Op->getConstantOperandVal(0))));
break;
}
case AArch64ISD::MVNIshift: {
Known = KnownBits::makeConstant(
APInt(Known.getBitWidth(),
(~Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
/*isSigned*/ false, /*implicitTrunc*/ true));
break;
}
case AArch64ISD::MVNImsl: {
Known = KnownBits::makeConstant(
APInt(Known.getBitWidth(),
~(Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
/*isSigned*/ false, /*implicitTrunc*/ true));
break;
}
case AArch64ISD::LOADgot:
case AArch64ISD::ADDlow: {
if (!Subtarget->isTargetILP32())
Expand Down Expand Up @@ -30637,6 +30663,16 @@ bool AArch64TargetLowering::isTargetCanonicalConstantNode(SDValue Op) const {
return Op.getOpcode() == AArch64ISD::DUP ||
Op.getOpcode() == AArch64ISD::MOVI ||
Op.getOpcode() == AArch64ISD::MOVIshift ||
Op.getOpcode() == AArch64ISD::MOVImsl ||
Op.getOpcode() == AArch64ISD::MOVIedit ||
Op.getOpcode() == AArch64ISD::MVNIshift ||
Op.getOpcode() == AArch64ISD::MVNImsl ||
// Ignoring fneg(movi(0)), because if it is folded to FPConstant(-0.0),
// ISel will select fmov(mov i64 0x8000000000000000), resulting in a
// fmov from fpr to gpr, which is more expensive than fneg(movi(0))
(Op.getOpcode() == ISD::FNEG &&
Op.getOperand(0).getOpcode() == AArch64ISD::MOVIedit &&
Op.getOperand(0).getConstantOperandVal(0) == 0) ||
(Op.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
Op.getOperand(0).getOpcode() == AArch64ISD::DUP) ||
TargetLowering::isTargetCanonicalConstantNode(Op);
Expand Down
112 changes: 112 additions & 0 deletions llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,118 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_UADDO_CARRY) {
EXPECT_EQ(Known.One, APInt(8, 0x86));
}

// Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) {
SDLoc Loc;
auto IntSca32VT = MVT::i32;
auto Int8Vec8VT = MVT::v8i8;
auto Int16Vec8VT = MVT::v16i8;
auto Int4Vec16VT = MVT::v4i16;
auto Int8Vec16VT = MVT::v8i16;
auto Int2Vec32VT = MVT::v2i32;
auto Int4Vec32VT = MVT::v4i32;
auto IntVec64VT = MVT::v1i64;
auto Int2Vec64VT = MVT::v2i64;
auto N0 = DAG->getConstant(0x000000A5, Loc, IntSca32VT);
KnownBits Known;

auto OpMOVIedit64 = DAG->getNode(AArch64ISD::MOVIedit, Loc, IntVec64VT, N0);
Known = DAG->computeKnownBits(OpMOVIedit64);
EXPECT_EQ(Known.Zero, APInt(64, 0x00FF00FFFF00FF00));
EXPECT_EQ(Known.One, APInt(64, 0xFF00FF0000FF00FF));

auto OpMOVIedit128 = DAG->getNode(AArch64ISD::MOVIedit, Loc, Int2Vec64VT, N0);
Known = DAG->computeKnownBits(OpMOVIedit128);
EXPECT_EQ(Known.Zero, APInt(64, 0x00FF00FFFF00FF00));
EXPECT_EQ(Known.One, APInt(64, 0xFF00FF0000FF00FF));

auto N1 = DAG->getConstant(264, Loc, IntSca32VT);
auto OpMOVImsl64 =
DAG->getNode(AArch64ISD::MOVImsl, Loc, Int2Vec32VT, N0, N1);
Known = DAG->computeKnownBits(OpMOVImsl64);
EXPECT_EQ(Known.Zero, APInt(32, 0xFFFF5A00));
EXPECT_EQ(Known.One, APInt(32, 0x0000A5FF));

auto N2 = DAG->getConstant(272, Loc, IntSca32VT);
auto OpMOVImsl128 =
DAG->getNode(AArch64ISD::MOVImsl, Loc, Int4Vec32VT, N0, N2);
Known = DAG->computeKnownBits(OpMOVImsl128);
EXPECT_EQ(Known.Zero, APInt(32, 0xFF5A0000));
EXPECT_EQ(Known.One, APInt(32, 0x00A5FFFF));

auto OpMVNImsl64 =
DAG->getNode(AArch64ISD::MVNImsl, Loc, Int2Vec32VT, N0, N2);
Known = DAG->computeKnownBits(OpMVNImsl64);
EXPECT_EQ(Known.Zero, APInt(32, 0x00A50000));
EXPECT_EQ(Known.One, APInt(32, 0xFF5AFFFF));

auto OpMVNImsl128 =
DAG->getNode(AArch64ISD::MVNImsl, Loc, Int4Vec32VT, N0, N1);
Known = DAG->computeKnownBits(OpMVNImsl128);
EXPECT_EQ(Known.Zero, APInt(32, 0x0000A500));
EXPECT_EQ(Known.One, APInt(32, 0xFFFF5AFF));

auto N3 = DAG->getConstant(0, Loc, IntSca32VT);
auto OpMOVIshift2Vec32 =
DAG->getNode(AArch64ISD::MOVIshift, Loc, Int2Vec32VT, N0, N3);
Known = DAG->computeKnownBits(OpMOVIshift2Vec32);
EXPECT_EQ(Known.Zero, APInt(32, 0xFFFFFF5A));
EXPECT_EQ(Known.One, APInt(32, 0x000000A5));

auto N4 = DAG->getConstant(24, Loc, IntSca32VT);
auto OpMOVIshift4Vec32 =
DAG->getNode(AArch64ISD::MOVIshift, Loc, Int4Vec32VT, N0, N4);
Known = DAG->computeKnownBits(OpMOVIshift4Vec32);
EXPECT_EQ(Known.Zero, APInt(32, 0x5AFFFFFF));
EXPECT_EQ(Known.One, APInt(32, 0xA5000000));

auto OpMVNIshift2Vec32 =
DAG->getNode(AArch64ISD::MVNIshift, Loc, Int2Vec32VT, N0, N4);
Known = DAG->computeKnownBits(OpMVNIshift2Vec32);
EXPECT_EQ(Known.Zero, APInt(32, 0xA5FFFFFF));
EXPECT_EQ(Known.One, APInt(32, 0x5A000000));

auto OpMVNIshift4Vec32 =
DAG->getNode(AArch64ISD::MVNIshift, Loc, Int4Vec32VT, N0, N3);
Known = DAG->computeKnownBits(OpMVNIshift4Vec32);
EXPECT_EQ(Known.Zero, APInt(32, 0x000000A5));
EXPECT_EQ(Known.One, APInt(32, 0xFFFFFF5A));

auto OpMOVIshift4Vec16 =
DAG->getNode(AArch64ISD::MOVIshift, Loc, Int4Vec16VT, N0, N3);
Known = DAG->computeKnownBits(OpMOVIshift4Vec16);
EXPECT_EQ(Known.One, APInt(16, 0x00A5));
EXPECT_EQ(Known.Zero, APInt(16, 0xFF5A));

auto OpMOVIshift8Vec16 =
DAG->getNode(AArch64ISD::MOVIshift, Loc, Int8Vec16VT, N0, N1);
Known = DAG->computeKnownBits(OpMOVIshift8Vec16);
EXPECT_EQ(Known.One, APInt(16, 0xA500));
EXPECT_EQ(Known.Zero, APInt(16, 0x5AFF));

auto OpMVNIshift4Vec16 =
DAG->getNode(AArch64ISD::MVNIshift, Loc, Int4Vec16VT, N0, N1);
Known = DAG->computeKnownBits(OpMVNIshift4Vec16);
EXPECT_EQ(Known.Zero, APInt(16, 0xA5FF));
EXPECT_EQ(Known.One, APInt(16, 0x5A00));

auto OpMVNIshift8Vec16 =
DAG->getNode(AArch64ISD::MVNIshift, Loc, Int8Vec16VT, N0, N3);
Known = DAG->computeKnownBits(OpMVNIshift8Vec16);
EXPECT_EQ(Known.Zero, APInt(16, 0x00A5));
EXPECT_EQ(Known.One, APInt(16, 0xFF5A));

auto OpMOVI8Vec8 = DAG->getNode(AArch64ISD::MOVI, Loc, Int8Vec8VT, N0);
Known = DAG->computeKnownBits(OpMOVI8Vec8);
EXPECT_EQ(Known.Zero, APInt(8, 0x5A));
EXPECT_EQ(Known.One, APInt(8, 0xA5));

auto OpMOVI16Vec8 = DAG->getNode(AArch64ISD::MOVI, Loc, Int16Vec8VT, N0);
Known = DAG->computeKnownBits(OpMOVI16Vec8);
EXPECT_EQ(Known.Zero, APInt(8, 0x5A));
EXPECT_EQ(Known.One, APInt(8, 0xA5));
}

// Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_SUB) {
SDLoc Loc;
Expand Down
Loading