[clang] [llvm] IR: Store the default subtarget info in named metadata instead of the context. (PR #98673)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 12 11:12:28 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (pcc)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/98673.diff


8 Files Affected:

- (modified) clang/lib/CodeGen/BackendUtil.cpp (+2) 
- (modified) clang/lib/CodeGen/CodeGenAction.cpp (-6) 
- (modified) llvm/include/llvm/IR/LLVMContext.h (-16) 
- (modified) llvm/include/llvm/IR/Module.h (+18) 
- (modified) llvm/lib/IR/Function.cpp (+2-2) 
- (modified) llvm/lib/IR/LLVMContext.cpp (-16) 
- (modified) llvm/lib/IR/Module.cpp (+35) 
- (modified) llvm/lib/Linker/IRMover.cpp (+11) 


``````````diff
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index e765bbf637a66..5654530b268ca 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1337,6 +1337,8 @@ void clang::EmitBackendOutput(
     }
   }
 
+  M->setDefaultSubtargetInfo(TOpts.CPU, llvm::join(TOpts.Features, ","));
+
   EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M, VFS);
   AsmHelper.EmitAssembly(Action, std::move(OS), BC);
 
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index e87226e60297c..6ffbbb5da0041 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -294,9 +294,6 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {
   Ctx.setDiagnosticHandler(std::make_unique<ClangDiagnosticHandler>(
       CodeGenOpts, this));
 
-  Ctx.setDefaultTargetCPU(TargetOpts.CPU);
-  Ctx.setDefaultTargetFeatures(llvm::join(TargetOpts.Features, ","));
-
   Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr =
     setupLLVMOptimizationRemarks(
       Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses,
@@ -1203,9 +1200,6 @@ void CodeGenAction::ExecuteAction() {
   Ctx.setDiagnosticHandler(
       std::make_unique<ClangDiagnosticHandler>(CodeGenOpts, &Result));
 
-  Ctx.setDefaultTargetCPU(TargetOpts.CPU);
-  Ctx.setDefaultTargetFeatures(llvm::join(TargetOpts.Features, ","));
-
   Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr =
       setupLLVMOptimizationRemarks(
           Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses,
diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h
index 6ffa2bdaa319a..89ad6f1572c67 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -327,22 +327,6 @@ class LLVMContext {
   [[deprecated("Always returns false")]]
   bool supportsTypedPointers() const;
 
-  /// Get or set the current "default" target CPU (target-cpu function
-  /// attribute). The intent is that compiler frontends will set this to a value
-  /// that reflects the attribute that a function would get "by default" without
-  /// any specific function attributes, and compiler passes will attach the
-  /// attribute to newly created functions that are not associated with a
-  /// particular function, such as global initializers.
-  /// Function::createWithDefaultAttr() will create functions with this
-  /// attribute. This function should only be called by passes that run at
-  /// compile time and not by the backend or LTO passes.
-  StringRef getDefaultTargetCPU();
-  void setDefaultTargetCPU(StringRef CPU);
-
-  /// Similar to {get,set}DefaultTargetCPU() but for default target-features.
-  StringRef getDefaultTargetFeatures();
-  void setDefaultTargetFeatures(StringRef Features);
-
 private:
   // Module needs access to the add/removeModule methods.
   friend class Module;
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index d2b2fe40b1ada..b390cb156aa5b 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -1064,6 +1064,24 @@ class LLVM_EXTERNAL_VISIBILITY Module {
 
   /// Set the target variant version build SDK version metadata.
   void setDarwinTargetVariantSDKVersion(VersionTuple Version);
+
+  /// Get the current "default" target CPU (target-cpu function
+  /// attribute). The intent is that compiler frontends will set this to a value
+  /// that reflects the attribute that a function would get "by default" without
+  /// any specific function attributes, and compiler passes will attach the
+  /// attribute to newly created functions that are not associated with a
+  /// particular function, such as global initializers.
+  /// Function::createWithDefaultAttr() will create functions with this
+  /// attribute. This function should only be called by passes that run at
+  /// compile time and not by the backend or LTO passes.
+  StringRef getDefaultTargetCPU();
+
+  /// Similar to getDefaultTargetCPU() but for default target-features.
+  StringRef getDefaultTargetFeatures();
+
+  /// Set the data returned by getDefaultTargetCPU() and
+  /// getDefaultTargetFeatures().
+  void setDefaultSubtargetInfo(StringRef CPU, StringRef Features);
 };
 
 /// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 5fb348a8bbcd4..8fdb564d8afec 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -401,10 +401,10 @@ Function *Function::createWithDefaultAttr(FunctionType *Ty,
   }
   if (M->getModuleFlag("function_return_thunk_extern"))
     B.addAttribute(Attribute::FnRetThunkExtern);
-  StringRef DefaultCPU = F->getContext().getDefaultTargetCPU();
+  StringRef DefaultCPU = M->getDefaultTargetCPU();
   if (!DefaultCPU.empty())
     B.addAttribute("target-cpu", DefaultCPU);
-  StringRef DefaultFeatures = F->getContext().getDefaultTargetFeatures();
+  StringRef DefaultFeatures = M->getDefaultTargetFeatures();
   if (!DefaultFeatures.empty())
     B.addAttribute("target-features", DefaultFeatures);
   F->addFnAttrs(B);
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 194c7e7581cfb..8120cccace40b 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -390,19 +390,3 @@ void LLVMContext::setOpaquePointers(bool Enable) const {
 bool LLVMContext::supportsTypedPointers() const {
   return false;
 }
-
-StringRef LLVMContext::getDefaultTargetCPU() {
-  return pImpl->DefaultTargetCPU;
-}
-
-void LLVMContext::setDefaultTargetCPU(StringRef CPU) {
-  pImpl->DefaultTargetCPU = CPU;
-}
-
-StringRef LLVMContext::getDefaultTargetFeatures() {
-  return pImpl->DefaultTargetFeatures;
-}
-
-void LLVMContext::setDefaultTargetFeatures(StringRef Features) {
-  pImpl->DefaultTargetFeatures = Features;
-}
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index c966c53d09baf..e315f01be61ab 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -44,6 +44,7 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/RandomNumberGenerator.h"
 #include "llvm/Support/VersionTuple.h"
+#include "llvm/TargetParser/Triple.h"
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
@@ -903,3 +904,37 @@ VersionTuple Module::getDarwinTargetVariantSDKVersion() const {
 void Module::setDarwinTargetVariantSDKVersion(VersionTuple Version) {
   addSDKVersionMD(Version, *this, "darwin.target_variant.SDK Version");
 }
+
+void Module::setDefaultSubtargetInfo(StringRef CPU, StringRef Features) {
+  auto *MD = getOrInsertNamedMetadata("llvm.subtarget.info");
+  MD->clearOperands();
+  MD->addOperand(
+      MDNode::get(getContext(), {MDString::get(getContext(), CPU),
+                                 MDString::get(getContext(), Features)}));
+}
+
+StringRef Module::getDefaultTargetCPU() {
+  auto *MD = getNamedMetadata("llvm.subtarget.info");
+  // FIXME: This function is only meant to be called pre-LTO, but the AMDGPU and
+  // NVPTX backends end up calling this function in their CtorDtorLowering
+  // passes. For now we just return an empty string to avoid breaking them.
+  if (!MD) {
+    Triple T(getTargetTriple());
+    if (T.isAMDGPU() || T.isNVPTX())
+      return "";
+    report_fatal_error("Invalid call to getDefaultTargetCPU()");
+  }
+  return cast<MDString>(MD->getOperand(0)->getOperand(0))->getString();
+}
+
+StringRef Module::getDefaultTargetFeatures() {
+  auto *MD = getNamedMetadata("llvm.subtarget.info");
+  // FIXME: See getDefaultTargetCPU().
+  if (!MD) {
+    Triple T(getTargetTriple());
+    if (T.isAMDGPU() || T.isNVPTX())
+      return "";
+    report_fatal_error("Invalid call to getDefaultTargetFeatures()");
+  }
+  return cast<MDString>(MD->getOperand(0)->getOperand(1))->getString();
+}
diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp
index ba8f371127764..6717ab443473c 100644
--- a/llvm/lib/Linker/IRMover.cpp
+++ b/llvm/lib/Linker/IRMover.cpp
@@ -1240,11 +1240,22 @@ void IRLinker::linkNamedMDNodes() {
     if (IsPerformingImport && NMD.getName() == "llvm.stats")
       continue;
 
+    // Default subtarget info is only intended to be used before LTO and
+    // shouldn't be present after merging because the default subtargets may be
+    // different. Even if they were the same we wouldn't want to keep them to
+    // avoid introducing bugs that would only occur when merging modules with
+    // different subtarget info.
+    if (NMD.getName() == "llvm.subtarget.info")
+      continue;
+      
     NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName());
     // Add Src elements into Dest node.
     for (const MDNode *Op : NMD.operands())
       DestNMD->addOperand(Mapper.mapMDNode(*Op));
   }
+
+  if (auto *NMD = DstM.getNamedMetadata("llvm.subtarget.info"))
+    DstM.eraseNamedMetadata(NMD);
 }
 
 /// Merge the linker flags in Src into the Dest module.

``````````

</details>


https://github.com/llvm/llvm-project/pull/98673


More information about the llvm-commits mailing list