[llvm-branch-commits] [llvm] [AArch64] Report accurate sizes for MOVaddr and MOVimm pseudos (PR #183506)

Guy David via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Feb 26 04:24:08 PST 2026


https://github.com/guy-david updated https://github.com/llvm/llvm-project/pull/183506

>From bb30e2892725f1342a113cceee3c293e45b1eabf Mon Sep 17 00:00:00 2001
From: Guy David <guyda96 at gmail.com>
Date: Thu, 26 Feb 2026 11:35:08 +0200
Subject: [PATCH] [AArch64] Report accurate sizes for MOVaddr and MOVimm
 pseudos

---
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 44 ++++++----
 llvm/unittests/Target/AArch64/InstSizes.cpp  | 89 ++++++++++++++++++++
 2 files changed, 117 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index f302b52a461e1..f6c6413e1622e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -194,6 +194,33 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
   case AArch64::SPACE:
     NumBytes = MI.getOperand(1).getImm();
     break;
+
+  case AArch64::MOVaddr:
+  case AArch64::MOVaddrJT:
+  case AArch64::MOVaddrCP:
+  case AArch64::MOVaddrBA:
+  case AArch64::MOVaddrTLS:
+  case AArch64::MOVaddrEXT: {
+    // Use the same logic as the pseudo expansion to count instructions.
+    SmallVector<AArch64_ExpandPseudo::AddrInsnModel, 3> Insn;
+    AArch64_ExpandPseudo::expandMOVAddr(Desc.getOpcode(),
+                                        MI.getOperand(1).getTargetFlags(),
+                                        Subtarget.isTargetMachO(), Insn);
+    NumBytes = Insn.size() * 4;
+    break;
+  }
+
+  case AArch64::MOVi32imm:
+  case AArch64::MOVi64imm: {
+    // Use the same logic as the pseudo expansion to count instructions.
+    unsigned BitSize = Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
+    SmallVector<AArch64_ExpandPseudo::ImmInsnModel, 4> Insn;
+    AArch64_ExpandPseudo::expandMOVImm(MI.getOperand(1).getImm(), BitSize,
+                                       Insn);
+    NumBytes = Insn.size() * 4;
+    break;
+  }
+
   case TargetOpcode::BUNDLE:
     NumBytes = getInstBundleLength(MI);
     break;
@@ -1215,20 +1242,6 @@ void AArch64InstrInfo::insertSelect(MachineBasicBlock &MBB,
       .addImm(CC);
 }
 
-// Return true if Imm can be loaded into a register by a "cheap" sequence of
-// instructions. For now, "cheap" means at most two instructions.
-static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize) {
-  if (BitSize == 32)
-    return true;
-
-  assert(BitSize == 64 && "Only bit sizes of 32 or 64 allowed");
-  uint64_t Imm = static_cast<uint64_t>(MI.getOperand(1).getImm());
-  SmallVector<AArch64_ExpandPseudo::ImmInsnModel, 4> Is;
-  AArch64_ExpandPseudo::expandMOVImm(Imm, BitSize, Is);
-
-  return Is.size() <= 2;
-}
-
 // Check if a COPY instruction is cheap.
 static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI) {
   assert(MI.isCopy() && "Expected COPY instruction");
@@ -1277,9 +1290,8 @@ bool AArch64InstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const {
   // ORRXri, it is as cheap as MOV.
   // Likewise if it can be expanded to MOVZ/MOVN/MOVK.
   case AArch64::MOVi32imm:
-    return isCheapImmediate(MI, 32);
   case AArch64::MOVi64imm:
-    return isCheapImmediate(MI, 64);
+    return getInstSizeInBytes(MI) <= 8;
   }
 }
 
diff --git a/llvm/unittests/Target/AArch64/InstSizes.cpp b/llvm/unittests/Target/AArch64/InstSizes.cpp
index c9faee80e7e49..9dffb6e600d62 100644
--- a/llvm/unittests/Target/AArch64/InstSizes.cpp
+++ b/llvm/unittests/Target/AArch64/InstSizes.cpp
@@ -251,6 +251,95 @@ TEST(InstSizes, JumpTable) {
             });
 }
 
+TEST(InstSizes, MOVaddr) {
+  std::unique_ptr<TargetMachine> TM = createTargetMachine();
+  std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
+
+  auto Check8 = [](AArch64InstrInfo &II, MachineFunction &MF) {
+    auto I = MF.begin()->begin();
+    EXPECT_EQ(8u, II.getInstSizeInBytes(*I));
+  };
+
+  runChecks(TM.get(), II.get(), "  @g = external global i32\n",
+            "    $x0 = MOVaddr target-flags(aarch64-page) @g, "
+            "target-flags(aarch64-pageoff, aarch64-nc) @g\n",
+            Check8);
+
+  runChecks(TM.get(), II.get(), "",
+            "    $x0 = MOVaddrJT target-flags(aarch64-page) %jump-table.0, "
+            "target-flags(aarch64-pageoff, aarch64-nc) %jump-table.0\n",
+            Check8);
+
+  runChecks(TM.get(), II.get(), "  @g = external global i32\n",
+            "    $x0 = MOVaddrTLS target-flags(aarch64-page) @g, "
+            "target-flags(aarch64-pageoff, aarch64-nc) @g\n",
+            Check8);
+
+  runChecks(TM.get(), II.get(), "",
+            "    $x0 = MOVaddrEXT target-flags(aarch64-page) &memcpy, "
+            "target-flags(aarch64-pageoff, aarch64-nc) &memcpy\n",
+            Check8);
+
+  runChecks(TM.get(), II.get(),
+            "  define void @test_bb() {\n"
+            "  entry:\n"
+            "    br label %block\n"
+            "  block:\n"
+            "    ret void\n"
+            "  }\n",
+            "    $x0 = MOVaddrBA target-flags(aarch64-page) "
+            "blockaddress(@test_bb, %ir-block.block), "
+            "target-flags(aarch64-pageoff, aarch64-nc) "
+            "blockaddress(@test_bb, %ir-block.block)\n",
+            Check8);
+}
+
+TEST(InstSizes, MOVaddrTagged) {
+  std::unique_ptr<TargetMachine> TM = createTargetMachine();
+  std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
+
+  runChecks(TM.get(), II.get(), "  @g = external global i32\n",
+            "    $x0 = MOVaddr target-flags(aarch64-page, aarch64-tagged) @g, "
+            "target-flags(aarch64-pageoff, aarch64-nc) @g\n",
+            [](AArch64InstrInfo &II, MachineFunction &MF) {
+              auto I = MF.begin()->begin();
+              EXPECT_EQ(12u, II.getInstSizeInBytes(*I));
+            });
+}
+
+TEST(InstSizes, MOVi32imm) {
+  std::unique_ptr<TargetMachine> TM = createTargetMachine();
+  std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
+
+  runChecks(TM.get(), II.get(), "",
+            "    $w0 = MOVi32imm 1\n"
+            "    $w1 = MOVi32imm 65536\n",
+            [](AArch64InstrInfo &II, MachineFunction &MF) {
+              auto I = MF.begin()->begin();
+              EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
+              ++I;
+              EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
+            });
+}
+
+TEST(InstSizes, MOVi64imm) {
+  std::unique_ptr<TargetMachine> TM = createTargetMachine();
+  std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
+
+  runChecks(TM.get(), II.get(), "",
+            "    $x0 = MOVi64imm 1\n"
+            "    $x1 = MOVi64imm 65537\n"
+            "    $x2 = MOVi64imm 1311768467463790320\n",
+            [](AArch64InstrInfo &II, MachineFunction &MF) {
+              auto I = MF.begin()->begin();
+              EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
+              ++I;
+              EXPECT_EQ(8u, II.getInstSizeInBytes(*I));
+              ++I;
+              EXPECT_EQ(16u, II.getInstSizeInBytes(*I));
+            });
+}
+
 TEST(InstSizes, MOPSMemoryPseudos) {
   std::unique_ptr<TargetMachine> TM = createTargetMachine();
   std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());



More information about the llvm-branch-commits mailing list