Skip to content

Commit 3f8d4a8

Browse files
authored
Reland [NVPTX] Add support for maxclusterrank in launch_bounds (#66496) (#67667)
This reverts commit 0afbcb2.
1 parent 7ac532e commit 3f8d4a8

File tree

15 files changed

+262
-61
lines changed

15 files changed

+262
-61
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,8 @@ def CUDAInvalidTarget : InheritableAttr {
12751275

12761276
def CUDALaunchBounds : InheritableAttr {
12771277
let Spellings = [GNU<"launch_bounds">, Declspec<"__launch_bounds__">];
1278-
let Args = [ExprArgument<"MaxThreads">, ExprArgument<"MinBlocks", 1>];
1278+
let Args = [ExprArgument<"MaxThreads">, ExprArgument<"MinBlocks", 1>,
1279+
ExprArgument<"MaxBlocks", 1>];
12791280
let LangOpts = [CUDA];
12801281
let Subjects = SubjectList<[ObjCMethod, FunctionLike]>;
12811282
// An AST node is created for this attribute, but is not used by other parts

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11850,6 +11850,10 @@ def err_sycl_special_type_num_init_method : Error<
1185011850
"types with 'sycl_special_class' attribute must have one and only one '__init' "
1185111851
"method defined">;
1185211852

11853+
def warn_cuda_maxclusterrank_sm_90 : Warning<
11854+
"maxclusterrank requires sm_90 or higher, CUDA arch provided: %0, ignoring "
11855+
"%1 attribute">, InGroup<IgnoredAttributes>;
11856+
1185311857
def err_bit_int_bad_size : Error<"%select{signed|unsigned}0 _BitInt must "
1185411858
"have a bit size of at least %select{2|1}0">;
1185511859
def err_bit_int_max_size : Error<"%select{signed|unsigned}0 _BitInt of bit "

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11053,12 +11053,13 @@ class Sema final {
1105311053
/// Create an CUDALaunchBoundsAttr attribute.
1105411054
CUDALaunchBoundsAttr *CreateLaunchBoundsAttr(const AttributeCommonInfo &CI,
1105511055
Expr *MaxThreads,
11056-
Expr *MinBlocks);
11056+
Expr *MinBlocks,
11057+
Expr *MaxBlocks);
1105711058

1105811059
/// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
1105911060
/// declaration.
1106011061
void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
11061-
Expr *MaxThreads, Expr *MinBlocks);
11062+
Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
1106211063

1106311064
/// AddModeAttr - Adds a mode attribute to a particular declaration.
1106411065
void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name,

clang/lib/Basic/Targets/NVPTX.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
181181

182182
bool hasBitIntType() const override { return true; }
183183
bool hasBFloat16Type() const override { return true; }
184+
185+
CudaArch getGPU() const { return GPU; }
184186
};
185187
} // namespace targets
186188
} // namespace clang

clang/lib/CodeGen/Targets/NVPTX.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,8 @@ void CodeGenModule::handleCUDALaunchBoundsAttr(
296296
NVPTXTargetCodeGenInfo::addNVVMMetadata(F, "maxntidx",
297297
MaxThreads.getExtValue());
298298

299-
// min blocks is an optional argument for CUDALaunchBoundsAttr. If it was
300-
// not specified in __launch_bounds__ or if the user specified a 0 value,
299+
// min and max blocks is an optional argument for CUDALaunchBoundsAttr. If it
300+
// was not specified in __launch_bounds__ or if the user specified a 0 value,
301301
// we don't have to add a PTX directive.
302302
if (Attr->getMinBlocks()) {
303303
llvm::APSInt MinBlocks(32);
@@ -307,6 +307,14 @@ void CodeGenModule::handleCUDALaunchBoundsAttr(
307307
NVPTXTargetCodeGenInfo::addNVVMMetadata(F, "minctasm",
308308
MinBlocks.getExtValue());
309309
}
310+
if (Attr->getMaxBlocks()) {
311+
llvm::APSInt MaxBlocks(32);
312+
MaxBlocks = Attr->getMaxBlocks()->EvaluateKnownConstInt(getContext());
313+
if (MaxBlocks > 0)
314+
// Create !{<func-ref>, metadata !"maxclusterrank", i32 <val>} node
315+
NVPTXTargetCodeGenInfo::addNVVMMetadata(F, "maxclusterrank",
316+
MaxBlocks.getExtValue());
317+
}
310318
}
311319

312320
std::unique_ptr<TargetCodeGenInfo>

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3739,7 +3739,8 @@ OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
37393739
continue;
37403740
if (auto *A = Actions.CreateLaunchBoundsAttr(
37413741
PA, PA.getArgAsExpr(0),
3742-
PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
3742+
PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
3743+
PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
37433744
Attrs.push_back(A);
37443745
continue;
37453746
default:

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5608,6 +5608,14 @@ bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) {
56085608
return false;
56095609
}
56105610

5611+
// Helper to get CudaArch.
5612+
static CudaArch getCudaArch(const TargetInfo &TI) {
5613+
if (!TI.getTriple().isNVPTX())
5614+
llvm_unreachable("getCudaArch is only valid for NVPTX triple");
5615+
auto &TO = TI.getTargetOpts();
5616+
return StringToCudaArch(TO.CPU);
5617+
}
5618+
56115619
// Checks whether an argument of launch_bounds attribute is
56125620
// acceptable, performs implicit conversion to Rvalue, and returns
56135621
// non-nullptr Expr result on success. Otherwise, it returns nullptr
@@ -5651,34 +5659,51 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
56515659

56525660
CUDALaunchBoundsAttr *
56535661
Sema::CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, Expr *MaxThreads,
5654-
Expr *MinBlocks) {
5655-
CUDALaunchBoundsAttr TmpAttr(Context, CI, MaxThreads, MinBlocks);
5662+
Expr *MinBlocks, Expr *MaxBlocks) {
5663+
CUDALaunchBoundsAttr TmpAttr(Context, CI, MaxThreads, MinBlocks, MaxBlocks);
56565664
MaxThreads = makeLaunchBoundsArgExpr(*this, MaxThreads, TmpAttr, 0);
5657-
if (MaxThreads == nullptr)
5665+
if (!MaxThreads)
56585666
return nullptr;
56595667

56605668
if (MinBlocks) {
56615669
MinBlocks = makeLaunchBoundsArgExpr(*this, MinBlocks, TmpAttr, 1);
5662-
if (MinBlocks == nullptr)
5670+
if (!MinBlocks)
56635671
return nullptr;
56645672
}
56655673

5674+
if (MaxBlocks) {
5675+
// '.maxclusterrank' ptx directive requires .target sm_90 or higher.
5676+
auto SM = getCudaArch(Context.getTargetInfo());
5677+
if (SM == CudaArch::UNKNOWN || SM < CudaArch::SM_90) {
5678+
Diag(MaxBlocks->getBeginLoc(), diag::warn_cuda_maxclusterrank_sm_90)
5679+
<< CudaArchToString(SM) << CI << MaxBlocks->getSourceRange();
5680+
// Ignore it by setting MaxBlocks to null;
5681+
MaxBlocks = nullptr;
5682+
} else {
5683+
MaxBlocks = makeLaunchBoundsArgExpr(*this, MaxBlocks, TmpAttr, 2);
5684+
if (!MaxBlocks)
5685+
return nullptr;
5686+
}
5687+
}
5688+
56665689
return ::new (Context)
5667-
CUDALaunchBoundsAttr(Context, CI, MaxThreads, MinBlocks);
5690+
CUDALaunchBoundsAttr(Context, CI, MaxThreads, MinBlocks, MaxBlocks);
56685691
}
56695692

56705693
void Sema::AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
5671-
Expr *MaxThreads, Expr *MinBlocks) {
5672-
if (auto *Attr = CreateLaunchBoundsAttr(CI, MaxThreads, MinBlocks))
5694+
Expr *MaxThreads, Expr *MinBlocks,
5695+
Expr *MaxBlocks) {
5696+
if (auto *Attr = CreateLaunchBoundsAttr(CI, MaxThreads, MinBlocks, MaxBlocks))
56735697
D->addAttr(Attr);
56745698
}
56755699

56765700
static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5677-
if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
5701+
if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3))
56785702
return;
56795703

56805704
S.AddLaunchBoundsAttr(D, AL, AL.getArgAsExpr(0),
5681-
AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr);
5705+
AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr,
5706+
AL.getNumArgs() > 2 ? AL.getArgAsExpr(2) : nullptr);
56825707
}
56835708

56845709
static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,15 @@ static void instantiateDependentCUDALaunchBoundsAttr(
302302
MinBlocks = Result.getAs<Expr>();
303303
}
304304

305-
S.AddLaunchBoundsAttr(New, Attr, MaxThreads, MinBlocks);
305+
Expr *MaxBlocks = nullptr;
306+
if (Attr.getMaxBlocks()) {
307+
Result = S.SubstExpr(Attr.getMaxBlocks(), TemplateArgs);
308+
if (Result.isInvalid())
309+
return;
310+
MaxBlocks = Result.getAs<Expr>();
311+
}
312+
313+
S.AddLaunchBoundsAttr(New, Attr, MaxThreads, MinBlocks, MaxBlocks);
306314
}
307315

308316
static void

clang/test/CodeGenCUDA/launch-bounds.cu

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
// RUN: %clang_cc1 %s -triple nvptx-unknown-unknown -fcuda-is-device -emit-llvm -o - | FileCheck %s
2+
// RUN: %clang_cc1 %s -triple nvptx-unknown-unknown -target-cpu sm_90 -DUSE_MAX_BLOCKS -fcuda-is-device -emit-llvm -o - | FileCheck -check-prefix=CHECK_MAX_BLOCKS %s
23

34
#include "Inputs/cuda.h"
45

56
#define MAX_THREADS_PER_BLOCK 256
67
#define MIN_BLOCKS_PER_MP 2
8+
#ifdef USE_MAX_BLOCKS
9+
#define MAX_BLOCKS_PER_MP 4
10+
#endif
711

812
// Test both max threads per block and Min cta per sm.
913
extern "C" {
@@ -17,6 +21,21 @@ Kernel1()
1721
// CHECK: !{{[0-9]+}} = !{ptr @Kernel1, !"maxntidx", i32 256}
1822
// CHECK: !{{[0-9]+}} = !{ptr @Kernel1, !"minctasm", i32 2}
1923

24+
#ifdef USE_MAX_BLOCKS
25+
// Test max threads per block and min/max cta per sm.
26+
extern "C" {
27+
__global__ void
28+
__launch_bounds__( MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP, MAX_BLOCKS_PER_MP )
29+
Kernel1_sm_90()
30+
{
31+
}
32+
}
33+
34+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @Kernel1_sm_90, !"maxntidx", i32 256}
35+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @Kernel1_sm_90, !"minctasm", i32 2}
36+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @Kernel1_sm_90, !"maxclusterrank", i32 4}
37+
#endif // USE_MAX_BLOCKS
38+
2039
// Test only max threads per block. Min cta per sm defaults to 0, and
2140
// CodeGen doesn't output a zero value for minctasm.
2241
extern "C" {
@@ -50,6 +69,20 @@ template __global__ void Kernel4<MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP>();
5069
// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4{{.*}}, !"maxntidx", i32 256}
5170
// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4{{.*}}, !"minctasm", i32 2}
5271

72+
#ifdef USE_MAX_BLOCKS
73+
template <int max_threads_per_block, int min_blocks_per_mp, int max_blocks_per_mp>
74+
__global__ void
75+
__launch_bounds__(max_threads_per_block, min_blocks_per_mp, max_blocks_per_mp)
76+
Kernel4_sm_90()
77+
{
78+
}
79+
template __global__ void Kernel4_sm_90<MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP, MAX_BLOCKS_PER_MP>();
80+
81+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4_sm_90{{.*}}, !"maxntidx", i32 256}
82+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4_sm_90{{.*}}, !"minctasm", i32 2}
83+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4_sm_90{{.*}}, !"maxclusterrank", i32 4}
84+
#endif //USE_MAX_BLOCKS
85+
5386
const int constint = 100;
5487
template <int max_threads_per_block, int min_blocks_per_mp>
5588
__global__ void
@@ -63,6 +96,23 @@ template __global__ void Kernel5<MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP>();
6396
// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5{{.*}}, !"maxntidx", i32 356}
6497
// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5{{.*}}, !"minctasm", i32 258}
6598

99+
#ifdef USE_MAX_BLOCKS
100+
101+
template <int max_threads_per_block, int min_blocks_per_mp, int max_blocks_per_mp>
102+
__global__ void
103+
__launch_bounds__(max_threads_per_block + constint,
104+
min_blocks_per_mp + max_threads_per_block,
105+
max_blocks_per_mp + max_threads_per_block)
106+
Kernel5_sm_90()
107+
{
108+
}
109+
template __global__ void Kernel5_sm_90<MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP, MAX_BLOCKS_PER_MP>();
110+
111+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5_sm_90{{.*}}, !"maxntidx", i32 356}
112+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5_sm_90{{.*}}, !"minctasm", i32 258}
113+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5_sm_90{{.*}}, !"maxclusterrank", i32 260}
114+
#endif //USE_MAX_BLOCKS
115+
66116
// Make sure we don't emit negative launch bounds values.
67117
__global__ void
68118
__launch_bounds__( -MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP )
@@ -80,7 +130,26 @@ Kernel7()
80130
// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel7{{.*}}, !"maxntidx",
81131
// CHECK-NOT: !{{[0-9]+}} = !{ptr @{{.*}}Kernel7{{.*}}, !"minctasm",
82132

133+
#ifdef USE_MAX_BLOCKS
134+
__global__ void
135+
__launch_bounds__( MAX_THREADS_PER_BLOCK, -MIN_BLOCKS_PER_MP, -MAX_BLOCKS_PER_MP )
136+
Kernel7_sm_90()
137+
{
138+
}
139+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel7_sm_90{{.*}}, !"maxntidx",
140+
// CHECK_MAX_BLOCKS-NOT: !{{[0-9]+}} = !{ptr @{{.*}}Kernel7_sm_90{{.*}}, !"minctasm",
141+
// CHECK_MAX_BLOCKS-NOT: !{{[0-9]+}} = !{ptr @{{.*}}Kernel7_sm_90{{.*}}, !"maxclusterrank",
142+
#endif // USE_MAX_BLOCKS
143+
83144
const char constchar = 12;
84145
__global__ void __launch_bounds__(constint, constchar) Kernel8() {}
85146
// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8{{.*}}, !"maxntidx", i32 100
86147
// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8{{.*}}, !"minctasm", i32 12
148+
149+
#ifdef USE_MAX_BLOCKS
150+
const char constchar_2 = 14;
151+
__global__ void __launch_bounds__(constint, constchar, constchar_2) Kernel8_sm_90() {}
152+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8_sm_90{{.*}}, !"maxntidx", i32 100
153+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8_sm_90{{.*}}, !"minctasm", i32 12
154+
// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8_sm_90{{.*}}, !"maxclusterrank", i32 14
155+
#endif // USE_MAX_BLOCKS

clang/test/SemaCUDA/launch_bounds.cu

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
1+
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -triple nvptx-unknown-unknown -target-cpu sm_75 -verify %s
22

33
#include "Inputs/cuda.h"
44

@@ -11,8 +11,9 @@ __launch_bounds__(0x10000000000000000) void TestWayTooBigArg(void); // expected-
1111

1212
__launch_bounds__(-128, 7) void TestNegArg1(void); // expected-warning {{'launch_bounds' attribute parameter 0 is negative and will be ignored}}
1313
__launch_bounds__(128, -7) void TestNegArg2(void); // expected-warning {{'launch_bounds' attribute parameter 1 is negative and will be ignored}}
14+
__launch_bounds__(128, 2, -8) void TestNegArg2(void); // expected-warning {{maxclusterrank requires sm_90 or higher, CUDA arch provided: sm_75, ignoring 'launch_bounds' attribute}}
1415

15-
__launch_bounds__(1, 2, 3) void Test3Args(void); // expected-error {{'launch_bounds' attribute takes no more than 2 arguments}}
16+
__launch_bounds__(1, 2, 3, 4) void Test4Args(void); // expected-error {{'launch_bounds' attribute takes no more than 3 arguments}}
1617
__launch_bounds__() void TestNoArgs(void); // expected-error {{'launch_bounds' attribute takes at least 1 argument}}
1718

1819
int TestNoFunction __launch_bounds__(128, 7); // expected-warning {{'launch_bounds' attribute only applies to Objective-C methods, functions, and function pointers}}
@@ -47,3 +48,5 @@ __launch_bounds__(Args) void TestTemplateVariadicArgs(void) {} // expected-error
4748

4849
template <int... Args>
4950
__launch_bounds__(1, Args) void TestTemplateVariadicArgs2(void) {} // expected-error {{expression contains unexpanded parameter pack 'Args'}}
51+
52+
__launch_bounds__(1, 2, 3) void Test3Args(void); // expected-warning {{maxclusterrank requires sm_90 or higher, CUDA arch provided: sm_75, ignoring 'launch_bounds' attribute}}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -triple nvptx-unknown-unknown -target-cpu sm_90 -verify %s
2+
3+
#include "Inputs/cuda.h"
4+
5+
__launch_bounds__(128, 7) void Test2Args(void);
6+
__launch_bounds__(128) void Test1Arg(void);
7+
8+
__launch_bounds__(0xffffffff) void TestMaxArg(void);
9+
__launch_bounds__(0x100000000) void TestTooBigArg(void); // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
10+
__launch_bounds__(0x10000000000000000) void TestWayTooBigArg(void); // expected-error {{integer literal is too large to be represented in any integer type}}
11+
__launch_bounds__(1, 1, 0x10000000000000000) void TestWayTooBigArg(void); // expected-error {{integer literal is too large to be represented in any integer type}}
12+
13+
__launch_bounds__(-128, 7) void TestNegArg1(void); // expected-warning {{'launch_bounds' attribute parameter 0 is negative and will be ignored}}
14+
__launch_bounds__(128, -7) void TestNegArg2(void); // expected-warning {{'launch_bounds' attribute parameter 1 is negative and will be ignored}}
15+
__launch_bounds__(-128, 1, 7) void TestNegArg2(void); // expected-warning {{'launch_bounds' attribute parameter 0 is negative and will be ignored}}
16+
__launch_bounds__(128, -1, 7) void TestNegArg2(void); // expected-warning {{'launch_bounds' attribute parameter 1 is negative and will be ignored}}
17+
__launch_bounds__(128, 1, -7) void TestNegArg2(void); // expected-warning {{'launch_bounds' attribute parameter 2 is negative and will be ignored}}
18+
// expected-warning@20 {{'launch_bounds' attribute parameter 0 is negative and will be ignored}}
19+
// expected-warning@20 {{'launch_bounds' attribute parameter 1 is negative and will be ignored}}
20+
__launch_bounds__(-128, -1, 7) void TestNegArg2(void);
21+
// expected-warning@23 {{'launch_bounds' attribute parameter 0 is negative and will be ignored}}
22+
// expected-warning@23 {{'launch_bounds' attribute parameter 2 is negative and will be ignored}}
23+
__launch_bounds__(-128, 1, -7) void TestNegArg2(void);
24+
// expected-warning@27 {{'launch_bounds' attribute parameter 0 is negative and will be ignored}}
25+
// expected-warning@27 {{'launch_bounds' attribute parameter 1 is negative and will be ignored}}
26+
// expected-warning@27 {{'launch_bounds' attribute parameter 2 is negative and will be ignored}}
27+
__launch_bounds__(-128, -1, -7) void TestNegArg2(void);
28+
29+
30+
__launch_bounds__(1, 2, 3, 4) void Test4Args(void); // expected-error {{'launch_bounds' attribute takes no more than 3 arguments}}
31+
__launch_bounds__() void TestNoArgs(void); // expected-error {{'launch_bounds' attribute takes at least 1 argument}}
32+
33+
int TestNoFunction __launch_bounds__(128, 7, 13); // expected-warning {{'launch_bounds' attribute only applies to Objective-C methods, functions, and function pointers}}
34+
35+
__launch_bounds__(true) void TestBool(void);
36+
__launch_bounds__(128, 1, 128.0) void TestFP(void); // expected-error {{'launch_bounds' attribute requires parameter 2 to be an integer constant}}
37+
__launch_bounds__(128, 1, (void*)0) void TestNullptr(void); // expected-error {{'launch_bounds' attribute requires parameter 2 to be an integer constant}}
38+
39+
int nonconstint = 256;
40+
__launch_bounds__(125, 1, nonconstint) void TestNonConstInt(void); // expected-error {{'launch_bounds' attribute requires parameter 2 to be an integer constant}}
41+
42+
const int constint = 512;
43+
__launch_bounds__(128, 1, constint) void TestConstInt(void);
44+
__launch_bounds__(128, 1, constint * 2 + 3) void TestConstIntExpr(void);
45+
46+
template <int a, int b, int c> __launch_bounds__(a, b, c) void TestTemplate2Args(void) {}
47+
template void TestTemplate2Args<128,7, 13>(void);
48+
49+
template <int a, int b, int c>
50+
__launch_bounds__(a + b, c + constint, a + b + c + constint) void TestTemplateExpr(void) {}
51+
template void TestTemplateExpr<128+constint, 3, 7>(void);
52+
53+
template <int... Args>
54+
__launch_bounds__(Args) void TestTemplateVariadicArgs(void) {} // expected-error {{expression contains unexpanded parameter pack 'Args'}}
55+
56+
template <int... Args>
57+
__launch_bounds__(1, 22, Args) void TestTemplateVariadicArgs2(void) {} // expected-error {{expression contains unexpanded parameter pack 'Args'}}

0 commit comments

Comments
 (0)