Skip to content

Commit b5f761f

Browse files
committed
[SYCL] Refactor of FPGA loop fusion function attributes
This patch 1. refactors two function attributes using intel#3224 : [[intel::loop_fuse()]] and [[intel::loop_fuse_independent()]] 2. store expression as ConstantExpr in Semantic Attributes 3. handles template instantiations properly for duplicate attributes on a given declaration. 4. adds test 5. updates codegen codes Signed-off-by: Soumi Manna <[email protected]>
1 parent 2a7a149 commit b5f761f

File tree

7 files changed

+137
-85
lines changed

7 files changed

+137
-85
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3471,8 +3471,6 @@ class Sema final {
34713471
EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D,
34723472
const EnforceTCBLeafAttr &AL);
34733473

3474-
SYCLIntelLoopFuseAttr *
3475-
mergeSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
34763474
void mergeDeclAttributes(NamedDecl *New, Decl *Old,
34773475
AvailabilityMergeKind AMK = AMK_Redeclaration);
34783476
void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
@@ -10232,6 +10230,10 @@ class Sema final {
1023210230
Expr *E);
1023310231
SYCLIntelNoGlobalWorkOffsetAttr *MergeSYCLIntelNoGlobalWorkOffsetAttr(
1023410232
Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A);
10233+
void AddSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI,
10234+
Expr *E);
10235+
SYCLIntelLoopFuseAttr *MergeSYCLIntelLoopFuseAttr(
10236+
Decl *D, const SYCLIntelLoopFuseAttr &A);
1023510237

1023610238
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
1023710239
void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
@@ -10286,8 +10288,6 @@ class Sema final {
1028610288
/// addSYCLIntelPipeIOAttr - Adds a pipe I/O attribute to a particular
1028710289
/// declaration.
1028810290
void addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &CI, Expr *ID);
10289-
void addSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI,
10290-
Expr *E);
1029110291

1029210292
bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
1029310293
bool checkAllowedSYCLInitializer(VarDecl *VD,

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -983,10 +983,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
983983

984984
if (getLangOpts().SYCLIsDevice && D) {
985985
if (const auto *A = D->getAttr<SYCLIntelLoopFuseAttr>()) {
986-
Expr *E = A->getValue();
986+
const Expr *Arg = A->getValue();
987+
assert(Arg && "Got an unexpected null argument");
988+
const auto *CE = dyn_cast<ConstantExpr>(Arg);
989+
assert(CE && "Not an integer constant expression");
990+
Optional<llvm::APSInt> ArgVal = CE->getResultAsAPSInt();
987991
llvm::Metadata *AttrMDArgs[] = {
988-
llvm::ConstantAsMetadata::get(Builder.getInt32(
989-
E->getIntegerConstantExpr(D->getASTContext())->getZExtValue())),
992+
llvm::ConstantAsMetadata::get(
993+
Builder.getInt32(ArgVal->getZExtValue())),
990994
llvm::ConstantAsMetadata::get(
991995
A->isIndependent() ? Builder.getInt32(1) : Builder.getInt32(0))};
992996
Fn->setMetadata("loop_fuse",

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,8 +2612,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
26122612
NewAttr = S.mergeImportModuleAttr(D, *IMA);
26132613
else if (const auto *INA = dyn_cast<WebAssemblyImportNameAttr>(Attr))
26142614
NewAttr = S.mergeImportNameAttr(D, *INA);
2615-
else if (const auto *LFA = dyn_cast<SYCLIntelLoopFuseAttr>(Attr))
2616-
NewAttr = S.mergeSYCLIntelLoopFuseAttr(D, *LFA, LFA->getValue());
2615+
else if (const auto *A = dyn_cast<SYCLIntelLoopFuseAttr>(Attr))
2616+
NewAttr = S.MergeSYCLIntelLoopFuseAttr(D, *A);
26172617
else if (const auto *TCBA = dyn_cast<EnforceTCBAttr>(Attr))
26182618
NewAttr = S.mergeEnforceTCBAttr(D, *TCBA);
26192619
else if (const auto *TCBLA = dyn_cast<EnforceTCBLeafAttr>(Attr))

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 76 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3453,87 +3453,95 @@ static void handleMaxGlobalWorkDimAttr(Sema &S, Decl *D, const ParsedAttr &A) {
34533453
S.addIntelSingleArgAttr<SYCLIntelMaxGlobalWorkDimAttr>(D, A, E);
34543454
}
34553455

3456-
SYCLIntelLoopFuseAttr *
3457-
Sema::mergeSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI,
3458-
Expr *E) {
3456+
// Handles [[intel::loop_fuse]] and [[intel::loop_fuse_independent]].
3457+
void Sema::AddSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI,
3458+
Expr *E) {
3459+
if (!E->isValueDependent()) {
3460+
// Validate that we have an integer constant expression and then store the
3461+
// converted constant expression into the semantic attribute so that we
3462+
// don't have to evaluate it again later.
3463+
llvm::APSInt ArgVal;
3464+
ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
3465+
if (Res.isInvalid())
3466+
return;
3467+
E = Res.get();
34593468

3460-
if (const auto ExistingAttr = D->getAttr<SYCLIntelLoopFuseAttr>()) {
3469+
// This attribute requires a non-negative value.
3470+
if (ArgVal < 0) {
3471+
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
3472+
<< CI << /*non-negative*/ 1;
3473+
return;
3474+
}
3475+
// Check to see if there's a duplicate attribute with different values
3476+
// already applied to the declaration.
3477+
if (const auto *DeclAttr = D->getAttr<SYCLIntelLoopFuseAttr>()) {
3478+
// If the other attribute argument is instantiation dependent, we won't
3479+
// have converted it to a constant expression yet and thus we test
3480+
// whether this is a null pointer.
3481+
const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
3482+
if (DeclExpr && ArgVal != DeclExpr->getResultAsAPSInt()) {
3483+
Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
3484+
Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
3485+
return;
3486+
}
3487+
// [[intel::loop_fuse]] and [[intel::loop_fuse_independent]] are
3488+
// incompatible.
3489+
// FIXME: If additional spellings are provided for this attribute,
3490+
// this code will do the wrong thing.
3491+
if (DeclAttr->getAttributeSpellingListIndex() !=
3492+
CI.getAttributeSpellingListIndex()) {
3493+
Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
3494+
<< CI << DeclAttr;
3495+
Diag(DeclAttr->getLocation(), diag::note_conflicting_attribute);
3496+
return;
3497+
}
3498+
}
3499+
}
3500+
3501+
D->addAttr(::new (Context) SYCLIntelLoopFuseAttr(Context, CI, E));
3502+
}
3503+
3504+
SYCLIntelLoopFuseAttr *Sema::MergeSYCLIntelLoopFuseAttr(
3505+
Decl *D, const SYCLIntelLoopFuseAttr &A) {
3506+
// Check to see if there's a duplicate attribute with different values
3507+
// already applied to the declaration.
3508+
if (const auto *DeclAttr = D->getAttr<SYCLIntelLoopFuseAttr>()) {
3509+
const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
3510+
const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue());
3511+
if (DeclExpr && MergeExpr &&
3512+
DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
3513+
Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
3514+
Diag(A.getLoc(), diag::note_previous_attribute);
3515+
return nullptr;
3516+
}
34613517
// [[intel::loop_fuse]] and [[intel::loop_fuse_independent]] are
34623518
// incompatible.
34633519
// FIXME: If additional spellings are provided for this attribute,
34643520
// this code will do the wrong thing.
3465-
if (ExistingAttr->getAttributeSpellingListIndex() !=
3466-
CI.getAttributeSpellingListIndex()) {
3467-
Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
3468-
<< CI << ExistingAttr;
3469-
Diag(ExistingAttr->getLocation(), diag::note_conflicting_attribute);
3521+
if (DeclAttr->getAttributeSpellingListIndex() !=
3522+
A.getAttributeSpellingListIndex()) {
3523+
Diag(A.getLoc(), diag::err_attributes_are_not_compatible)
3524+
<< &A << DeclAttr;
3525+
Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute);
34703526
return nullptr;
34713527
}
3472-
3473-
if (!E->isValueDependent()) {
3474-
Optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(Context);
3475-
Optional<llvm::APSInt> ExistingArgVal =
3476-
ExistingAttr->getValue()->getIntegerConstantExpr(Context);
3477-
3478-
assert(ArgVal && ExistingArgVal &&
3479-
"Argument should be an integer constant expression");
3480-
// Compare attribute argument value and warn if there is a mismatch.
3481-
if (ArgVal->getExtValue() != ExistingArgVal->getExtValue())
3482-
Diag(ExistingAttr->getLoc(), diag::warn_duplicate_attribute)
3483-
<< ExistingAttr;
3484-
}
3485-
3486-
// If there is no mismatch, silently ignore duplicate attribute.
3487-
return nullptr;
3488-
}
3489-
return ::new (Context) SYCLIntelLoopFuseAttr(Context, CI, E);
3490-
}
3491-
3492-
static bool checkSYCLIntelLoopFuseArgument(Sema &S,
3493-
const AttributeCommonInfo &CI,
3494-
Expr *E) {
3495-
// Dependent expressions are checked when instantiated.
3496-
if (E->isValueDependent())
3497-
return false;
3498-
3499-
Optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(S.Context);
3500-
if (!ArgVal) {
3501-
S.Diag(E->getExprLoc(), diag::err_attribute_argument_type)
3502-
<< CI << AANT_ArgumentIntegerConstant << E->getSourceRange();
3503-
return true;
35043528
}
35053529

3506-
if (!ArgVal->isNonNegative()) {
3507-
S.Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
3508-
<< CI << /*non-negative*/ 1;
3509-
return true;
3510-
}
3511-
3512-
return false;
3530+
return ::new (Context)
3531+
SYCLIntelLoopFuseAttr(Context, A, A.getValue());
35133532
}
35143533

3515-
void Sema::addSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI,
3516-
Expr *E) {
3517-
assert(E && "argument has unexpected null value");
3518-
3519-
if (checkSYCLIntelLoopFuseArgument(*this, CI, E))
3520-
return;
3521-
3522-
SYCLIntelLoopFuseAttr *NewAttr = mergeSYCLIntelLoopFuseAttr(D, CI, E);
3523-
3524-
if (NewAttr)
3525-
D->addAttr(NewAttr);
3526-
}
3534+
static void handleSYCLIntelLoopFuseAttr(Sema &S, Decl *D,
3535+
const ParsedAttr &A) {
3536+
S.CheckDeprecatedSYCLAttributeSpelling(A);
35273537

3528-
// Handles [[intel::loop_fuse]] and [[intel::loop_fuse_independent]].
3529-
static void handleLoopFuseAttr(Sema &S, Decl *D, const ParsedAttr &Attr) {
3530-
// Default argument value is set to 1.
3531-
Expr *E = Attr.isArgExpr(0)
3532-
? Attr.getArgAsExpr(0)
3538+
// If no attribute argument is specified, set to default value '1'.
3539+
Expr *E = A.isArgExpr(0)
3540+
? A.getArgAsExpr(0)
35333541
: IntegerLiteral::Create(S.Context, llvm::APInt(32, 1),
3534-
S.Context.IntTy, Attr.getLoc());
3542+
S.Context.IntTy, A.getLoc());
35353543

3536-
S.addSYCLIntelLoopFuseAttr(D, Attr, E);
3544+
S.AddSYCLIntelLoopFuseAttr(D, A, E);
35373545
}
35383546

35393547
static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
@@ -9136,7 +9144,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
91369144
handleUseStallEnableClustersAttr(S, D, AL);
91379145
break;
91389146
case ParsedAttr::AT_SYCLIntelLoopFuse:
9139-
handleLoopFuseAttr(S, D, AL);
9147+
handleSYCLIntelLoopFuseAttr(S, D, AL);
91409148
break;
91419149
case ParsedAttr::AT_VecTypeHint:
91429150
handleVecTypeHint(S, D, AL);

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ static void instantiateSYCLIntelLoopFuseAttr(
640640
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
641641
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
642642
if (!Result.isInvalid())
643-
S.addSYCLIntelLoopFuseAttr(New, *Attr, Result.getAs<Expr>());
643+
S.AddSYCLIntelLoopFuseAttr(New, *Attr, Result.getAs<Expr>());
644644
}
645645

646646
static void instantiateIntelReqdSubGroupSize(

clang/test/SemaSYCL/loop_fusion.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[[intel::loop_fuse(5)]] int a; // expected-error{{'loop_fuse' attribute only applies to functions}}
44

5-
[[intel::loop_fuse("foo")]] void func() {} // expected-error{{'loop_fuse' attribute requires an integer constant}}
5+
[[intel::loop_fuse("foo")]] void func() {} // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'const char [4]'}}
66

77
[[intel::loop_fuse(1048577)]] void func1() {} // OK
88
[[intel::loop_fuse_independent(-1)]] void func2() {} // expected-error{{'loop_fuse_independent' attribute requires a non-negative integral compile time constant expression}}
@@ -14,19 +14,22 @@
1414
[[intel::loop_fuse]] [[intel::loop_fuse]] void func5() {}
1515
[[intel::loop_fuse_independent(10)]] [[intel::loop_fuse_independent(10)]] void func6() {}
1616

17-
[[intel::loop_fuse]] [[intel::loop_fuse(10)]] void func7() {} // expected-warning {{attribute 'loop_fuse' is already applied with different arguments}}
18-
[[intel::loop_fuse_independent(5)]] [[intel::loop_fuse_independent(10)]] void func8() {} // expected-warning {{attribute 'loop_fuse_independent' is already applied with different arguments}}
17+
[[intel::loop_fuse]] // expected-note {{previous attribute is here}}
18+
[[intel::loop_fuse(10)]] void func7() {} // expected-warning {{attribute 'loop_fuse' is already applied with different arguments}}
19+
20+
[[intel::loop_fuse_independent(5)]] // expected-note {{previous attribute is here}}
21+
[[intel::loop_fuse_independent(10)]] void func8() {} // expected-warning {{attribute 'loop_fuse_independent' is already applied with different arguments}}
1922

2023
[[intel::loop_fuse]] void func9();
2124
[[intel::loop_fuse]] void func9();
2225

2326
[[intel::loop_fuse_independent(10)]] void func10();
2427
[[intel::loop_fuse_independent(10)]] void func10();
2528

26-
[[intel::loop_fuse(1)]] void func11();
29+
[[intel::loop_fuse(1)]] void func11(); // expected-note {{previous attribute is here}}
2730
[[intel::loop_fuse(3)]] void func11(); // expected-warning {{attribute 'loop_fuse' is already applied with different arguments}}
2831

29-
[[intel::loop_fuse_independent(1)]] void func12();
32+
[[intel::loop_fuse_independent(1)]] void func12(); // expected-note {{previous attribute is here}}
3033
[[intel::loop_fuse_independent(3)]] void func12(); // expected-warning {{attribute 'loop_fuse_independent' is already applied with different arguments}}
3134

3235
// expected-error@+2 {{'loop_fuse_independent' and 'loop_fuse' attributes are not compatible}}
@@ -51,13 +54,34 @@ template <int N>
5154
[[intel::loop_fuse(N)]] void func17(); // expected-error{{'loop_fuse' attribute requires a non-negative integral compile time constant expression}}
5255

5356
template <typename Ty>
54-
[[intel::loop_fuse(Ty{})]] void func18() {} // expected-error{{'loop_fuse' attribute requires an integer constant}}
57+
[[intel::loop_fuse(Ty{})]] void func18() {} // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'float'}}
58+
59+
template <int size>
60+
[[intel::loop_fuse(12)]] void func19(); // expected-note {{previous attribute is here}}
61+
template <int size>
62+
[[intel::loop_fuse(size)]] void func19() {} // expected-warning {{attribute 'loop_fuse' is already applied with different arguments}}
63+
64+
template <int size>
65+
[[intel::loop_fuse_independent(5)]] void func20(); // expected-note {{previous attribute is here}}
66+
template <int size>
67+
[[intel::loop_fuse_independent(size)]] void func20() {} // expected-warning {{attribute 'loop_fuse_independent' is already applied with different arguments}}
5568

5669
void checkTemplates() {
5770
func17<-1>(); // expected-note{{in instantiation of}}
5871
func17<0>(); // OK
5972
func18<float>(); // expected-note{{in instantiation of}}
73+
func19<20>(); //expected-note {{in instantiation of function template specialization 'func19<20>' requested here}}
74+
func20<14>(); //expected-note {{in instantiation of function template specialization 'func20<14>' requested here}}
6075
}
6176

77+
// expected-note@+3 {{declared here}}
78+
// expected-note@+3 {{non-constexpr function 'baz' cannot be used in a constant expression}}
79+
// expected-error@+2 {{expression is not an integral constant expression}}
6280
int baz();
63-
[[intel::loop_fuse(baz())]] void func19(); // expected-error{{'loop_fuse' attribute requires an integer constant}}
81+
[[intel::loop_fuse(baz())]] void func21();
82+
83+
[[intel::loop_fuse_independent]]
84+
[[intel::loop_fuse_independent]] void func22() {} //OK
85+
86+
[[intel::loop_fuse_independent]] // expected-note {{previous attribute is here}}
87+
[[intel::loop_fuse_independent(10)]] void func23() {} // expected-warning {{attribute 'loop_fuse_independent' is already applied with different arguments}}

clang/test/SemaSYCL/loop_fusion_ast.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,32 @@ queue q;
88
// CHECK: FunctionDecl {{.*}} func1 'void ()'
99
// CHECK-NEXT: CompoundStmt
1010
// CHECK-NEXT: SYCLIntelLoopFuseAttr {{.*}} loop_fuse
11+
// CHECK-NEXT: ConstantExpr{{.*}}'int'
12+
// CHECK-NEXT: value: Int 1
1113
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
1214
[[intel::loop_fuse]] void func1() {}
1315

1416
// CHECK: FunctionDecl {{.*}} func2 'void ()'
1517
// CHECK-NEXT: CompoundStmt
1618
// CHECK-NEXT: SYCLIntelLoopFuseAttr {{.*}} loop_fuse
19+
// CHECK-NEXT: ConstantExpr{{.*}}'int'
20+
// CHECK-NEXT: value: Int 0
1721
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0
1822
[[intel::loop_fuse(0)]] void func2() {}
1923

2024
// CHECK: FunctionDecl {{.*}} func3 'void ()'
2125
// CHECK-NEXT: CompoundStmt
2226
// CHECK-NEXT: SYCLIntelLoopFuseAttr {{.*}} loop_fuse_independent
27+
// CHECK-NEXT: ConstantExpr{{.*}}'int'
28+
// CHECK-NEXT: value: Int 1
2329
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
2430
[[intel::loop_fuse_independent]] void func3() {}
2531

2632
// CHECK: FunctionDecl {{.*}} func4 'void ()'
2733
// CHECK-NEXT: CompoundStmt
2834
// CHECK-NEXT: SYCLIntelLoopFuseAttr {{.*}} loop_fuse_independent
35+
// CHECK-NEXT: ConstantExpr{{.*}}'int'
36+
// CHECK-NEXT: value: Int 3
2937
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
3038
[[intel::loop_fuse_independent(3)]] void func4() {}
3139

@@ -38,6 +46,8 @@ queue q;
3846
// CHECK-NEXT: TemplateArgument integral 1
3947
// CHECK-NEXT: CompoundStmt
4048
// CHECK-NEXT: SYCLIntelLoopFuseAttr {{.*}} loop_fuse
49+
// CHECK-NEXT: ConstantExpr{{.*}}'int'
50+
// CHECK-NEXT: value: Int 1
4151
// CHECK-NEXT: SubstNonTypeTemplateParmExpr
4252
// CHECK-NEXT: NonTypeTemplateParmDecl
4353
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
@@ -53,6 +63,8 @@ template <int N>
5363
// CHECK-NEXT: TemplateArgument integral 5
5464
// CHECK-NEXT: CompoundStmt
5565
// CHECK-NEXT: SYCLIntelLoopFuseAttr {{.*}} loop_fuse_independent
66+
// CHECK-NEXT: ConstantExpr{{.*}}'int'
67+
// CHECK-NEXT: value: Int 5
5668
// CHECK-NEXT: SubstNonTypeTemplateParmExpr
5769
// CHECK-NEXT: NonTypeTemplateParmDecl
5870
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 5
@@ -83,6 +95,8 @@ void foo() {
8395

8496
// CHECK: FunctionDecl {{.*}}kernel_name_2
8597
// CHECK: SYCLIntelLoopFuseAttr {{.*}} loop_fuse
98+
// CHECK-NEXT: ConstantExpr{{.*}}'int'
99+
// CHECK-NEXT: value: Int 3
86100
// CHECK-NEXT: SubstNonTypeTemplateParmExpr
87101
// CHECK-NEXT: NonTypeTemplateParmDecl
88102
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
@@ -91,6 +105,8 @@ void foo() {
91105

92106
// CHECK: FunctionDecl {{.*}}kernel_name_3
93107
// CHECK: SYCLIntelLoopFuseAttr {{.*}} loop_fuse_independent
108+
// CHECK-NEXT: ConstantExpr{{.*}}'int'
109+
// CHECK-NEXT: value: Int 1
94110
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
95111
h.single_task<class kernel_name_3>(
96112
[]() [[intel::loop_fuse_independent]]{});

0 commit comments

Comments
 (0)