diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 52bcd971dc8c90..38ab144ee75ba6 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -922,8 +922,10 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, if (UsesCodeGen && !TM) return; - if (TM) + if (TM) { + TM->initializeOptionsWithModuleMetadata(*TheModule); TheModule->setDataLayout(TM->createDataLayout()); + } legacy::PassManager PerModulePasses; PerModulePasses.add( diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp index 0dc12c7a84b564..d673cf0391056a 100644 --- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -159,6 +159,12 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, std::string Linker = getToolChain().GetLinkerPath(); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + } + bool WantCRTs = !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.h b/clang/lib/Driver/ToolChains/RISCVToolchain.h index 62099bee040476..e22ac4c5c20a2f 100644 --- a/clang/lib/Driver/ToolChains/RISCVToolchain.h +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.h @@ -26,6 +26,7 @@ class LLVM_LIBRARY_VISIBILITY RISCVToolChain : public Generic_ELF { void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind) const override; + bool HasNativeLLVMSupport() const override { return true; } RuntimeLibType GetDefaultRuntimeLibType() const override; UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override; diff --git a/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp index 4adb6eb39d09ec..d5541a742a6def 100644 --- a/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp +++ b/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp @@ -117,6 +117,8 @@ static std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) { if (!TM) ErrorAndExit("Could not create target machine"); + TM->initializeOptionsWithModuleMetadata(*M); + codegen::setFunctionAttributes(codegen::getCPUStr(), codegen::getFeaturesStr(), *M); diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp index 6858c7134d33a4..9cbb12cd340ea4 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp @@ -147,6 +147,7 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) { target_machine->createDataLayout().getStringRepresentation().c_str()); } module.setTargetTriple(real_triple); + target_machine->initializeOptionsWithModuleMetadata(module); module.setDataLayout(target_machine->createDataLayout()); } return changed_module; diff --git a/llvm/docs/tutorial/MyFirstLanguageFrontend/LangImpl08.rst b/llvm/docs/tutorial/MyFirstLanguageFrontend/LangImpl08.rst index 16b45323154a95..d01f29d3dd22e7 100644 --- a/llvm/docs/tutorial/MyFirstLanguageFrontend/LangImpl08.rst +++ b/llvm/docs/tutorial/MyFirstLanguageFrontend/LangImpl08.rst @@ -129,8 +129,9 @@ layout. .. code-block:: c++ - TheModule->setDataLayout(TargetMachine->createDataLayout()); TheModule->setTargetTriple(TargetTriple); + TargetMachine->initializeOptionsWithModuleMetadata(*TheModule); + TheModule->setDataLayout(TargetMachine->createDataLayout()); Emit Object Code ================ diff --git a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp index a1fe89a9f8440f..d7e096143ae21f 100644 --- a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp @@ -1246,6 +1246,7 @@ int main() { auto TheTargetMachine = Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM); + TheTargetMachine->initializeOptionsWithModuleMetadata(*TheModule); TheModule->setDataLayout(TheTargetMachine->createDataLayout()); auto Filename = "output.o"; diff --git a/llvm/include/llvm/CodeGen/ParallelCG.h b/llvm/include/llvm/CodeGen/ParallelCG.h index 5504baa6225c4d..348387abc3ff15 100644 --- a/llvm/include/llvm/CodeGen/ParallelCG.h +++ b/llvm/include/llvm/CodeGen/ParallelCG.h @@ -37,7 +37,7 @@ class raw_pwrite_stream; std::unique_ptr splitCodeGen(std::unique_ptr M, ArrayRef OSs, ArrayRef BCOSs, - const std::function()> &TMFactory, + const std::function(Module &)> &TMFactory, CodeGenFileType FileType = CGFT_ObjectFile, bool PreserveLocals = false); diff --git a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h index fc7b8fc25bd917..84e187851e7441 100644 --- a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -204,7 +204,7 @@ struct LTOCodeGenerator { llvm::function_ref mustPreserveGV); bool determineTarget(); - std::unique_ptr createTargetMachine(); + std::unique_ptr createTargetMachine(Module &M); void emitError(const std::string &ErrMsg); void emitWarning(const std::string &ErrMsg); diff --git a/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h index 210a2ce00bdf81..b2d630212ad1d7 100644 --- a/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -41,6 +41,7 @@ struct TargetMachineBuilder { Optional RelocModel; CodeGenOpt::Level CGOptLevel = CodeGenOpt::Aggressive; + std::unique_ptr create(Module &TheModule) const; std::unique_ptr create() const; }; diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index f9a054dbed3d64..8df8b46f05e4a3 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -110,6 +110,9 @@ class TargetMachine { unsigned RequireStructuredCFG : 1; unsigned O0WantsFastISel : 1; +private: + mutable unsigned OptionsCanBeInitalizedFromModule : 1; + public: const TargetOptions DefaultOptions; mutable TargetOptions Options; @@ -163,7 +166,10 @@ class TargetMachine { } /// Create a DataLayout. - const DataLayout createDataLayout() const { return DL; } + const DataLayout createDataLayout() const { + OptionsCanBeInitalizedFromModule = false; + return DL; + } /// Test if a DataLayout if compatible with the CodeGen for this target. /// @@ -193,6 +199,17 @@ class TargetMachine { return DL.getPointerSize(DL.getAllocaAddrSpace()); } + /// Target hook for updating this TargetMachine's Options based + // on the provided module metadata. + virtual void + setTargetOptionsWithModuleMetadata(const Module &M LLVM_ATTRIBUTE_UNUSED) {} + + /// This method ensures that `setTargetOptionsWithModuleMetadata` is + // called, and ensures that is called before `createDataLayout` so that + // Options set from module metadata are modified as early as possible + // before they are used. + void initializeOptionsWithModuleMetadata(const Module &M); + /// Reset the target options based on the function's attributes. // FIXME: Remove TargetOptions that affect per-function code generation // from TargetMachine. diff --git a/llvm/lib/CodeGen/ParallelCG.cpp b/llvm/lib/CodeGen/ParallelCG.cpp index 849b667254bd0e..58f03b0d21b92c 100644 --- a/llvm/lib/CodeGen/ParallelCG.cpp +++ b/llvm/lib/CodeGen/ParallelCG.cpp @@ -25,9 +25,9 @@ using namespace llvm; static void codegen(Module *M, llvm::raw_pwrite_stream &OS, - function_ref()> TMFactory, + function_ref(Module &)> TMFactory, CodeGenFileType FileType) { - std::unique_ptr TM = TMFactory(); + std::unique_ptr TM = TMFactory(*M); assert(TM && "Failed to create target machine!"); legacy::PassManager CodeGenPasses; @@ -39,7 +39,7 @@ static void codegen(Module *M, llvm::raw_pwrite_stream &OS, std::unique_ptr llvm::splitCodeGen( std::unique_ptr M, ArrayRef OSs, ArrayRef BCOSs, - const std::function()> &TMFactory, + const std::function(Module &)> &TMFactory, CodeGenFileType FileType, bool PreserveLocals) { assert(BCOSs.empty() || BCOSs.size() == OSs.size()); diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index 1796d6ba60cc68..9751e1c9d3786a 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -201,6 +201,7 @@ createTargetMachine(const Config &Conf, const Target *TheTarget, Module &M) { TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel, CodeModel, Conf.CGOptLevel)); assert(TM && "Failed to create target machine"); + TM->initializeOptionsWithModuleMetadata(M); return TM; } diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp index 027e197e1e0d81..3f16052afc3f05 100644 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -377,16 +377,18 @@ bool LTOCodeGenerator::determineTarget() { MCpu = "cyclone"; } - TargetMach = createTargetMachine(); + TargetMach = createTargetMachine(*MergedModule); assert(TargetMach && "Unable to create target machine"); return true; } -std::unique_ptr LTOCodeGenerator::createTargetMachine() { +std::unique_ptr LTOCodeGenerator::createTargetMachine(Module &M) { assert(MArch && "MArch is not set!"); - return std::unique_ptr(MArch->createTargetMachine( + std::unique_ptr TM(MArch->createTargetMachine( TripleStr, MCpu, FeatureStr, Options, RelocModel, None, CGOptLevel)); + TM->initializeOptionsWithModuleMetadata(M); + return TM; } // If a linkonce global is present in the MustPreserveSymbols, we need to make @@ -619,7 +621,7 @@ bool LTOCodeGenerator::compileOptimized(ArrayRef Out) { // original module at parallelism level 1 which we then assign back to // MergedModule. MergedModule = splitCodeGen(std::move(MergedModule), Out, {}, - [&]() { return createTargetMachine(); }, FileType, + [&](Module &M) { return createTargetMachine(M); }, FileType, ShouldRestoreGlobalsLinkage); // If statistics were requested, save them to the specified file or diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp index 38f49693b62e24..7c9e23563cbdc1 100644 --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -565,7 +565,8 @@ void ThinLTOCodeGenerator::crossReferenceSymbol(StringRef Name) { } // TargetMachine factory -std::unique_ptr TargetMachineBuilder::create() const { +std::unique_ptr +TargetMachineBuilder::create(Module &TheModule) const { std::string ErrMsg; const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple.str(), ErrMsg); @@ -582,6 +583,7 @@ std::unique_ptr TargetMachineBuilder::create() const { TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options, RelocModel, None, CGOptLevel)); assert(TM && "Cannot create target machine"); + TM->initializeOptionsWithModuleMetadata(TheModule); return TM; } @@ -879,8 +881,8 @@ void ThinLTOCodeGenerator::optimize(Module &TheModule) { initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple())); // Optimize now - optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding, - nullptr); + optimizeModule(TheModule, *TMBuilder.create(TheModule), OptLevel, + Freestanding, nullptr); } /// Write out the generated object file, either from CacheEntryPath or from @@ -951,7 +953,8 @@ void ThinLTOCodeGenerator::run() { /*IsImporting*/ false); // CodeGen - auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create()); + auto OutputBuffer = + codegenModule(*TheModule, *TMBuilder.create(*TheModule)); if (SavedObjectsDirectoryPath.empty()) ProducedBinaries[count] = std::move(OutputBuffer); else @@ -1124,8 +1127,8 @@ void ThinLTOCodeGenerator::run() { auto &ImportList = ImportLists[ModuleIdentifier]; // Run the main process now, and generates a binary auto OutputBuffer = ProcessThinLTOModule( - *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList, - ExportList, GUIDPreservedSymbols, + *TheModule, *Index, ModuleMap, *TMBuilder.create(*TheModule), + ImportList, ExportList, GUIDPreservedSymbols, ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions, DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count); diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td index e86ac85ff0dc32..4f65a701c80369 100644 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -313,6 +313,7 @@ def : ProcessorModel<"snitch", SnitchModel, [FeatureStdExtM, FeatureStdExtA, FeatureStdExtF, FeatureStdExtD, + FeatureExtZfh, FeatureExtXfrep, FeatureExtXdma, FeatureExtXssr]>; diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp index 8e2d269021bbba..b563127f86c022 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -109,6 +109,19 @@ RISCVTargetMachine::getSubtargetImpl(const Function &F) const { return I.get(); } +void RISCVTargetMachine::setTargetOptionsWithModuleMetadata( + const Module &M LLVM_ATTRIBUTE_UNUSED) { + StringRef ABIName = Options.MCOptions.getABIName(); + if (const MDString *ModuleTargetABI = + dyn_cast_or_null(M.getModuleFlag("target-abi"))) { + StringRef ModuleABIName = ModuleTargetABI->getString(); + if (!ABIName.empty() && ModuleABIName != ABIName) + report_fatal_error("-target-abi option != target-abi module flag"); + if (ABIName.empty()) + Options.MCOptions.ABIName = ModuleABIName.str(); + } +} + TargetTransformInfo RISCVTargetMachine::getTargetTransformInfo(const Function &F) { return TargetTransformInfo(RISCVTTIImpl(this, F)); diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.h b/llvm/lib/Target/RISCV/RISCVTargetMachine.h index 3156333f7ee175..3f0a9ae69e5dbb 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.h +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.h @@ -42,6 +42,9 @@ class RISCVTargetMachine : public LLVMTargetMachine { return TLOF.get(); } + void setTargetOptionsWithModuleMetadata( + const Module &M LLVM_ATTRIBUTE_UNUSED) override; + TargetTransformInfo getTargetTransformInfo(const Function &F) override; virtual bool isNoopAddrSpaceCast(unsigned SrcAS, diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 2aee0e5c3fb83e..0dcb3693c926df 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -37,7 +37,8 @@ TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString, : TheTarget(T), DL(DataLayoutString), TargetTriple(TT), TargetCPU(std::string(CPU)), TargetFS(std::string(FS)), AsmInfo(nullptr), MRI(nullptr), MII(nullptr), STI(nullptr), RequireStructuredCFG(false), - O0WantsFastISel(false), DefaultOptions(Options), Options(Options) {} + O0WantsFastISel(false), OptionsCanBeInitalizedFromModule(true), + DefaultOptions(Options), Options(Options) {} TargetMachine::~TargetMachine() = default; @@ -45,6 +46,19 @@ bool TargetMachine::isPositionIndependent() const { return getRelocationModel() == Reloc::PIC_; } +void TargetMachine::initializeOptionsWithModuleMetadata(const Module &M) { + // TODO: This was added in the original patch (D72624) but now fails for llc + // because the lambda function `SetDataLayout` is called during IR parsing (llc.cpp). + // For RISCV the data layout is independent of the module metadata currently parsed + // (target-abi). Other targets don't use this hook + + // assert( + // OptionsCanBeInitalizedFromModule && + // "setOptionsWithModuleMetadata cannot be called after createDataLayout"); + + setTargetOptionsWithModuleMetadata(M); +} + /// Reset the target options based on the function's attributes. /// setFunctionAttributes should have made the raw attribute value consistent /// with the command line flag if used. diff --git a/llvm/lib/Target/TargetMachineC.cpp b/llvm/lib/Target/TargetMachineC.cpp index 60fe84cadacc22..8f9df6f3d5d07e 100644 --- a/llvm/lib/Target/TargetMachineC.cpp +++ b/llvm/lib/Target/TargetMachineC.cpp @@ -193,6 +193,7 @@ static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M, std::string error; + TM->initializeOptionsWithModuleMetadata(*Mod); Mod->setDataLayout(TM->createDataLayout()); CodeGenFileType ft; diff --git a/llvm/test/CodeGen/RISCV/module-target-abi2.ll b/llvm/test/CodeGen/RISCV/module-target-abi2.ll index 8664c9add06919..f5fc69c2d28a2c 100644 --- a/llvm/test/CodeGen/RISCV/module-target-abi2.ll +++ b/llvm/test/CodeGen/RISCV/module-target-abi2.ll @@ -8,8 +8,7 @@ ; RV32IF-ILP32: -target-abi option != target-abi module flag -; FLAGS: Flags: 0x0 -; // this should be "Flags :0x2, single-float ABI", it will be fixed later. +; FLAGS: Flags: 0x2, single-float ABI define float @foo(i32 %a) nounwind #0 { ; DEFAULT: # %bb.0: diff --git a/llvm/test/LTO/RISCV/Inputs/mabi-invalid.ll b/llvm/test/LTO/RISCV/Inputs/mabi-invalid.ll new file mode 100644 index 00000000000000..2898fde78f599e --- /dev/null +++ b/llvm/test/LTO/RISCV/Inputs/mabi-invalid.ll @@ -0,0 +1,14 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +define float @foo(float %x) #0 { + %conv = fpext float %x to double + %add = fadd double %conv, 0x400921FD80C9BEFB + %conv1 = fptrunc double %add to float + ret float %conv1 +} + +attributes #0 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"ilp32"} diff --git a/llvm/test/LTO/RISCV/Inputs/mabi.ll b/llvm/test/LTO/RISCV/Inputs/mabi.ll new file mode 100644 index 00000000000000..114e2580d1605c --- /dev/null +++ b/llvm/test/LTO/RISCV/Inputs/mabi.ll @@ -0,0 +1,14 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +define float @foo(float %x) #0 { + %conv = fpext float %x to double + %add = fadd double %conv, 0x400921FD80C9BEFB + %conv1 = fptrunc double %add to float + ret float %conv1 +} + +attributes #0 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"ilp32f"} diff --git a/llvm/test/LTO/RISCV/lit.local.cfg b/llvm/test/LTO/RISCV/lit.local.cfg new file mode 100644 index 00000000000000..f54903a14088af --- /dev/null +++ b/llvm/test/LTO/RISCV/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'RISCV' in config.root.targets: + config.unsupported = True \ No newline at end of file diff --git a/llvm/test/LTO/RISCV/mabi-invalid.ll b/llvm/test/LTO/RISCV/mabi-invalid.ll new file mode 100644 index 00000000000000..e74abd4ddf51d6 --- /dev/null +++ b/llvm/test/LTO/RISCV/mabi-invalid.ll @@ -0,0 +1,35 @@ +; Check with regular LTO +; RUN: rm -f %t* +; RUN: llvm-as < %s >%t1 +; RUN: llvm-as < %p/Inputs/mabi-invalid.ll >%t2 +; Check old API +; RUN: not llvm-lto -exported-symbol=main -o %t3 %t1 %t2 2>&1 | FileCheck %s +; Check new API +; RUN: not llvm-lto2 run -r %t1,foo, -r %t1,main,plx -r %t2,foo,plx -o %t3.o %t1 %t2 2>&1 | FileCheck %s + +; Check with ThinLTO. +; RUN: rm -f %t* +; RUN: opt -module-summary -o %t1 %s +; RUN: opt -module-summary -o %t2 %p/Inputs/mabi-invalid.ll +; Check old API +; RUN: not --crash llvm-lto -thinlto -thinlto-action=run %t1 %t2 -exported-symbol=main 2>&1 | FileCheck %s +; Check new API +; RUN: not --crash llvm-lto2 run -r %t1,foo, -r %t1,main,plx -r %t2,foo,plx -o %t3.o %t1 %t2 2>&1 | FileCheck %s + +; CHECK: 'target-abi': IDs have conflicting values + +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +declare float @foo(float) #1 + +define float @main(float %x) #0 { + %retval = call float @foo(float 10.0) + ret float %retval +} + +attributes #0 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } +attributes #1 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"ilp32f"} diff --git a/llvm/test/LTO/RISCV/mabi.ll b/llvm/test/LTO/RISCV/mabi.ll new file mode 100644 index 00000000000000..10450a06aa3718 --- /dev/null +++ b/llvm/test/LTO/RISCV/mabi.ll @@ -0,0 +1,44 @@ +; Test target-abi module flag generate correct elf flags. + +; Check with regular LTO +; RUN: rm -f %t* +; RUN: llvm-as < %s >%t1 +; RUN: llvm-as < %p/Inputs/mabi.ll >%t2 +; Check old API +; RUN: llvm-lto -exported-symbol=main -o %t3 %t1 %t2 +; RUN: llvm-readelf -h %t3 | FileCheck %s +; Check new API +; RUN: llvm-lto2 run -r %t1,foo, -r %t1,main,plx -r %t2,foo,plx -o %t3.o %t1 %t2 +; RUN: llvm-readelf -h %t3.o.0 | FileCheck %s + +; Check with ThinLTO. +; RUN: rm -f %t* +; RUN: opt -module-summary -o %t1 %s +; RUN: opt -module-summary -o %t2 %p/Inputs/mabi.ll +; Check old API +; RUN: llvm-lto -thinlto -thinlto-action=run %t1 %t2 -exported-symbol=main +; RUN: llvm-readelf -h %t1.thinlto.o | FileCheck %s +; RUN: llvm-readelf -h %t2.thinlto.o | FileCheck %s +; Check new API +; RUN: llvm-lto2 run -r %t1,foo, -r %t1,main,plx -r %t2,foo,plx -o %t3.o %t1 %t2 +; RUN: llvm-readelf -h %t3.o.1 | FileCheck %s +; RUN: llvm-readelf -h %t3.o.2 | FileCheck %s + +; CHECK: Flags: 0x2, single-float ABI + +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +declare float @foo(float) #1 + +define float @main(float %x) #0 { + %retval = call float @foo(float 10.0) + ret float %retval +} + +attributes #0 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } +attributes #1 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"ilp32f"} + diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py index 348ab62c7bb89e..3c08ebca081978 100644 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -305,6 +305,10 @@ def have_ld_plugin_support(): if len(fields) != 3: return False emulations = fields[2].split() + # default RISC-V ld supports linker plugin + if 'elf32lriscv' in emulations: + config.available_features.add('ld_emu_elf32lriscv') + return True if 'elf_x86_64' not in emulations: return False if 'elf32ppc' in emulations: diff --git a/llvm/test/tools/gold/RISCV/Inputs/mixed_lto.ll b/llvm/test/tools/gold/RISCV/Inputs/mixed_lto.ll new file mode 100644 index 00000000000000..37ad960585ccfb --- /dev/null +++ b/llvm/test/tools/gold/RISCV/Inputs/mixed_lto.ll @@ -0,0 +1,14 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +declare float @g() #1 +define i32 @main() #0 { + call float @g() + ret i32 0 +} + +attributes #0 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } +attributes #1 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"ilp32f"} \ No newline at end of file diff --git a/llvm/test/tools/gold/RISCV/lit.local.cfg b/llvm/test/tools/gold/RISCV/lit.local.cfg new file mode 100644 index 00000000000000..6075bb0f7d4161 --- /dev/null +++ b/llvm/test/tools/gold/RISCV/lit.local.cfg @@ -0,0 +1,2 @@ +if (not 'ld_plugin' in config.available_features): + config.unsupported = True diff --git a/llvm/test/tools/gold/RISCV/mixed_lto.ll b/llvm/test/tools/gold/RISCV/mixed_lto.ll new file mode 100644 index 00000000000000..fe27d21d564c91 --- /dev/null +++ b/llvm/test/tools/gold/RISCV/mixed_lto.ll @@ -0,0 +1,57 @@ +; REQUIRES: ld_emu_elf32lriscv + +; RUN: rm -f %t*.o + +;; Test mixed-mode LTO (mix of regular and thin LTO objects) +; RUN: opt -module-summary %s -o %t1.o +; RUN: opt %p/Inputs/mixed_lto.ll -o %t2.o +; RUN: %gold -m elf32lriscv -plugin %llvmshlibdir/LLVMgold%shlibext \ +; RUN: --plugin-opt=thinlto \ +; RUN: -shared --plugin-opt=-import-instr-limit=0 \ +; RUN: -o %t3.o %t2.o %t1.o +; RUN: llvm-nm %t3.o | FileCheck %s + +;; ChecK target ABI info +; RUN: llvm-readelf -h %t3.o | FileCheck %s --check-prefix=CHECK-ABI + +;; Test regular LTO +; RUN: opt %s -o %t1.o +; RUN: opt %p/Inputs/mixed_lto.ll -o %t2.o +; RUN: %gold -m elf32lriscv -plugin %llvmshlibdir/LLVMgold%shlibext \ +; RUN: --plugin-opt=thinlto \ +; RUN: -shared --plugin-opt=-import-instr-limit=0 \ +; RUN: -o %t3.o %t2.o %t1.o +; RUN: llvm-nm %t3.o | FileCheck %s + +;; ChecK target ABI info +; RUN: llvm-readelf -h %t3.o | FileCheck %s --check-prefix=CHECK-ABI + +;; Test thin LTO +; RUN: opt -module-summary %s -o %t1.o +; RUN: opt -module-summary %p/Inputs/mixed_lto.ll -o %t2.o +; RUN: %gold -m elf32lriscv -plugin %llvmshlibdir/LLVMgold%shlibext \ +; RUN: --plugin-opt=thinlto \ +; RUN: -shared --plugin-opt=-import-instr-limit=0 \ +; RUN: -o %t3.o %t2.o %t1.o +; RUN: llvm-nm %t3.o | FileCheck %s + +;; ChecK target ABI info +; RUN: llvm-readelf -h %t3.o | FileCheck %s --check-prefix=CHECK-ABI + + +; CHECK-DAG: T main +; CHECK-DAG: T g + +; CHECK-ABI: Flags: 0x2, single-float ABI + + +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" +define i32 @g() #0 { + ret i32 0 +} + +attributes #0 = { nounwind "target-features"="+a,+c,+f,+m,+relax" } + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"ilp32f"} \ No newline at end of file diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index 48f0adf7c7263e..eb05927f303aa4 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -565,6 +565,10 @@ static int compileModule(char **argv, LLVMContext &Context) { } assert(M && "Should have exited if we didn't have a module!"); + + // Initialise target default options from module metadata + Target->initializeOptionsWithModuleMetadata(*M); + if (codegen::getFloatABIForCalls() != FloatABI::Default) Options.FloatABIType = codegen::getFloatABIForCalls(); diff --git a/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp b/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp index 1d93299b9e81ec..83d1d3d813e10f 100644 --- a/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp +++ b/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp @@ -94,6 +94,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { // Set up the module to build for our target. M->setTargetTriple(TM->getTargetTriple().normalize()); + TM->initializeOptionsWithModuleMetadata(*M); M->setDataLayout(TM->createDataLayout()); // Build up a PM to do instruction selection. diff --git a/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp b/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp index dbe396d23ce29c..2a0747092e00b4 100644 --- a/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp +++ b/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp @@ -129,6 +129,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { // M->setTargetTriple(TM->getTargetTriple().normalize()); + TM->initializeOptionsWithModuleMetadata(*M); M->setDataLayout(TM->createDataLayout()); codegen::setFunctionAttributes(TM->getTargetCPU(), TM->getTargetFeatureString(), *M); diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp index 5cb59f85ccf827..049f31a27d8752 100644 --- a/llvm/tools/opt/opt.cpp +++ b/llvm/tools/opt/opt.cpp @@ -706,6 +706,9 @@ int main(int argc, char **argv) { std::unique_ptr TM(Machine); + if (TM) + TM->initializeOptionsWithModuleMetadata(*M); + // Override function attributes based on CPUStr, FeaturesStr, and command line // flags. codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M); diff --git a/mlir/lib/ExecutionEngine/ExecutionEngine.cpp b/mlir/lib/ExecutionEngine/ExecutionEngine.cpp index 9cd2054530ef52..bbb949a5737fac 100644 --- a/mlir/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/mlir/lib/ExecutionEngine/ExecutionEngine.cpp @@ -134,8 +134,9 @@ bool ExecutionEngine::setupTargetTriple(Module *llvmModule) { errs() << "Unable to create target machine\n"; return true; } - llvmModule->setDataLayout(machine->createDataLayout()); llvmModule->setTargetTriple(targetTriple); + machine->initializeOptionsWithModuleMetadata(*llvmModule); + llvmModule->setDataLayout(machine->createDataLayout()); return false; }