[llvm] [AArch64] Add support for custom MOVI and MVN (PR #148698)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 14 11:34:37 PDT 2025


https://github.com/aabhinavg1 created https://github.com/llvm/llvm-project/pull/148698

- Implemented custom pattern matching for MOVI and MVNI vector instructions.
- Added tests to verify MOVI.16b, MOVI.4s, MVNI.4s with shift and without shift.
- Ensured correct codegen for specific immediate constants using AArch64 ISel lowering.
Fixes #148634

>From 1259e7378e51e9c6f3d2af71a9270895c9a9a7ef Mon Sep 17 00:00:00 2001
From: aabhinavg1 <tiwariabhinavak at gmail.com>
Date: Mon, 14 Jul 2025 23:59:41 +0530
Subject: [PATCH] [AArch64] Add support for custom MOVI and MVN

- Implemented custom pattern matching for MOVI and MVNI vector instructions.
- Added tests to verify MOVI.16b, MOVI.4s, MVNI.4s with shift and without shift.
- Ensured correct codegen for specific immediate constants using AArch64 ISel lowering.
---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 40 +++++++++++++++++--
 llvm/test/CodeGen/AArch64/movi-custom.ll      | 30 ++++++++++++++
 2 files changed, 67 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/movi-custom.ll

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 55601e6327e98..43e5ed6c53f61 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -2599,6 +2599,36 @@ void AArch64TargetLowering::computeKnownBitsForTargetNode(
     Known = KnownBits::makeConstant(
         APInt(Known.getBitWidth(), Op->getConstantOperandVal(0)));
     break;
+  }
+    case AArch64ISD::MOVIedit: {
+    if (Op.getNumOperands() < 2 || !isa<ConstantSDNode>(Op.getOperand(0)) ||
+        !isa<ConstantSDNode>(Op.getOperand(1))) {
+      break; // Or assert, or return
+    }
+    uint64_t Val = Op->getConstantOperandVal(0);
+    uint64_t Mask = Op->getConstantOperandVal(1);
+    Known = KnownBits::makeConstant(APInt(Known.getBitWidth(), Val | Mask));
+    break;
+  }
+  case AArch64ISD::MOVImsl: {
+    uint64_t Val = Op->getConstantOperandVal(0);
+    uint64_t Shift = Op->getConstantOperandVal(1);
+    Known = KnownBits::makeConstant(
+        APInt(Known.getBitWidth(), Val * (1ULL << Shift)));
+    break;
+  }
+  case AArch64ISD::MVNIshift: {
+    uint64_t Val = Op->getConstantOperandVal(0);
+    uint64_t Shift = Op->getConstantOperandVal(1);
+    Known = KnownBits::makeConstant(~APInt(Known.getBitWidth(), Val << Shift));
+    break;
+  }
+  case AArch64ISD::MVNImsl: {
+    uint64_t Val = Op->getConstantOperandVal(0);
+    uint64_t Shift = Op->getConstantOperandVal(1);
+    Known = KnownBits::makeConstant(
+        ~APInt(Known.getBitWidth(), Val * (1ULL << Shift)));
+    break;
   }
   case AArch64ISD::LOADgot:
   case AArch64ISD::ADDlow: {
@@ -30285,13 +30315,17 @@ bool AArch64TargetLowering::SimplifyDemandedBitsForTargetNode(
 }
 
 bool AArch64TargetLowering::isTargetCanonicalConstantNode(SDValue Op) const {
-  return Op.getOpcode() == AArch64ISD::DUP ||
-         Op.getOpcode() == AArch64ISD::MOVI ||
-         (Op.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
+  unsigned Opc = Op.getOpcode();
+  return Opc == AArch64ISD::DUP || Opc == AArch64ISD::MOVI ||
+         Opc == AArch64ISD::MOVIshift || Opc == AArch64ISD::MOVIedit ||
+         Opc == AArch64ISD::MOVImsl || Opc == AArch64ISD::MVNIshift ||
+         Opc == AArch64ISD::MVNImsl ||
+         (Opc == ISD::EXTRACT_SUBVECTOR &&
           Op.getOperand(0).getOpcode() == AArch64ISD::DUP) ||
          TargetLowering::isTargetCanonicalConstantNode(Op);
 }
 
+
 bool AArch64TargetLowering::isComplexDeinterleavingSupported() const {
   return Subtarget->hasSVE() || Subtarget->hasSVE2() ||
          Subtarget->hasComplxNum();
diff --git a/llvm/test/CodeGen/AArch64/movi-custom.ll b/llvm/test/CodeGen/AArch64/movi-custom.ll
new file mode 100644
index 0000000000000..14c8fd5c994d9
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/movi-custom.ll
@@ -0,0 +1,30 @@
+; RUN: llc -mtriple=aarch64-linux-gnu < %s -o - | FileCheck %s
+
+; Test 1: AArch64ISD::MOVIedit
+define <16 x i8> @test_movi_edit() {
+; CHECK-LABEL: test_movi_edit:
+; CHECK:       movi v0.16b, #63
+  ret <16 x i8> <i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63,
+                 i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63>
+}
+
+; Test 2: AArch64ISD::MOVImsl
+define <4 x i32> @test_movi_msl() {
+; CHECK-LABEL: test_movi_msl:
+; CHECK:       movi v0.4s, #64
+  ret <4 x i32> <i32 64, i32 64, i32 64, i32 64>
+}
+
+; Test 3: AArch64ISD::MVNIshift
+define <4 x i32> @test_mvni_shift() {
+; CHECK-LABEL: test_mvni_shift:
+; CHECK:       movi v0.2d, #0xffff00ffffff00ff
+  ret <4 x i32> <i32 -65281, i32 -65281, i32 -65281, i32 -65281>
+}
+
+; Test 4: AArch64ISD::MVNImsl
+define <4 x i32> @test_mvnimsl() {
+; CHECK-LABEL: test_mvnimsl:
+; CHECK:       mvni v0.4s, #64
+  ret <4 x i32> <i32 -65, i32 -65, i32 -65, i32 -65>
+}



More information about the llvm-commits mailing list