-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[clang/LLVM] Add flatten_deep attribute for depth-limited inlining (1/2) #165777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4032,6 +4032,29 @@ callee is unavailable or if the callee has the ``noinline`` attribute. | |
| }]; | ||
| } | ||
|
|
||
| def FlattenDeepDocs : Documentation { | ||
| let Category = DocCatFunction; | ||
| let Content = [{ | ||
| The ``flatten_deep`` attribute causes calls within the attributed function and | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Grammatically, I am not a big fan of this name. It probably makes better sense if it's called "flatten_at_depth(3)". |
||
| their transitive callees to be inlined up to a specified depth, unless it is | ||
| impossible to do so (for example if the body of the callee is unavailable or if | ||
| the callee has the ``noinline`` attribute). | ||
|
|
||
| This attribute takes a single unsigned integer argument representing the maximum | ||
| depth of the call tree to inline. For example, ``__attribute__((flatten_deep(3)))`` | ||
| will inline all calls within the function, then inline all calls within those | ||
| inlined functions (depth 2), and then inline all calls within those functions | ||
| (depth 3). | ||
|
|
||
| .. code-block:: c++ | ||
|
|
||
| __attribute__((flatten_deep(3))) | ||
| void process_data() { | ||
| // All calls up to 3 levels deep in the call tree will be inlined | ||
| } | ||
| }]; | ||
| } | ||
|
|
||
| def FormatDocs : Documentation { | ||
| let Category = DocCatFunction; | ||
| let Content = [{ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2749,6 +2749,15 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, | |
| B.addAttribute("aarch64_new_zt0"); | ||
| } | ||
|
|
||
| // Handle flatten_deep attribute for depth-based inlining | ||
| if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | ||
| if (const FlattenDeepAttr *FDA = FD->getAttr<FlattenDeepAttr>()) { | ||
| // Add the flatten_deep attribute with the max depth value as a typed int | ||
| // attribute | ||
| B.addRawIntAttr(llvm::Attribute::FlattenDeep, FDA->getMaxDepth()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
| } | ||
|
|
||
| // Track whether we need to add the optnone LLVM attribute, | ||
| // starting with the default for this optimization level. | ||
| bool ShouldAddOptNone = | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s | ||
|
|
||
| // CHECK-LABEL: define {{.*}} @test1 | ||
| // CHECK-SAME: #[[ATTR1:[0-9]+]] | ||
| __attribute__((flatten_deep(3))) | ||
| void test1() { | ||
| } | ||
|
|
||
| // Verify the attribute is present in the attribute groups | ||
| // CHECK-DAG: attributes #[[ATTR1]] = { {{.*}}flatten_deep=3{{.*}} } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // RUN: %clang_cc1 -fsyntax-only -verify %s | ||
|
|
||
| // Test basic usage - valid | ||
| __attribute__((flatten_deep(3))) | ||
| void test_valid() { | ||
| } | ||
|
|
||
| // Test attribute on non-function - should error | ||
| __attribute__((flatten_deep(3))) int x; // expected-error {{'flatten_deep' attribute only applies to functions}} | ||
|
|
||
| // Test depth = 0 - should error (depth must be >= 1) | ||
| __attribute__((flatten_deep(0))) // expected-error {{'flatten_deep' attribute must be greater than 0}} | ||
| void test_depth_zero() { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| ; RUN: llvm-as < %s | llvm-dis | FileCheck %s | ||
| ; RUN: verify-uselistorder %s | ||
|
|
||
| ; Test that flatten_deep attribute with integer values is properly handled | ||
| ; in both attribute groups (flatten_deep=N syntax) and inline (flatten_deep(N) syntax) | ||
|
|
||
| ; Test inline syntax | ||
| ; CHECK: define void @test_inline() #0 | ||
| define void @test_inline() flatten_deep(5) { | ||
| ret void | ||
| } | ||
|
|
||
| ; Test attribute group alone | ||
| ; CHECK: define void @test_group_alone() #1 | ||
| define void @test_group_alone() #1 { | ||
| ret void | ||
| } | ||
|
|
||
| ; Test attribute group with other attributes | ||
| ; CHECK: define void @test_group_combined() #2 | ||
| define void @test_group_combined() #2 { | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK: attributes #0 = { flatten_deep=5 } | ||
| attributes #0 = { flatten_deep=5 } | ||
|
|
||
| ; CHECK: attributes #1 = { flatten_deep=3 } | ||
| attributes #1 = { flatten_deep=3 } | ||
|
|
||
| ; CHECK: attributes #2 = { noinline nounwind flatten_deep=7 } | ||
| attributes #2 = { noinline nounwind flatten_deep=7 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am actually wondering why we don't merge this with
flatten. Is it because of compatibility with the GCC attribute? It seems possible to have an optional argument.