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/mabi-invalid.ll b/llvm/test/LTO/RISCV/Inputs/mabi-invalid.ll new file mode 100644 --- /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 --- /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 --- /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,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 --- /dev/null +++ b/llvm/test/LTO/RISCV/mabi.ll @@ -0,0 +1,43 @@ +; 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 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -281,6 +281,10 @@ 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 --- /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,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 --- /dev/null +++ b/llvm/test/tools/gold/RISCV/mixed_lto.ll @@ -0,0 +1,43 @@ +; REQUIRES: ld_emu_elf32lriscv + +; RUN: rm -f %t*.o +;; 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: -shared --plugin-opt=-import-instr-limit=0 \ +; RUN: -o %t3.o %t2.o %t.o +; RUN: llvm-nm %t3.o | FileCheck %s +;; ChecK target ABI info +; RUN: llvm-readelf -h %t3.o | FileCheck %s --check-prefix=CHECK-ABI + +; RUN: opt %s -module-summary -o %thin0.o +; RUN: opt %p/Inputs/mixed_lto.ll -module-summary -o %thin1.o +; RUN: %gold -m elf32lriscv -plugin %llvmshlibdir/LLVMgold%shlibext \ +; RUN: --plugin-opt=thinlto \ +; RUN: -shared --plugin-opt=-import-instr-limit=0 \ +; RUN: -o %thin2.o %thin0.o %thin1.o +; RUN: llvm-nm %t3.o | FileCheck %s +;; ChecK target ABI info +; RUN: llvm-readelf -h %t3.o | FileCheck %s --check-prefix=CHECK-ABI +; RUN: llvm-readelf -h %thin2.o | FileCheck %s --check-prefix=CHECK-ABI + +;; Test ThinLTO +; 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"}