[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