-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[AArch64] canCreateUndefOrPoisonForTargetNode - AArch64ISD::MOVI opcodes can't create undef/poison #149323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…des can't create undef/poison Possible fix for failed fold in llvm#148191
| case AArch64ISD::MOVIedit: | ||
| case AArch64ISD::MOVImsl: | ||
| case AArch64ISD::MOVIshift: | ||
| case AArch64ISD::MVNIshift: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact I think these can be put into a AArch64TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode implementation, but this should have the same effect
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds OK to me, they should never be poison. Do we have a standard way of creating tests for changes like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be that #148191 is the first case where we manage to show the problem (we need a case where the freeze needs removing quite late into lowering) - I haven't had time to investigate though.
…'t create undef/poison We can always fold freeze(vashr(x,y)) -> vashr(freeze(x),freeze(y)) as VASHR has defined behaviour for out-of-range shift amounts. Test coverage can be tricky, so I've hijacked a ComputeNumSignBits test to show that value tracking can still analyse the VASHR node as the FREEZE will have been discarded by the canCreateUndefOrPoison/isGuaranteedNotToBeUndefOrPoison logic in getFreeze(). If this AArch64SelectionDAGTest.cpp approach is OK I'm intending to use it in llvm#149323 once llvm#155696 has landed.
… the freeze will be removed.
|
@davemgreen I've added test coverage similar to what I'm attempting on #156445 |
davemgreen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds great, thanks. LGTM
|
@llvm/pr-subscribers-backend-aarch64 Author: Simon Pilgrim (RKSimon) ChangesPossible fix for failed fold in #148191 Full diff: https://github.com/llvm/llvm-project/pull/149323.diff 3 Files Affected:
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.
|
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/163/builds/25881 Here is the relevant piece of the build log for the reference |
Possible fix for failed fold in #148191