[llvm] [AArch64] AArch64TargetLowering::computeKnownBitsForTargetNode - add support for AArch64ISD::MOV/MVN constants (PR #154039)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 26 09:37:43 PDT 2025


https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/154039

>From 38bedfef00e82c2c5c25e0ba0e89a0b444fd959b Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Fri, 15 Aug 2025 17:25:36 -0700
Subject: [PATCH 1/6] [AArch64]
 AArch64TargetLowering::computeKnownBitsForTargetNode - add support for
 AArch64ISD::MOV/MVN constants

---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 30 ++++++++++
 llvm/test/CodeGen/AArch64/urem-vector-lkk.ll  | 16 ++---
 .../AArch64/AArch64SelectionDAGTest.cpp       | 58 +++++++++++++++++++
 3 files changed, 96 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 63a85faf344c4..6adb3b721113f 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -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)),
+              false, true));
+    break;
+  }
+  case AArch64ISD::MVNImsl: {
+    Known = KnownBits::makeConstant(
+        APInt(Known.getBitWidth(),
+              ~(Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
+              false, true));
+    break;
+  }
   case AArch64ISD::LOADgot:
   case AArch64ISD::ADDlow: {
     if (!Subtarget->isTargetILP32())
@@ -30637,6 +30663,10 @@ 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 ||
          (Op.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
           Op.getOperand(0).getOpcode() == AArch64ISD::DUP) ||
          TargetLowering::isTargetCanonicalConstantNode(Op);
diff --git a/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll b/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
index 468a33ce5bfcf..4dd86769c1dd5 100644
--- a/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
+++ b/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
@@ -8,14 +8,14 @@ define <4 x i16> @fold_urem_vec_1(<4 x i16> %x) {
 ; CHECK-NEXT:    ldr d1, [x8, :lo12:.LCPI0_0]
 ; CHECK-NEXT:    adrp x8, .LCPI0_1
 ; CHECK-NEXT:    ldr d2, [x8, :lo12:.LCPI0_1]
-; CHECK-NEXT:    adrp x8, .LCPI0_2
-; CHECK-NEXT:    ushl v1.4h, v0.4h, v1.4h
-; CHECK-NEXT:    umull v1.4s, v1.4h, v2.4h
-; CHECK-NEXT:    movi d2, #0000000000000000
-; CHECK-NEXT:    shrn v1.4h, v1.4s, #16
-; CHECK-NEXT:    fneg d2, d2
-; CHECK-NEXT:    sub v3.4h, v0.4h, v1.4h
-; CHECK-NEXT:    umull v2.4s, v3.4h, v2.4h
+; CHECK-NEXT:    mov     x8, #-9223372036854775808       // =0x8000000000000000
+; CHECK-NEXT:    ushl    v1.4h, v0.4h, v1.4h
+; CHECK-NEXT:    fmov    d3, x8
+; CHECK-NEXT:    adrp    x8, .LCPI0_2
+; CHECK-NEXT:    umull   v1.4s, v1.4h, v2.4h
+; CHECK-NEXT:    shrn    v1.4h, v1.4s, #16
+; CHECK-NEXT:    sub     v2.4h, v0.4h, v1.4h
+; CHECK-NEXT:    umull   v2.4s, v2.4h, v3.4h
 ; CHECK-NEXT:    shrn v2.4h, v2.4s, #16
 ; CHECK-NEXT:    add v1.4h, v2.4h, v1.4h
 ; CHECK-NEXT:    ldr d2, [x8, :lo12:.LCPI0_2]
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index f06f03bb35a5d..131b7eca942d0 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -318,6 +318,64 @@ 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 Int8VT = EVT::getIntegerVT(Context, 8);
+  auto Int16VT = EVT::getIntegerVT(Context, 16);
+  auto Int32VT = EVT::getIntegerVT(Context, 32);
+  auto Int64VT = EVT::getIntegerVT(Context, 64);
+  auto N0 = DAG->getConstant(0xA5, Loc, Int8VT);
+  KnownBits Known;
+
+  auto OpMOVIedit = DAG->getNode(AArch64ISD::MOVIedit, Loc, Int64VT, N0);
+  Known = DAG->computeKnownBits(OpMOVIedit);
+  EXPECT_EQ(Known.Zero, APInt(64, 0x00FF00FFFF00FF00));
+  EXPECT_EQ(Known.One, APInt(64, 0xFF00FF0000FF00FF));
+
+  auto N1 = DAG->getConstant(16, Loc, Int8VT);
+  auto OpMOVImsl = DAG->getNode(AArch64ISD::MOVImsl, Loc, Int32VT, N0, N1);
+  Known = DAG->computeKnownBits(OpMOVImsl);
+  EXPECT_EQ(Known.Zero, APInt(32, 0xFF5A0000));
+  EXPECT_EQ(Known.One, APInt(32, 0x00A5FFFF));
+
+  auto OpMVNImsl = DAG->getNode(AArch64ISD::MVNImsl, Loc, Int32VT, N0, N1);
+  Known = DAG->computeKnownBits(OpMVNImsl);
+  EXPECT_EQ(Known.Zero, APInt(32, 0x00A50000));
+  EXPECT_EQ(Known.One, APInt(32, 0xFF5AFFFF));
+
+  auto N2 = DAG->getConstant(16, Loc, Int8VT);
+  auto OpMOVIshift32 =
+      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int32VT, N0, N2);
+  Known = DAG->computeKnownBits(OpMOVIshift32);
+  EXPECT_EQ(Known.Zero, APInt(32, 0xFF5AFFFF));
+  EXPECT_EQ(Known.One, APInt(32, 0x00A50000));
+
+  auto OpMVNIshift32 =
+      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int32VT, N0, N2);
+  Known = DAG->computeKnownBits(OpMVNIshift32);
+  EXPECT_EQ(Known.Zero, APInt(32, 0x00A5FFFF));
+  EXPECT_EQ(Known.One, APInt(32, 0xFF5A0000));
+
+  auto N3 = DAG->getConstant(8, Loc, Int8VT);
+  auto OpMOVIshift16 =
+      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int16VT, N0, N3);
+  Known = DAG->computeKnownBits(OpMOVIshift16);
+  EXPECT_EQ(Known.One, APInt(16, 0xA500));
+  EXPECT_EQ(Known.Zero, APInt(16, 0x5AFF));
+
+  auto OpMVNIshift16 =
+      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int16VT, N0, N3);
+  Known = DAG->computeKnownBits(OpMVNIshift16);
+  EXPECT_EQ(Known.Zero, APInt(16, 0xA5FF));
+  EXPECT_EQ(Known.One, APInt(16, 0x5A00));
+
+  auto OpMOVI = DAG->getNode(AArch64ISD::MOVI, Loc, Int8VT, N0);
+  Known = DAG->computeKnownBits(OpMOVI);
+  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;

>From 7366510a4f2634c5aef1777212a86fabcb79d705 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Mon, 18 Aug 2025 08:02:14 -0700
Subject: [PATCH 2/6] Fixed urem-vector-lkk.ll with udpate_llc_test_checks.py

---
 llvm/test/CodeGen/AArch64/urem-vector-lkk.ll | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll b/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
index 4dd86769c1dd5..98290f485ed45 100644
--- a/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
+++ b/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
@@ -8,14 +8,14 @@ define <4 x i16> @fold_urem_vec_1(<4 x i16> %x) {
 ; CHECK-NEXT:    ldr d1, [x8, :lo12:.LCPI0_0]
 ; CHECK-NEXT:    adrp x8, .LCPI0_1
 ; CHECK-NEXT:    ldr d2, [x8, :lo12:.LCPI0_1]
-; CHECK-NEXT:    mov     x8, #-9223372036854775808       // =0x8000000000000000
-; CHECK-NEXT:    ushl    v1.4h, v0.4h, v1.4h
-; CHECK-NEXT:    fmov    d3, x8
-; CHECK-NEXT:    adrp    x8, .LCPI0_2
-; CHECK-NEXT:    umull   v1.4s, v1.4h, v2.4h
-; CHECK-NEXT:    shrn    v1.4h, v1.4s, #16
-; CHECK-NEXT:    sub     v2.4h, v0.4h, v1.4h
-; CHECK-NEXT:    umull   v2.4s, v2.4h, v3.4h
+; CHECK-NEXT:    mov x8, #-9223372036854775808 // =0x8000000000000000
+; CHECK-NEXT:    ushl v1.4h, v0.4h, v1.4h
+; CHECK-NEXT:    fmov d3, x8
+; CHECK-NEXT:    adrp x8, .LCPI0_2
+; CHECK-NEXT:    umull v1.4s, v1.4h, v2.4h
+; CHECK-NEXT:    shrn v1.4h, v1.4s, #16
+; CHECK-NEXT:    sub v2.4h, v0.4h, v1.4h
+; CHECK-NEXT:    umull v2.4s, v2.4h, v3.4h
 ; CHECK-NEXT:    shrn v2.4h, v2.4s, #16
 ; CHECK-NEXT:    add v1.4h, v2.4h, v1.4h
 ; CHECK-NEXT:    ldr d2, [x8, :lo12:.LCPI0_2]

>From 507e931718dedfce386212770e5cdd17a8224c36 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Wed, 20 Aug 2025 13:48:59 -0700
Subject: [PATCH 3/6] Update MOVI tests in AArch64SelectionDAGTest to use
 vector types

---
 .../AArch64/AArch64SelectionDAGTest.cpp       | 122 +++++++++++++-----
 1 file changed, 88 insertions(+), 34 deletions(-)

diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index 131b7eca942d0..8d6b74b3cb0a6 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -321,57 +321,111 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_UADDO_CARRY) {
 // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
 TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) {
   SDLoc Loc;
-  auto Int8VT = EVT::getIntegerVT(Context, 8);
-  auto Int16VT = EVT::getIntegerVT(Context, 16);
-  auto Int32VT = EVT::getIntegerVT(Context, 32);
-  auto Int64VT = EVT::getIntegerVT(Context, 64);
-  auto N0 = DAG->getConstant(0xA5, Loc, Int8VT);
+  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 OpMOVIedit = DAG->getNode(AArch64ISD::MOVIedit, Loc, Int64VT, N0);
-  Known = DAG->computeKnownBits(OpMOVIedit);
+  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 N1 = DAG->getConstant(16, Loc, Int8VT);
-  auto OpMOVImsl = DAG->getNode(AArch64ISD::MOVImsl, Loc, Int32VT, N0, N1);
-  Known = DAG->computeKnownBits(OpMOVImsl);
+  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 OpMVNImsl = DAG->getNode(AArch64ISD::MVNImsl, Loc, Int32VT, N0, N1);
-  Known = DAG->computeKnownBits(OpMVNImsl);
+  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 N2 = DAG->getConstant(16, Loc, Int8VT);
-  auto OpMOVIshift32 =
-      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int32VT, N0, N2);
-  Known = DAG->computeKnownBits(OpMOVIshift32);
-  EXPECT_EQ(Known.Zero, APInt(32, 0xFF5AFFFF));
-  EXPECT_EQ(Known.One, APInt(32, 0x00A50000));
-
-  auto OpMVNIshift32 =
-      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int32VT, N0, N2);
-  Known = DAG->computeKnownBits(OpMVNIshift32);
-  EXPECT_EQ(Known.Zero, APInt(32, 0x00A5FFFF));
-  EXPECT_EQ(Known.One, APInt(32, 0xFF5A0000));
-
-  auto N3 = DAG->getConstant(8, Loc, Int8VT);
-  auto OpMOVIshift16 =
-      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int16VT, N0, N3);
-  Known = DAG->computeKnownBits(OpMOVIshift16);
+  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 OpMVNIshift16 =
-      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int16VT, N0, N3);
-  Known = DAG->computeKnownBits(OpMVNIshift16);
+  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 OpMOVI = DAG->getNode(AArch64ISD::MOVI, Loc, Int8VT, N0);
-  Known = DAG->computeKnownBits(OpMOVI);
+  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));
 }

>From 38a936b86eb7b521ac22e5dc4142835f7deaef08 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Thu, 21 Aug 2025 10:08:28 -0700
Subject: [PATCH 4/6] Ignore fneg(-0.0)

---
 llvm/lib/Target/AArch64/AArch64ISelLowering.cpp |  3 +++
 llvm/test/CodeGen/AArch64/urem-vector-lkk.ll    | 10 +++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 6adb3b721113f..4a1a7512bbce1 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -30667,6 +30667,9 @@ bool AArch64TargetLowering::isTargetCanonicalConstantNode(SDValue Op) const {
          Op.getOpcode() == AArch64ISD::MOVIedit ||
          Op.getOpcode() == AArch64ISD::MVNIshift ||
          Op.getOpcode() == AArch64ISD::MVNImsl ||
+         (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);
diff --git a/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll b/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
index 98290f485ed45..468a33ce5bfcf 100644
--- a/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
+++ b/llvm/test/CodeGen/AArch64/urem-vector-lkk.ll
@@ -8,14 +8,14 @@ define <4 x i16> @fold_urem_vec_1(<4 x i16> %x) {
 ; CHECK-NEXT:    ldr d1, [x8, :lo12:.LCPI0_0]
 ; CHECK-NEXT:    adrp x8, .LCPI0_1
 ; CHECK-NEXT:    ldr d2, [x8, :lo12:.LCPI0_1]
-; CHECK-NEXT:    mov x8, #-9223372036854775808 // =0x8000000000000000
-; CHECK-NEXT:    ushl v1.4h, v0.4h, v1.4h
-; CHECK-NEXT:    fmov d3, x8
 ; CHECK-NEXT:    adrp x8, .LCPI0_2
+; CHECK-NEXT:    ushl v1.4h, v0.4h, v1.4h
 ; CHECK-NEXT:    umull v1.4s, v1.4h, v2.4h
+; CHECK-NEXT:    movi d2, #0000000000000000
 ; CHECK-NEXT:    shrn v1.4h, v1.4s, #16
-; CHECK-NEXT:    sub v2.4h, v0.4h, v1.4h
-; CHECK-NEXT:    umull v2.4s, v2.4h, v3.4h
+; CHECK-NEXT:    fneg d2, d2
+; CHECK-NEXT:    sub v3.4h, v0.4h, v1.4h
+; CHECK-NEXT:    umull v2.4s, v3.4h, v2.4h
 ; CHECK-NEXT:    shrn v2.4h, v2.4s, #16
 ; CHECK-NEXT:    add v1.4h, v2.4h, v1.4h
 ; CHECK-NEXT:    ldr d2, [x8, :lo12:.LCPI0_2]

>From 567b7fa0d40ef1f9496077ca3da722a39ed10887 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Thu, 21 Aug 2025 10:27:39 -0700
Subject: [PATCH 5/6] Add comments

---
 llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 4a1a7512bbce1..e0a43b4a90922 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -2635,14 +2635,14 @@ void AArch64TargetLowering::computeKnownBitsForTargetNode(
     Known = KnownBits::makeConstant(
         APInt(Known.getBitWidth(),
               (~Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
-              false, true));
+              /*isSigned*/ false, /*implicitTrunc*/ true));
     break;
   }
   case AArch64ISD::MVNImsl: {
     Known = KnownBits::makeConstant(
         APInt(Known.getBitWidth(),
               ~(Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
-              false, true));
+              /*isSigned*/ false, /*implicitTrunc*/ true));
     break;
   }
   case AArch64ISD::LOADgot:
@@ -30667,6 +30667,9 @@ bool AArch64TargetLowering::isTargetCanonicalConstantNode(SDValue Op) const {
          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) ||

>From ed822410421f705d6f301cdae9297e0852d0c566 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Thu, 21 Aug 2025 13:22:29 -0700
Subject: [PATCH 6/6] Fix MVNIshift and MVNImsl

---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  4 +-
 .../AArch64/AArch64SelectionDAGTest.cpp       | 64 ++++++++++---------
 2 files changed, 35 insertions(+), 33 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e0a43b4a90922..af7a76b5a35c2 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -2634,14 +2634,14 @@ void AArch64TargetLowering::computeKnownBitsForTargetNode(
   case AArch64ISD::MVNIshift: {
     Known = KnownBits::makeConstant(
         APInt(Known.getBitWidth(),
-              (~Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
+              ~(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)),
+              (~Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
               /*isSigned*/ false, /*implicitTrunc*/ true));
     break;
   }
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index 8d6b74b3cb0a6..675fdc7b0db3b 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -330,101 +330,103 @@ TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_MOVI) {
   auto Int4Vec32VT = MVT::v4i32;
   auto IntVec64VT = MVT::v1i64;
   auto Int2Vec64VT = MVT::v2i64;
-  auto N0 = DAG->getConstant(0x000000A5, Loc, IntSca32VT);
+  auto N165 = DAG->getConstant(0x000000A5, Loc, IntSca32VT);
   KnownBits Known;
 
-  auto OpMOVIedit64 = DAG->getNode(AArch64ISD::MOVIedit, Loc, IntVec64VT, N0);
+  auto OpMOVIedit64 = DAG->getNode(AArch64ISD::MOVIedit, Loc, IntVec64VT, N165);
   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);
+  auto OpMOVIedit128 =
+      DAG->getNode(AArch64ISD::MOVIedit, Loc, Int2Vec64VT, N165);
   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 N264 = DAG->getConstant(264, Loc, IntSca32VT);
   auto OpMOVImsl64 =
-      DAG->getNode(AArch64ISD::MOVImsl, Loc, Int2Vec32VT, N0, N1);
+      DAG->getNode(AArch64ISD::MOVImsl, Loc, Int2Vec32VT, N165, N264);
   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 N272 = DAG->getConstant(272, Loc, IntSca32VT);
   auto OpMOVImsl128 =
-      DAG->getNode(AArch64ISD::MOVImsl, Loc, Int4Vec32VT, N0, N2);
+      DAG->getNode(AArch64ISD::MOVImsl, Loc, Int4Vec32VT, N165, N272);
   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);
+      DAG->getNode(AArch64ISD::MVNImsl, Loc, Int2Vec32VT, N165, N272);
   Known = DAG->computeKnownBits(OpMVNImsl64);
-  EXPECT_EQ(Known.Zero, APInt(32, 0x00A50000));
-  EXPECT_EQ(Known.One, APInt(32, 0xFF5AFFFF));
+  EXPECT_EQ(Known.Zero, APInt(32, 0x00A5FFFF));
+  EXPECT_EQ(Known.One, APInt(32, 0xFF5A0000));
 
   auto OpMVNImsl128 =
-      DAG->getNode(AArch64ISD::MVNImsl, Loc, Int4Vec32VT, N0, N1);
+      DAG->getNode(AArch64ISD::MVNImsl, Loc, Int4Vec32VT, N165, N264);
   Known = DAG->computeKnownBits(OpMVNImsl128);
-  EXPECT_EQ(Known.Zero, APInt(32, 0x0000A500));
-  EXPECT_EQ(Known.One, APInt(32, 0xFFFF5AFF));
+  EXPECT_EQ(Known.Zero, APInt(32, 0x0000A5FF));
+  EXPECT_EQ(Known.One, APInt(32, 0xFFFF5A00));
 
-  auto N3 = DAG->getConstant(0, Loc, IntSca32VT);
+  auto N0 = DAG->getConstant(0, Loc, IntSca32VT);
   auto OpMOVIshift2Vec32 =
-      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int2Vec32VT, N0, N3);
+      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int2Vec32VT, N165, N0);
   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 N24 = DAG->getConstant(24, Loc, IntSca32VT);
   auto OpMOVIshift4Vec32 =
-      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int4Vec32VT, N0, N4);
+      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int4Vec32VT, N165, N24);
   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);
+      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int2Vec32VT, N165, N24);
   Known = DAG->computeKnownBits(OpMVNIshift2Vec32);
-  EXPECT_EQ(Known.Zero, APInt(32, 0xA5FFFFFF));
-  EXPECT_EQ(Known.One, APInt(32, 0x5A000000));
+  EXPECT_EQ(Known.Zero, APInt(32, 0xA5000000));
+  EXPECT_EQ(Known.One, APInt(32, 0x5AFFFFFF));
 
   auto OpMVNIshift4Vec32 =
-      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int4Vec32VT, N0, N3);
+      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int4Vec32VT, N165, N0);
   Known = DAG->computeKnownBits(OpMVNIshift4Vec32);
   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, N0, N3);
+      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int4Vec16VT, N165, N0);
   Known = DAG->computeKnownBits(OpMOVIshift4Vec16);
-  EXPECT_EQ(Known.One, APInt(16, 0x00A5));
   EXPECT_EQ(Known.Zero, APInt(16, 0xFF5A));
+  EXPECT_EQ(Known.One, APInt(16, 0x00A5));
 
   auto OpMOVIshift8Vec16 =
-      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int8Vec16VT, N0, N1);
+      DAG->getNode(AArch64ISD::MOVIshift, Loc, Int8Vec16VT, N165, N8);
   Known = DAG->computeKnownBits(OpMOVIshift8Vec16);
-  EXPECT_EQ(Known.One, APInt(16, 0xA500));
   EXPECT_EQ(Known.Zero, APInt(16, 0x5AFF));
+  EXPECT_EQ(Known.One, APInt(16, 0xA500));
 
   auto OpMVNIshift4Vec16 =
-      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int4Vec16VT, N0, N1);
+      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int4Vec16VT, N165, N8);
   Known = DAG->computeKnownBits(OpMVNIshift4Vec16);
-  EXPECT_EQ(Known.Zero, APInt(16, 0xA5FF));
-  EXPECT_EQ(Known.One, APInt(16, 0x5A00));
+  EXPECT_EQ(Known.Zero, APInt(16, 0xA500));
+  EXPECT_EQ(Known.One, APInt(16, 0x5AFF));
 
   auto OpMVNIshift8Vec16 =
-      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int8Vec16VT, N0, N3);
+      DAG->getNode(AArch64ISD::MVNIshift, Loc, Int8Vec16VT, N165, N0);
   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);
+  auto OpMOVI8Vec8 = DAG->getNode(AArch64ISD::MOVI, Loc, Int8Vec8VT, N165);
   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);
+  auto OpMOVI16Vec8 = DAG->getNode(AArch64ISD::MOVI, Loc, Int16Vec8VT, N165);
   Known = DAG->computeKnownBits(OpMOVI16Vec8);
   EXPECT_EQ(Known.Zero, APInt(8, 0x5A));
   EXPECT_EQ(Known.One, APInt(8, 0xA5));



More information about the llvm-commits mailing list