diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -45,6 +45,9 @@ CodeModel::Model getCodeModel(); std::optional getExplicitCodeModel(); +uint64_t getLargeDataThreshold(); +std::optional getExplicitLargeDataThreshold(); + llvm::ExceptionHandling getExceptionModel(); std::optional getExplicitFileType(); diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -100,6 +100,7 @@ Reloc::Model RM = Reloc::Static; CodeModel::Model CMModel = CodeModel::Small; + uint64_t LargeDataThreshold = 0; CodeGenOpt::Level OptLevel = CodeGenOpt::Default; /// Contains target specific asm information. @@ -235,7 +236,8 @@ /// Set the code model. void setCodeModel(CodeModel::Model CM) { CMModel = CM; } - bool isLargeData() const; + void setLargeDataThreshold(uint64_t LDT) { LargeDataThreshold = LDT; } + bool isLargeData(const GlobalVariable *GV) const; bool isPositionIndependent() const; diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -58,6 +58,7 @@ CGOPT_EXP(Reloc::Model, RelocModel) CGOPT(ThreadModel::Model, ThreadModel) CGOPT_EXP(CodeModel::Model, CodeModel) +CGOPT_EXP(uint64_t, LargeDataThreshold) CGOPT(ExceptionHandling, ExceptionModel) CGOPT_EXP(CodeGenFileType, FileType) CGOPT(FramePointerKind, FramePointerUsage) @@ -161,6 +162,12 @@ clEnumValN(CodeModel::Large, "large", "Large code model"))); CGBINDOPT(CodeModel); + static cl::opt LargeDataThreshold( + "large-data-threshold", + cl::desc("Choose large data threshold for x86_64 medium code model"), + cl::init(0)); + CGBINDOPT(LargeDataThreshold); + static cl::opt ExceptionModel( "exception-model", cl::desc("exception model"), cl::init(ExceptionHandling::None), diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -651,8 +651,8 @@ Name += utostr(EntrySize); } else { bool IsLarge = false; - if (isa(GO)) - IsLarge = TM.isLargeData(); + if (auto *GV = dyn_cast(GO)) + IsLarge = TM.isLargeData(GV); Name = getSectionPrefixForGlobal(Kind, IsLarge); } @@ -855,8 +855,8 @@ Group = C->getName(); IsComdat = C->getSelectionKind() == Comdat::Any; } - if (isa(GO)) { - if (TM.isLargeData()) { + if (auto *GV = dyn_cast(GO)) { + if (TM.isLargeData(GV)) { assert(TM.getTargetTriple().getArch() == Triple::x86_64); Flags |= ELF::SHF_X86_64_LARGE; } diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -39,14 +39,16 @@ TargetMachine::~TargetMachine() = default; -bool TargetMachine::isLargeData() const { +bool TargetMachine::isLargeData(const GlobalVariable *GV) const { if (getTargetTriple().getArch() != Triple::x86_64) return false; // Large data under the large code model still needs to be thought about, so // restrict this to medium. if (getCodeModel() != CodeModel::Medium) return false; - return true; + const DataLayout &DL = GV->getParent()->getDataLayout(); + uint64_t Size = DL.getTypeSizeInBits(GV->getValueType()) / 8; + return Size == 0 || Size > LargeDataThreshold; } bool TargetMachine::isPositionIndependent() const { diff --git a/llvm/test/CodeGen/X86/code-model-elf-sections.ll b/llvm/test/CodeGen/X86/code-model-elf-sections.ll --- a/llvm/test/CodeGen/X86/code-model-elf-sections.ll +++ b/llvm/test/CodeGen/X86/code-model-elf-sections.ll @@ -2,6 +2,10 @@ ; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=SMALL ; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -o %t ; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=LARGE +; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -large-data-threshold=79 -o %t +; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=LARGE +; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -large-data-threshold=80 -o %t +; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=SMALL ; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -o %t ; RUN: llvm-readobj -S %t | FileCheck %s --check-prefix=SMALL @@ -73,9 +77,9 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64--linux" -@data = internal global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], align 16 -@bss = internal global [10 x i32] zeroinitializer, align 16 -@rodata = internal constant [10 x i32] zeroinitializer, align 16 -@relro = internal constant ptr @func, align 16 +@data = internal global [10 x i64] [i64 1, i64 2, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0] +@bss = internal global [10 x i64] zeroinitializer +@rodata = internal constant [10 x i64] zeroinitializer +@relro = internal constant [10 x ptr] [ptr @func, ptr @func, ptr @func, ptr @func, ptr @func, ptr @func, ptr @func, ptr @func, ptr @func, ptr @func] declare void @func() diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -596,6 +596,8 @@ std::optional CM_IR = M->getCodeModel(); if (!CM && CM_IR) Target->setCodeModel(*CM_IR); + if (auto LDT = codegen::getExplicitLargeDataThreshold()) + Target->setLargeDataThreshold(*LDT); } else { TheTriple = Triple(Triple::normalize(TargetTriple)); if (TheTriple.getTriple().empty())