Skip to content

Commit fdfc161

Browse files
committed
Also handle [[clang::always_inline]] statement attributes
Change-Id: I48ea9dc200cbb60cb1bacd2873cc015f200b0f32
1 parent cbbe039 commit fdfc161

File tree

3 files changed

+81
-6
lines changed

3 files changed

+81
-6
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5690,7 +5690,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
56905690
Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoInline);
56915691

56925692
// Add call-site always_inline attribute if exists.
5693-
if (InAlwaysInlineAttributedStmt)
5693+
// Note: This corresponds to the [[clang::always_inline]] statement attribute.
5694+
if (InAlwaysInlineAttributedStmt &&
5695+
!CGM.getTargetCodeGenInfo().wouldInliningViolateFunctionCallABI(
5696+
CallerDecl, CalleeDecl))
56945697
Attrs =
56955698
Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::AlwaysInline);
56965699

clang/lib/CodeGen/TargetInfo.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ class TargetCodeGenInfo {
102102
/// for the current target and should be ignored (even with the always_inline
103103
/// or flatten attributes).
104104
///
105-
/// Note: This probably should be handled in LLVM. However, the `alwaysinline`
106-
/// attribute currently means the inliner will ignore mismatched attributes
107-
/// (which sometimes can generate invalid code). So, this hook allows targets
108-
/// to avoid adding the `alwaysinline` attributes based on attributes or other
109-
/// target-specific reasons.
105+
/// Note: This probably should be handled in LLVM. However, the LLVM
106+
/// `alwaysinline` attribute currently means the inliner will ignore
107+
/// mismatched attributes (which sometimes can generate invalid code). So,
108+
/// this hook allows targets to avoid adding the LLVM `alwaysinline` attribute
109+
/// based on C/C++ attributes or other target-specific reasons.
110110
///
111111
/// See previous discussion here:
112112
/// https://discourse.llvm.org/t/rfc-avoid-inlining-alwaysinline-functions-when-they-cannot-be-inlined/79528
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -target-feature +sme %s -o - | FileCheck %s
2+
3+
// REQUIRES: aarch64-registered-target
4+
5+
extern void was_inlined(void);
6+
7+
void fn(void) { was_inlined(); }
8+
void fn_streaming_compatible(void) __arm_streaming_compatible { was_inlined(); }
9+
void fn_streaming(void) __arm_streaming { was_inlined(); }
10+
__arm_locally_streaming void fn_locally_streaming(void) { was_inlined(); }
11+
__arm_new("za") void fn_streaming_new_za(void) __arm_streaming { was_inlined(); }
12+
13+
void caller(void) {
14+
[[clang::always_inline]] fn();
15+
[[clang::always_inline]] fn_streaming_compatible();
16+
[[clang::always_inline]] fn_streaming();
17+
[[clang::always_inline]] fn_locally_streaming();
18+
[[clang::always_inline]] fn_streaming_new_za();
19+
}
20+
// CHECK-LABEL: void @caller()
21+
// CHECK-NEXT: entry:
22+
// CHECK-NEXT: call void @was_inlined
23+
// CHECK-NEXT: call void @was_inlined
24+
// CHECK-NEXT: call void @fn_streaming
25+
// CHECK-NEXT: call void @fn_locally_streaming
26+
// CHECK-NEXT: call void @fn_streaming_new_za
27+
28+
void caller_streaming_compatible(void) __arm_streaming_compatible {
29+
[[clang::always_inline]] fn();
30+
[[clang::always_inline]] fn_streaming_compatible();
31+
[[clang::always_inline]] fn_streaming();
32+
[[clang::always_inline]] fn_locally_streaming();
33+
[[clang::always_inline]] fn_streaming_new_za();
34+
}
35+
// CHECK-LABEL: void @caller_streaming_compatible()
36+
// CHECK-NEXT: entry:
37+
// CHECK-NEXT: call void @fn
38+
// CHECK-NEXT: call void @was_inlined
39+
// CHECK-NEXT: call void @fn_streaming
40+
// CHECK-NEXT: call void @fn_locally_streaming
41+
// CHECK-NEXT: call void @fn_streaming_new_za
42+
43+
void caller_streaming(void) __arm_streaming {
44+
[[clang::always_inline]] fn();
45+
[[clang::always_inline]] fn_streaming_compatible();
46+
[[clang::always_inline]] fn_streaming();
47+
[[clang::always_inline]] fn_locally_streaming();
48+
[[clang::always_inline]] fn_streaming_new_za();
49+
}
50+
// CHECK-LABEL: void @caller_streaming()
51+
// CHECK-NEXT: entry:
52+
// CHECK-NEXT: call void @fn
53+
// CHECK-NEXT: call void @was_inlined
54+
// CHECK-NEXT: call void @was_inlined
55+
// CHECK-NEXT: call void @was_inlined
56+
// CHECK-NEXT: call void @fn_streaming_new_za
57+
58+
__arm_locally_streaming
59+
void caller_locally_streaming(void) {
60+
[[clang::always_inline]] fn();
61+
[[clang::always_inline]] fn_streaming_compatible();
62+
[[clang::always_inline]] fn_streaming();
63+
[[clang::always_inline]] fn_locally_streaming();
64+
[[clang::always_inline]] fn_streaming_new_za();
65+
}
66+
// CHECK-LABEL: void @caller_locally_streaming()
67+
// CHECK-NEXT: entry:
68+
// CHECK-NEXT: call void @fn
69+
// CHECK-NEXT: call void @was_inlined
70+
// CHECK-NEXT: call void @was_inlined
71+
// CHECK-NEXT: call void @was_inlined
72+
// CHECK-NEXT: call void @fn_streaming_new_za

0 commit comments

Comments
 (0)