Skip to content

Commit

Permalink
[AArch64,ELF] Restrict MOVZ/MOVK to non-PIC large code model (#70178)
Browse files Browse the repository at this point in the history
There is no PIC support for -mcmodel=large

(https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst)
and Clang recently rejects -mcmodel= with PIC (#70262).

The current backend code assumes that the large code model is non-PIC.
This patch adds `!getTargetMachine().isPositionIndependent()` conditions
to clarify that the support is non-PIC only. In addition, add some tests
as change detectors in case PIC large code model is supported in the
future.

If other front-ends/JITs use the large code model with PIC, they will
get small code model code sequence, instead of potentially-incorrect
MOVZ/MOVK sequence, which is only suitable for non-PIC. The sequence
will cause text relocations using ELF linkers.

(The small code model code sequence is usually sufficient as ADRP+ADD or
ADRP+LDR targets [-2**32,2**32), which has a doubled range of x86-64
R_X86_64_REX_GOTPCRELX/R_X86_64_PC32 [-2**32,2**32).)
  • Loading branch information
MaskRay committed Nov 1, 2023
1 parent 442da60 commit a62b86a
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 120 deletions.
32 changes: 17 additions & 15 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8203,7 +8203,8 @@ SDValue AArch64TargetLowering::LowerGlobalAddress(SDValue Op,
}

SDValue Result;
if (getTargetMachine().getCodeModel() == CodeModel::Large) {
if (getTargetMachine().getCodeModel() == CodeModel::Large &&
!getTargetMachine().isPositionIndependent()) {
Result = getAddrLarge(GN, DAG, OpFlags);
} else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
Result = getAddrTiny(GN, DAG, OpFlags);
Expand Down Expand Up @@ -9568,12 +9569,12 @@ SDValue AArch64TargetLowering::LowerJumpTable(SDValue Op,
// is necessary here. Just get the address of the jump table.
JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);

if (getTargetMachine().getCodeModel() == CodeModel::Large &&
!Subtarget->isTargetMachO()) {
CodeModel::Model CM = getTargetMachine().getCodeModel();
if (CM == CodeModel::Large && !getTargetMachine().isPositionIndependent() &&
!Subtarget->isTargetMachO())
return getAddrLarge(JT, DAG);
} else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
if (CM == CodeModel::Tiny)
return getAddrTiny(JT, DAG);
}
return getAddr(JT, DAG);
}

Expand All @@ -9599,27 +9600,28 @@ SDValue AArch64TargetLowering::LowerBR_JT(SDValue Op,
SDValue AArch64TargetLowering::LowerConstantPool(SDValue Op,
SelectionDAG &DAG) const {
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);

if (getTargetMachine().getCodeModel() == CodeModel::Large) {
CodeModel::Model CM = getTargetMachine().getCodeModel();
if (CM == CodeModel::Large) {
// Use the GOT for the large code model on iOS.
if (Subtarget->isTargetMachO()) {
return getGOT(CP, DAG);
}
return getAddrLarge(CP, DAG);
} else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
if (!getTargetMachine().isPositionIndependent())
return getAddrLarge(CP, DAG);
} else if (CM == CodeModel::Tiny) {
return getAddrTiny(CP, DAG);
} else {
return getAddr(CP, DAG);
}
return getAddr(CP, DAG);
}

SDValue AArch64TargetLowering::LowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
BlockAddressSDNode *BA = cast<BlockAddressSDNode>(Op);
if (getTargetMachine().getCodeModel() == CodeModel::Large &&
!Subtarget->isTargetMachO()) {
return getAddrLarge(BA, DAG);
} else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
CodeModel::Model CM = getTargetMachine().getCodeModel();
if (CM == CodeModel::Large && !Subtarget->isTargetMachO()) {
if (!getTargetMachine().isPositionIndependent())
return getAddrLarge(BA, DAG);
} else if (CM == CodeModel::Tiny) {
return getAddrTiny(BA, DAG);
}
return getAddr(BA, DAG);
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2849,7 +2849,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
if (OpFlags & AArch64II::MO_GOT) {
I.setDesc(TII.get(AArch64::LOADgot));
I.getOperand(1).setTargetFlags(OpFlags);
} else if (TM.getCodeModel() == CodeModel::Large) {
} else if (TM.getCodeModel() == CodeModel::Large &&
!TM.isPositionIndependent()) {
// Materialize the global using movz/movk instructions.
materializeLargeCMVal(I, GV, OpFlags);
I.eraseFromParent();
Expand Down Expand Up @@ -3502,7 +3503,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
return true;
}
case TargetOpcode::G_BLOCK_ADDR: {
if (TM.getCodeModel() == CodeModel::Large) {
if (TM.getCodeModel() == CodeModel::Large && !TM.isPositionIndependent()) {
materializeLargeCMVal(I, I.getOperand(1).getBlockAddress(), 0);
I.eraseFromParent();
return true;
Expand Down
13 changes: 12 additions & 1 deletion llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=aarch64-unknown-unknown -o - -verify-machineinstrs -run-pass=instruction-select %s | FileCheck %s
# RUN: llc -mtriple=aarch64-unknown-unknown -o - -verify-machineinstrs -run-pass=instruction-select -code-model=large %s | FileCheck %s --check-prefix=LARGE
# RUN: llc -mtriple=aarch64-unknown-unknown -o - -verify-machineinstrs -run-pass=instruction-select -code-model=large -relocation-model=pic %s | FileCheck %s --check-prefix=LARGE-PIC
--- |
; ModuleID = 'blockaddress.ll'
source_filename = "blockaddress.ll"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-none-linux-gnu"
Expand Down Expand Up @@ -37,6 +37,7 @@ body: |
; CHECK-NEXT: BR [[MOVaddrBA]]
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1.block (ir-block-address-taken %ir-block.block):
;
; LARGE-LABEL: name: test_blockaddress
; LARGE: bb.0 (%ir-block.0):
; LARGE-NEXT: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block), 0
Expand All @@ -51,6 +52,16 @@ body: |
; LARGE-NEXT: BR [[MOVKXi2]]
; LARGE-NEXT: {{ $}}
; LARGE-NEXT: bb.1.block (ir-block-address-taken %ir-block.block):
;
; LARGE-PIC-LABEL: name: test_blockaddress
; LARGE-PIC: bb.0 (%ir-block.0):
; LARGE-PIC-NEXT: [[MOVaddrBA:%[0-9]+]]:gpr64common = MOVaddrBA target-flags(aarch64-page) blockaddress(@test_blockaddress, %ir-block.block), target-flags(aarch64-pageoff, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block)
; LARGE-PIC-NEXT: [[MOVaddr:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @addr, target-flags(aarch64-pageoff, aarch64-nc) @addr
; LARGE-PIC-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY [[MOVaddrBA]]
; LARGE-PIC-NEXT: STRXui [[COPY]], [[MOVaddr]], 0 :: (store (p0) into @addr)
; LARGE-PIC-NEXT: BR [[MOVaddrBA]]
; LARGE-PIC-NEXT: {{ $}}
; LARGE-PIC-NEXT: bb.1.block (ir-block-address-taken %ir-block.block):
bb.1 (%ir-block.0):
%0:gpr(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)
%1:gpr(p0) = G_GLOBAL_VALUE @addr
Expand Down
49 changes: 31 additions & 18 deletions llvm/test/CodeGen/AArch64/GlobalISel/select-gv-cmodel-large.mir
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=aarch64-linux-gnu -code-model=large -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s
# RUN: llc -mtriple=aarch64-linux-gnu -code-model=large -relocation-model=static -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=STATIC
# RUN: llc -mtriple=aarch64-linux-gnu -code-model=large -relocation-model=pic -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=PIC
--- |
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"

Expand Down Expand Up @@ -29,23 +30,35 @@ stack:
constants:
body: |
bb.1:
; CHECK-LABEL: name: gv_large
; CHECK: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @foo1, 0
; CHECK: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) @foo1, 16
; CHECK: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) @foo1, 32
; CHECK: [[MOVKXi2:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi1]], target-flags(aarch64-g3) @foo1, 48
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY [[MOVKXi2]]
; CHECK: [[MOVZXi1:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @foo2, 0
; CHECK: [[MOVKXi3:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi1]], target-flags(aarch64-g1, aarch64-nc) @foo2, 16
; CHECK: [[MOVKXi4:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi3]], target-flags(aarch64-g2, aarch64-nc) @foo2, 32
; CHECK: [[MOVKXi5:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi4]], target-flags(aarch64-g3) @foo2, 48
; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY [[MOVKXi5]]
; CHECK: STRWui $wzr, %stack.0.retval, 0 :: (store (s32) into %ir.retval)
; CHECK: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load (s32) from @foo1)
; CHECK: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY1]], 0 :: (load (s32) from @foo2)
; CHECK: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[LDRWui]], [[LDRWui1]]
; CHECK: $w0 = COPY [[ADDWrr]]
; CHECK: RET_ReallyLR implicit $w0
; STATIC-LABEL: name: gv_large
; STATIC: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @foo1, 0
; STATIC-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) @foo1, 16
; STATIC-NEXT: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) @foo1, 32
; STATIC-NEXT: [[MOVKXi2:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi1]], target-flags(aarch64-g3) @foo1, 48
; STATIC-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY [[MOVKXi2]]
; STATIC-NEXT: [[MOVZXi1:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @foo2, 0
; STATIC-NEXT: [[MOVKXi3:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi1]], target-flags(aarch64-g1, aarch64-nc) @foo2, 16
; STATIC-NEXT: [[MOVKXi4:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi3]], target-flags(aarch64-g2, aarch64-nc) @foo2, 32
; STATIC-NEXT: [[MOVKXi5:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi4]], target-flags(aarch64-g3) @foo2, 48
; STATIC-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY [[MOVKXi5]]
; STATIC-NEXT: STRWui $wzr, %stack.0.retval, 0 :: (store (s32) into %ir.retval)
; STATIC-NEXT: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load (s32) from @foo1)
; STATIC-NEXT: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY1]], 0 :: (load (s32) from @foo2)
; STATIC-NEXT: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[LDRWui]], [[LDRWui1]]
; STATIC-NEXT: $w0 = COPY [[ADDWrr]]
; STATIC-NEXT: RET_ReallyLR implicit $w0
;
; PIC-LABEL: name: gv_large
; PIC: [[MOVaddr:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @foo1, target-flags(aarch64-pageoff, aarch64-nc) @foo1
; PIC-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY [[MOVaddr]]
; PIC-NEXT: [[MOVaddr1:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @foo2, target-flags(aarch64-pageoff, aarch64-nc) @foo2
; PIC-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY [[MOVaddr1]]
; PIC-NEXT: STRWui $wzr, %stack.0.retval, 0 :: (store (s32) into %ir.retval)
; PIC-NEXT: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load (s32) from @foo1)
; PIC-NEXT: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY1]], 0 :: (load (s32) from @foo2)
; PIC-NEXT: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[LDRWui]], [[LDRWui1]]
; PIC-NEXT: $w0 = COPY [[ADDWrr]]
; PIC-NEXT: RET_ReallyLR implicit $w0
%1:gpr(s32) = G_CONSTANT i32 0
%4:gpr(p0) = G_GLOBAL_VALUE @foo1
%3:gpr(p0) = COPY %4(p0)
Expand Down
37 changes: 25 additions & 12 deletions llvm/test/CodeGen/AArch64/GlobalISel/select-gv-with-offset.mir
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=aarch64 -code-model=large -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=LARGE
# RUN: llc -mtriple=aarch64 -code-model=large -relocation-model=pic -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=LARGE-PIC
# RUN: llc -mtriple=aarch64 -code-model=small -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=SMALL
# RUN: llc -mtriple=aarch64 -code-model=tiny -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=TINY

Expand All @@ -17,22 +18,34 @@ body: |
liveins: $x0
; LARGE-LABEL: name: select_gv_with_offset
; LARGE: liveins: $x0
; LARGE: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @g + 1, 0
; LARGE: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) @g + 1, 16
; LARGE: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) @g + 1, 32
; LARGE: %g:gpr64 = MOVKXi [[MOVKXi1]], target-flags(aarch64-g3) @g + 1, 48
; LARGE: $x0 = COPY %g
; LARGE: RET_ReallyLR implicit $x0
; LARGE-NEXT: {{ $}}
; LARGE-NEXT: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @g + 1, 0
; LARGE-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) @g + 1, 16
; LARGE-NEXT: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) @g + 1, 32
; LARGE-NEXT: %g:gpr64 = MOVKXi [[MOVKXi1]], target-flags(aarch64-g3) @g + 1, 48
; LARGE-NEXT: $x0 = COPY %g
; LARGE-NEXT: RET_ReallyLR implicit $x0
;
; LARGE-PIC-LABEL: name: select_gv_with_offset
; LARGE-PIC: liveins: $x0
; LARGE-PIC-NEXT: {{ $}}
; LARGE-PIC-NEXT: %g:gpr64common = MOVaddr target-flags(aarch64-page) @g + 1, target-flags(aarch64-pageoff, aarch64-nc) @g + 1
; LARGE-PIC-NEXT: $x0 = COPY %g
; LARGE-PIC-NEXT: RET_ReallyLR implicit $x0
;
; SMALL-LABEL: name: select_gv_with_offset
; SMALL: liveins: $x0
; SMALL: %g:gpr64common = MOVaddr target-flags(aarch64-page) @g + 1, target-flags(aarch64-pageoff, aarch64-nc) @g + 1
; SMALL: $x0 = COPY %g
; SMALL: RET_ReallyLR implicit $x0
; SMALL-NEXT: {{ $}}
; SMALL-NEXT: %g:gpr64common = MOVaddr target-flags(aarch64-page) @g + 1, target-flags(aarch64-pageoff, aarch64-nc) @g + 1
; SMALL-NEXT: $x0 = COPY %g
; SMALL-NEXT: RET_ReallyLR implicit $x0
;
; TINY-LABEL: name: select_gv_with_offset
; TINY: liveins: $x0
; TINY: %g:gpr64 = ADR @g + 1
; TINY: $x0 = COPY %g
; TINY: RET_ReallyLR implicit $x0
; TINY-NEXT: {{ $}}
; TINY-NEXT: %g:gpr64 = ADR @g + 1
; TINY-NEXT: $x0 = COPY %g
; TINY-NEXT: RET_ReallyLR implicit $x0
%g:gpr(p0) = G_GLOBAL_VALUE @g + 1
$x0 = COPY %g(p0)
RET_ReallyLR implicit $x0
1 change: 1 addition & 0 deletions llvm/test/CodeGen/AArch64/blockaddress.ll
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
; RUN: llc -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck %s
; RUN: llc -code-model=large -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-LARGE %s
; RUN: llc -code-model=large -relocation-model=pic -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 < %s | FileCheck %s
; RUN: llc -code-model=tiny -mtriple=aarch64-none-elf -aarch64-enable-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-TINY %s

@addr = global ptr null
Expand Down
72 changes: 0 additions & 72 deletions llvm/test/CodeGen/AArch64/code-model-large-abs.ll

This file was deleted.

0 comments on commit a62b86a

Please sign in to comment.