Skip to content

Commit 7358c29

Browse files
committed
[llvm] Teach FastISel for AArch64 about tagged globals
This addresses llvm#57750. For some globals, the tag wasn't propagated correctly because the necessary movk wasn't emitted sometimes. Differential Revision: https://reviews.llvm.org/D138615
1 parent 3c278e5 commit 7358c29

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

llvm/lib/Target/AArch64/AArch64FastISel.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,30 @@ unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) {
496496
ADRPReg)
497497
.addGlobalAddress(GV, 0, AArch64II::MO_PAGE | OpFlags);
498498

499+
if (OpFlags & AArch64II::MO_TAGGED) {
500+
// MO_TAGGED on the page indicates a tagged address. Set the tag now.
501+
// We do so by creating a MOVK that sets bits 48-63 of the register to
502+
// (global address + 0x100000000 - PC) >> 48. This assumes that we're in
503+
// the small code model so we can assume a binary size of <= 4GB, which
504+
// makes the untagged PC relative offset positive. The binary must also be
505+
// loaded into address range [0, 2^48). Both of these properties need to
506+
// be ensured at runtime when using tagged addresses.
507+
//
508+
// TODO: There is duplicate logic in AArch64ExpandPseudoInsts.cpp that
509+
// also uses BuildMI for making an ADRP (+ MOVK) + ADD, but the operands
510+
// are not exactly 1:1 with FastISel so we cannot easily abstract this
511+
// out. At some point, it would be nice to find a way to not have this
512+
// duplciate code.
513+
unsigned DstReg = createResultReg(&AArch64::GPR64spRegClass);
514+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::MOVKXi),
515+
DstReg)
516+
.addReg(ADRPReg)
517+
.addGlobalAddress(GV, /*Offset=*/0x100000000,
518+
AArch64II::MO_PREL | AArch64II::MO_G3)
519+
.addImm(48);
520+
ADRPReg = DstReg;
521+
}
522+
499523
ResultReg = createResultReg(&AArch64::GPR64spRegClass);
500524
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(AArch64::ADDXri),
501525
ResultReg)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
; RUN: llc < %s -fast-isel -relocation-model=pic | FileCheck %s
2+
3+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
4+
target triple = "aarch64-unknown-linux-gnu"
5+
6+
@glob.hwasan = private constant i64 0
7+
8+
;; The constant here is 0x2F << 56. This effectively makes the alias a tagged version of the original global.
9+
@glob = private alias i64, inttoptr (i64 add (i64 ptrtoint (ptr @glob.hwasan to i64), i64 3386706919782612992) to ptr)
10+
11+
; CHECK-LABEL: func
12+
define void @func() #0 {
13+
entry:
14+
; CHECK: adrp [[REG:x[0-9]+]], :pg_hi21_nc:.Lglob
15+
; CHECK-NEXT: movk [[REG]], #:prel_g3:.Lglob+4294967296
16+
; CHECK-NEXT: add x0, [[REG]], :lo12:.Lglob
17+
call void @extern_func(ptr @glob)
18+
ret void
19+
}
20+
21+
declare void @extern_func(ptr)
22+
23+
attributes #0 = { "target-features"="+tagged-globals" }

0 commit comments

Comments
 (0)