khchen created this revision.
Herald added subscribers: llvm-commits, cfe-commits, luismarques, apazos, 
sameer.abuasal, pzheng, s.egerton, lenary, Jim, benna, psnobl, dang, jocewei, 
PkmX, rkruppe, dexonsmith, the_o, brucehoult, MartinMosbeck, rogfer01, 
steven_wu, edward-jones, zzheng, MaskRay, jrtc27, shiva0217, kito-cheng, 
niosHD, sabuasal, simoncook, johnrusso, rbar, asb, hiraditya, inglorion, 
mehdi_amini.
Herald added projects: clang, LLVM.

1. Support ABI checking with per function target-features

if users don't specific -mattr, the default target-feature come from IR 
attribute.

2. Enable LTO for RISCV
3. Init MCOptions.ABIName via module flag metadata


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72245

Files:
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Driver/ToolChains/RISCVToolchain.cpp
  clang/lib/Driver/ToolChains/RISCVToolchain.h
  clang/test/CodeGen/riscv-metadata.c
  clang/test/Driver/gold-lto.c
  llvm/lib/LTO/LTOBackend.cpp
  llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
  llvm/lib/Target/RISCV/RISCVISelLowering.cpp
  llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
  llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
  llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
  llvm/test/CodeGen/RISCV/subtarget-features-std-ext.ll
  llvm/test/CodeGen/RISCV/subtarget-features-target-abi.ll
  llvm/tools/llc/llc.cpp

Index: llvm/tools/llc/llc.cpp
===================================================================
--- llvm/tools/llc/llc.cpp
+++ llvm/tools/llc/llc.cpp
@@ -472,6 +472,17 @@
   if (FloatABIForCalls != FloatABI::Default)
     Options.FloatABIType = FloatABIForCalls;
 
+  if (const MDString *ModuleTargetABI =
+          dyn_cast_or_null<MDString>(M->getModuleFlag("target-abi"))) {
+    if (Options.MCOptions.ABIName != "" &&
+        Options.MCOptions.ABIName != ModuleTargetABI->getString()) {
+      WithColor::warning(errs(), argv[0])
+          << ": warning: -target-abi option != target-abi module flag(ignoring "
+             "target-abi option)\n";
+    }
+    Options.MCOptions.ABIName = ModuleTargetABI->getString();
+  }
+
   // Figure out where we are going to send the output.
   std::unique_ptr<ToolOutputFile> Out =
       GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]);
Index: llvm/test/CodeGen/RISCV/subtarget-features-target-abi.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/subtarget-features-target-abi.ll
@@ -0,0 +1,26 @@
+; RUN: llc -mtriple=riscv32 < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=DEFAULT %s
+; RUN: llc -mtriple=riscv32 -target-abi ilp32 < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32IF-ILP32 %s
+; RUN: llc -mtriple=riscv32 -target-abi ilp32f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32IF-ILP32F %s
+; RUN: llc -mtriple=riscv32 -filetype=obj < %s | llvm-readelf -h - | FileCheck -check-prefixes=FLAGS %s
+
+; RV32IF-ILP32: -target-abi option != target-abi module flag(ignoring target-abi option)
+
+; FLAGS: Flags: 0x2, single-float ABI
+
+define float @foo(i32 %a) nounwind #0 {
+; DEFAULT: # %bb.0:
+; DEFAULT-NEXT: fcvt.s.w  fa0, a0
+; DEFAULT-NEXT: ret
+; RV32IF-ILP32F: # %bb.0:
+; RV32IF-ILP32F-NEXT: fcvt.s.w  fa0, a0
+; RV32IF-ILP32F-NEXT: ret
+  %conv = sitofp i32 %a to float
+  ret float %conv
+}
+
+attributes #0 = { "target-features"="+f"}
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"target-abi", !"ilp32f"}
Index: llvm/test/CodeGen/RISCV/subtarget-features-std-ext.ll
===================================================================
--- llvm/test/CodeGen/RISCV/subtarget-features-std-ext.ll
+++ llvm/test/CodeGen/RISCV/subtarget-features-std-ext.ll
@@ -2,12 +2,17 @@
 ; RUN:   | FileCheck -check-prefix=RV32IF-ILP32 %s
 ; RUN: llc -mtriple=riscv32 -target-abi ilp32f < %s 2>&1 \
 ; RUN:   | FileCheck -check-prefix=RV32IF-ILP32F %s
+; RUN: llc -mtriple=riscv32 -mattr=-f -target-abi ilp32f <%s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32I-ILP32F-FAILED %s
+
+; RV32I-ILP32F-FAILED: Hard-float 'f' ABI can't be used for a target that doesn't support the F instruction set extension
 
-; RV32IF-ILP32F: Hard-float 'f' ABI can't be used for a target that doesn't support the F instruction set extension (ignoring target-abi)
 
 define float @foo(i32 %a) nounwind #0 {
-; RV32IF-ILP32: # %bb.0:
-; RV32IF-ILP32-NEXT: fcvt.s.w  ft0, a0
+; RV32IF-ILP32: fcvt.s.w  ft0, a0
+; RV32IF-ILP32-NEXT: fmv.x.w a0, ft0
+; RV32IF-ILP32F: fcvt.s.w fa0, a0
+; RV32IF-ILP32F-NEXT: ret
   %conv = sitofp i32 %a to float
   ret float %conv
 }
Index: llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
===================================================================
--- llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
+++ llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
@@ -202,6 +202,8 @@
 ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
                      StringRef ABIName);
 
+ABI getTargetABI(StringRef ABIName);
+
 // Returns the register used to hold the stack pointer after realignment.
 Register getBPReg();
 
Index: llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
===================================================================
--- llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
+++ llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
@@ -12,16 +12,7 @@
 namespace RISCVABI {
 ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
                      StringRef ABIName) {
-  auto TargetABI = StringSwitch<ABI>(ABIName)
-                       .Case("ilp32", ABI_ILP32)
-                       .Case("ilp32f", ABI_ILP32F)
-                       .Case("ilp32d", ABI_ILP32D)
-                       .Case("ilp32e", ABI_ILP32E)
-                       .Case("lp64", ABI_LP64)
-                       .Case("lp64f", ABI_LP64F)
-                       .Case("lp64d", ABI_LP64D)
-                       .Default(ABI_Unknown);
-
+  auto TargetABI = getTargetABI(ABIName);
   bool IsRV64 = TT.isArch64Bit();
   bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
 
@@ -37,17 +28,8 @@
     errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "
               "target-abi)\n";
     TargetABI = ABI_Unknown;
-  } else if (ABIName.endswith("f") && !FeatureBits[RISCV::FeatureStdExtF]) {
-    errs() << "Hard-float 'f' ABI can't be used for a target that "
-              "doesn't support the F instruction set extension (ignoring "
-              "target-abi)\n";
-    TargetABI = ABI_Unknown;
-  } else if (ABIName.endswith("d") && !FeatureBits[RISCV::FeatureStdExtD]) {
-    errs() << "Hard-float 'd' ABI can't be used for a target that "
-              "doesn't support the D instruction set extension (ignoring "
-              "target-abi)\n";
-    TargetABI = ABI_Unknown;
   } else if (IsRV32E && TargetABI != ABI_ILP32E && TargetABI != ABI_Unknown) {
+    // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
     errs()
         << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n";
     TargetABI = ABI_Unknown;
@@ -67,6 +49,19 @@
   return ABI_ILP32;
 }
 
+ABI getTargetABI(StringRef ABIName) {
+  auto TargetABI = StringSwitch<ABI>(ABIName)
+                       .Case("ilp32", ABI_ILP32)
+                       .Case("ilp32f", ABI_ILP32F)
+                       .Case("ilp32d", ABI_ILP32D)
+                       .Case("ilp32e", ABI_ILP32E)
+                       .Case("lp64", ABI_LP64)
+                       .Case("lp64f", ABI_LP64F)
+                       .Case("lp64d", ABI_LP64D)
+                       .Default(ABI_Unknown);
+  return TargetABI;
+}
+
 // To avoid the BP value clobbered by a function call, we need to choose a
 // callee saved register to save the value. RV32E only has X8 and X9 as callee
 // saved registers and X8 will be used as fp. So we choose X9 as bp.
Index: llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -15,6 +15,7 @@
 #include "RISCVTargetObjectFile.h"
 #include "RISCVTargetTransformInfo.h"
 #include "TargetInfo/RISCVTargetInfo.h"
+#include "Utils/RISCVBaseInfo.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
@@ -89,8 +90,19 @@
     // creation will depend on the TM and the code generation flags on the
     // function that reside in TargetOptions.
     resetTargetOptions(F);
-    I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, FS,
-                                         Options.MCOptions.getABIName(), *this);
+    auto ABIName = Options.MCOptions.getABIName();
+    if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
+            F.getParent()->getModuleFlag("target-abi"))) {
+      auto TargetABI = RISCVABI::getTargetABI(ABIName);
+      if (TargetABI != RISCVABI::ABI_Unknown &&
+          ModuleTargetABI->getString() != ABIName) {
+        errs() << "-target-abi option != target-abi module flag(ignoring "
+                  "target-abi option)\n";
+      }
+      ABIName = ModuleTargetABI->getString();
+    }
+
+    I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, FS, ABIName, *this);
   }
   return I.get();
 }
Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -51,6 +51,20 @@
   RISCVABI::ABI ABI = Subtarget.getTargetABI();
   assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
 
+  if ((ABI == RISCVABI::ABI_ILP32F || ABI == RISCVABI::ABI_LP64F) &&
+      !Subtarget.hasStdExtF()) {
+    errs() << "Hard-float 'f' ABI can't be used for a target that "
+                "doesn't support the F instruction set extension (ignoring "
+                          "target-abi)\n";
+    ABI = Subtarget.is64Bit() ? RISCVABI::ABI_LP64 : RISCVABI::ABI_ILP32;
+  } else if ((ABI == RISCVABI::ABI_ILP32D || ABI == RISCVABI::ABI_LP64D) &&
+             !Subtarget.hasStdExtD()) {
+    errs() << "Hard-float 'd' ABI can't be used for a target that "
+              "doesn't support the D instruction set extension (ignoring "
+              "target-abi)\n";
+    ABI = Subtarget.is64Bit() ? RISCVABI::ABI_LP64 : RISCVABI::ABI_ILP32;
+  }
+
   switch (ABI) {
   default:
     report_fatal_error("Don't know how to lower this ABI");
Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
===================================================================
--- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -188,6 +188,18 @@
     Parser.addAliasForDirective(".word", ".4byte");
     Parser.addAliasForDirective(".dword", ".8byte");
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+
+    if (Options.ABIName.back() == 'f' &&
+        !getSTI().getFeatureBits()[RISCV::FeatureStdExtF]) {
+      errs() << "Hard-float 'f' ABI can't be used for a target that "
+                "doesn't support the F instruction set extension (ignoring "
+                "target-abi)\n";
+    } else if (Options.ABIName.back() == 'd' &&
+               !getSTI().getFeatureBits()[RISCV::FeatureStdExtD]) {
+      errs() << "Hard-float 'd' ABI can't be used for a target that "
+                "doesn't support the D instruction set extension (ignoring "
+                "target-abi)\n";
+    }
   }
 };
 
Index: llvm/lib/LTO/LTOBackend.cpp
===================================================================
--- llvm/lib/LTO/LTOBackend.cpp
+++ llvm/lib/LTO/LTOBackend.cpp
@@ -341,6 +341,18 @@
 
   std::unique_ptr<ToolOutputFile> DwoOut;
   SmallString<1024> DwoFile(Conf.SplitDwarfOutput);
+
+  if (const MDString *ModuleTargetABI =
+          dyn_cast_or_null<MDString>(Mod.getModuleFlag("target-abi"))) {
+    if (TM->Options.MCOptions.ABIName != "" &&
+        TM->Options.MCOptions.ABIName != ModuleTargetABI->getString()) {
+      errs()
+          << ": warning: -target-abi option != target-abi module flag(ignoring "
+             "target-abi option)\n";
+    }
+    TM->Options.MCOptions.ABIName = ModuleTargetABI->getString();
+  }
+
   if (!Conf.DwoDir.empty()) {
     std::error_code EC;
     if (auto EC = llvm::sys::fs::create_directories(Conf.DwoDir))
Index: clang/test/Driver/gold-lto.c
===================================================================
--- clang/test/Driver/gold-lto.c
+++ clang/test/Driver/gold-lto.c
@@ -26,3 +26,15 @@
 // RUN: %clang -target i686-linux-android -### %t.o -flto 2>&1 \
 // RUN:     | FileCheck %s --check-prefix=CHECK-X86-ANDROID
 // CHECK-X86-ANDROID: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+//
+//RUN: %clang -target riscv64-unknown-elf -### %t.o -flto 2>&1 \
+//RUN:     -march=rv64imf -mabi=lp64f \
+//RUN:     | FileCheck %s --check-prefix=CHECK-RISCV-BAREMETAL
+//
+//CHECK-RISCV-BAREMETAL: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
+//
+//RUN: %clang -target riscv64-unknown-linux-gnu -### %t.o -flto 2>&1 \
+//RUN:     -march=rv64imf -mabi=lp64f \
+//RUN:     | FileCheck %s --check-prefix=CHECK-RISCV-LINUX
+//
+//CHECK-RISCV-LINUX: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
Index: clang/test/CodeGen/riscv-metadata.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/riscv-metadata.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple riscv32 -target-abi ilp32 -emit-llvm -o - %s | FileCheck -check-prefix=ILP32 %s
+// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm -o - %s | FileCheck -check-prefix=ILP32F %s
+// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm -o - %s | FileCheck -check-prefix=ILP32D %s
+// RUN: %clang_cc1 -triple riscv64 -target-abi lp64 -emit-llvm -o - %s | FileCheck -check-prefix=LP64 %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm -o - %s | FileCheck -check-prefix=LP64F %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm -o - %s | FileCheck -check-prefix=LP64D %s
+
+// ILP32: !{{[0-9]+}} = !{i32 1, !"target-abi", !"ilp32"}
+// ILP32F: !{{[0-9]+}} = !{i32 1, !"target-abi", !"ilp32f"}
+// ILP32D: !{{[0-9]+}} = !{i32 1, !"target-abi", !"ilp32d"}
+
+// LP64: !{{[0-9]+}} = !{i32 1, !"target-abi", !"lp64"}
+// LP64F: !{{[0-9]+}} = !{i32 1, !"target-abi", !"lp64f"}
+// LP64D: !{{[0-9]+}} = !{i32 1, !"target-abi", !"lp64d"}
Index: clang/lib/Driver/ToolChains/RISCVToolchain.h
===================================================================
--- clang/lib/Driver/ToolChains/RISCVToolchain.h
+++ clang/lib/Driver/ToolChains/RISCVToolchain.h
@@ -28,6 +28,7 @@
   RuntimeLibType GetDefaultRuntimeLibType() const override;
   UnwindLibType
   GetUnwindLibType(const llvm::opt::ArgList &Args) const override;
+  bool HasNativeLLVMSupport() const override { return true; }
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                             llvm::opt::ArgStringList &CC1Args) const override;
Index: clang/lib/Driver/ToolChains/RISCVToolchain.cpp
===================================================================
--- clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -144,6 +144,12 @@
 
   std::string Linker = getToolChain().GetProgramPath(getShortName());
 
+  if (D.isUsingLTO()) {
+    assert(!Inputs.empty() && "Must have at least one input.");
+    AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+                  D.getLTOMode() == LTOK_Thin);
+  }
+
   bool WantCRTs =
       !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
 
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -537,6 +537,13 @@
     getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth);
   }
 
+  if (Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64) {
+    StringRef ABIStr = Target.getABI();
+    llvm::LLVMContext &Ctx = TheModule.getContext();
+    getModule().addModuleFlag(llvm::Module::Error, "target-abi",
+                              llvm::MDString::get(Ctx, ABIStr));
+  }
+
   if (CodeGenOpts.SanitizeCfiCrossDso) {
     // Indicate that we want cross-DSO control flow integrity checks.
     getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to