[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:16 PST 2023


https://github.com/heiher created https://github.com/llvm/llvm-project/pull/72077

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 at google.com>

>From 1db42907230511288a3ebc8f2a7b1453d11e62ac Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Fri, 10 Nov 2023 21:07:43 -0600
Subject: [PATCH] [llvm][IR] Add per-global code model attribute

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 at google.com>
Signed-off-by: WANG Rui <wangrui at loongson.cn>
---
 llvm/docs/LangRef.rst                         |   1 +
 llvm/include/llvm/AsmParser/LLParser.h        |   1 +
 llvm/include/llvm/AsmParser/LLToken.h         |   1 +
 llvm/include/llvm/IR/GlobalObject.h           |  21 +++++++++++++
 llvm/lib/AsmParser/LLLexer.cpp                |   1 +
 llvm/lib/AsmParser/LLParser.cpp               |  29 ++++++++++++++++++
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp     |  16 ++++++++++
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp     |  18 +++++++++--
 llvm/lib/IR/AsmWriter.cpp                     |  21 +++++++++++++
 llvm/lib/IR/Globals.cpp                       |  12 ++++++++
 llvm/lib/IR/LLVMContextImpl.h                 |   3 ++
 .../Bitcode/global-variables-code-model.ll    |  17 ++++++++++
 .../Bitcode/global-variables-code-model.ll.bc | Bin 0 -> 1568 bytes
 13 files changed, 139 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/Bitcode/global-variables-code-model.ll
 create mode 100644 llvm/test/Bitcode/global-variables-code-model.ll.bc

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index ff4f769dcc0dbac3..c3d708532b5b0e71 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 eca908a24aac7b2c..9e5968c5917f73fd 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 c9dcd29b31955dca..56a8db2d68df238f 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 889bd3a28e12b377..08af50191a05b1a3 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 da9e9f4a3c9833b0..3b96f0e4fe866bdd 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 9940bfb15d1979e4..784f2e71c726a679 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 76431e883b8d96d2..740692894e39f01f 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 d16b5c7781c2413d..44f4b9e2dcf6aafe 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 6d66b34423949fba..afc4ba1f2392b21e 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 7bd4503a689e4ae8..3fc338fc767678d0 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 ebc444fcb6896e9d..44602ea10142e98a 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 0000000000000000..f8cae4475028510a
--- /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 0000000000000000000000000000000000000000..c63ce041784a83952fb76450e43571c34a946da1
GIT binary patch
literal 1568
zcmXw3Z%i9y7{9jAD^TAn3v<-nop-<{9|Ue?xOQ!mwl}p-7Q6W;n7FK0Xc?|RDP8$9
zV_J at Rp#9L1#x#lvm?i%C#3m;DK-}76tYdZJG=@Y%T4@<G-5?H^na#xaKrXrG-sjDG
z&-45Jp67XO?6u{l3Ir)e5X7ZsYL318gXhO5({Joe)f|!OiV<3kAaBbMq)bjDa(HGB
ze9>_A1#7D4HKj&p7?TaF_Z6$OWYH(Ckm_Z*ZLG|8M5C+Ft14eF)m4qyeY14+kzGPW
zV;z&XrBs(HDE5^R>ZVLrHQWNC<@Ay0<j|LLt%%;*T~ZZMk5ULy0&`S(iZqvPL!+7#
z&_sKZ4tr_Ie%oBJt!lqY`B^o>hY{o`rYaw^d=!ZxvV*qxcvALxXZO{$yy4${&A;5}
z_WyI%bM-nGyhVQcmFNl%EI)VkX8xTg$Lha3>3sxBE%F3Rv;D|IPV{_D*tz3}kkAzW
zam>Q(Y*-NIqP6oVRk^c4A(q0#JXKPp*x4yUN=KiOpZ^|;blI}4r;d!PwdKvxNXh<J
z=Ze^Gi{RNyFocx2Q5C{xv$&^1W*%Yn!(zl1LI?WM-gu9C6~XRnz-9<Es%>O4LEN6i
zJxuY|F at A4aVNS8;h{Bxij|6<^ITbo!7koZ+(5DFY3qDHFrprMg3bG8=#b7HNV8a0#
zHM7JrjW5zfk|RCLsBwljF0h7ag=vO24J(Z4jf$WXJ$D*CbXxF38xnj`!RJJSwP^5h
zF$~)m5>Bavo=U+V7Y5?t7aweZ2O049HBev_uGA!+o5a&wc8SC1X?!+J%yY`$qO2js
z8sb~_il~pV`VoaOCN{vNPlt at ZDvVR2`bLM~YZ3fDK5!cCcM5?@Auu6mZ at -B>K(N0Y
zAQuHI7A#AF0%Sqe5=#j(X(jK__)?f$%HX*y at u!URR36t)v4_WbW7<*kKM|+U*N^tc
zk2h~dF-ZaPeR7_|*JxrnL3}79CBQVX!71N5&+F5oaf&rVL7pZ}Io3D=T`_XK6fzb1
zARZMuSd04O;rCWFpl}W39pE8Tow#EqbJ;zMSz;LiuxpJ|ym^}6J1puWtRXF$t|Sa8
z5pp!8?bAIf6r$>Z0=5X+-{(NViQUgAHz+L6V0j9A<N#e7u)+Z7KFlcZWkAjW9y8T{
z6gWH?CKj`M3N*1w6SFh{E4W5K at 1edh&amby3PX%Hq+4cS^&#0oh|@0g`2_8)yI`Hc
zvKesCg58^dSwxwl_iGe#ITeSkA}JhLfTau%TMZczN at s?ZN?T?pi1|q(V<ndpxTmI-
z0a>ZO7z~nUSeiduiT2usQxn1mA^7j5n9LLrO)*iwz#fL}l!l6_?euONM?$E#6U2#d
zg{Qfl0qYdDo>8tluuUlx$Y+$R6qa28c{l?X;4DaYN}1ZFkxwAVH_)$>{8E1{>^XF>
z#TSP>C5VOvacC8vn|x-?Dvbopv0ck&53V at DT?cFtEGIPzcGm$mr$S+LpmwW+`vs`J
zRKFJAxTv3&887nYm?%F3hXG&8;!6~s<0QKlCX*b#Fo~zOMduPSY!d>7xI>_9WSe~P
zPkKmo5jM04r8mM#!#PYTj1V&Nvj#zw at QbER7kT42Y;=Wrf;YjYkBad6M0%)gt~#Kp
zlI{WNISKF97vOi7BF0E(0v%lg^+C?x+sS#o(&CKU-{sy~b-LR+&UQ+BUe4d{mKF!}
z^-Mj}-VvbOx+c!e8FZZfCC<gT44nIb+u%9Wrsobewz?Xd4tNf=HZo1EUT?6oA>i%}
nG}t-<t=(<zhIVhai}TjOXdRr(>+Y?ScI!H!@z#6262|`k8uBb>

literal 0
HcmV?d00001




More information about the llvm-commits mailing list