[llvm] [llvm][IR] Add per-global code model attribute (PR #72077)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 12 18:48:51 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
Author: hev (heiher)
<details>
<summary>Changes</summary>
This adds a per-global code model attribute, which can override the target's code model to access global variables.
Link: https://discourse.llvm.org/t/how-to-best-implement-code-model-overriding-for-certain-values/71816
Suggested-by: Arthur Eubanks <aeubanks@<!-- -->google.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/72077.diff
13 Files Affected:
- (modified) llvm/docs/LangRef.rst (+1)
- (modified) llvm/include/llvm/AsmParser/LLParser.h (+1)
- (modified) llvm/include/llvm/AsmParser/LLToken.h (+1)
- (modified) llvm/include/llvm/IR/GlobalObject.h (+21)
- (modified) llvm/lib/AsmParser/LLLexer.cpp (+1)
- (modified) llvm/lib/AsmParser/LLParser.cpp (+29)
- (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+16)
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+16-2)
- (modified) llvm/lib/IR/AsmWriter.cpp (+21)
- (modified) llvm/lib/IR/Globals.cpp (+12)
- (modified) llvm/lib/IR/LLVMContextImpl.h (+3)
- (added) llvm/test/Bitcode/global-variables-code-model.ll (+17)
- (added) llvm/test/Bitcode/global-variables-code-model.ll.bc ()
``````````diff
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index ff4f769dcc0dbac..c3d708532b5b0e7 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -757,6 +757,7 @@ Syntax::
<global | constant> <Type> [<InitializerConstant>]
[, section "name"] [, partition "name"]
[, comdat [($name)]] [, align <Alignment>]
+ [, code_model "model"]
[, no_sanitize_address] [, no_sanitize_hwaddress]
[, sanitize_address_dyninit] [, sanitize_memtag]
(, !name !N)*
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index eca908a24aac7b2..9e5968c5917f73f 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -290,6 +290,7 @@ namespace llvm {
bool parseOptionalCallingConv(unsigned &CC);
bool parseOptionalAlignment(MaybeAlign &Alignment,
bool AllowParens = false);
+ bool parseOptionalCodeModel(CodeModel::Model &model);
bool parseOptionalDerefAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes);
bool parseOptionalUWTableKind(UWTableKind &Kind);
bool parseAllocKind(AllocFnKind &Kind);
diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index c9dcd29b31955dc..56a8db2d68df238 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -115,6 +115,7 @@ enum Kind {
kw_addrspace,
kw_section,
kw_partition,
+ kw_code_model,
kw_alias,
kw_ifunc,
kw_module,
diff --git a/llvm/include/llvm/IR/GlobalObject.h b/llvm/include/llvm/IR/GlobalObject.h
index 889bd3a28e12b37..08af50191a05b1a 100644
--- a/llvm/include/llvm/IR/GlobalObject.h
+++ b/llvm/include/llvm/IR/GlobalObject.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Value.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Alignment.h"
namespace llvm {
@@ -52,6 +53,7 @@ class GlobalObject : public GlobalValue {
enum {
LastAlignmentBit = 5,
HasSectionHashEntryBit,
+ HasCodeModelHashEntryBit,
GlobalObjectBits,
};
@@ -124,6 +126,24 @@ class GlobalObject : public GlobalValue {
/// appropriate default object file section.
void setSection(StringRef S);
+ /// Check if this global has a custom code model.
+ ///
+ bool hasCodeModel() const {
+ return getGlobalValueSubClassData() & (1 << HasCodeModelHashEntryBit);
+ }
+
+ /// Get the custom code model of this global if it has one.
+ ///
+ /// If this global does not have a custom code model, the default small code
+ /// model will be used.
+ CodeModel::Model getCodeModel() const {
+ return hasCodeModel() ? getCodeModelImpl() : CodeModel::Small;
+ }
+
+ /// Change the code model for this global.
+ ///
+ void setCodeModel(CodeModel::Model M);
+
bool hasComdat() const { return getComdat() != nullptr; }
const Comdat *getComdat() const { return ObjComdat; }
Comdat *getComdat() { return ObjComdat; }
@@ -170,6 +190,7 @@ class GlobalObject : public GlobalValue {
}
StringRef getSectionImpl() const;
+ CodeModel::Model getCodeModelImpl() const;
};
} // end namespace llvm
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index da9e9f4a3c9833b..3b96f0e4fe866bd 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -570,6 +570,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(addrspace);
KEYWORD(section);
KEYWORD(partition);
+ KEYWORD(code_model);
KEYWORD(alias);
KEYWORD(ifunc);
KEYWORD(module);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 9940bfb15d1979e..784f2e71c726a67 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1286,6 +1286,11 @@ bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc,
return true;
if (Alignment)
GV->setAlignment(*Alignment);
+ } else if (Lex.getKind() == lltok::kw_code_model) {
+ CodeModel::Model CodeModel;
+ if (parseOptionalCodeModel(CodeModel))
+ return true;
+ GV->setCodeModel(CodeModel);
} else if (Lex.getKind() == lltok::MetadataVar) {
if (parseGlobalObjectMetadataAttachment(*GV))
return true;
@@ -2166,6 +2171,30 @@ bool LLParser::parseOptionalAlignment(MaybeAlign &Alignment, bool AllowParens) {
return false;
}
+/// parseOptionalCodeModel
+/// ::= /* empty */
+/// ::= 'code_model' "large"
+bool LLParser::parseOptionalCodeModel(CodeModel::Model &model) {
+ Lex.Lex();
+ auto StrVal = Lex.getStrVal();
+ auto ErrMsg = "expected global code model string";
+ if (StrVal == "tiny")
+ model = CodeModel::Tiny;
+ else if (StrVal == "small")
+ model = CodeModel::Small;
+ else if (StrVal == "kernel")
+ model = CodeModel::Kernel;
+ else if (StrVal == "medium")
+ model = CodeModel::Medium;
+ else if (StrVal == "large")
+ model = CodeModel::Large;
+ else
+ return tokError(ErrMsg);
+ if (parseToken(lltok::StringConstant, ErrMsg))
+ return true;
+ return false;
+}
+
/// parseOptionalDerefAttrBytes
/// ::= /* empty */
/// ::= AttrKind '(' 4 ')'
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 76431e883b8d96d..740692894e39f01 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1144,6 +1144,17 @@ static bool getDecodedDSOLocal(unsigned Val) {
}
}
+static CodeModel::Model getDecodedCodeModel(unsigned Val) {
+ switch(Val) {
+ case 1: return CodeModel::Tiny;
+ default: // Map unknown values to small.
+ case 2: return CodeModel::Small;
+ case 3: return CodeModel::Kernel;
+ case 4: return CodeModel::Medium;
+ case 5: return CodeModel::Large;
+ }
+}
+
static GlobalVariable::ThreadLocalMode getDecodedThreadLocalMode(unsigned Val) {
switch (Val) {
case 0: return GlobalVariable::NotThreadLocal;
@@ -3809,6 +3820,7 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
// dllstorageclass, comdat, attributes, preemption specifier,
// partition strtab offset, partition strtab size] (name in VST)
// v2: [strtab_offset, strtab_size, v1]
+ // v3: [v2, code_model]
StringRef Name;
std::tie(Name, Record) = readNameFromStrtab(Record);
@@ -3917,6 +3929,10 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
NewGV->setSanitizerMetadata(Meta);
}
+ if (Record.size() > 17 && Record[17]) {
+ NewGV->setCodeModel(getDecodedCodeModel(Record[17]));
+ }
+
return Error::success();
}
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index d16b5c7781c2413..44f4b9e2dcf6aaf 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1212,6 +1212,19 @@ static unsigned getEncodedUnnamedAddr(const GlobalValue &GV) {
llvm_unreachable("Invalid unnamed_addr");
}
+static unsigned getEncodedCodeModel(const GlobalVariable &GV) {
+ if (!GV.hasCodeModel())
+ return 0;
+ switch (GV.getCodeModel()) {
+ case CodeModel::Tiny: return 1;
+ case CodeModel::Small: return 2;
+ case CodeModel::Kernel: return 3;
+ case CodeModel::Medium: return 4;
+ case CodeModel::Large: return 5;
+ }
+ llvm_unreachable("Invalid code model");
+}
+
size_t ModuleBitcodeWriter::addToStrtab(StringRef Str) {
if (GenerateHash)
Hasher.update(Str);
@@ -1404,7 +1417,7 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// GLOBALVAR: [strtab offset, strtab size, type, isconst, initid,
// linkage, alignment, section, visibility, threadlocal,
// unnamed_addr, externally_initialized, dllstorageclass,
- // comdat, attributes, DSO_Local, GlobalSanitizer]
+ // comdat, attributes, DSO_Local, GlobalSanitizer, code_model]
Vals.push_back(addToStrtab(GV.getName()));
Vals.push_back(GV.getName().size());
Vals.push_back(VE.getTypeID(GV.getValueType()));
@@ -1421,7 +1434,7 @@ void ModuleBitcodeWriter::writeModuleInfo() {
GV.isExternallyInitialized() ||
GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass ||
GV.hasComdat() || GV.hasAttributes() || GV.isDSOLocal() ||
- GV.hasPartition() || GV.hasSanitizerMetadata()) {
+ GV.hasPartition() || GV.hasSanitizerMetadata() || GV.hasCodeModel()) {
Vals.push_back(getEncodedVisibility(GV));
Vals.push_back(getEncodedThreadLocalMode(GV));
Vals.push_back(getEncodedUnnamedAddr(GV));
@@ -1439,6 +1452,7 @@ void ModuleBitcodeWriter::writeModuleInfo() {
Vals.push_back((GV.hasSanitizerMetadata() ? serializeSanitizerMetadata(
GV.getSanitizerMetadata())
: 0));
+ Vals.push_back(getEncodedCodeModel(GV));
} else {
AbbrevToUse = SimpleGVarAbbrev;
}
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 6d66b34423949fb..afc4ba1f2392b21 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -3647,6 +3647,27 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
printEscapedString(GV->getPartition(), Out);
Out << '"';
}
+ if (GV->hasCodeModel()) {
+ Out << ", code_model \"";
+ switch (GV->getCodeModel()) {
+ case CodeModel::Tiny:
+ printEscapedString("tiny", Out);
+ break;
+ case CodeModel::Small:
+ printEscapedString("small", Out);
+ break;
+ case CodeModel::Kernel:
+ printEscapedString("kernel", Out);
+ break;
+ case CodeModel::Medium:
+ printEscapedString("medium", Out);
+ break;
+ case CodeModel::Large:
+ printEscapedString("large", Out);
+ break;
+ }
+ Out << '"';
+ }
using SanitizerMetadata = llvm::GlobalValue::SanitizerMetadata;
if (GV->hasSanitizerMetadata()) {
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 7bd4503a689e4ae..3fc338fc767678d 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -139,6 +139,8 @@ void GlobalObject::copyAttributesFrom(const GlobalObject *Src) {
GlobalValue::copyAttributesFrom(Src);
setAlignment(Src->getAlign());
setSection(Src->getSection());
+ if (Src->hasCodeModel())
+ setCodeModel(Src->getCodeModel());
}
std::string GlobalValue::getGlobalIdentifier(StringRef Name,
@@ -263,6 +265,16 @@ void GlobalObject::setSection(StringRef S) {
setGlobalObjectFlag(HasSectionHashEntryBit, !S.empty());
}
+void GlobalObject::setCodeModel(CodeModel::Model M) {
+ getContext().pImpl->GlobalObjectCodeModels[this] = M;
+ setGlobalObjectFlag(HasCodeModelHashEntryBit, true);
+}
+
+CodeModel::Model GlobalObject::getCodeModelImpl() const {
+ assert(hasCodeModel());
+ return getContext().pImpl->GlobalObjectCodeModels[this];
+}
+
bool GlobalValue::isNobuiltinFnDef() const {
const Function *F = dyn_cast<Function>(this);
if (!F || F->empty())
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index ebc444fcb6896e9..44602ea10142e98 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1570,6 +1570,9 @@ class LLVMContextImpl {
/// Collection of per-GlobalObject sections used in this context.
DenseMap<const GlobalObject *, StringRef> GlobalObjectSections;
+ /// Collection of per-GlobalObject code models used in this context.
+ DenseMap<const GlobalObject *, CodeModel::Model> GlobalObjectCodeModels;
+
/// Collection of per-GlobalValue partitions used in this context.
DenseMap<const GlobalValue *, StringRef> GlobalValuePartitions;
diff --git a/llvm/test/Bitcode/global-variables-code-model.ll b/llvm/test/Bitcode/global-variables-code-model.ll
new file mode 100644
index 000000000000000..f8cae4475028510
--- /dev/null
+++ b/llvm/test/Bitcode/global-variables-code-model.ll
@@ -0,0 +1,17 @@
+; RUN: llvm-dis < %s.bc| FileCheck %s
+; RUN: verify-uselistorder < %s.bc
+
+ at tiny.var = global i32 1, code_model "tiny"
+; CHECK: @tiny.var = global i32 1, code_model "tiny"
+
+ at small.var = global i32 1, code_model "small"
+; CHECK: @small.var = global i32 1, code_model "small"
+
+ at kernel.var = global i32 1, code_model "kernel"
+; CHECK: @kernel.var = global i32 1, code_model "kernel"
+
+ at medium.var = global i32 1, code_model "medium"
+; CHECK: @medium.var = global i32 1, code_model "medium"
+
+ at large.var = global i32 1, code_model "large"
+; CHECK: @large.var = global i32 1, code_model "large"
diff --git a/llvm/test/Bitcode/global-variables-code-model.ll.bc b/llvm/test/Bitcode/global-variables-code-model.ll.bc
new file mode 100644
index 000000000000000..c63ce041784a839
Binary files /dev/null and b/llvm/test/Bitcode/global-variables-code-model.ll.bc differ
``````````
</details>
https://github.com/llvm/llvm-project/pull/72077
More information about the llvm-commits
mailing list