@@ -332,42 +332,69 @@ CheckForIncompatibleAttributes(Sema &S,
332332 }
333333}
334334
335-
336- template <typename FPGALoopAttrT> static void
337- CheckForDuplicationFPGALoopAttribute (Sema &S,
338- const SmallVectorImpl<const Attr *>
339- &Attrs, SourceRange Range) {
340- const FPGALoopAttrT *LoopFPGAAttr = nullptr ;
335+ template <typename LoopAttrT>
336+ static void CheckForDuplicationSYCLLoopAttribute (
337+ Sema &S, const SmallVectorImpl<const Attr *> &Attrs, SourceRange Range,
338+ bool isIntelFPGAAttr = true ) {
339+ const LoopAttrT *LoopAttr = nullptr ;
341340
342341 for (const auto *I : Attrs) {
343- if (LoopFPGAAttr ) {
344- if (isa<FPGALoopAttrT >(I)) {
342+ if (LoopAttr ) {
343+ if (isa<LoopAttrT >(I)) {
345344 SourceLocation Loc = Range.getBegin ();
346345 // Cannot specify same type of attribute twice.
347- S.Diag (Loc, diag::err_intel_fpga_loop_attr_duplication )
348- << LoopFPGAAttr ->getName ();
346+ S.Diag (Loc, diag::err_sycl_loop_attr_duplication )
347+ << isIntelFPGAAttr << LoopAttr ->getName ();
349348 }
350349 }
351- if (isa<FPGALoopAttrT >(I))
352- LoopFPGAAttr = cast<FPGALoopAttrT >(I);
350+ if (isa<LoopAttrT >(I))
351+ LoopAttr = cast<LoopAttrT >(I);
353352 }
354353}
355354
356- static void
357- CheckForIncompatibleFPGALoopAttributes (Sema &S,
358- const SmallVectorImpl<const Attr *>
359- &Attrs, SourceRange Range) {
360- CheckForDuplicationFPGALoopAttribute<SYCLIntelFPGAIVDepAttr>(S, Attrs, Range);
361- CheckForDuplicationFPGALoopAttribute<SYCLIntelFPGAIIAttr>(S, Attrs, Range);
362- CheckForDuplicationFPGALoopAttribute<
363- SYCLIntelFPGAMaxConcurrencyAttr>(S, Attrs, Range);
355+ static void CheckForIncompatibleSYCLLoopAttributes (
356+ Sema &S, const SmallVectorImpl<const Attr *> &Attrs, SourceRange Range) {
357+ CheckForDuplicationSYCLLoopAttribute<SYCLIntelFPGAIVDepAttr>(S, Attrs, Range);
358+ CheckForDuplicationSYCLLoopAttribute<SYCLIntelFPGAIIAttr>(S, Attrs, Range);
359+ CheckForDuplicationSYCLLoopAttribute<SYCLIntelFPGAMaxConcurrencyAttr>(
360+ S, Attrs, Range);
361+ CheckForDuplicationSYCLLoopAttribute<LoopUnrollHintAttr>(S, Attrs, Range,
362+ false );
363+ }
364+
365+ void CheckForIncompatibleUnrollHintAttributes (
366+ Sema &S, const SmallVectorImpl<const Attr *> &Attrs, SourceRange Range) {
367+
368+ // This check is entered after it was analyzed that there are no duplicating
369+ // pragmas and loop attributes. So, let's perform check that there are no
370+ // conflicting pragma unroll and unroll attribute for the loop.
371+ const LoopUnrollHintAttr *AttrUnroll = nullptr ;
372+ const LoopHintAttr *PragmaUnroll = nullptr ;
373+ for (const auto *I : Attrs) {
374+ if (auto *LH = dyn_cast<LoopUnrollHintAttr>(I))
375+ AttrUnroll = LH;
376+ if (auto *LH = dyn_cast<LoopHintAttr>(I)) {
377+ LoopHintAttr::OptionType Opt = LH->getOption ();
378+ if (Opt == LoopHintAttr::Unroll || Opt == LoopHintAttr::UnrollCount)
379+ PragmaUnroll = LH;
380+ }
381+ }
382+
383+ if (AttrUnroll && PragmaUnroll) {
384+ PrintingPolicy Policy (S.Context .getLangOpts ());
385+ SourceLocation Loc = Range.getBegin ();
386+ S.Diag (Loc, diag::err_loop_unroll_compatibility)
387+ << PragmaUnroll->getDiagnosticName (Policy)
388+ << AttrUnroll->getDiagnosticName ();
389+ }
364390}
365391
366- static Attr *handleOpenCLUnrollHint (Sema &S, Stmt *St, const ParsedAttr &A,
367- SourceRange Range) {
392+ template <typename LoopUnrollAttrT>
393+ static Attr *handleLoopUnrollHint (Sema &S, Stmt *St, const ParsedAttr &A,
394+ SourceRange Range) {
368395 // Although the feature was introduced only in OpenCL C v2.0 s6.11.5, it's
369396 // useful for OpenCL 1.x too and doesn't require HW support.
370- // opencl_unroll_hint can have 0 arguments (compiler
397+ // opencl_unroll_hint or clang::unroll can have 0 arguments (compiler
371398 // determines unrolling factor) or 1 argument (the unroll factor provided
372399 // by the user).
373400
@@ -401,7 +428,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
401428 UnrollFactor = Val;
402429 }
403430
404- return OpenCLUnrollHintAttr ::CreateImplicit (S.Context , UnrollFactor);
431+ return LoopUnrollAttrT ::CreateImplicit (S.Context , UnrollFactor);
405432}
406433
407434static Attr *ProcessStmtAttribute (Sema &S, Stmt *St, const ParsedAttr &A,
@@ -424,7 +451,9 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
424451 case ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency:
425452 return handleIntelFPGALoopAttr<SYCLIntelFPGAMaxConcurrencyAttr>(S, St, A);
426453 case ParsedAttr::AT_OpenCLUnrollHint:
427- return handleOpenCLUnrollHint (S, St, A, Range);
454+ return handleLoopUnrollHint<OpenCLUnrollHintAttr>(S, St, A, Range);
455+ case ParsedAttr::AT_LoopUnrollHint:
456+ return handleLoopUnrollHint<LoopUnrollHintAttr>(S, St, A, Range);
428457 case ParsedAttr::AT_Suppress:
429458 return handleSuppressAttr (S, St, A, Range);
430459 default :
@@ -446,7 +475,8 @@ StmtResult Sema::ProcessStmtAttributes(Stmt *S,
446475 }
447476
448477 CheckForIncompatibleAttributes (*this , Attrs);
449- CheckForIncompatibleFPGALoopAttributes (*this , Attrs, Range);
478+ CheckForIncompatibleSYCLLoopAttributes (*this , Attrs, Range);
479+ CheckForIncompatibleUnrollHintAttributes (*this , Attrs, Range);
450480
451481 if (Attrs.empty ())
452482 return S;
0 commit comments