Skip to content

Commit 1225381

Browse files
author
Greg Roth
committed
[HLSL] set alwaysinline on HLSL functions
HLSL inlines all its functions by default. This uses the alwaysinline attribute to force that in the corresponding pass for user functions by default and overrides the default noinline of some implicit functions. This makes an instance of explicit inlining for buffer subscripts unnecessary. Adds tests for function and constructor inlining and augments some existing tests to verify correct inlining of implicitly created functions as well. incidentally restore RUN line that I believe was mistakenly removed as part of llvm#88918 fixes llvm#89282
1 parent ecd65e6 commit 1225381

10 files changed

+279
-43
lines changed

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,9 +414,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
414414

415415
void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD,
416416
llvm::Function *Fn) {
417-
if (FD->isInExportDeclContext()) {
418-
const StringRef ExportAttrKindStr = "hlsl.export";
419-
Fn->addFnAttr(ExportAttrKindStr);
417+
if (FD) { // "explicit" functions with declarations
418+
if (FD->isInExportDeclContext()) {
419+
const StringRef ExportAttrKindStr = "hlsl.export";
420+
Fn->addFnAttr(ExportAttrKindStr);
421+
}
422+
// Respect noinline if the explicit functions use it
423+
// otherwise default to alwaysinline
424+
if (!Fn->hasFnAttribute(Attribute::NoInline))
425+
Fn->addFnAttr(llvm::Attribute::AlwaysInline);
426+
} else { // "implicit" autogenerated functions with no declaration
427+
// Implicit functions might get marked as noinline by default
428+
// but we override that for HLSL
429+
Fn->removeFnAttr(Attribute::NoInline);
430+
Fn->addFnAttr(Attribute::AlwaysInline);
420431
}
421432
}
422433

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,9 +1239,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
12391239
if (getLangOpts().OpenMP && CurCodeDecl)
12401240
CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);
12411241

1242-
if (FD && getLangOpts().HLSL) {
1242+
if (getLangOpts().HLSL) {
12431243
// Handle emitting HLSL entry functions.
1244-
if (FD->hasAttr<HLSLShaderAttr>()) {
1244+
if (FD && FD->hasAttr<HLSLShaderAttr>()) {
12451245
CGM.getHLSLRuntime().emitEntryFunction(FD, Fn);
12461246
}
12471247
CGM.getHLSLRuntime().setHLSLFunctionAttributes(FD, Fn);

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,6 @@ struct BuiltinTypeDeclBuilder {
290290
SourceLocation()));
291291
MethodDecl->setLexicalDeclContext(Record);
292292
MethodDecl->setAccess(AccessSpecifier::AS_public);
293-
MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
294-
AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
295293
Record->addDecl(MethodDecl);
296294

297295
return *this;
Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
2+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
23

34
int i;
45

@@ -7,7 +8,7 @@ __attribute__((constructor)) void call_me_first(void) {
78
}
89

910
__attribute__((constructor)) void then_call_me(void) {
10-
i = 12;
11+
i = 13;
1112
}
1213

1314
__attribute__((destructor)) void call_me_last(void) {
@@ -21,11 +22,21 @@ void main(unsigned GI : SV_GroupIndex) {}
2122
// CHECK-NOT:@llvm.global_ctors
2223
// CHECK-NOT:@llvm.global_dtors
2324

24-
//CHECK: define void @main()
25-
//CHECK-NEXT: entry:
26-
//CHECK-NEXT: call void @"?call_me_first@@YAXXZ"()
27-
//CHECK-NEXT: call void @"?then_call_me@@YAXXZ"()
28-
//CHECK-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
29-
//CHECK-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
30-
//CHECK-NEXT: call void @"?call_me_last@@YAXXZ"(
31-
//CHECK-NEXT: ret void
25+
// CHECK: define void @main()
26+
// CHECK-NEXT: entry:
27+
// Verify function constructors are emitted
28+
// NOINLINE-NEXT: call void @"?call_me_first@@YAXXZ"()
29+
// NOINLINE-NEXT: call void @"?then_call_me@@YAXXZ"()
30+
// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
31+
// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
32+
// NOINLINE-NEXT: call void @"?call_me_last@@YAXXZ"(
33+
// NOINLINE-NEXT: ret void
34+
35+
// Verify constructor calls are inlined when AlwaysInline is run
36+
// INLINE-NEXT: alloca
37+
// INLINE-NEXT: store i32 12
38+
// INLINE-NEXT: store i32 13
39+
// INLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
40+
// INLINE-NEXT: store i32 %
41+
// INLINE-NEXT: store i32 0
42+
// INLINE: ret void

clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
2+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
23

34
// Make sure global variable for ctors exist for lib profile.
45
// CHECK:@llvm.global_ctors
@@ -11,13 +12,27 @@ void FirstEntry() {}
1112

1213
// CHECK: define void @FirstEntry()
1314
// CHECK-NEXT: entry:
14-
// CHECK-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
15+
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
16+
// NOINLINE-NEXT: call void @"?FirstEntry@@YAXXZ"()
17+
// Verify inlining leaves only calls to "llvm." intrinsics
18+
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
19+
// CHECK: ret void
1520

1621
[shader("compute")]
1722
[numthreads(1,1,1)]
1823
void SecondEntry() {}
1924

2025
// CHECK: define void @SecondEntry()
2126
// CHECK-NEXT: entry:
22-
// CHECK-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
23-
// CHECK-NEXT: call void @"?SecondEntry@@YAXXZ"()
27+
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
28+
// NOINLINE-NEXT: call void @"?SecondEntry@@YAXXZ"()
29+
// Verify inlining leaves only calls to "llvm." intrinsics
30+
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
31+
// CHECK: ret void
32+
33+
34+
// Verify the constructor is alwaysinline
35+
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
36+
// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[IntAttr:\#[0-9]+]]
37+
38+
// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline

clang/test/CodeGenHLSL/GlobalDestructors.hlsl

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,CHECK
2-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,CHECK
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE,CHECK
2+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE,CHECK
3+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
4+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
35

4-
// Make sure global variable for dtors exist for lib profile.
6+
// Tests that constructors and destructors are appropriately generated for globals
7+
// and that their calls are inlined when AlwaysInline is run
8+
// but global variables are retained for the library profiles
9+
10+
// Make sure global variable for ctors/dtors exist for lib profile.
11+
// LIB:@llvm.global_ctors
512
// LIB:@llvm.global_dtors
6-
// Make sure global variable for dtors removed for compute profile.
7-
// CS-NOT:llvm.global_dtors
13+
// Make sure global variable for ctors/dtors removed for compute profile.
14+
// CS-NOT:@llvm.global_ctors
15+
// CS-NOT:@llvm.global_dtors
816

917
struct Tail {
1018
Tail() {
@@ -46,22 +54,25 @@ void main(unsigned GI : SV_GroupIndex) {
4654
Wag();
4755
}
4856

49-
// Make sure global variable for ctors/dtors removed.
50-
// CHECK-NOT:@llvm.global_ctors
51-
// CHECK-NOT:@llvm.global_dtors
52-
//CHECK: define void @main()
53-
//CHECK-NEXT: entry:
54-
//CHECK-NEXT: call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
55-
//CHECK-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
56-
//CHECK-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
57-
//CHECK-NEXT: call void @_GLOBAL__D_a()
58-
//CHECK-NEXT: ret void
57+
// CHECK: define void @main()
58+
// CHECK-NEXT: entry:
59+
// Verify destructor is emitted
60+
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
61+
// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
62+
// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
63+
// NOINLINE-NEXT: call void @_GLOBAL__D_a()
64+
// NOINLINE-NEXT: ret void
65+
// Verify inlining leaves only calls to "llvm." intrinsics
66+
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
67+
// INLINE: ret void
5968

6069
// This is really just a sanity check I needed for myself to verify that
6170
// function scope static variables also get destroyed properly.
6271

63-
//CHECK: define internal void @_GLOBAL__D_a()
64-
//CHECK-NEXT: entry:
65-
//CHECK-NEXT: call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
66-
//CHECK-NEXT: call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
67-
//CHECK-NEXT: ret void
72+
// NOINLINE: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
73+
// NOINLINE-NEXT: entry:
74+
// NOINLINE-NEXT: call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
75+
// NOINLINE-NEXT: call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
76+
// NOINLINE-NEXT: ret void
77+
78+
// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline

clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
12
// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
23

34
RWBuffer<float> Buf;

clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ void main(unsigned GI : SV_GroupIndex) {
1111
// Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy
1212
// and confusing to follow so the match here is pretty weak.
1313

14-
// CHECK: define internal void @"?main@@YAXI@Z"
15-
// CHECK-NOT: call
14+
// CHECK: define void @main()
15+
// Verify inlining leaves only calls to "llvm." intrinsics
16+
// CHECK-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
1617
// CHECK: ret void
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
2+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
3+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
4+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
5+
6+
// Tests that implicit contstructor calls for user classes will always be inlined.
7+
8+
struct Weed {
9+
Weed() {Count += 1;}
10+
[[maybe_unused]] void pull() {Count--;}
11+
static int weedCount() { return Count; }
12+
private:
13+
static int Count;
14+
15+
} YardWeeds;
16+
17+
int Weed::Count = 1; // It begins. . .
18+
19+
struct Kitty {
20+
unsigned burrsInFur;
21+
22+
Kitty() {
23+
burrsInFur = 0;
24+
}
25+
26+
void wanderInYard(int hours) {
27+
burrsInFur = hours*Weed::weedCount()/8;
28+
}
29+
30+
void lick() {
31+
if(burrsInFur) {
32+
burrsInFur--;
33+
Weed w;
34+
}
35+
}
36+
37+
} Nion;
38+
39+
void NionsDay(int hours) {
40+
static Kitty Nion;
41+
Nion.wanderInYard(hours);
42+
while(Nion.burrsInFur) Nion.lick();
43+
}
44+
45+
// CHECK: define void @main()
46+
// CHECK-NEXT: entry:
47+
// Verify constructor is emitted
48+
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_inline_constructors.hlsl()
49+
// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
50+
// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
51+
// Verify inlining leaves only calls to "llvm." intrinsics
52+
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
53+
// CHECK: ret void
54+
[shader("compute")]
55+
[numthreads(1,1,1)]
56+
void main(unsigned GI : SV_GroupIndex) {
57+
NionsDay(10);
58+
}
59+
60+
61+
// CHECK: define void @rainyMain()
62+
// CHECK-NEXT: entry:
63+
// Verify constructor is emitted
64+
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_inline_constructors.hlsl()
65+
// NOINLINE-NEXT: call void @"?rainyMain@@YAXXZ"()
66+
// Verify inlining leaves only calls to "llvm." intrinsics
67+
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
68+
// CHECK: ret void
69+
[shader("compute")]
70+
[numthreads(1,1,1)]
71+
void rainyMain() {
72+
NionsDay(1);
73+
}
74+
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// RUN: %clang_cc1 -x hlsl -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
2+
// RUN: %clang_cc1 -x hlsl -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
3+
// RUN: %clang_cc1 -x hlsl -triple dxil-pc-shadermodel6.0-compute %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
4+
// RUN: %clang_cc1 -x hlsl -triple dxil-pc-shadermodel6.0-compute %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
5+
6+
// Tests that user functions will always be inlined.
7+
// This includes exported functions and mangled entry point implementation functions.
8+
// The unmangled entry functions must not be alwaysinlined.
9+
10+
#define MAX 100
11+
12+
float nums[MAX];
13+
14+
// Verify that all functions have the alwaysinline attribute
15+
// CHECK: Function Attrs: alwaysinline
16+
// CHECK: define void @"?swap@@YAXY0GE@III@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %ix1, i32 noundef %ix2) [[IntAttr:\#[0-9]+]]
17+
// CHECK: ret void
18+
// Swap the values of Buf at indices ix1 and ix2
19+
void swap(unsigned Buf[MAX], unsigned ix1, unsigned ix2) {
20+
float tmp = Buf[ix1];
21+
Buf[ix1] = Buf[ix2];
22+
Buf[ix2] = tmp;
23+
}
24+
25+
// CHECK: Function Attrs: alwaysinline
26+
// CHECK: define void @"?BubbleSort@@YAXY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[IntAttr]]
27+
// CHECK: ret void
28+
// Inefficiently sort Buf in place
29+
void BubbleSort(unsigned Buf[MAX], unsigned size) {
30+
bool swapped = true;
31+
while (swapped) {
32+
swapped = false;
33+
for (unsigned i = 1; i < size; i++) {
34+
if (Buf[i] < Buf[i-1]) {
35+
swap(Buf, i, i-1);
36+
swapped = true;
37+
}
38+
}
39+
}
40+
}
41+
42+
// Note ExtAttr is the inlined export set of attribs
43+
// CHECK: Function Attrs: alwaysinline
44+
// CHECK: define noundef i32 @"?RemoveDupes@@YAIY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[ExtAttr:\#[0-9]+]]
45+
// CHECK: ret i32
46+
// Sort Buf and remove any duplicate values
47+
// returns the number of values left
48+
export
49+
unsigned RemoveDupes(unsigned Buf[MAX], unsigned size) {
50+
BubbleSort(Buf, size);
51+
unsigned insertPt = 0;
52+
for (unsigned i = 1; i < size; i++) {
53+
if (Buf[i] == Buf[i-1])
54+
insertPt++;
55+
else
56+
Buf[insertPt] = Buf[i];
57+
}
58+
return insertPt;
59+
}
60+
61+
62+
RWBuffer<unsigned> Indices;
63+
64+
// The mangled version of main only remains without inlining
65+
// because it has internal linkage from the start
66+
// Note main functions get the norecurse attrib, which IntAttr reflects
67+
// NOINLINE: Function Attrs: alwaysinline
68+
// NOINLINE: define internal void @"?main@@YAXI@Z"(i32 noundef %GI) [[IntAttr]]
69+
// NOINLINE: ret void
70+
71+
// The unmangled version is not inlined, EntryAttr reflects that
72+
// CHECK: Function Attrs: convergent norecurse
73+
// CHECK: define void @main() [[EntryAttr:\#[0-9]+]]
74+
// Make sure function calls are inlined when AlwaysInline is run
75+
// This only leaves calls to llvm. intrinsics
76+
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
77+
// CHECK: ret void
78+
79+
[numthreads(1,1,1)]
80+
[shader("compute")]
81+
void main(unsigned int GI : SV_GroupIndex) {
82+
unsigned tmpIndices[MAX];
83+
if (GI > MAX) return;
84+
for (unsigned i = 1; i < GI; i++)
85+
tmpIndices[i] = Indices[i];
86+
RemoveDupes(tmpIndices, GI);
87+
for (unsigned i = 1; i < GI; i++)
88+
tmpIndices[i] = Indices[i];
89+
}
90+
91+
// The mangled version of main only remains without inlining
92+
// because it has internal linkage from the start
93+
// Note main functions get the norecurse attrib, which IntAttr reflects
94+
// NOINLINE: Function Attrs: alwaysinline
95+
// NOINLINE: define internal void @"?main10@@YAXXZ"() [[IntAttr]]
96+
// NOINLINE: ret void
97+
98+
// The unmangled version is not inlined, EntryAttr reflects that
99+
// CHECK: Function Attrs: convergent norecurse
100+
// CHECK: define void @main10() [[EntryAttr]]
101+
// Make sure function calls are inlined when AlwaysInline is run
102+
// This only leaves calls to llvm. intrinsics
103+
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
104+
// CHECK: ret void
105+
106+
[numthreads(1,1,1)]
107+
[shader("compute")]
108+
void main10() {
109+
main(10);
110+
}
111+
112+
// CHECK: attributes [[IntAttr]] = {{.*}} alwaysinline
113+
// CHECK: attributes [[ExtAttr]] = {{.*}} alwaysinline
114+
// CHECK-NOT: attributes [[EntryAttr]] = {{.*}} alwaysinline

0 commit comments

Comments
 (0)