[llvm] [AArch64] canCreateUndefOrPoisonForTargetNode - AArch64ISD::MOVI opcodes can't create undef/poison (PR #149323)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 3 01:55:38 PDT 2025
https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/149323
>From 8c0a8829c9889b6f1e2a2fa86092c74f5d881b85 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Thu, 17 Jul 2025 15:39:06 +0100
Subject: [PATCH 1/2] [AArch64] canCreateUndefOrPoisonForTargetNode -
AArch64ISD::MOVI opcodes can't create undef/poison
Possible fix for failed fold in #148191
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 17 +++++++++++++++++
llvm/lib/Target/AArch64/AArch64ISelLowering.h | 6 ++++++
2 files changed, 23 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index ff23f76fadccd..ea8a8e1c0219e 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30398,6 +30398,23 @@ 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::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 7b1de3d3254f2..12f07682868e5 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -851,6 +851,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
>From 222da9308a24ee1c1d57e470f481523342049999 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Wed, 3 Sep 2025 09:55:19 +0100
Subject: [PATCH 2/2] Add frozen MOV/MVN nodes to ComputeKnownBits_MOVI to
demonstrate that the freeze will be removed.
---
.../Target/AArch64/AArch64ISelLowering.cpp | 1 +
.../AArch64/AArch64SelectionDAGTest.cpp | 41 +++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 9b357973ee51d..cfac182859c4b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30837,6 +30837,7 @@ bool AArch64TargetLowering::canCreateUndefOrPoisonForTargetNode(
case AArch64ISD::MOVIedit:
case AArch64ISD::MOVImsl:
case AArch64ISD::MOVIshift:
+ case AArch64ISD::MVNImsl:
case AArch64ISD::MVNIshift:
return false;
}
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index 675fdc7b0db3b..ddcc9fffe32fa 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.
More information about the llvm-commits
mailing list