[RISCV] Passing small data limitation value to RISCV backend

Passing small data limit to RISCVELFTargetObjectFile by module flag,
So the backend can set small data section threshold by the value.
The data will be put into the small data section if the data smaller than
the threshold.

Differential Revision: https://reviews.llvm.org/D57497
This commit is contained in:
Shiva Chen 2020-03-10 10:23:59 +08:00 committed by shiva
parent 0ddd04391d
commit fc3752665f
11 changed files with 125 additions and 1 deletions

View File

@ -2403,7 +2403,7 @@ Target-dependent compilation options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. option:: -G<size>, -G=<arg>, -msmall-data-threshold=<arg>
Put objects of at most <size> bytes into small data section (MIPS / Hexagon)
Put objects of at most <size> bytes into small data section (MIPS / Hexagon / RISCV)
.. option:: -ffixed-x1
@ -3201,6 +3201,10 @@ Enable linker relaxation
Enable using library calls for save and restore
.. option:: -msmall-data-limit=<limit>
Put global and static data smaller than the limit into a special section
Long double flags
-----------------
Selects the long double implementation

View File

@ -306,6 +306,9 @@ CODEGENOPT(LTOVisibilityPublicStd, 1, 0)
/// or 0 if unspecified.
VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
/// The threshold to put data into small data section.
VALUE_CODEGENOPT(SmallDataLimit, 32, 0)
/// The lower bound for a buffer to be considered for stack protection.
VALUE_CODEGENOPT(SSPBufferSize, 32, 0)

View File

@ -399,6 +399,9 @@ def warn_drv_unsupported_gpopt : Warning<
"ignoring '-mgpopt' option as it cannot be used with %select{|the implicit"
" usage of }0-mabicalls">,
InGroup<UnsupportedGPOpt>;
def warn_drv_unsupported_sdata : Warning<
"ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">,
InGroup<OptionIgnored>;
def warn_drv_unsupported_longcalls : Warning<
"ignoring '-mlong-calls' option as it is not currently supported with "
"%select{|the implicit usage of }0-mabicalls">,

View File

@ -313,6 +313,8 @@ def mno_zero_initialized_in_bss : Flag<["-"], "mno-zero-initialized-in-bss">,
HelpText<"Do not put zero initialized data in the BSS">;
def mregparm : Separate<["-"], "mregparm">,
HelpText<"Limit the number of registers available for integer arguments">;
def msmall_data_limit : Separate<["-"], "msmall-data-limit">,
HelpText<"Put global and static data smaller than the limit into a special section">;
def munwind_tables : Flag<["-"], "munwind-tables">,
HelpText<"Generate unwinding tables for all functions">;
def mconstructor_aliases : Flag<["-"], "mconstructor-aliases">,

View File

@ -2300,6 +2300,9 @@ def mrelax : Flag<["-"], "mrelax">, Group<m_riscv_Features_Group>,
HelpText<"Enable linker relaxation">;
def mno_relax : Flag<["-"], "mno-relax">, Group<m_riscv_Features_Group>,
HelpText<"Disable linker relaxation">;
def msmall_data_limit_EQ : Joined<["-"], "msmall-data-limit=">, Group<m_Group>,
Alias<G>,
HelpText<"Put global and static data smaller than the limit into a special section">;
def msave_restore : Flag<["-"], "msave-restore">, Group<m_riscv_Features_Group>,
HelpText<"Enable using library calls for save and restore">;
def mno_save_restore : Flag<["-"], "mno-save-restore">, Group<m_riscv_Features_Group>,

View File

@ -660,6 +660,8 @@ void CodeGenModule::Release() {
EmitCommandLineMetadata();
EmitTargetMetadata();
EmitBackendOptionsMetadata(getCodeGenOpts());
}
void CodeGenModule::EmitOpenCLMetadata() {
@ -679,6 +681,19 @@ void CodeGenModule::EmitOpenCLMetadata() {
OCLVerMD->addOperand(llvm::MDNode::get(Ctx, OCLVerElts));
}
void CodeGenModule::EmitBackendOptionsMetadata(
const CodeGenOptions CodeGenOpts) {
switch (getTriple().getArch()) {
default:
break;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
getModule().addModuleFlag(llvm::Module::Error, "SmallDataLimit",
CodeGenOpts.SmallDataLimit);
break;
}
}
void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {
// Make sure that this type is translated.
Types.UpdateCompletedType(TD);

View File

@ -1512,6 +1512,10 @@ private:
/// Emits target specific Metadata for global declarations.
void EmitTargetMetadata();
/// Emit the module flag metadata used to pass options controlling the
/// the backend to LLVM.
void EmitBackendOptionsMetadata(const CodeGenOptions CodeGenOpts);
/// Emits OpenCL specific Metadata e.g. OpenCL version.
void EmitOpenCLMetadata();

View File

@ -1960,6 +1960,36 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
}
}
static void SetRISCVSmallDataLimit(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
const Driver &D = TC.getDriver();
const llvm::Triple &Triple = TC.getTriple();
// Default small data limitation is eight.
const char *SmallDataLimit = "8";
// Get small data limitation.
if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
options::OPT_fPIC)) {
// Not support linker relaxation for PIC.
SmallDataLimit = "0";
if (Args.hasArg(options::OPT_G)) {
D.Diag(diag::warn_drv_unsupported_sdata);
}
} else if (Args.getLastArgValue(options::OPT_mcmodel_EQ)
.equals_lower("large") &&
(Triple.getArch() == llvm::Triple::riscv64)) {
// Not support linker relaxation for RV64 with large code model.
SmallDataLimit = "0";
if (Args.hasArg(options::OPT_G)) {
D.Diag(diag::warn_drv_unsupported_sdata);
}
} else if (Arg *A = Args.getLastArg(options::OPT_G)) {
SmallDataLimit = A->getValue();
}
// Forward the -msmall-data-limit= option.
CmdArgs.push_back("-msmall-data-limit");
CmdArgs.push_back(SmallDataLimit);
}
void Clang::AddRISCVTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const llvm::Triple &Triple = getToolChain().getTriple();
@ -1967,6 +1997,8 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs);
}
void Clang::AddSparcTargetArgs(const ArgList &Args,

View File

@ -921,6 +921,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Opts.SmallDataLimit =
getLastArgIntValue(Args, OPT_msmall_data_limit, 0, Diags);
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn);
Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks);

View File

@ -0,0 +1,48 @@
// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -o - \
// RUN: | FileCheck %s -check-prefix=RV32-DEFAULT
// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -G4 -o - \
// RUN: | FileCheck %s -check-prefix=RV32-G4
// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -msmall-data-limit=0 -o - \
// RUN: | FileCheck %s -check-prefix=RV32-S0
// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -msmall-data-limit=2 -G4 -o - \
// RUN: | FileCheck %s -check-prefix=RV32-S2G4
// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -msmall-data-threshold=16 -o - \
// RUN: | FileCheck %s -check-prefix=RV32-T16
// RUN: %clang -target riscv32-unknown-elf %s -S -emit-llvm -fpic -o - \
// RUN: | FileCheck %s -check-prefix=RV32-PIC
// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -o - \
// RUN: | FileCheck %s -check-prefix=RV64-DEFAULT
// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -G4 -o - \
// RUN: | FileCheck %s -check-prefix=RV64-G4
// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -msmall-data-limit=0 -o - \
// RUN: | FileCheck %s -check-prefix=RV64-S0
// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -msmall-data-limit=2 -G4 -o - \
// RUN: | FileCheck %s -check-prefix=RV64-S2G4
// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -msmall-data-threshold=16 -o - \
// RUN: | FileCheck %s -check-prefix=RV64-T16
// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -fpic -o - \
// RUN: | FileCheck %s -check-prefix=RV64-PIC
// RUN: %clang -target riscv64-unknown-elf %s -S -emit-llvm -mcmodel=large -o - \
// RUN: | FileCheck %s -check-prefix=RV64-LARGE
void test() {}
// RV32-DEFAULT: !{i32 1, !"SmallDataLimit", i32 8}
// RV32-G4: !{i32 1, !"SmallDataLimit", i32 4}
// RV32-S0: !{i32 1, !"SmallDataLimit", i32 0}
// RV32-S2G4: !{i32 1, !"SmallDataLimit", i32 4}
// RV32-T16: !{i32 1, !"SmallDataLimit", i32 16}
// RV32-PIC: !{i32 1, !"SmallDataLimit", i32 0}
// RV64-DEFAULT: !{i32 1, !"SmallDataLimit", i32 8}
// RV64-G4: !{i32 1, !"SmallDataLimit", i32 4}
// RV64-S0: !{i32 1, !"SmallDataLimit", i32 0}
// RV64-S2G4: !{i32 1, !"SmallDataLimit", i32 4}
// RV64-T16: !{i32 1, !"SmallDataLimit", i32 16}
// RV64-PIC: !{i32 1, !"SmallDataLimit", i32 0}
// RV64-LARGE: !{i32 1, !"SmallDataLimit", i32 0}
// The value will be passed by module flag instead of target feature.
// RV32-S0-NOT: +small-data-limit=
// RV64-S0-NOT: +small-data-limit=

View File

@ -0,0 +1,8 @@
// REQUIRES: riscv-registered-target
// RUN: %clang -S -target riscv32-unknown-elf -fpic -msmall-data-limit=8 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-PIC-SDATA %s
// CHECK-PIC-SDATA: warning: ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64
// RUN: %clang -S -target riscv64-unknown-elf -mcmodel=large -msmall-data-limit=8 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-RV64-LARGE-SDATA %s
// CHECK-RV64-LARGE-SDATA: warning: ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64