[llvm] 9f49b77 - [NFC][AArch64] Extract MOVaddr* expansion model into common header (#183503)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 13 05:41:40 PDT 2026
Author: Guy David
Date: 2026-05-13T15:41:35+03:00
New Revision: 9f49b779a34664220fb2895012aa50e8dbf19a6d
URL: https://github.com/llvm/llvm-project/commit/9f49b779a34664220fb2895012aa50e8dbf19a6d
DIFF: https://github.com/llvm/llvm-project/commit/9f49b779a34664220fb2895012aa50e8dbf19a6d.diff
LOG: [NFC][AArch64] Extract MOVaddr* expansion model into common header (#183503)
This makes the expansion logic reusable by getInstSizeInBytes in a
follow-up patch.
Added:
Modified:
llvm/lib/Target/AArch64/AArch64ExpandImm.cpp
llvm/lib/Target/AArch64/AArch64ExpandImm.h
llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp b/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp
index f44cb8a0628d7..04c217ca34f00 100644
--- a/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp
@@ -720,3 +720,18 @@ void AArch64_IMM::expandMOVImm(uint64_t Imm, unsigned BitSize,
// four-instruction sequence.
expandMOVImmSimple(Imm, BitSize, OneChunks, ZeroChunks, Insn);
}
+
+void AArch64_IMM::expandMOVAddr(unsigned Opcode, unsigned TargetFlags,
+ bool IsTargetMachO,
+ SmallVectorImpl<AddrInsnModel> &Insn) {
+ if (Opcode == AArch64::MOVaddrBA && IsTargetMachO) {
+ // Block address on Mach-O goes through a constant pool.
+ Insn.push_back({AArch64::ADRP});
+ Insn.push_back({AArch64::LDRXui});
+ return;
+ }
+ Insn.push_back({AArch64::ADRP});
+ if (TargetFlags & AArch64II::MO_TAGGED)
+ Insn.push_back({AArch64::MOVKXi});
+ Insn.push_back({AArch64::ADDXri});
+}
diff --git a/llvm/lib/Target/AArch64/AArch64ExpandImm.h b/llvm/lib/Target/AArch64/AArch64ExpandImm.h
index 42c97d2c3e9b5..c3376520eb410 100644
--- a/llvm/lib/Target/AArch64/AArch64ExpandImm.h
+++ b/llvm/lib/Target/AArch64/AArch64ExpandImm.h
@@ -25,8 +25,15 @@ struct ImmInsnModel {
uint64_t Op2;
};
+struct AddrInsnModel {
+ unsigned Opcode;
+};
+
void expandMOVImm(uint64_t Imm, unsigned BitSize,
- SmallVectorImpl<ImmInsnModel> &Insn);
+ SmallVectorImpl<ImmInsnModel> &Insn);
+
+void expandMOVAddr(unsigned Opcode, unsigned TargetFlags, bool IsTargetMachO,
+ SmallVectorImpl<AddrInsnModel> &Insn);
} // end namespace AArch64_IMM
diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
index 535f9e4fac8c5..5fa93da1544fc 100644
--- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
@@ -1539,70 +1539,88 @@ bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &MBB,
MI.eraseFromParent();
return true;
}
- case AArch64::MOVaddrBA: {
- MachineFunction &MF = *MI.getParent()->getParent();
- if (MF.getSubtarget<AArch64Subtarget>().isTargetMachO()) {
- // blockaddress expressions have to come from a constant pool because the
- // largest addend (and hence offset within a function) allowed for ADRP is
- // only 8MB.
- const BlockAddress *BA = MI.getOperand(1).getBlockAddress();
- assert(MI.getOperand(1).getOffset() == 0 && "unexpected offset");
-
- MachineConstantPool *MCP = MF.getConstantPool();
- unsigned CPIdx = MCP->getConstantPoolIndex(BA, Align(8));
-
- Register DstReg = MI.getOperand(0).getReg();
- auto MIB1 =
- BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
- .addConstantPoolIndex(CPIdx, 0, AArch64II::MO_PAGE);
- auto MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
- TII->get(AArch64::LDRXui), DstReg)
- .addUse(DstReg)
- .addConstantPoolIndex(
- CPIdx, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
- transferImpOps(MI, MIB1, MIB2);
- MI.eraseFromParent();
- return true;
- }
- }
- [[fallthrough]];
+ case AArch64::MOVaddrBA:
case AArch64::MOVaddr:
case AArch64::MOVaddrJT:
case AArch64::MOVaddrCP:
case AArch64::MOVaddrTLS:
case AArch64::MOVaddrEXT: {
- // Expand into ADRP + ADD.
+ MachineFunction &MF = *MI.getParent()->getParent();
Register DstReg = MI.getOperand(0).getReg();
assert(DstReg != AArch64::XZR);
- MachineInstrBuilder MIB1 =
- BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
- .add(MI.getOperand(1));
-
- if (MI.getOperand(1).getTargetFlags() & AArch64II::MO_TAGGED) {
- // MO_TAGGED on the page indicates a tagged address. Set the tag now.
- // We do so by creating a MOVK that sets bits 48-63 of the register to
- // (global address + 0x100000000 - PC) >> 48. This assumes that we're in
- // the small code model so we can assume a binary size of <= 4GB, which
- // makes the untagged PC relative offset positive. The binary must also be
- // loaded into address range [0, 2^48). Both of these properties need to
- // be ensured at runtime when using tagged addresses.
- auto Tag = MI.getOperand(1);
- Tag.setTargetFlags(AArch64II::MO_PREL | AArch64II::MO_G3);
- Tag.setOffset(0x100000000);
- BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi), DstReg)
- .addReg(DstReg)
- .add(Tag)
- .addImm(48);
+
+ bool IsTargetMachO = MF.getSubtarget<AArch64Subtarget>().isTargetMachO();
+ SmallVector<AArch64_IMM::AddrInsnModel, 3> Insn;
+ AArch64_IMM::expandMOVAddr(
+ MI.getOpcode(), MI.getOperand(1).getTargetFlags(), IsTargetMachO, Insn);
+
+ // Compute the constant pool index, if any.
+ std::optional<unsigned> CPIdx;
+ if (Opcode == AArch64::MOVaddrBA && IsTargetMachO) {
+ // blockaddress expressions have to come from a constant pool because the
+ // largest addend (and hence offset within a function) allowed for ADRP is
+ // only 8MB.
+ const BlockAddress *BA = MI.getOperand(1).getBlockAddress();
+ assert(MI.getOperand(1).getOffset() == 0 && "unexpected offset");
+ MachineConstantPool *MCP = MF.getConstantPool();
+ CPIdx = MCP->getConstantPoolIndex(BA, Align(8));
}
- MachineInstrBuilder MIB2 =
- BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
- .add(MI.getOperand(0))
- .addReg(DstReg)
- .add(MI.getOperand(2))
- .addImm(0);
+ MachineInstrBuilder FirstMIB;
+ MachineInstrBuilder LastMIB;
+ for (const auto &I : Insn) {
+ MachineInstrBuilder MIB;
+ switch (I.Opcode) {
+ case AArch64::ADRP:
+ MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP),
+ DstReg);
+ if (CPIdx)
+ MIB.addConstantPoolIndex(*CPIdx, 0, AArch64II::MO_PAGE);
+ else
+ MIB.add(MI.getOperand(1));
+ break;
+ case AArch64::LDRXui:
+ MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRXui),
+ DstReg)
+ .addUse(DstReg)
+ .addConstantPoolIndex(
+ *CPIdx, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
+ break;
+ case AArch64::MOVKXi: {
+ // MO_TAGGED on the page indicates a tagged address. Set the tag now.
+ // We do so by creating a MOVK that sets bits 48-63 of the register to
+ // (global address + 0x100000000 - PC) >> 48. This assumes that we're in
+ // the small code model so we can assume a binary size of <= 4GB, which
+ // makes the untagged PC relative offset positive. The binary must also
+ // be loaded into address range [0, 2^48). Both of these properties need
+ // to be ensured at runtime when using tagged addresses.
+ auto Tag = MI.getOperand(1);
+ Tag.setTargetFlags(AArch64II::MO_PREL | AArch64II::MO_G3);
+ Tag.setOffset(0x100000000);
+ MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi),
+ DstReg)
+ .addReg(DstReg)
+ .add(Tag)
+ .addImm(48);
+ break;
+ }
+ case AArch64::ADDXri:
+ MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
+ .add(MI.getOperand(0))
+ .addReg(DstReg)
+ .add(MI.getOperand(2))
+ .addImm(0);
+ break;
+ default:
+ llvm_unreachable("unexpected opcode in MOVaddr expansion");
+ }
+
+ if (!FirstMIB.getInstr())
+ FirstMIB = MIB;
+ LastMIB = MIB;
+ }
- transferImpOps(MI, MIB1, MIB2);
+ transferImpOps(MI, FirstMIB, LastMIB);
MI.eraseFromParent();
return true;
}
More information about the llvm-commits
mailing list