Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ Non-comprehensive list of changes in this release
allocation functions with a token ID can be enabled via the
``-fsanitize=alloc-token`` flag.

- Added a new attribute, ``[[clang::nooutline]]`` to suppress outlining from
annotated functions. This uses the LLVM `nooutline` attribute.
Comment on lines +272 to +273
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a dedicated section called ‘Attribute Changes in Clang’ below


New Compiler Flags
------------------
- New option ``-fno-sanitize-debug-trap-reasons`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2355,6 +2355,13 @@ def NoInline : DeclOrStmtAttr {
let SimpleHandler = 1;
}

def NoOutline : DeclOrStmtAttr {
let Spellings = [Clang<"nooutline">];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let Spellings = [Clang<"nooutline">];
let Spellings = [Clang<"no_outline">];

perhaps? Makes it... somewhat consistent with the force_inline/etc type attributes, and makes it a better mental 'parse'.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote a longer comment about this, see above.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks.

Hmm... my mental parse is still not really picking up the actual meaning of what this is (and as I'm the second one to mention that, perhaps something we should care about?). The rest don't have that parse problem for me. While I appreciate the symmetry, at the same time readability should, IMO trump it.

let Subjects = SubjectList<[Function], ErrorDiag>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your examples all use prototyped functions, is there a reason this cant be used on a no-prototype function? If so, this should reflect that (alternatively, write a codegen test to show its lack of importance).

let Documentation = [NoOutlineDocs];
let SimpleHandler = 1;
}

def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"nomips16">];
let Subjects = SubjectList<[Function], ErrorDiag>;
Expand Down
30 changes: 30 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

}];
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why one would not want this to happen? Perhaps a quick example? And can you show a psuedo-code version of x2/x3 (though I'd probably suggest only a single-one of those examples, they aren't unique enough to have 2) as to what it might look like as an 'outlined' version?


def MustTailDocs : Documentation {
let Category = DocCatStmt;
let Content = [{
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2820,6 +2820,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();
Expand Down
25 changes: 25 additions & 0 deletions clang/test/CodeGen/attr-nooutline.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// 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 -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

// 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:.*:]]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The body in these tests are probably not worth it since all we care about are the FunctionAttrs line and the one with the declaration. The rest seems fragile for no value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the fragility aspect, is there a better way to automatically test these or should I just write the checks by hand?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are short/easy enough I'd suggest just writing them by hand (or just deleting everything in the body of the function manually).

// 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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,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)
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Sema/attr-nooutline.c
Original file line number Diff line number Diff line change
@@ -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}}
7 changes: 7 additions & 0 deletions clang/test/Sema/attr-nooutline.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++17-extensions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++17-extensions
// RUN: %clang_cc1 -verify -fsyntax-only %s

I don’t think we need to pass -Wno-c++17-extensions here since we’re not using any from what I can tell (and Clang defaults to C++17 anyway).


[[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}}
Loading