[llvm-branch-commits] [clang] [clang] Add clang::nooutline Attribute (PR #163666)
Sam Elliott via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Feb 9 22:48:29 PST 2026
https://github.com/lenary updated https://github.com/llvm/llvm-project/pull/163666
>From 44a5ae384da96462fa2b85ca5647d9a3a4080c14 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Wed, 15 Oct 2025 17:26:19 -0700
Subject: [PATCH 1/4] [clang] Add clang::nooutline Attribute
This change:
- Adds a `[[clang::nooutline]]` function attribute for C and C++. There
is no equivalent GNU syntax for this attribute, so no `__attribute__`
syntax.
- Uses the presence of `[[clang::nooutline]]` to add the `nooutline`
attribute to IR function definitions.
- Adds test for the above.
The `nooutline` attribute disables both the Machine Outliner (enabled at
Oz for some targets), and the IR Outliner (disabled by default).
---
clang/include/clang/Basic/Attr.td | 7 +++++++
clang/lib/CodeGen/CodeGenModule.cpp | 3 +++
clang/test/CodeGen/attr-nooutline.c | 16 ++++++++++++++++
...agma-attribute-supported-attributes-list.test | 1 +
clang/test/Sema/attr-nooutline.c | 7 +++++++
clang/test/Sema/attr-nooutline.cpp | 7 +++++++
6 files changed, 41 insertions(+)
create mode 100644 clang/test/CodeGen/attr-nooutline.c
create mode 100644 clang/test/Sema/attr-nooutline.c
create mode 100644 clang/test/Sema/attr-nooutline.cpp
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index ea3f9df6d8342..361ae41da97dc 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2371,6 +2371,13 @@ def NoInline : DeclOrStmtAttr {
let SimpleHandler = 1;
}
+def NoOutline : DeclOrStmtAttr {
+ let Spellings = [CXX11<"clang", "nooutline">, C23<"clang", "nooutline">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+ let SimpleHandler = 1;
+}
+
def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"nomips16">];
let Subjects = SubjectList<[Function], ErrorDiag>;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 65f5468c4b998..6a087be3751f0 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2928,6 +2928,9 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
B.addAttribute(llvm::Attribute::MinSize);
}
+ if (D->hasAttr<NoOutlineAttr>())
+ B.addAttribute(llvm::Attribute::NoOutline);
+
F->addFnAttrs(B);
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
diff --git a/clang/test/CodeGen/attr-nooutline.c b/clang/test/CodeGen/attr-nooutline.c
new file mode 100644
index 0000000000000..b9f175da24cb5
--- /dev/null
+++ b/clang/test/CodeGen/attr-nooutline.c
@@ -0,0 +1,16 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --version 6
+// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -disable-O0-optnone -o - | FileCheck %s
+
+
+// CHECK: Function Attrs: noinline nooutline nounwind
+// CHECK-LABEL: define dso_local i32 @t1(
+// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: ret i32 [[TMP0]]
+//
+[[clang::nooutline]] int t1(int x) {
+ return x;
+}
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index d6d900f3caf84..a7c667fa6018d 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -130,6 +130,7 @@
// CHECK-NEXT: NoMerge (SubjectMatchRule_function, SubjectMatchRule_variable)
// CHECK-NEXT: NoMicroMips (SubjectMatchRule_function)
// CHECK-NEXT: NoMips16 (SubjectMatchRule_function)
+// CHECK-NEXT: NoOutline (SubjectMatchRule_function)
// CHECK-NEXT: NoProfileFunction (SubjectMatchRule_function)
// CHECK-NEXT: NoRandomizeLayout (SubjectMatchRule_record)
// CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
diff --git a/clang/test/Sema/attr-nooutline.c b/clang/test/Sema/attr-nooutline.c
new file mode 100644
index 0000000000000..83848c22d1003
--- /dev/null
+++ b/clang/test/Sema/attr-nooutline.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+[[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
+
+[[clang::nooutline]] void t1(void);
+
+[[clang::nooutline(2)]] void t2(void); // expected-error {{'clang::nooutline' attribute takes no arguments}}
diff --git a/clang/test/Sema/attr-nooutline.cpp b/clang/test/Sema/attr-nooutline.cpp
new file mode 100644
index 0000000000000..b6c9b3995081a
--- /dev/null
+++ b/clang/test/Sema/attr-nooutline.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++17-extensions
+
+[[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
+
+[[clang::nooutline]] void t1(void);
+
+[[clang::nooutline(2)]] void t2(void); // expected-error {{'clang::nooutline' attribute takes no arguments}}
>From 62dcb6101bc55e193a57162326a6138a8f474772 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 16 Oct 2025 13:25:32 -0700
Subject: [PATCH 2/4] Address reviewer feedback: Tests, Docs, TableGen
---
clang/include/clang/Basic/Attr.td | 4 ++--
clang/include/clang/Basic/AttrDocs.td | 30 +++++++++++++++++++++++++++
clang/test/CodeGen/attr-nooutline.c | 29 +++++++++++++++++---------
3 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 361ae41da97dc..f2a372503c041 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2372,9 +2372,9 @@ def NoInline : DeclOrStmtAttr {
}
def NoOutline : DeclOrStmtAttr {
- let Spellings = [CXX11<"clang", "nooutline">, C23<"clang", "nooutline">];
+ let Spellings = [Clang<"nooutline">];
let Subjects = SubjectList<[Function], ErrorDiag>;
- let Documentation = [Undocumented];
+ let Documentation = [NoOutlineDocs];
let SimpleHandler = 1;
}
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index cad45501df6d2..67fadaff6e4a9 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -862,6 +862,36 @@ with ``__noinline__`` defined as a macro as ``__attribute__((noinline))``.
}];
}
+def NoOutlineDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+This function attribute suppresses outlining from the annotated function.
+
+Outlining is the process where common parts of separate functions are extracted
+into a separate function (or assembly snippet), and calls to that function or
+snippet are inserted in the original functions. In this way, it can be seen as
+the opposite of inlining. It can help to reduce code size.
+
+.. code-block:: c
+
+ [[clang::nooutline]] int x1(int y) {
+ int z = COMPLEX_MACRO(y); // Not outlined
+ return z + const1;
+ }
+
+ int x2(int y) {
+ int z = COMPLEX_MACRO(y); // May be outlined
+ return z * const2;
+ }
+
+ int x3(int y) {
+ int z = COMPLEX_MACRO(y); // May be outlined
+ reutrn z / const3;
+ }
+
+ }];
+}
+
def MustTailDocs : Documentation {
let Category = DocCatStmt;
let Content = [{
diff --git a/clang/test/CodeGen/attr-nooutline.c b/clang/test/CodeGen/attr-nooutline.c
index b9f175da24cb5..8519414397a8b 100644
--- a/clang/test/CodeGen/attr-nooutline.c
+++ b/clang/test/CodeGen/attr-nooutline.c
@@ -1,15 +1,24 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --version 6
-// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -disable-O0-optnone -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s --check-prefix=C
+// RUN: %clang_cc1 -emit-llvm -x c++ %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s --check-prefix=CXX
-
-// CHECK: Function Attrs: noinline nooutline nounwind
-// CHECK-LABEL: define dso_local i32 @t1(
-// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// CHECK-NEXT: ret i32 [[TMP0]]
+// C: Function Attrs: noinline nooutline nounwind optnone
+// C-LABEL: define dso_local i32 @t1(
+// C-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+// C-NEXT: [[ENTRY:.*:]]
+// C-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// C-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// C-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// C-NEXT: ret i32 [[TMP0]]
+//
+// CXX: Function Attrs: mustprogress noinline nooutline nounwind optnone
+// CXX-LABEL: define dso_local noundef i32 @_Z2t1i(
+// CXX-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+// CXX-NEXT: [[ENTRY:.*:]]
+// CXX-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CXX-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// CXX-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CXX-NEXT: ret i32 [[TMP0]]
//
[[clang::nooutline]] int t1(int x) {
return x;
>From 66969e52f04e3b5b49727aec9606beb2cf9e3451 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 16 Oct 2025 13:46:36 -0700
Subject: [PATCH 3/4] Release Notes
---
clang/docs/ReleaseNotes.rst | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59fdbc80e8bed..91571aee7ad6c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -138,6 +138,9 @@ Non-comprehensive list of changes in this release
Usable in constant expressions. Implicit conversion is supported for
class/struct types with conversion operators.
+- Added a new attribute, ``[[clang::nooutline]]`` to suppress outlining from
+ annotated functions. This uses the LLVM `nooutline` attribute.
+
New Compiler Flags
------------------
- New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added
>From 2d1b2b782a39c1083bc6ab8e4a5bc5f032351ae0 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Thu, 16 Oct 2025 14:07:51 -0700
Subject: [PATCH 4/4] Address Review Feedback: Flags, Release Notes
---
clang/docs/ReleaseNotes.rst | 6 +++---
clang/test/Sema/attr-nooutline.c | 2 +-
clang/test/Sema/attr-nooutline.cpp | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 91571aee7ad6c..3c40407faf9d1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -138,9 +138,6 @@ Non-comprehensive list of changes in this release
Usable in constant expressions. Implicit conversion is supported for
class/struct types with conversion operators.
-- Added a new attribute, ``[[clang::nooutline]]`` to suppress outlining from
- annotated functions. This uses the LLVM `nooutline` attribute.
-
New Compiler Flags
------------------
- New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added
@@ -165,6 +162,9 @@ Attribute Changes in Clang
will still generate a stack protector if other local variables or command line flags
require it.
+- Added a new attribute, ``[[clang::nooutline]]`` to suppress outlining from
+ annotated functions. This uses the LLVM `nooutline` attribute.
+
Improvements to Clang's diagnostics
-----------------------------------
- Added ``-Wlifetime-safety`` to enable lifetime safety analysis,
diff --git a/clang/test/Sema/attr-nooutline.c b/clang/test/Sema/attr-nooutline.c
index 83848c22d1003..ceb77c5d59bd8 100644
--- a/clang/test/Sema/attr-nooutline.c
+++ b/clang/test/Sema/attr-nooutline.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang_cc1 -verify -fsyntax-only %s
[[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
diff --git a/clang/test/Sema/attr-nooutline.cpp b/clang/test/Sema/attr-nooutline.cpp
index b6c9b3995081a..ceb77c5d59bd8 100644
--- a/clang/test/Sema/attr-nooutline.cpp
+++ b/clang/test/Sema/attr-nooutline.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++17-extensions
+// RUN: %clang_cc1 -verify -fsyntax-only %s
[[clang::nooutline]] int a; // expected-error {{'clang::nooutline' attribute only applies to functions}}
More information about the llvm-branch-commits
mailing list