Skip to content

Commit a62b86a

Browse files
authored
[AArch64,ELF] Restrict MOVZ/MOVK to non-PIC large code model (#70178)
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).)
1 parent 442da60 commit a62b86a

9 files changed

+234
-120
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

+17-15
Original file line numberDiff line numberDiff line change
@@ -8203,7 +8203,8 @@ SDValue AArch64TargetLowering::LowerGlobalAddress(SDValue Op,
82038203
}
82048204

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

9571-
if (getTargetMachine().getCodeModel() == CodeModel::Large &&
9572-
!Subtarget->isTargetMachO()) {
9572+
CodeModel::Model CM = getTargetMachine().getCodeModel();
9573+
if (CM == CodeModel::Large && !getTargetMachine().isPositionIndependent() &&
9574+
!Subtarget->isTargetMachO())
95739575
return getAddrLarge(JT, DAG);
9574-
} else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
9576+
if (CM == CodeModel::Tiny)
95759577
return getAddrTiny(JT, DAG);
9576-
}
95779578
return getAddr(JT, DAG);
95789579
}
95799580

@@ -9599,27 +9600,28 @@ SDValue AArch64TargetLowering::LowerBR_JT(SDValue Op,
95999600
SDValue AArch64TargetLowering::LowerConstantPool(SDValue Op,
96009601
SelectionDAG &DAG) const {
96019602
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
9602-
9603-
if (getTargetMachine().getCodeModel() == CodeModel::Large) {
9603+
CodeModel::Model CM = getTargetMachine().getCodeModel();
9604+
if (CM == CodeModel::Large) {
96049605
// Use the GOT for the large code model on iOS.
96059606
if (Subtarget->isTargetMachO()) {
96069607
return getGOT(CP, DAG);
96079608
}
9608-
return getAddrLarge(CP, DAG);
9609-
} else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
9609+
if (!getTargetMachine().isPositionIndependent())
9610+
return getAddrLarge(CP, DAG);
9611+
} else if (CM == CodeModel::Tiny) {
96109612
return getAddrTiny(CP, DAG);
9611-
} else {
9612-
return getAddr(CP, DAG);
96139613
}
9614+
return getAddr(CP, DAG);
96149615
}
96159616

96169617
SDValue AArch64TargetLowering::LowerBlockAddress(SDValue Op,
96179618
SelectionDAG &DAG) const {
96189619
BlockAddressSDNode *BA = cast<BlockAddressSDNode>(Op);
9619-
if (getTargetMachine().getCodeModel() == CodeModel::Large &&
9620-
!Subtarget->isTargetMachO()) {
9621-
return getAddrLarge(BA, DAG);
9622-
} else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
9620+
CodeModel::Model CM = getTargetMachine().getCodeModel();
9621+
if (CM == CodeModel::Large && !Subtarget->isTargetMachO()) {
9622+
if (!getTargetMachine().isPositionIndependent())
9623+
return getAddrLarge(BA, DAG);
9624+
} else if (CM == CodeModel::Tiny) {
96239625
return getAddrTiny(BA, DAG);
96249626
}
96259627
return getAddr(BA, DAG);

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -2849,7 +2849,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
28492849
if (OpFlags & AArch64II::MO_GOT) {
28502850
I.setDesc(TII.get(AArch64::LOADgot));
28512851
I.getOperand(1).setTargetFlags(OpFlags);
2852-
} else if (TM.getCodeModel() == CodeModel::Large) {
2852+
} else if (TM.getCodeModel() == CodeModel::Large &&
2853+
!TM.isPositionIndependent()) {
28532854
// Materialize the global using movz/movk instructions.
28542855
materializeLargeCMVal(I, GV, OpFlags);
28552856
I.eraseFromParent();
@@ -3502,7 +3503,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
35023503
return true;
35033504
}
35043505
case TargetOpcode::G_BLOCK_ADDR: {
3505-
if (TM.getCodeModel() == CodeModel::Large) {
3506+
if (TM.getCodeModel() == CodeModel::Large && !TM.isPositionIndependent()) {
35063507
materializeLargeCMVal(I, I.getOperand(1).getBlockAddress(), 0);
35073508
I.eraseFromParent();
35083509
return true;

llvm/test/CodeGen/AArch64/GlobalISel/select-blockaddress.mir

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
22
# RUN: llc -mtriple=aarch64-unknown-unknown -o - -verify-machineinstrs -run-pass=instruction-select %s | FileCheck %s
33
# RUN: llc -mtriple=aarch64-unknown-unknown -o - -verify-machineinstrs -run-pass=instruction-select -code-model=large %s | FileCheck %s --check-prefix=LARGE
4+
# 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
45
--- |
5-
; ModuleID = 'blockaddress.ll'
66
source_filename = "blockaddress.ll"
77
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
88
target triple = "aarch64-none-linux-gnu"
@@ -37,6 +37,7 @@ body: |
3737
; CHECK-NEXT: BR [[MOVaddrBA]]
3838
; CHECK-NEXT: {{ $}}
3939
; CHECK-NEXT: bb.1.block (ir-block-address-taken %ir-block.block):
40+
;
4041
; LARGE-LABEL: name: test_blockaddress
4142
; LARGE: bb.0 (%ir-block.0):
4243
; LARGE-NEXT: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) blockaddress(@test_blockaddress, %ir-block.block), 0
@@ -51,6 +52,16 @@ body: |
5152
; LARGE-NEXT: BR [[MOVKXi2]]
5253
; LARGE-NEXT: {{ $}}
5354
; LARGE-NEXT: bb.1.block (ir-block-address-taken %ir-block.block):
55+
;
56+
; LARGE-PIC-LABEL: name: test_blockaddress
57+
; LARGE-PIC: bb.0 (%ir-block.0):
58+
; 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)
59+
; LARGE-PIC-NEXT: [[MOVaddr:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @addr, target-flags(aarch64-pageoff, aarch64-nc) @addr
60+
; LARGE-PIC-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY [[MOVaddrBA]]
61+
; LARGE-PIC-NEXT: STRXui [[COPY]], [[MOVaddr]], 0 :: (store (p0) into @addr)
62+
; LARGE-PIC-NEXT: BR [[MOVaddrBA]]
63+
; LARGE-PIC-NEXT: {{ $}}
64+
; LARGE-PIC-NEXT: bb.1.block (ir-block-address-taken %ir-block.block):
5465
bb.1 (%ir-block.0):
5566
%0:gpr(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)
5667
%1:gpr(p0) = G_GLOBAL_VALUE @addr

llvm/test/CodeGen/AArch64/GlobalISel/select-gv-cmodel-large.mir

+31-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2-
# RUN: llc -mtriple=aarch64-linux-gnu -code-model=large -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s
2+
# 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
3+
# 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
34
--- |
45
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
56

@@ -29,23 +30,35 @@ stack:
2930
constants:
3031
body: |
3132
bb.1:
32-
; CHECK-LABEL: name: gv_large
33-
; CHECK: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @foo1, 0
34-
; CHECK: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) @foo1, 16
35-
; CHECK: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) @foo1, 32
36-
; CHECK: [[MOVKXi2:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi1]], target-flags(aarch64-g3) @foo1, 48
37-
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY [[MOVKXi2]]
38-
; CHECK: [[MOVZXi1:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @foo2, 0
39-
; CHECK: [[MOVKXi3:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi1]], target-flags(aarch64-g1, aarch64-nc) @foo2, 16
40-
; CHECK: [[MOVKXi4:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi3]], target-flags(aarch64-g2, aarch64-nc) @foo2, 32
41-
; CHECK: [[MOVKXi5:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi4]], target-flags(aarch64-g3) @foo2, 48
42-
; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY [[MOVKXi5]]
43-
; CHECK: STRWui $wzr, %stack.0.retval, 0 :: (store (s32) into %ir.retval)
44-
; CHECK: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load (s32) from @foo1)
45-
; CHECK: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY1]], 0 :: (load (s32) from @foo2)
46-
; CHECK: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[LDRWui]], [[LDRWui1]]
47-
; CHECK: $w0 = COPY [[ADDWrr]]
48-
; CHECK: RET_ReallyLR implicit $w0
33+
; STATIC-LABEL: name: gv_large
34+
; STATIC: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @foo1, 0
35+
; STATIC-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) @foo1, 16
36+
; STATIC-NEXT: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) @foo1, 32
37+
; STATIC-NEXT: [[MOVKXi2:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi1]], target-flags(aarch64-g3) @foo1, 48
38+
; STATIC-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY [[MOVKXi2]]
39+
; STATIC-NEXT: [[MOVZXi1:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @foo2, 0
40+
; STATIC-NEXT: [[MOVKXi3:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi1]], target-flags(aarch64-g1, aarch64-nc) @foo2, 16
41+
; STATIC-NEXT: [[MOVKXi4:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi3]], target-flags(aarch64-g2, aarch64-nc) @foo2, 32
42+
; STATIC-NEXT: [[MOVKXi5:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi4]], target-flags(aarch64-g3) @foo2, 48
43+
; STATIC-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY [[MOVKXi5]]
44+
; STATIC-NEXT: STRWui $wzr, %stack.0.retval, 0 :: (store (s32) into %ir.retval)
45+
; STATIC-NEXT: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load (s32) from @foo1)
46+
; STATIC-NEXT: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY1]], 0 :: (load (s32) from @foo2)
47+
; STATIC-NEXT: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[LDRWui]], [[LDRWui1]]
48+
; STATIC-NEXT: $w0 = COPY [[ADDWrr]]
49+
; STATIC-NEXT: RET_ReallyLR implicit $w0
50+
;
51+
; PIC-LABEL: name: gv_large
52+
; PIC: [[MOVaddr:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @foo1, target-flags(aarch64-pageoff, aarch64-nc) @foo1
53+
; PIC-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY [[MOVaddr]]
54+
; PIC-NEXT: [[MOVaddr1:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @foo2, target-flags(aarch64-pageoff, aarch64-nc) @foo2
55+
; PIC-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY [[MOVaddr1]]
56+
; PIC-NEXT: STRWui $wzr, %stack.0.retval, 0 :: (store (s32) into %ir.retval)
57+
; PIC-NEXT: [[LDRWui:%[0-9]+]]:gpr32 = LDRWui [[COPY]], 0 :: (load (s32) from @foo1)
58+
; PIC-NEXT: [[LDRWui1:%[0-9]+]]:gpr32 = LDRWui [[COPY1]], 0 :: (load (s32) from @foo2)
59+
; PIC-NEXT: [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[LDRWui]], [[LDRWui1]]
60+
; PIC-NEXT: $w0 = COPY [[ADDWrr]]
61+
; PIC-NEXT: RET_ReallyLR implicit $w0
4962
%1:gpr(s32) = G_CONSTANT i32 0
5063
%4:gpr(p0) = G_GLOBAL_VALUE @foo1
5164
%3:gpr(p0) = COPY %4(p0)
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
22
# RUN: llc -mtriple=aarch64 -code-model=large -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=LARGE
3+
# 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
34
# RUN: llc -mtriple=aarch64 -code-model=small -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=SMALL
45
# RUN: llc -mtriple=aarch64 -code-model=tiny -run-pass=instruction-select -verify-machineinstrs -O0 %s -o - | FileCheck %s --check-prefix=TINY
56

@@ -17,22 +18,34 @@ body: |
1718
liveins: $x0
1819
; LARGE-LABEL: name: select_gv_with_offset
1920
; LARGE: liveins: $x0
20-
; LARGE: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @g + 1, 0
21-
; LARGE: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) @g + 1, 16
22-
; LARGE: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) @g + 1, 32
23-
; LARGE: %g:gpr64 = MOVKXi [[MOVKXi1]], target-flags(aarch64-g3) @g + 1, 48
24-
; LARGE: $x0 = COPY %g
25-
; LARGE: RET_ReallyLR implicit $x0
21+
; LARGE-NEXT: {{ $}}
22+
; LARGE-NEXT: [[MOVZXi:%[0-9]+]]:gpr64 = MOVZXi target-flags(aarch64-g0, aarch64-nc) @g + 1, 0
23+
; LARGE-NEXT: [[MOVKXi:%[0-9]+]]:gpr64 = MOVKXi [[MOVZXi]], target-flags(aarch64-g1, aarch64-nc) @g + 1, 16
24+
; LARGE-NEXT: [[MOVKXi1:%[0-9]+]]:gpr64 = MOVKXi [[MOVKXi]], target-flags(aarch64-g2, aarch64-nc) @g + 1, 32
25+
; LARGE-NEXT: %g:gpr64 = MOVKXi [[MOVKXi1]], target-flags(aarch64-g3) @g + 1, 48
26+
; LARGE-NEXT: $x0 = COPY %g
27+
; LARGE-NEXT: RET_ReallyLR implicit $x0
28+
;
29+
; LARGE-PIC-LABEL: name: select_gv_with_offset
30+
; LARGE-PIC: liveins: $x0
31+
; LARGE-PIC-NEXT: {{ $}}
32+
; LARGE-PIC-NEXT: %g:gpr64common = MOVaddr target-flags(aarch64-page) @g + 1, target-flags(aarch64-pageoff, aarch64-nc) @g + 1
33+
; LARGE-PIC-NEXT: $x0 = COPY %g
34+
; LARGE-PIC-NEXT: RET_ReallyLR implicit $x0
35+
;
2636
; SMALL-LABEL: name: select_gv_with_offset
2737
; SMALL: liveins: $x0
28-
; SMALL: %g:gpr64common = MOVaddr target-flags(aarch64-page) @g + 1, target-flags(aarch64-pageoff, aarch64-nc) @g + 1
29-
; SMALL: $x0 = COPY %g
30-
; SMALL: RET_ReallyLR implicit $x0
38+
; SMALL-NEXT: {{ $}}
39+
; SMALL-NEXT: %g:gpr64common = MOVaddr target-flags(aarch64-page) @g + 1, target-flags(aarch64-pageoff, aarch64-nc) @g + 1
40+
; SMALL-NEXT: $x0 = COPY %g
41+
; SMALL-NEXT: RET_ReallyLR implicit $x0
42+
;
3143
; TINY-LABEL: name: select_gv_with_offset
3244
; TINY: liveins: $x0
33-
; TINY: %g:gpr64 = ADR @g + 1
34-
; TINY: $x0 = COPY %g
35-
; TINY: RET_ReallyLR implicit $x0
45+
; TINY-NEXT: {{ $}}
46+
; TINY-NEXT: %g:gpr64 = ADR @g + 1
47+
; TINY-NEXT: $x0 = COPY %g
48+
; TINY-NEXT: RET_ReallyLR implicit $x0
3649
%g:gpr(p0) = G_GLOBAL_VALUE @g + 1
3750
$x0 = COPY %g(p0)
3851
RET_ReallyLR implicit $x0

llvm/test/CodeGen/AArch64/blockaddress.ll

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
; RUN: llc -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck %s
22
; 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
3+
; RUN: llc -code-model=large -relocation-model=pic -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 < %s | FileCheck %s
34
; RUN: llc -code-model=tiny -mtriple=aarch64-none-elf -aarch64-enable-atomic-cfg-tidy=0 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-TINY %s
45

56
@addr = global ptr null

llvm/test/CodeGen/AArch64/code-model-large-abs.ll

-72
This file was deleted.

0 commit comments

Comments
 (0)