llvm.org GIT mirror llvm / 209d9a9
[RISCV] Put data smaller than eight bytes to small data section Because of gp = sdata_start_address + 0x800, gp with signed twelve-bit offset could covert most of the small data section. Linker relaxation could transfer the multiple data accessing instructions to a gp base with signed twelve-bit offset instruction. Differential Revision: https://reviews.llvm.org/D57493 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358150 91177308-0d34-0410-b5e6-96231b3b80d8 Shiva Chen 1 year, 7 months ago
8 changed file(s) with 186 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
7878 /// Emit the module-level metadata that the platform cares about.
7979 virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {}
8080
81 /// Get the module-level metadata that the platform cares about.
82 virtual void getModuleMetadata(Module &M) {}
83
8184 /// Given a constant with the SectionKind, return a section that it should be
8285 /// placed in.
8386 virtual MCSection *getSectionForConstant(const DataLayout &DL,
258258 const_cast(getObjFileLowering())
259259 .Initialize(OutContext, TM);
260260
261 const_cast(getObjFileLowering())
262 .getModuleMetadata(M);
263
261264 OutStreamer->InitSections(false);
262265
263266 // Emit the version-min deployment target directive if needed.
77
88 #include "RISCVTargetObjectFile.h"
99 #include "RISCVTargetMachine.h"
10 #include "llvm/BinaryFormat/ELF.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCSectionELF.h"
1013
1114 using namespace llvm;
1215
1417 const TargetMachine &TM) {
1518 TargetLoweringObjectFileELF::Initialize(Ctx, TM);
1619 InitializeELF(TM.Options.UseInitArray);
20
21 SmallDataSection = getContext().getELFSection(
22 ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
23 SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
24 ELF::SHF_WRITE | ELF::SHF_ALLOC);
1725 }
26
27 // A address must be loaded from a small section if its size is less than the
28 // small section size threshold. Data in this section could be addressed by
29 // using gp_rel operator.
30 bool RISCVELFTargetObjectFile::isInSmallSection(uint64_t Size) const {
31 // gcc has traditionally not treated zero-sized objects as small data, so this
32 // is effectively part of the ABI.
33 return Size > 0 && Size <= SSThreshold;
34 }
35
36 // Return true if this global address should be placed into small data/bss
37 // section.
38 bool RISCVELFTargetObjectFile::isGlobalInSmallSection(
39 const GlobalObject *GO, const TargetMachine &TM) const {
40 // Only global variables, not functions.
41 const GlobalVariable *GVA = dyn_cast(GO);
42 if (!GVA)
43 return false;
44
45 // If the variable has an explicit section, it is placed in that section.
46 if (GVA->hasSection()) {
47 StringRef Section = GVA->getSection();
48
49 // Explicitly placing any variable in the small data section overrides
50 // the global -G value.
51 if (Section == ".sdata" || Section == ".sbss")
52 return true;
53
54 // Otherwise reject putting the variable to small section if it has an
55 // explicit section name.
56 return false;
57 }
58
59 if (((GVA->hasExternalLinkage() && GVA->isDeclaration()) ||
60 GVA->hasCommonLinkage()))
61 return false;
62
63 Type *Ty = GVA->getValueType();
64 // It is possible that the type of the global is unsized, i.e. a declaration
65 // of a extern struct. In this case don't presume it is in the small data
66 // section. This happens e.g. when building the FreeBSD kernel.
67 if (!Ty->isSized())
68 return false;
69
70 return isInSmallSection(
71 GVA->getParent()->getDataLayout().getTypeAllocSize(Ty));
72 }
73
74 MCSection *RISCVELFTargetObjectFile::SelectSectionForGlobal(
75 const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
76 // Handle Small Section classification here.
77 if (Kind.isBSS() && isGlobalInSmallSection(GO, TM))
78 return SmallBSSSection;
79 if (Kind.isData() && isGlobalInSmallSection(GO, TM))
80 return SmallDataSection;
81
82 // Otherwise, we work the same as ELF.
83 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
84 }
85
86 void RISCVELFTargetObjectFile::getModuleMetadata(Module &M) {
87 SmallVector ModuleFlags;
88 M.getModuleFlagsMetadata(ModuleFlags);
89
90 for (const auto &MFE : ModuleFlags) {
91 StringRef Key = MFE.Key->getString();
92 if (Key == "SmallDataLimit") {
93 SSThreshold = mdconst::extract(MFE.Val)->getZExtValue();
94 break;
95 }
96 }
97 }
98
99 /// Return true if this constant should be placed into small data section.
100 bool RISCVELFTargetObjectFile::isConstantInSmallSection(
101 const DataLayout &DL, const Constant *CN) const {
102 return isInSmallSection(DL.getTypeAllocSize(CN->getType()));
103 }
104
105 MCSection *RISCVELFTargetObjectFile::getSectionForConstant(
106 const DataLayout &DL, SectionKind Kind, const Constant *C,
107 unsigned &Align) const {
108 if (isConstantInSmallSection(DL, C))
109 return SmallDataSection;
110
111 // Otherwise, we work the same as ELF.
112 return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align);
113 }
1515
1616 /// This implementation is used for RISCV ELF targets.
1717 class RISCVELFTargetObjectFile : public TargetLoweringObjectFileELF {
18 MCSection *SmallDataSection;
19 MCSection *SmallBSSSection;
20 unsigned SSThreshold = 8;
21
22 public:
1823 void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
24
25 /// Return true if this global address should be placed into small data/bss
26 /// section.
27 bool isGlobalInSmallSection(const GlobalObject *GO,
28 const TargetMachine &TM) const;
29
30 MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
31 const TargetMachine &TM) const override;
32
33 /// Return true if this constant should be placed into small data section.
34 bool isConstantInSmallSection(const DataLayout &DL, const Constant *CN) const;
35
36 MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
37 const Constant *C,
38 unsigned &Align) const override;
39
40 void getModuleMetadata(Module &M) override;
41
42 bool isInSmallSection(uint64_t Size) const;
1943 };
2044
2145 } // end namespace llvm
0 ; RUN: llc -mtriple=riscv32 < %s | FileCheck -check-prefix=RV32 %s
1 ; RUN: llc -mtriple=riscv64 < %s | FileCheck -check-prefix=RV64 %s
2
3 @v = dso_local global i32 0, align 4
4 @r = dso_local global i64 7, align 8
5
6 ; SmallDataLimit set to 0, so we expect no data will put in sbss and sdata.
7 !llvm.module.flags = !{!0}
8 !0 = !{i32 1, !"SmallDataLimit", i32 0}
9
10 ; RV32-NOT: .section .sbss
11 ; RV32-NOT: .section .sdata
12 ; RV64-NOT: .section .sbss
13 ; RV64-NOT: .section .sdata
0 ; RUN: llc -mtriple=riscv32 < %s | FileCheck -check-prefix=RV32 %s
1 ; RUN: llc -mtriple=riscv64 < %s | FileCheck -check-prefix=RV64 %s
2
3 @v = dso_local global i32 0, align 4
4 @r = dso_local global i64 7, align 8
5
6 ; SmallDataLimit set to 4, so we expect @v will be put in sbss,
7 ; but @r won't be put in sdata.
8 !llvm.module.flags = !{!0}
9 !0 = !{i32 1, !"SmallDataLimit", i32 4}
10
11 ; RV32: .section .sbss
12 ; RV32-NOT: .section .sdata
13 ; RV64: .section .sbss
14 ; RV64-NOT: .section .sdata
0 ; RUN: llc -mtriple=riscv32 < %s | FileCheck -check-prefix=RV32 %s
1 ; RUN: llc -mtriple=riscv64 < %s | FileCheck -check-prefix=RV64 %s
2
3 @v = dso_local global i32 0, align 4
4 @r = dso_local global i64 7, align 8
5
6 ; SmallDataLimit set to 8, so we expect @v will be put in sbss
7 ; and @r will be put in sdata.
8 !llvm.module.flags = !{!0}
9 !0 = !{i32 1, !"SmallDataLimit", i32 8}
10
11 ; RV32: .section .sbss
12 ; RV32: .section .sdata
13 ; RV64: .section .sbss
14 ; RV64: .section .sdata
0 ; RUN: llc -mtriple=riscv32 < %s | FileCheck -check-prefix=RV32 %s
1 ; RUN: llc -mtriple=riscv64 < %s | FileCheck -check-prefix=RV64 %s
2
3 @v = internal global i32 0, align 4
4 @r = internal global i64 7, align 8
5
6 ; @v and @r are local symbols.
7 ; SmallDataLimit set to 8, so we expect @v will be put in sbss
8 ; and @r will be put in sdata.
9 !llvm.module.flags = !{!0}
10 !0 = !{i32 1, !"SmallDataLimit", i32 8}
11
12 ; RV32: .section .sbss
13 ; RV32: .section .sdata
14 ; RV64: .section .sbss
15 ; RV64: .section .sdata