From c93d50dd716879a7edb2c28f4bf9d435651f3766 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Mon, 8 Feb 2021 14:47:14 +0000 Subject: [PATCH] AArch64: use a constpool for blockaddress(...) on MachO More MachO madness for everyone. MachO relocations are only 32-bits, which means the ARM64_RELOC_ADDEND one only actually has 24 (signed) bits for the actual addend. This is a problem when calculating the address of a basic block; because it has no symbol of its own, the sequence adrp x0, Ltmp0@PAGE add x0, x0, x0 Ltmp0@PAGEOFF is represented by relocation with an addend that contains the offset from the function start to Ltmp, and so the largest function where this is guaranteed to work is 8MB. That's not quite big enough that we can call it user error (IMO). So this patch puts the any blockaddress into a constant-pool, where the addend is instead stored in the (x)word being relocated, which is obviously big enough for any function. --- .../Target/AArch64/AArch64ExpandPseudoInsts.cpp | 28 +++++++++++++++++++++- llvm/test/CodeGen/AArch64/arm64-blockaddress.ll | 11 +++++---- llvm/test/CodeGen/AArch64/arm64_32.ll | 4 ++-- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index e57650a..f72d3cf 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -23,6 +23,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" @@ -877,11 +878,36 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } + case AArch64::MOVaddrBA: { + MachineFunction &MF = *MI.getParent()->getParent(); + if (MF.getSubtarget().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; + } + } + LLVM_FALLTHROUGH; case AArch64::MOVaddr: case AArch64::MOVaddrJT: case AArch64::MOVaddrCP: - case AArch64::MOVaddrBA: case AArch64::MOVaddrTLS: case AArch64::MOVaddrEXT: { // Expand into ADRP + ADD. diff --git a/llvm/test/CodeGen/AArch64/arm64-blockaddress.ll b/llvm/test/CodeGen/AArch64/arm64-blockaddress.ll index b35cb28..68b8fcb 100644 --- a/llvm/test/CodeGen/AArch64/arm64-blockaddress.ll +++ b/llvm/test/CodeGen/AArch64/arm64-blockaddress.ll @@ -1,4 +1,5 @@ -; RUN: llc < %s -mtriple=arm64-apple-ios | FileCheck %s +; RUN: llc < %s -mtriple=arm64-apple-ios | FileCheck %s --check-prefix=CHECK-IOS +; RUN: llc < %s -mtriple=arm64-apple-ios -global-isel | FileCheck %s --check-prefix=CHECK-IOS ; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s --check-prefix=CHECK-LINUX ; RUN: llc < %s -mtriple=arm64-linux-gnu -code-model=large| FileCheck %s --check-prefix=CHECK-LARGE @@ -6,9 +7,11 @@ define i64 @t() nounwind ssp { entry: -; CHECK-LABEL: t: -; CHECK: adrp [[REG:x[0-9]+]], Ltmp0@PAGE -; CHECK: add {{x[0-9]+}}, [[REG]], Ltmp0@PAGEOFF +; CHECK-IOS: lCPI0_0: +; CHECK-IOS: .quad Ltmp0 +; CHECK-IOS-LABEL: _t: +; CHECK-IOS: adrp x[[TMP:[0-9]+]], lCPI0_0@PAGE +; CHECK-IOS: ldr {{x[0-9]+}}, [x[[TMP]], lCPI0_0@PAGEOFF] ; CHECK-LINUX-LABEL: t: ; CHECK-LINUX: adrp [[REG:x[0-9]+]], .Ltmp0 diff --git a/llvm/test/CodeGen/AArch64/arm64_32.ll b/llvm/test/CodeGen/AArch64/arm64_32.ll index 7853229..b5c2c6e 100644 --- a/llvm/test/CodeGen/AArch64/arm64_32.ll +++ b/llvm/test/CodeGen/AArch64/arm64_32.ll @@ -452,8 +452,8 @@ define double @test_constpool() { define i8* @test_blockaddress() { ; CHECK-LABEL: test_blockaddress: ; CHECK: [[BLOCK:Ltmp[0-9]+]]: -; CHECK: adrp [[PAGE:x[0-9]+]], [[BLOCK]]@PAGE -; CHECK: add x0, [[PAGE]], [[BLOCK]]@PAGEOFF +; CHECK: adrp x[[PAGE:[0-9]+]], lCPI{{[0-9]+_[0-9]+}}@PAGE +; CHECK: ldr x0, [x[[PAGE]], lCPI{{[0-9]+_[0-9]+}}@PAGEOFF] br label %dest dest: ret i8* blockaddress(@test_blockaddress, %dest) -- 2.7.4