[clang] [clang][X86] Support __attribute__((model("small"/"large"))) (PR #124834)

Arthur Eubanks via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 12 15:16:28 PST 2025


https://github.com/aeubanks updated https://github.com/llvm/llvm-project/pull/124834

>From 7c40169ec7430ec64aaeb053e423eca1ceff7f0d Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Tue, 28 Jan 2025 20:36:58 +0000
Subject: [PATCH 01/11] [clang][X86] Support
 __attribute__((model("small"/"large")))

Following up #72078, on x86-64 this allows a global to be considered
small or large regardless of the code model. For example, x86-64's
medium code model by default classifies globals as small or large
depending on their size relative to -mlarge-data-threshold.
---
 clang/docs/ReleaseNotes.rst          |  5 +++++
 clang/include/clang/Basic/Attr.td    | 13 +++++++++----
 clang/lib/Sema/SemaDeclAttr.cpp      | 11 ++++++++++-
 clang/test/CodeGen/X86/codemodel.cpp | 27 +++++++++++++++++++++++++++
 clang/test/Sema/attr-model.cpp       | 22 ++++++++++------------
 5 files changed, 61 insertions(+), 17 deletions(-)
 create mode 100644 clang/test/CodeGen/X86/codemodel.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7b5562a80a35a..dba3ed593dae2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -657,6 +657,11 @@ Attribute Changes in Clang
 
 - Clang now disallows the use of attributes after the namespace name. (#GH121407)
 
+- Clang now allows ``__attribute__((model("small")))`` and
+  ``__attribute__((model("large")))`` on non-TLS globals in x86-64 compilations.
+  This forces the global to be considered small or large in regards to the
+  x86-64 code model, regardless of the code model specified for the compilation.
+
 Improvements to Clang's diagnostics
 -----------------------------------
 
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index f4ba2bc3c6de3..092dc751d79f2 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -462,6 +462,7 @@ def TargetMSP430 : TargetArch<["msp430"]>;
 def TargetM68k : TargetArch<["m68k"]>;
 def TargetRISCV : TargetArch<["riscv32", "riscv64"]>;
 def TargetX86 : TargetArch<["x86"]>;
+def TargetX86_64 : TargetArch<["x86_64"]>;
 def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
 def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>;
 def TargetNVPTX : TargetArch<["nvptx", "nvptx64"]>;
@@ -3117,11 +3118,15 @@ def PragmaClangTextSection : InheritableAttr {
   let Documentation = [InternalOnly];
 }
 
-def CodeModel : InheritableAttr, TargetSpecificAttr<TargetLoongArch> {
+def CodeModel : InheritableAttr,
+                TargetSpecificAttr<TargetArch<!listconcat(
+                    TargetLoongArch.Arches, TargetX86_64.Arches)>> {
   let Spellings = [GCC<"model">];
-  let Args = [EnumArgument<"Model", "llvm::CodeModel::Model", /*is_string=*/1,
-              ["normal", "medium", "extreme"], ["Small", "Medium", "Large"],
-              /*opt=*/0, /*fake=*/0, /*isExternalType=*/1, /*isCovered=*/0>];
+  let Args = [EnumArgument<
+      "Model", "llvm::CodeModel::Model",
+      /*is_string=*/1, ["small", "normal", "medium", "large", "extreme"],
+      ["Small", "Small", "Medium", "Large", "Large"],
+      /*opt=*/0, /*fake=*/0, /*isExternalType=*/1, /*isCovered=*/0>];
   let Subjects = SubjectList<[NonTLSGlobalVar], ErrorDiag>;
   let Documentation = [CodeModelDocs];
 }
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 9d7d22590bce4..e2c752df06c25 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -64,6 +64,7 @@
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Triple.h"
@@ -2949,6 +2950,13 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   }
 }
 
+static bool isValidCodeModelAttr(Sema &S, StringRef Str) {
+  bool IsX8664Target =
+      S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64;
+  bool IsX8664Spelling = Str == "small" || Str == "large";
+  return IsX8664Target == IsX8664Spelling;
+}
+
 static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   StringRef Str;
   SourceLocation LiteralLoc;
@@ -2957,7 +2965,8 @@ static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
     return;
 
   llvm::CodeModel::Model CM;
-  if (!CodeModelAttr::ConvertStrToModel(Str, CM)) {
+  if (!CodeModelAttr::ConvertStrToModel(Str, CM) ||
+      !isValidCodeModelAttr(S, Str)) {
     S.Diag(LiteralLoc, diag::err_attr_codemodel_arg) << Str;
     return;
   }
diff --git a/clang/test/CodeGen/X86/codemodel.cpp b/clang/test/CodeGen/X86/codemodel.cpp
new file mode 100644
index 0000000000000..60a840665b49c
--- /dev/null
+++ b/clang/test/CodeGen/X86/codemodel.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown %s -o - | FileCheck %s
+
+// CHECK: @_ZL2v1 ={{.*}} global i32 0, code_model "small"
+static int v1 __attribute__((model("small")));
+
+void use1() {
+  v1 = 1;
+}
+
+// CHECK: @v2 ={{.*}} global float 0.000000e+00, code_model "large"
+float v2 __attribute__((model("large")));
+
+// CHECK: @_ZL2v3IiE ={{.*}} global i32 0, code_model "small"
+template <typename T>
+static T v3 __attribute__((model("small")));
+
+void use2() {
+  v3<int> = 1;
+}
+struct S {
+  double d;
+};
+
+typedef void (*F)();
+
+// CHECK: @v4 ={{.*}} global ptr null, code_model "large"
+F v4 __attribute__((model("large")));
diff --git a/clang/test/Sema/attr-model.cpp b/clang/test/Sema/attr-model.cpp
index 898cc03939843..725ec502df396 100644
--- a/clang/test/Sema/attr-model.cpp
+++ b/clang/test/Sema/attr-model.cpp
@@ -5,7 +5,7 @@
 // RUN: %clang_cc1 -triple riscv64 -verify=expected,riscv64 -fsyntax-only %s
 // RUN: %clang_cc1 -triple x86_64 -verify=expected,x86_64 -fsyntax-only %s
 
-#if defined(__loongarch__) && !__has_attribute(model)
+#if (defined(__loongarch__) || defined(__x86_64__)) && !__has_attribute(model)
 #error "Should support model attribute"
 #endif
 
@@ -14,51 +14,49 @@ int a __attribute((model("tiny")));    // aarch64-warning {{unknown attribute 'm
                                        // mips64-warning {{unknown attribute 'model' ignored}} \
                                        // powerpc64-warning {{unknown attribute 'model' ignored}} \
                                        // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-warning {{unknown attribute 'model' ignored}}
+                                       // x86_64-error {{code model 'tiny' is not supported on this target}}
 int b __attribute((model("small")));   // aarch64-warning {{unknown attribute 'model' ignored}} \
                                        // loongarch64-error {{code model 'small' is not supported on this target}} \
                                        // mips64-warning {{unknown attribute 'model' ignored}} \
                                        // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-warning {{unknown attribute 'model' ignored}}
+                                       // riscv64-warning {{unknown attribute 'model' ignored}}
 int c __attribute((model("normal")));  // aarch64-warning {{unknown attribute 'model' ignored}} \
                                        // mips64-warning {{unknown attribute 'model' ignored}} \
                                        // powerpc64-warning {{unknown attribute 'model' ignored}} \
                                        // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-warning {{unknown attribute 'model' ignored}}
+                                       // x86_64-error {{code model 'normal' is not supported on this target}}
 int d __attribute((model("kernel")));  // aarch64-warning {{unknown attribute 'model' ignored}} \
                                        // loongarch64-error {{code model 'kernel' is not supported on this target}} \
                                        // mips64-warning {{unknown attribute 'model' ignored}} \
                                        // powerpc64-warning {{unknown attribute 'model' ignored}} \
                                        // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-warning {{unknown attribute 'model' ignored}}
+                                       // x86_64-error {{code model 'kernel' is not supported on this target}}
 int e __attribute((model("medium")));  // aarch64-warning {{unknown attribute 'model' ignored}} \
                                        // mips64-warning {{unknown attribute 'model' ignored}} \
                                        // powerpc64-warning {{unknown attribute 'model' ignored}} \
                                        // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-warning {{unknown attribute 'model' ignored}}
+                                       // x86_64-error {{code model 'medium' is not supported on this target}}
 int f __attribute((model("large")));   // aarch64-warning {{unknown attribute 'model' ignored}} \
                                        // loongarch64-error {{code model 'large' is not supported on this target}} \
                                        // mips64-warning {{unknown attribute 'model' ignored}} \
                                        // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-warning {{unknown attribute 'model' ignored}}
+                                       // riscv64-warning {{unknown attribute 'model' ignored}}
 int g __attribute((model("extreme"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
                                        // mips64-warning {{unknown attribute 'model' ignored}} \
                                        // powerpc64-warning {{unknown attribute 'model' ignored}} \
                                        // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-warning {{unknown attribute 'model' ignored}}
+                                       // x86_64-error {{code model 'extreme' is not supported on this target}}
 
 void __attribute((model("extreme"))) h() {} // aarch64-warning {{unknown attribute 'model' ignored}} \
                                             // loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
                                             // mips64-warning {{unknown attribute 'model' ignored}} \
                                             // powerpc64-warning {{unknown attribute 'model' ignored}} \
                                             // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                            // x86_64-warning {{unknown attribute 'model' ignored}}
+                                            // x86_64-error {{'model' attribute only applies to non-TLS global variables}}
 
 thread_local int i __attribute((model("extreme"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
                                                     // loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
                                                     // mips64-warning {{unknown attribute 'model' ignored}} \
                                                     // powerpc64-warning {{unknown attribute 'model' ignored}} \
                                                     // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                                    // x86_64-warning {{unknown attribute 'model' ignored}}
+                                                    // x86_64-error {{'model' attribute only applies to non-TLS global variables}}

>From 8aa6b3fd3a7c33b80e598fc13b08aafcf6eae66e Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Wed, 29 Jan 2025 19:32:27 +0000
Subject: [PATCH 02/11] address comments

---
 clang/lib/Sema/SemaDeclAttr.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index e2c752df06c25..bb69d3226eb41 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2951,10 +2951,14 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
 }
 
 static bool isValidCodeModelAttr(Sema &S, StringRef Str) {
-  bool IsX8664Target =
-      S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64;
-  bool IsX8664Spelling = Str == "small" || Str == "large";
-  return IsX8664Target == IsX8664Spelling;
+  if (S.Context.getTargetInfo().getTriple().isLoongArch()) {
+    return Str == "normal" || Str == "medium" || Str == "extreme";
+  } else {
+    assert(S.Context.getTargetInfo().getTriple().getArch() ==
+               llvm::Triple::x86_64 &&
+           "only loongarch/x86-64 supported");
+    return Str == "small" || Str == "large";
+  }
 }
 
 static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

>From 2fdf2eed3ab3513ea30ee23354cf4a249087b323 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Wed, 29 Jan 2025 20:55:54 +0000
Subject: [PATCH 03/11] add nvptx RUN line to test, refactor test

---
 clang/test/Sema/attr-model.cpp | 66 ++++++++++++----------------------
 1 file changed, 22 insertions(+), 44 deletions(-)

diff --git a/clang/test/Sema/attr-model.cpp b/clang/test/Sema/attr-model.cpp
index 725ec502df396..938e3857a859d 100644
--- a/clang/test/Sema/attr-model.cpp
+++ b/clang/test/Sema/attr-model.cpp
@@ -1,62 +1,40 @@
-// RUN: %clang_cc1 -triple aarch64 -verify=expected,aarch64 -fsyntax-only %s
+// RUN: %clang_cc1 -triple aarch64 -verify=expected,unsupported -fsyntax-only %s
 // RUN: %clang_cc1 -triple loongarch64 -verify=expected,loongarch64 -fsyntax-only %s
-// RUN: %clang_cc1 -triple mips64 -verify=expected,mips64 -fsyntax-only %s
-// RUN: %clang_cc1 -triple powerpc64 -verify=expected,powerpc64 -fsyntax-only %s
-// RUN: %clang_cc1 -triple riscv64 -verify=expected,riscv64 -fsyntax-only %s
+// RUN: %clang_cc1 -triple mips64 -verify=expected,unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple powerpc64 -verify=expected,unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple riscv64 -verify=expected,unsupported -fsyntax-only %s
 // RUN: %clang_cc1 -triple x86_64 -verify=expected,x86_64 -fsyntax-only %s
+// RUN: %clang_cc1 -triple nvptx64 -fcuda-is-device -verify=expected,unsupported -fsyntax-only %s
 
 #if (defined(__loongarch__) || defined(__x86_64__)) && !__has_attribute(model)
 #error "Should support model attribute"
 #endif
 
-int a __attribute((model("tiny")));    // aarch64-warning {{unknown attribute 'model' ignored}} \
+int a __attribute((model("tiny")));    // unsupported-warning {{unknown attribute 'model' ignored}} \
                                        // loongarch64-error {{code model 'tiny' is not supported on this target}} \
-                                       // mips64-warning {{unknown attribute 'model' ignored}} \
-                                       // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}} \
                                        // x86_64-error {{code model 'tiny' is not supported on this target}}
-int b __attribute((model("small")));   // aarch64-warning {{unknown attribute 'model' ignored}} \
-                                       // loongarch64-error {{code model 'small' is not supported on this target}} \
-                                       // mips64-warning {{unknown attribute 'model' ignored}} \
-                                       // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}}
-int c __attribute((model("normal")));  // aarch64-warning {{unknown attribute 'model' ignored}} \
-                                       // mips64-warning {{unknown attribute 'model' ignored}} \
-                                       // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}} \
+int b __attribute((model("small")));   // unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // loongarch64-error {{code model 'small' is not supported on this target}}
+int c __attribute((model("normal")));  // unsupported-warning {{unknown attribute 'model' ignored}} \
                                        // x86_64-error {{code model 'normal' is not supported on this target}}
-int d __attribute((model("kernel")));  // aarch64-warning {{unknown attribute 'model' ignored}} \
+int d __attribute((model("kernel")));  // unsupported-warning {{unknown attribute 'model' ignored}} \
                                        // loongarch64-error {{code model 'kernel' is not supported on this target}} \
-                                       // mips64-warning {{unknown attribute 'model' ignored}} \
-                                       // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}} \
                                        // x86_64-error {{code model 'kernel' is not supported on this target}}
-int e __attribute((model("medium")));  // aarch64-warning {{unknown attribute 'model' ignored}} \
-                                       // mips64-warning {{unknown attribute 'model' ignored}} \
-                                       // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}} \
+int e __attribute((model("medium")));  // unsupported-warning {{unknown attribute 'model' ignored}} \
                                        // x86_64-error {{code model 'medium' is not supported on this target}}
-int f __attribute((model("large")));   // aarch64-warning {{unknown attribute 'model' ignored}} \
-                                       // loongarch64-error {{code model 'large' is not supported on this target}} \
-                                       // mips64-warning {{unknown attribute 'model' ignored}} \
-                                       // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}}
-int g __attribute((model("extreme"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
-                                       // mips64-warning {{unknown attribute 'model' ignored}} \
-                                       // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                       // riscv64-warning {{unknown attribute 'model' ignored}} \
+int f __attribute((model("large")));   // unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // loongarch64-error {{code model 'large' is not supported on this target}}
+int g __attribute((model("extreme"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
                                        // x86_64-error {{code model 'extreme' is not supported on this target}}
 
-void __attribute((model("extreme"))) h() {} // aarch64-warning {{unknown attribute 'model' ignored}} \
+void __attribute((model("extreme"))) h() {} // unsupported-warning {{unknown attribute 'model' ignored}} \
                                             // loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
-                                            // mips64-warning {{unknown attribute 'model' ignored}} \
-                                            // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                            // riscv64-warning {{unknown attribute 'model' ignored}} \
                                             // x86_64-error {{'model' attribute only applies to non-TLS global variables}}
 
-thread_local int i __attribute((model("extreme"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
-                                                    // loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
-                                                    // mips64-warning {{unknown attribute 'model' ignored}} \
-                                                    // powerpc64-warning {{unknown attribute 'model' ignored}} \
-                                                    // riscv64-warning {{unknown attribute 'model' ignored}} \
-                                                    // x86_64-error {{'model' attribute only applies to non-TLS global variables}}
+// NVPTX doesn't support thread_local at all.
+#ifndef __NVPTX__
+thread_local
+#endif
+int i __attribute((model("extreme"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
+                                       // x86_64-error {{'model' attribute only applies to non-TLS global variables}}

>From 1a32c3106f7732c78f482b77129e8fa8ef0804bb Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Wed, 29 Jan 2025 21:24:59 +0000
Subject: [PATCH 04/11] add more flags to RUN line

---
 clang/test/Sema/attr-model.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Sema/attr-model.cpp b/clang/test/Sema/attr-model.cpp
index 938e3857a859d..37a0152ca8e46 100644
--- a/clang/test/Sema/attr-model.cpp
+++ b/clang/test/Sema/attr-model.cpp
@@ -4,7 +4,7 @@
 // RUN: %clang_cc1 -triple powerpc64 -verify=expected,unsupported -fsyntax-only %s
 // RUN: %clang_cc1 -triple riscv64 -verify=expected,unsupported -fsyntax-only %s
 // RUN: %clang_cc1 -triple x86_64 -verify=expected,x86_64 -fsyntax-only %s
-// RUN: %clang_cc1 -triple nvptx64 -fcuda-is-device -verify=expected,unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple nvptx64-unknown-cuda -fcuda-is-device -x cuda -verify=expected,unsupported -fsyntax-only %s
 
 #if (defined(__loongarch__) || defined(__x86_64__)) && !__has_attribute(model)
 #error "Should support model attribute"

>From 7ce06bdfc776eb3d8492da3042c4a05248425a78 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Mon, 3 Feb 2025 20:36:13 +0000
Subject: [PATCH 05/11] allow and ignore attribute on nvptx compiles

---
 clang/include/clang/Basic/Attr.td | 10 +++++++---
 clang/lib/Sema/SemaDeclAttr.cpp   |  5 +++++
 clang/test/Sema/attr-model.cpp    | 15 ++++++++-------
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 092dc751d79f2..d411842e6376e 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3118,9 +3118,13 @@ def PragmaClangTextSection : InheritableAttr {
   let Documentation = [InternalOnly];
 }
 
-def CodeModel : InheritableAttr,
-                TargetSpecificAttr<TargetArch<!listconcat(
-                    TargetLoongArch.Arches, TargetX86_64.Arches)>> {
+// The code model attribute only applies to LoongArch and x86-64, but for NVPTX
+// compilations that share code with the host, we want to ignore the attribute
+// rather than warn on it.
+def CodeModel
+    : InheritableAttr,
+      TargetSpecificAttr<TargetArch<!listconcat(
+          TargetLoongArch.Arches, TargetX86_64.Arches, TargetNVPTX.Arches)>> {
   let Spellings = [GCC<"model">];
   let Args = [EnumArgument<
       "Model", "llvm::CodeModel::Model",
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index bb69d3226eb41..1237ee4d70854 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2968,6 +2968,11 @@ static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
     return;
 
+  // Ignore the attribute for NVPTX compiles since it only applies to host
+  // globals.
+  if (S.Context.getTargetInfo().getTriple().isNVPTX())
+    return;
+
   llvm::CodeModel::Model CM;
   if (!CodeModelAttr::ConvertStrToModel(Str, CM) ||
       !isValidCodeModelAttr(S, Str)) {
diff --git a/clang/test/Sema/attr-model.cpp b/clang/test/Sema/attr-model.cpp
index 37a0152ca8e46..fcd06f294ef81 100644
--- a/clang/test/Sema/attr-model.cpp
+++ b/clang/test/Sema/attr-model.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -triple aarch64 -verify=expected,unsupported -fsyntax-only %s
-// RUN: %clang_cc1 -triple loongarch64 -verify=expected,loongarch64 -fsyntax-only %s
-// RUN: %clang_cc1 -triple mips64 -verify=expected,unsupported -fsyntax-only %s
-// RUN: %clang_cc1 -triple powerpc64 -verify=expected,unsupported -fsyntax-only %s
-// RUN: %clang_cc1 -triple riscv64 -verify=expected,unsupported -fsyntax-only %s
-// RUN: %clang_cc1 -triple x86_64 -verify=expected,x86_64 -fsyntax-only %s
-// RUN: %clang_cc1 -triple nvptx64-unknown-cuda -fcuda-is-device -x cuda -verify=expected,unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple aarch64 -verify=unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple loongarch64 -verify=loongarch64 -fsyntax-only %s
+// RUN: %clang_cc1 -triple mips64 -verify=unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple powerpc64 -verify=unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple riscv64 -verify=unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple x86_64 -verify=x86_64 -fsyntax-only %s
+// RUN: %clang_cc1 -triple nvptx64-unknown-cuda -fcuda-is-device -x cuda -verify=ignored -fsyntax-only %s
 
 #if (defined(__loongarch__) || defined(__x86_64__)) && !__has_attribute(model)
 #error "Should support model attribute"
@@ -28,6 +28,7 @@ int g __attribute((model("extreme"))); // unsupported-warning {{unknown attribut
                                        // x86_64-error {{code model 'extreme' is not supported on this target}}
 
 void __attribute((model("extreme"))) h() {} // unsupported-warning {{unknown attribute 'model' ignored}} \
+                                            // ignored-error {{'model' attribute only applies to non-TLS global variables}} \
                                             // loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
                                             // x86_64-error {{'model' attribute only applies to non-TLS global variables}}
 

>From 677970567ad179e4d0c49ffccf6fabaffafcee38 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Tue, 4 Feb 2025 23:22:07 +0000
Subject: [PATCH 06/11] ignore amdgpu/spirv

---
 clang/include/clang/Basic/Attr.td | 5 ++++-
 clang/lib/Sema/SemaDeclAttr.cpp   | 6 ++++--
 clang/test/Sema/attr-model.cpp    | 7 ++++++-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 01c60044526a9..eadbcdd72cb20 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -452,6 +452,7 @@ class TargetArch<list<string> arches> : TargetSpec {
 }
 def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
 def TargetAArch64 : TargetArch<["aarch64", "aarch64_be", "aarch64_32"]>;
+def TargetAMDGPU : TargetArch<["amdgcn", "r600"]>;
 def TargetAnyArm : TargetArch<!listconcat(TargetARM.Arches, TargetAArch64.Arches)>;
 def TargetAVR : TargetArch<["avr"]>;
 def TargetBPF : TargetArch<["bpfel", "bpfeb"]>;
@@ -464,6 +465,7 @@ def TargetRISCV : TargetArch<["riscv32", "riscv64"]>;
 def TargetX86 : TargetArch<["x86"]>;
 def TargetX86_64 : TargetArch<["x86_64"]>;
 def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
+def TargetSPIRV : TargetArch<["spirv", "spirv32", "spirv64"]>;
 def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>;
 def TargetNVPTX : TargetArch<["nvptx", "nvptx64"]>;
 def TargetWindows : TargetSpec {
@@ -3124,7 +3126,8 @@ def PragmaClangTextSection : InheritableAttr {
 def CodeModel
     : InheritableAttr,
       TargetSpecificAttr<TargetArch<!listconcat(
-          TargetLoongArch.Arches, TargetX86_64.Arches, TargetNVPTX.Arches)>> {
+          TargetLoongArch.Arches, TargetX86_64.Arches, TargetNVPTX.Arches,
+          TargetAMDGPU.Arches, TargetSPIRV.Arches)>> {
   let Spellings = [GCC<"model">];
   let Args = [EnumArgument<
       "Model", "llvm::CodeModel::Model",
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 1237ee4d70854..84248733a482d 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2968,9 +2968,11 @@ static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
     return;
 
-  // Ignore the attribute for NVPTX compiles since it only applies to host
+  // Ignore the attribute for GPU device compiles since it only applies to host
   // globals.
-  if (S.Context.getTargetInfo().getTriple().isNVPTX())
+  if (S.Context.getTargetInfo().getTriple().isNVPTX() ||
+      S.Context.getTargetInfo().getTriple().isAMDGPU() ||
+      S.Context.getTargetInfo().getTriple().isSPIRV())
     return;
 
   llvm::CodeModel::Model CM;
diff --git a/clang/test/Sema/attr-model.cpp b/clang/test/Sema/attr-model.cpp
index fcd06f294ef81..d4b6f592e8d81 100644
--- a/clang/test/Sema/attr-model.cpp
+++ b/clang/test/Sema/attr-model.cpp
@@ -5,6 +5,11 @@
 // RUN: %clang_cc1 -triple riscv64 -verify=unsupported -fsyntax-only %s
 // RUN: %clang_cc1 -triple x86_64 -verify=x86_64 -fsyntax-only %s
 // RUN: %clang_cc1 -triple nvptx64-unknown-cuda -fcuda-is-device -x cuda -verify=ignored -fsyntax-only %s
+// RUN: %clang_cc1 -triple amdgcn -verify=ignored -fsyntax-only %s
+// RUN: %clang_cc1 -triple r600 -verify=ignored -fsyntax-only %s
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -verify=ignored -fsyntax-only %s
+// RUN: %clang_cc1 -triple spirv32-unknown-unknown -verify=ignored -fsyntax-only %s
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -verify=ignored -fsyntax-only %s
 
 #if (defined(__loongarch__) || defined(__x86_64__)) && !__has_attribute(model)
 #error "Should support model attribute"
@@ -33,7 +38,7 @@ void __attribute((model("extreme"))) h() {} // unsupported-warning {{unknown att
                                             // x86_64-error {{'model' attribute only applies to non-TLS global variables}}
 
 // NVPTX doesn't support thread_local at all.
-#ifndef __NVPTX__
+#if !defined(__NVPTX__) && !defined(__AMDGCN__) && !defined(__R600__) && !defined(__SPIRV__)
 thread_local
 #endif
 int i __attribute((model("extreme"))); // unsupported-warning {{unknown attribute 'model' ignored}} \

>From 2263db165f5b77810b7b631f352286bbdceed6f2 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Wed, 5 Feb 2025 18:28:17 +0000
Subject: [PATCH 07/11] update AttrDocs.td

---
 clang/include/clang/Basic/AttrDocs.td | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index a8b588169725a..b609c5488cdce 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -62,6 +62,10 @@ def CodeModelDocs : Documentation {
   let Content = [{
 The ``model`` attribute allows overriding the translation unit's
 code model (specified by ``-mcmodel``) for a specific global variable.
+
+On LoongArch, allowed values are "normal", "medium", "extreme".
+
+On x86-64, allowed values are "small" and "large".
   }];
   let Heading = "model";
 }

>From bf8f7d41dda1d553ce69a24133c916f0cd4b41e9 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Wed, 5 Feb 2025 21:14:34 +0000
Subject: [PATCH 08/11] more descriptive docs (at least for x86-64)

---
 clang/include/clang/Basic/AttrDocs.td | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index b609c5488cdce..a59d3a42cf8f1 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -65,7 +65,13 @@ code model (specified by ``-mcmodel``) for a specific global variable.
 
 On LoongArch, allowed values are "normal", "medium", "extreme".
 
-On x86-64, allowed values are "small" and "large".
+On x86-64, allowed values are ``"small"`` and ``"large"``. ``"small"`` is
+roughly equivalent to ``-mcmodel=small``, meaning the global is considered
+"small" placed closer to the ``.text`` section relative to "large" globals, and
+to prefer using 32-bit relocations to access the global. ``"large"`` is roughly
+equivalent to ``-mcmodel=large``, meaning the global is considered "large" and
+placed further from the ``.text`` section relative to "small" globals, and
+64-bit relocations must be used to access the global.
   }];
   let Heading = "model";
 }

>From d314c8ebb83c21d960b53bc0b309aabfce914125 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Wed, 12 Feb 2025 22:02:46 +0000
Subject: [PATCH 09/11] warn if host triple doesn't support attribute

---
 clang/lib/Sema/SemaDeclAttr.cpp | 35 ++++++++++++++++++-------
 clang/test/Sema/attr-model.cpp  | 46 +++++++++++++++++++++++++--------
 2 files changed, 60 insertions(+), 21 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 84248733a482d..6632ed62605f3 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2950,12 +2950,11 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   }
 }
 
-static bool isValidCodeModelAttr(Sema &S, StringRef Str) {
-  if (S.Context.getTargetInfo().getTriple().isLoongArch()) {
+static bool isValidCodeModelAttr(llvm::Triple Triple, StringRef Str) {
+  if (Triple.isLoongArch()) {
     return Str == "normal" || Str == "medium" || Str == "extreme";
   } else {
-    assert(S.Context.getTargetInfo().getTriple().getArch() ==
-               llvm::Triple::x86_64 &&
+    assert(Triple.getArch() == llvm::Triple::x86_64 &&
            "only loongarch/x86-64 supported");
     return Str == "small" || Str == "large";
   }
@@ -2964,20 +2963,36 @@ static bool isValidCodeModelAttr(Sema &S, StringRef Str) {
 static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   StringRef Str;
   SourceLocation LiteralLoc;
+  auto IsTripleSupported = [](const llvm::Triple Triple) {
+    return Triple.getArch() == llvm::Triple::ArchType::x86_64 ||
+           Triple.isLoongArch();
+  };
+
   // Check that it is a string.
   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
     return;
 
-  // Ignore the attribute for GPU device compiles since it only applies to host
-  // globals.
-  if (S.Context.getTargetInfo().getTriple().isNVPTX() ||
-      S.Context.getTargetInfo().getTriple().isAMDGPU() ||
-      S.Context.getTargetInfo().getTriple().isSPIRV())
+  SmallVector<llvm::Triple, 2> Triples = {
+      S.Context.getTargetInfo().getTriple()};
+  if (auto *aux = S.Context.getAuxTargetInfo()) {
+    Triples.push_back(aux->getTriple());
+  } else if (S.Context.getTargetInfo().getTriple().isNVPTX() ||
+             S.Context.getTargetInfo().getTriple().isAMDGPU() ||
+             S.Context.getTargetInfo().getTriple().isSPIRV()) {
+    // Ignore the attribute for pure GPU device compiles since it only applies
+    // to host globals.
+    return;
+  }
+
+  auto SupportedTripleIt = llvm::find_if(Triples, IsTripleSupported);
+  if (SupportedTripleIt == Triples.end()) {
+    S.Diag(LiteralLoc, diag::warn_unknown_attribute_ignored) << AL;
     return;
+  }
 
   llvm::CodeModel::Model CM;
   if (!CodeModelAttr::ConvertStrToModel(Str, CM) ||
-      !isValidCodeModelAttr(S, Str)) {
+      !isValidCodeModelAttr(*SupportedTripleIt, Str)) {
     S.Diag(LiteralLoc, diag::err_attr_codemodel_arg) << Str;
     return;
   }
diff --git a/clang/test/Sema/attr-model.cpp b/clang/test/Sema/attr-model.cpp
index d4b6f592e8d81..558439cf8db0f 100644
--- a/clang/test/Sema/attr-model.cpp
+++ b/clang/test/Sema/attr-model.cpp
@@ -11,36 +11,60 @@
 // RUN: %clang_cc1 -triple spirv32-unknown-unknown -verify=ignored -fsyntax-only %s
 // RUN: %clang_cc1 -triple spirv64-unknown-unknown -verify=ignored -fsyntax-only %s
 
+// RUN: %clang_cc1 -triple x86_64 -aux-triple nvptx64 -x cuda -verify=x86_64 -fsyntax-only %s
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple x86_64 -x cuda -fcuda-is-device -verify=nvptx64-x86_64 -fsyntax-only %s
+// RUN: %clang_cc1 -triple aarch64 -aux-triple nvptx64 -x cuda -verify=unsupported -fsyntax-only %s
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple aarch64 -x cuda -fcuda-is-device -verify=nvptx64-unsupported -fsyntax-only %s
+
 #if (defined(__loongarch__) || defined(__x86_64__)) && !__has_attribute(model)
 #error "Should support model attribute"
 #endif
 
 int a __attribute((model("tiny")));    // unsupported-warning {{unknown attribute 'model' ignored}} \
                                        // loongarch64-error {{code model 'tiny' is not supported on this target}} \
-                                       // x86_64-error {{code model 'tiny' is not supported on this target}}
+                                       // x86_64-error {{code model 'tiny' is not supported on this target}} \
+                                       // nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // nvptx64-x86_64-error {{code model 'tiny' is not supported on this target}}
 int b __attribute((model("small")));   // unsupported-warning {{unknown attribute 'model' ignored}} \
-                                       // loongarch64-error {{code model 'small' is not supported on this target}}
+                                       // loongarch64-error {{code model 'small' is not supported on this target}} \
+                                       // nvptx64-unsupported-warning {{unknown attribute 'model' ignored}}
 int c __attribute((model("normal")));  // unsupported-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-error {{code model 'normal' is not supported on this target}}
+                                       // x86_64-error {{code model 'normal' is not supported on this target}} \
+                                       // nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // nvptx64-x86_64-error {{code model 'normal' is not supported on this target}}
 int d __attribute((model("kernel")));  // unsupported-warning {{unknown attribute 'model' ignored}} \
                                        // loongarch64-error {{code model 'kernel' is not supported on this target}} \
-                                       // x86_64-error {{code model 'kernel' is not supported on this target}}
+                                       // x86_64-error {{code model 'kernel' is not supported on this target}} \
+                                       // nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // nvptx64-x86_64-error {{code model 'kernel' is not supported on this target}}
 int e __attribute((model("medium")));  // unsupported-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-error {{code model 'medium' is not supported on this target}}
+                                       // x86_64-error {{code model 'medium' is not supported on this target}} \
+                                       // nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // nvptx64-x86_64-error {{code model 'medium' is not supported on this target}}
 int f __attribute((model("large")));   // unsupported-warning {{unknown attribute 'model' ignored}} \
-                                       // loongarch64-error {{code model 'large' is not supported on this target}}
+                                       // loongarch64-error {{code model 'large' is not supported on this target}} \
+                                       // nvptx64-unsupported-warning {{unknown attribute 'model' ignored}}
 int g __attribute((model("extreme"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
-                                       // x86_64-error {{code model 'extreme' is not supported on this target}}
+                                       // x86_64-error {{code model 'extreme' is not supported on this target}} \
+                                       // nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // nvptx64-x86_64-error {{code model 'extreme' is not supported on this target}}
 
 void __attribute((model("extreme"))) h() {} // unsupported-warning {{unknown attribute 'model' ignored}} \
                                             // ignored-error {{'model' attribute only applies to non-TLS global variables}} \
                                             // loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
-                                            // x86_64-error {{'model' attribute only applies to non-TLS global variables}}
+                                            // x86_64-error {{'model' attribute only applies to non-TLS global variables}} \
+                                            // nvptx64-unsupported-error {{'model' attribute only applies to non-TLS global variables}} \
+                                            // nvptx64-x86_64-error {{'model' attribute only applies to non-TLS global variables}}
 
-// NVPTX doesn't support thread_local at all.
-#if !defined(__NVPTX__) && !defined(__AMDGCN__) && !defined(__R600__) && !defined(__SPIRV__)
+#if !defined(__CUDA__) || !defined(__CUDA_ARCH__)
+// if we are compiling for non-cuda host, or host mode in a CUDA compile
+#if !defined(__AMDGCN__) && !defined(__R600__) && !defined(__SPIRV__)
+// for all non-cuda hosts, above targets don't support thread_local
 thread_local
 #endif
+#endif
 int i __attribute((model("extreme"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
                                        // loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
-                                       // x86_64-error {{'model' attribute only applies to non-TLS global variables}}
+                                       // x86_64-error {{'model' attribute only applies to non-TLS global variables}} \
+                                       // nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
+                                       // nvptx64-x86_64-error {{code model 'extreme' is not supported on this target}}

>From 17290295e8305e344341577545a1fad3a733023f Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Wed, 12 Feb 2025 23:15:00 +0000
Subject: [PATCH 10/11] llvm::Triple&

---
 clang/lib/Sema/SemaDeclAttr.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 6632ed62605f3..3db100e148efa 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2950,7 +2950,7 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   }
 }
 
-static bool isValidCodeModelAttr(llvm::Triple Triple, StringRef Str) {
+static bool isValidCodeModelAttr(llvm::Triple &Triple, StringRef Str) {
   if (Triple.isLoongArch()) {
     return Str == "normal" || Str == "medium" || Str == "extreme";
   } else {

>From c664880f0b673e4700abfaf5779fa2a3806228ce Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Wed, 12 Feb 2025 23:16:02 +0000
Subject: [PATCH 11/11] one more &

---
 clang/lib/Sema/SemaDeclAttr.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 3db100e148efa..7eddf58b2e7da 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2963,7 +2963,7 @@ static bool isValidCodeModelAttr(llvm::Triple &Triple, StringRef Str) {
 static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   StringRef Str;
   SourceLocation LiteralLoc;
-  auto IsTripleSupported = [](const llvm::Triple Triple) {
+  auto IsTripleSupported = [](llvm::Triple &Triple) {
     return Triple.getArch() == llvm::Triple::ArchType::x86_64 ||
            Triple.isLoongArch();
   };



More information about the cfe-commits mailing list