diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.h b/clang/lib/Driver/ToolChains/RISCVToolchain.h --- a/clang/lib/Driver/ToolChains/RISCVToolchain.h +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.h @@ -25,6 +25,7 @@ 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/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp --- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -144,6 +144,12 @@ 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/llvm/lib/Target/RISCV/RISCVTargetMachine.h b/llvm/lib/Target/RISCV/RISCVTargetMachine.h --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.h +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.h @@ -42,6 +42,9 @@ return TLOF.get(); } + void setTargetOptionsWithModuleMetadata( + const Module &M LLVM_ATTRIBUTE_UNUSED) const override; + TargetTransformInfo getTargetTransformInfo(const Function &F) override; }; } diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -105,6 +105,19 @@ return I.get(); } +void RISCVTargetMachine::setTargetOptionsWithModuleMetadata( + const Module &M LLVM_ATTRIBUTE_UNUSED) const { + 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/test/CodeGen/RISCV/module-target-abi2.ll b/llvm/test/CodeGen/RISCV/module-target-abi2.ll --- 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/foo_ilp32.ll b/llvm/test/LTO/RISCV/Inputs/foo_ilp32.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/RISCV/Inputs/foo_ilp32.ll @@ -0,0 +1,14 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-unknown-elf" + +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/foo_ilp32f.ll b/llvm/test/LTO/RISCV/Inputs/foo_ilp32f.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/RISCV/Inputs/foo_ilp32f.ll @@ -0,0 +1,14 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-unknown-elf" + +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 --- /dev/null +++ b/llvm/test/LTO/RISCV/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'RISCV' in config.root.targets: + config.unsupported = True diff --git a/llvm/test/LTO/RISCV/mabi-invalid.ll b/llvm/test/LTO/RISCV/mabi-invalid.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/RISCV/mabi-invalid.ll @@ -0,0 +1,28 @@ +; XFAIL: * +; Check with regular LTO +; RUN: llvm-as < %s > %t1 +; RUN: llvm-as < %S/Inputs/foo_ilp32.ll > %t2 +; RUN: llvm-lto -exported-symbol=main -o %t3 %t1 %t2 2>&1 | FileCheck %s + +; Check with ThinLTO. +; RUN: opt -module-summary -o %t1.summary %s +; RUN: opt -module-summary -o %t2.summary %S/Inputs/foo_ilp32.ll +; RUN: llvm-lto2 run -r %t2.summary,foo,plx -r %t1.summary,main,plx -r %t1.summary,foo, -o %t3 %t1.summary %t2.summary 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-unknown-elf" + +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 --- /dev/null +++ b/llvm/test/LTO/RISCV/mabi.ll @@ -0,0 +1,29 @@ +; Test target-abi module flag generate correct elf flags. + +; Check with regular LTO +; RUN: llvm-as < %s >%t1 +; RUN: llvm-lto -exported-symbol=main -o %t2 %t1 +; RUN: llvm-readelf -h %t2 | FileCheck %s + +; Check with ThinLTO. +; RUN: opt -module-summary -o %t1.summary %s +; RUN: llvm-lto2 run -r %t1.summary,foo, -r %t1.summary,main,plx -o %t2 %t1.summary +; RUN: llvm-readelf -h %t2.1 | FileCheck %s + +; CHECK: Flags: 0x2, single-float ABI + +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-unknown-elf" + +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/tools/gold/RISCV/Inputs/mixed_lto.ll b/llvm/test/tools/gold/RISCV/Inputs/mixed_lto.ll new file mode 100644 --- /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"} diff --git a/llvm/test/tools/gold/RISCV/lit.local.cfg b/llvm/test/tools/gold/RISCV/lit.local.cfg new file mode 100644 --- /dev/null +++ b/llvm/test/tools/gold/RISCV/lit.local.cfg @@ -0,0 +1,3 @@ +if (not 'ld_plugin' in config.available_features or + not 'RISCV' in config.root.targets): + 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 --- /dev/null +++ b/llvm/test/tools/gold/RISCV/mixed_lto.ll @@ -0,0 +1,36 @@ +; REQUIRES: ld_emu_elf32lriscv + +; Test mixed-mode LTO (mix of regular and thin LTO objects) +; RUN: opt %s -o %t.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: --plugin-opt=-import-instr-limit=0 \ +; RUN: -shared -o %t3.o %t2.o %t.o +; RUN: llvm-nm %t3.o | FileCheck %s + +; Test ThinLTO + +; CHECK-DAG: T main +; CHECK-DAG: T g + +; RUN: opt %s -module-hash -module-summary -o %thin0.o +; RUN: opt %p/miaxed_lto.ll -module-hash -module-summary -o %thin1.o +; RUN: %gold -m elf32lriscv -plugin %llvmshlibdir/LLVMgold%shlibext \ +; RUN: --plugin-opt=thinlto \ +; RUN: -shared -o %thin3.o %thin0.o %thin1.o +; RUN: llvm-readelf -h %thin3 | FileCheck %s --check-prefix=THINLTO + +; CHECK-THINLTO: 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"}