[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