diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index d3515cf81f443..f59cb9c5c6770 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -30959,6 +30959,24 @@ bool AArch64TargetLowering::SimplifyDemandedBitsForTargetNode( Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO, Depth); } +bool AArch64TargetLowering::canCreateUndefOrPoisonForTargetNode( + SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, + bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const { + + // TODO: Add more target nodes. + switch (Op.getOpcode()) { + case AArch64ISD::MOVI: + case AArch64ISD::MOVIedit: + case AArch64ISD::MOVImsl: + case AArch64ISD::MOVIshift: + case AArch64ISD::MVNImsl: + case AArch64ISD::MVNIshift: + return false; + } + return TargetLowering::canCreateUndefOrPoisonForTargetNode( + Op, DemandedElts, DAG, PoisonOnly, ConsiderFlags, Depth); +} + bool AArch64TargetLowering::isTargetCanonicalConstantNode(SDValue Op) const { return Op.getOpcode() == AArch64ISD::DUP || Op.getOpcode() == AArch64ISD::MOVI || diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index b840af36be7e7..1988ee82880a8 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -869,6 +869,12 @@ class AArch64TargetLowering : public TargetLowering { TargetLoweringOpt &TLO, unsigned Depth) const override; + bool canCreateUndefOrPoisonForTargetNode(SDValue Op, + const APInt &DemandedElts, + const SelectionDAG &DAG, + bool PoisonOnly, bool ConsiderFlags, + unsigned Depth) const override; + bool isTargetCanonicalConstantNode(SDValue Op) const override; // With the exception of data-predicate transitions, no instructions are diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp index 18c8d4a69e7a8..c4cbd4f7015e6 100644 --- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp +++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp @@ -319,6 +319,7 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_UADDO_CARRY) { } // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. +// Attempt to FREEZE the MOV/MVN nodes to show that they can still be analysed. TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { SDLoc Loc; auto IntSca32VT = MVT::i32; @@ -344,6 +345,11 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { EXPECT_EQ(Known.Zero, APInt(64, 0x00FF00FFFF00FF00)); EXPECT_EQ(Known.One, APInt(64, 0xFF00FF0000FF00FF)); + auto FrMOVIedit128 = DAG->getFreeze(OpMOVIedit128); + Known = DAG->computeKnownBits(FrMOVIedit128); + EXPECT_EQ(Known.Zero, APInt(64, 0x00FF00FFFF00FF00)); + EXPECT_EQ(Known.One, APInt(64, 0xFF00FF0000FF00FF)); + auto N264 = DAG->getConstant(264, Loc, IntSca32VT); auto OpMOVImsl64 = DAG->getNode(AArch64ISD::MOVImsl, Loc, Int2Vec32VT, N165, N264); @@ -358,6 +364,11 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { EXPECT_EQ(Known.Zero, APInt(32, 0xFF5A0000)); EXPECT_EQ(Known.One, APInt(32, 0x00A5FFFF)); + auto FrMOVImsl128 = DAG->getFreeze(OpMOVImsl128); + Known = DAG->computeKnownBits(FrMOVImsl128); + EXPECT_EQ(Known.Zero, APInt(32, 0xFF5A0000)); + EXPECT_EQ(Known.One, APInt(32, 0x00A5FFFF)); + auto OpMVNImsl64 = DAG->getNode(AArch64ISD::MVNImsl, Loc, Int2Vec32VT, N165, N272); Known = DAG->computeKnownBits(OpMVNImsl64); @@ -370,6 +381,11 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { EXPECT_EQ(Known.Zero, APInt(32, 0x0000A5FF)); EXPECT_EQ(Known.One, APInt(32, 0xFFFF5A00)); + auto FrMVNImsl128 = DAG->getFreeze(OpMVNImsl128); + Known = DAG->computeKnownBits(FrMVNImsl128); + EXPECT_EQ(Known.Zero, APInt(32, 0x0000A5FF)); + EXPECT_EQ(Known.One, APInt(32, 0xFFFF5A00)); + auto N0 = DAG->getConstant(0, Loc, IntSca32VT); auto OpMOVIshift2Vec32 = DAG->getNode(AArch64ISD::MOVIshift, Loc, Int2Vec32VT, N165, N0); @@ -384,6 +400,11 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { EXPECT_EQ(Known.Zero, APInt(32, 0x5AFFFFFF)); EXPECT_EQ(Known.One, APInt(32, 0xA5000000)); + auto FrMOVIshift4Vec32 = DAG->getFreeze(OpMOVIshift4Vec32); + Known = DAG->computeKnownBits(FrMOVIshift4Vec32); + EXPECT_EQ(Known.Zero, APInt(32, 0x5AFFFFFF)); + EXPECT_EQ(Known.One, APInt(32, 0xA5000000)); + auto OpMVNIshift2Vec32 = DAG->getNode(AArch64ISD::MVNIshift, Loc, Int2Vec32VT, N165, N24); Known = DAG->computeKnownBits(OpMVNIshift2Vec32); @@ -396,6 +417,11 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { EXPECT_EQ(Known.Zero, APInt(32, 0x000000A5)); EXPECT_EQ(Known.One, APInt(32, 0xFFFFFF5A)); + auto FrMVNIshift4Vec32 = DAG->getFreeze(OpMVNIshift4Vec32); + Known = DAG->computeKnownBits(FrMVNIshift4Vec32); + EXPECT_EQ(Known.Zero, APInt(32, 0x000000A5)); + EXPECT_EQ(Known.One, APInt(32, 0xFFFFFF5A)); + auto N8 = DAG->getConstant(8, Loc, IntSca32VT); auto OpMOVIshift4Vec16 = DAG->getNode(AArch64ISD::MOVIshift, Loc, Int4Vec16VT, N165, N0); @@ -409,6 +435,11 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { EXPECT_EQ(Known.Zero, APInt(16, 0x5AFF)); EXPECT_EQ(Known.One, APInt(16, 0xA500)); + auto FrMOVIshift8Vec16 = DAG->getFreeze(OpMOVIshift8Vec16); + Known = DAG->computeKnownBits(FrMOVIshift8Vec16); + EXPECT_EQ(Known.Zero, APInt(16, 0x5AFF)); + EXPECT_EQ(Known.One, APInt(16, 0xA500)); + auto OpMVNIshift4Vec16 = DAG->getNode(AArch64ISD::MVNIshift, Loc, Int4Vec16VT, N165, N8); Known = DAG->computeKnownBits(OpMVNIshift4Vec16); @@ -421,6 +452,11 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { EXPECT_EQ(Known.Zero, APInt(16, 0x00A5)); EXPECT_EQ(Known.One, APInt(16, 0xFF5A)); + auto FrMVNIshift8Vec16 = DAG->getFreeze(OpMVNIshift8Vec16); + Known = DAG->computeKnownBits(FrMVNIshift8Vec16); + EXPECT_EQ(Known.Zero, APInt(16, 0x00A5)); + EXPECT_EQ(Known.One, APInt(16, 0xFF5A)); + auto OpMOVI8Vec8 = DAG->getNode(AArch64ISD::MOVI, Loc, Int8Vec8VT, N165); Known = DAG->computeKnownBits(OpMOVI8Vec8); EXPECT_EQ(Known.Zero, APInt(8, 0x5A)); @@ -430,6 +466,11 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) { Known = DAG->computeKnownBits(OpMOVI16Vec8); EXPECT_EQ(Known.Zero, APInt(8, 0x5A)); EXPECT_EQ(Known.One, APInt(8, 0xA5)); + + auto FrMOVI16Vec8 = DAG->getFreeze(OpMOVI16Vec8); + Known = DAG->computeKnownBits(FrMOVI16Vec8); + EXPECT_EQ(Known.Zero, APInt(8, 0x5A)); + EXPECT_EQ(Known.One, APInt(8, 0xA5)); } // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.