Skip to content

Commit d8a0439

Browse files
committed
Reland [X86] With large code model, put functions into .ltext with large section flag (#73037)
So that when mixing small and large text, large text stays out of the way of the rest of the binary. This is useful for mixing precompiled small code model object files and built-from-source large code model binaries so that the the text sections don't get merged. The reland fixes an issue where a function in the large code model would reference small data without GOTOFF. This was incorrectly reverted in 76f78ec.
1 parent 8206b75 commit d8a0439

File tree

8 files changed

+66
-51
lines changed

8 files changed

+66
-51
lines changed

llvm/include/llvm/Target/TargetMachine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class TargetMachine {
239239
void setCodeModel(CodeModel::Model CM) { CMModel = CM; }
240240

241241
void setLargeDataThreshold(uint64_t LDT) { LargeDataThreshold = LDT; }
242-
bool isLargeData(const GlobalVariable *GV) const;
242+
bool isLargeGlobalObject(const GlobalObject *GO) const;
243243

244244
bool isPositionIndependent() const;
245245

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ static unsigned getEntrySizeForKind(SectionKind Kind) {
616616
/// DataSections.
617617
static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) {
618618
if (Kind.isText())
619-
return ".text";
619+
return IsLarge ? ".ltext" : ".text";
620620
if (Kind.isReadOnly())
621621
return IsLarge ? ".lrodata" : ".rodata";
622622
if (Kind.isBSS())
@@ -650,10 +650,7 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
650650
Name = ".rodata.cst";
651651
Name += utostr(EntrySize);
652652
} else {
653-
bool IsLarge = false;
654-
if (auto *GV = dyn_cast<GlobalVariable>(GO))
655-
IsLarge = TM.isLargeData(GV);
656-
Name = getSectionPrefixForGlobal(Kind, IsLarge);
653+
Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalObject(GO));
657654
}
658655

659656
bool HasPrefix = false;
@@ -773,12 +770,8 @@ getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) {
773770
Group = C->getName();
774771
IsComdat = C->getSelectionKind() == Comdat::Any;
775772
}
776-
if (auto *GV = dyn_cast<GlobalVariable>(GO)) {
777-
if (TM.isLargeData(GV)) {
778-
assert(TM.getTargetTriple().getArch() == Triple::x86_64);
779-
Flags |= ELF::SHF_X86_64_LARGE;
780-
}
781-
}
773+
if (TM.isLargeGlobalObject(GO))
774+
Flags |= ELF::SHF_X86_64_LARGE;
782775
return {Group, IsComdat, Flags};
783776
}
784777

llvm/lib/Target/TargetMachine.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,21 @@ TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,
3939

4040
TargetMachine::~TargetMachine() = default;
4141

42-
bool TargetMachine::isLargeData(const GlobalVariable *GV) const {
43-
if (getTargetTriple().getArch() != Triple::x86_64 || GV->isThreadLocal())
42+
bool TargetMachine::isLargeGlobalObject(const GlobalObject *GO) const {
43+
if (getTargetTriple().getArch() != Triple::x86_64)
4444
return false;
4545

4646
if (getCodeModel() != CodeModel::Medium && getCodeModel() != CodeModel::Large)
4747
return false;
4848

49+
if (isa<Function>(GO))
50+
return getCodeModel() == CodeModel::Large;
51+
52+
auto *GV = cast<GlobalVariable>(GO);
53+
54+
if (GV->isThreadLocal())
55+
return false;
56+
4957
// Allowing large metadata sections in the presence of an explicit section is
5058
// useful, even if GCC does not allow them. However, we should not mark
5159
// certain well-known prefixes as large, because it would make the whole

llvm/lib/Target/X86/X86Subtarget.cpp

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,32 +83,20 @@ X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
8383
if (is64Bit()) {
8484
// 64-bit ELF PIC local references may use GOTOFF relocations.
8585
if (isTargetELF()) {
86-
switch (TM.getCodeModel()) {
87-
// 64-bit small code model is simple: All rip-relative.
88-
case CodeModel::Tiny:
89-
llvm_unreachable("Tiny codesize model not supported on X86");
90-
case CodeModel::Small:
91-
case CodeModel::Kernel:
92-
return X86II::MO_NO_FLAG;
93-
94-
// The large PIC code model uses GOTOFF.
95-
case CodeModel::Large:
86+
CodeModel::Model CM = TM.getCodeModel();
87+
assert(CM != CodeModel::Tiny &&
88+
"Tiny codesize model not supported on X86");
89+
// In the large code model, even referencing a global under the large data
90+
// threshold which is considered "small", we need to use GOTOFF.
91+
if (CM == CodeModel::Large)
9692
return X86II::MO_GOTOFF;
97-
98-
// Medium is a hybrid: RIP-rel for code and non-large data, GOTOFF for
99-
// remaining DSO local data.
100-
case CodeModel::Medium:
101-
// Constant pool and jump table handling pass a nullptr to this
102-
// function so we need to use isa_and_nonnull.
103-
if (isa_and_nonnull<Function>(GV))
104-
return X86II::MO_NO_FLAG; // All code is RIP-relative
105-
if (auto *GVar = dyn_cast_or_null<GlobalVariable>(GV)) {
106-
if (TM.isLargeData(GVar))
107-
return X86II::MO_GOTOFF;
108-
}
109-
return X86II::MO_NO_FLAG; // Local symbols use GOTOFF.
110-
}
111-
llvm_unreachable("invalid code model");
93+
// Large objects use GOTOFF, otherwise use RIP-rel access.
94+
if (auto *GO = dyn_cast_or_null<GlobalObject>(GV))
95+
return TM.isLargeGlobalObject(GO) ? X86II::MO_GOTOFF
96+
: X86II::MO_NO_FLAG;
97+
// For non-GlobalObjects, the small and medium code models treat them as
98+
// accessible with a RIP-rel access.
99+
return X86II::MO_NO_FLAG;
112100
}
113101

114102
// Otherwise, this is either a RIP-relative reference or a 64-bit movabsq,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=small -o %t
2+
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL
3+
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -o %t
4+
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL
5+
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -o %t
6+
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=LARGE
7+
8+
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=small -function-sections -o %t
9+
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL-DS
10+
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -function-sections -o %t
11+
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL-DS
12+
; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -function-sections -o %t
13+
; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=LARGE-DS
14+
15+
; SMALL: .text {{.*}} AX {{.*}}
16+
; SMALL-DS: .text.func {{.*}} AX {{.*}}
17+
; LARGE: .ltext {{.*}} AXl {{.*}}
18+
; LARGE-DS: .ltext.func {{.*}} AXl {{.*}}
19+
20+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
21+
target triple = "x86_64--linux"
22+
23+
define void @func() {
24+
ret void
25+
}

llvm/test/CodeGen/X86/code-model-elf.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=medium -large-data-threshold=1000 | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-SMALL-DATA-PIC
1010
; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=medium | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-PIC
1111
; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-PIC
12+
; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large -large-data-threshold=1000 | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-PIC
1213

1314
; Generated from this C source:
1415
;

llvm/test/CodeGen/X86/pcsections.ll

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ define void @empty_no_aux() !pcsections !0 {
1919
; CHECK: # %bb.0: # %entry
2020
; CHECK-NEXT: retq
2121
; CHECK-NEXT: .Lfunc_end0:
22-
; CHECK: .section section_no_aux,"awo",@progbits,.text
22+
; CHECK: .section section_no_aux,"awo",@progbits,.{{l?}}text
2323
; CHECK-NEXT: .Lpcsection_base0:
2424
; DEFCM-NEXT: .long .Lfunc_begin0-.Lpcsection_base0
2525
; LARGE-NEXT: .quad .Lfunc_begin0-.Lpcsection_base0
2626
; CHECK-NEXT: .long .Lfunc_end0-.Lfunc_begin0
27-
; CHECK-NEXT: .text
27+
; CHECK-NEXT: .{{l?}}text
2828
entry:
2929
ret void
3030
}
@@ -35,15 +35,15 @@ define void @empty_aux() !pcsections !1 {
3535
; CHECK: # %bb.0: # %entry
3636
; CHECK-NEXT: retq
3737
; CHECK-NEXT: .Lfunc_end1:
38-
; CHECK: .section section_aux,"awo",@progbits,.text
38+
; CHECK: .section section_aux,"awo",@progbits,.{{l?}}text
3939
; CHECK-NEXT: .Lpcsection_base1:
4040
; DEFCM-NEXT: .long .Lfunc_begin1-.Lpcsection_base1
4141
; LARGE-NEXT: .quad .Lfunc_begin1-.Lpcsection_base1
4242
; CHECK-NEXT: .long .Lfunc_end1-.Lfunc_begin1
4343
; CHECK-NEXT: .long 10
4444
; CHECK-NEXT: .long 20
4545
; CHECK-NEXT: .long 30
46-
; CHECK-NEXT: .text
46+
; CHECK-NEXT: .{{l?}}text
4747
entry:
4848
ret void
4949
}
@@ -56,44 +56,44 @@ define i64 @multiple() !pcsections !0 {
5656
; CHECK-NEXT: movq
5757
; CHECK-NEXT: retq
5858
; CHECK-NEXT: .Lfunc_end2:
59-
; CHECK: .section section_no_aux,"awo",@progbits,.text
59+
; CHECK: .section section_no_aux,"awo",@progbits,.{{l?}}text
6060
; CHECK-NEXT: .Lpcsection_base2:
6161
; DEFCM-NEXT: .long .Lfunc_begin2-.Lpcsection_base2
6262
; LARGE-NEXT: .quad .Lfunc_begin2-.Lpcsection_base2
6363
; CHECK-NEXT: .long .Lfunc_end2-.Lfunc_begin2
64-
; CHECK-NEXT: .section section_aux_42,"awo",@progbits,.text
64+
; CHECK-NEXT: .section section_aux_42,"awo",@progbits,.{{l?}}text
6565
; CHECK-NEXT: .Lpcsection_base3:
6666
; DEFCM-NEXT: .long .Lpcsection0-.Lpcsection_base3
6767
; LARGE-NEXT: .quad .Lpcsection0-.Lpcsection_base3
6868
; CHECK-NEXT: .long 42
69-
; CHECK-NEXT: .section section_aux_21264,"awo",@progbits,.text
69+
; CHECK-NEXT: .section section_aux_21264,"awo",@progbits,.{{l?}}text
7070
; CHECK-NEXT: .Lpcsection_base4:
7171
; DEFCM-NEXT: .long .Lpcsection0-.Lpcsection_base4
7272
; LARGE-NEXT: .quad .Lpcsection0-.Lpcsection_base4
7373
; CHECK-NEXT: .long 21264
74-
; CHECK-NEXT: .text
74+
; CHECK-NEXT: .{{l?}}text
7575
entry:
7676
%0 = load i64, ptr @bar, align 8, !pcsections !2
7777
ret i64 %0
7878
}
7979

8080
define void @multiple_uleb128() !pcsections !6 {
8181
; CHECK-LABEL: multiple_uleb128:
82-
; CHECK: .section section_aux,"awo",@progbits,.text
82+
; CHECK: .section section_aux,"awo",@progbits,.{{l?}}text
8383
; CHECK-NEXT: .Lpcsection_base5:
8484
; DEFCM-NEXT: .long .Lfunc_begin3-.Lpcsection_base5
8585
; LARGE-NEXT: .quad .Lfunc_begin3-.Lpcsection_base5
8686
; CHECK-NEXT: .uleb128 .Lfunc_end3-.Lfunc_begin3
8787
; CHECK-NEXT: .byte 42
8888
; CHECK-NEXT: .ascii "\345\216&"
8989
; CHECK-NEXT: .byte 255
90-
; CHECK-NEXT: .section section_aux_21264,"awo",@progbits,.text
90+
; CHECK-NEXT: .section section_aux_21264,"awo",@progbits,.{{l?}}text
9191
; CHECK-NEXT: .Lpcsection_base6:
9292
; DEFCM-NEXT: .long .Lfunc_begin3-.Lpcsection_base6
9393
; LARGE-NEXT: .quad .Lfunc_begin3-.Lpcsection_base6
9494
; CHECK-NEXT: .long .Lfunc_end3-.Lfunc_begin3
9595
; CHECK-NEXT: .long 21264
96-
; CHECK-NEXT: .text
96+
; CHECK-NEXT: .{{l?}}text
9797
entry:
9898
ret void
9999
}

llvm/test/ExecutionEngine/OrcLazy/debug-objects-elf-minimal.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
; RUN: --generate=__dump_jit_debug_objects %s | llvm-objdump --section-headers - | \
4545
; RUN: FileCheck --check-prefix=CHECK_LOAD_ADDR %s
4646
;
47-
; CHECK_LOAD_ADDR-NOT: {{[0-9]*}} .text {{.*}} 0000000000000000 TEXT
47+
; CHECK_LOAD_ADDR-NOT: {{[0-9]*}} .ltext {{.*}} 0000000000000000 TEXT
4848

4949
target triple = "x86_64-unknown-unknown-elf"
5050

0 commit comments

Comments
 (0)