From 15d6be28f5a7a948562ac65b9ea26c5f519c49b0 Mon Sep 17 00:00:00 2001 From: Viktoria Maksimova Date: Mon, 27 Jan 2020 15:13:45 +0300 Subject: [PATCH 1/4] [SYCL][FPGA] Enable a set of loop attributes This patch introduces the following loop attributes: - loop_coalesce: Indicates that the loop nest should be coalesced into a single loop without affecting functionality - speculated_iterations: Specifies the number of concurrent speculated iterations that will be in flight for a loop invocation - disable_loop_pipelining: Disables pipelining of the loop data path, causing the loop to be executed serially - max_interleaving: Places a maximum limit N on the number of interleaved invocations of an inner loop by an outer loop Signed-off-by: Viktoria Maksimova --- clang/include/clang/Basic/Attr.td | 51 ++++++++ clang/include/clang/Basic/AttrDocs.td | 47 +++++++ clang/include/clang/Sema/Sema.h | 2 +- clang/lib/CodeGen/CGLoopInfo.cpp | 136 ++++++++++++++++++-- clang/lib/CodeGen/CGLoopInfo.h | 56 ++++++++ clang/lib/Parse/ParseStmt.cpp | 6 + clang/lib/Sema/SemaStmtAttr.cpp | 92 +++++++++++-- clang/lib/Sema/SemaTemplateInstantiate.cpp | 33 +++++ clang/test/CodeGenSYCL/intel-fpga-loops.cpp | 79 +++++++++++- clang/test/SemaSYCL/intel-fpga-loops.cpp | 121 +++++++++++++++++ 10 files changed, 602 insertions(+), 21 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index fc8d392e3937a..9e8a188a285a9 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1654,6 +1654,57 @@ def SYCLIntelFPGAMaxConcurrency : Attr { let Documentation = [SYCLIntelFPGAMaxConcurrencyAttrDocs]; } +def SYCLIntelFPGALoopCoalesce : Attr { + let Spellings = [CXX11<"intelfpga","loop_coalesce">]; + let Args = [ExprArgument<"NExpr">]; + let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let HasCustomTypeTransform = 1; + let AdditionalMembers = [{ + static const char *getName() { + return "loop_coalesce"; + } + }]; + let Documentation = [SYCLIntelFPGALoopCoalesceAttrDocs]; +} + +def SYCLIntelFPGADisableLoopPipelining : Attr { + let Spellings = [CXX11<"intelfpga","disable_loop_pipelining">]; + let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let HasCustomTypeTransform = 1; + let AdditionalMembers = [{ + static const char *getName() { + return "disable_loop_pipelining"; + } + }]; + let Documentation = [SYCLIntelFPGADisableLoopPipeliningAttrDocs]; +} + +def SYCLIntelFPGAMaxInterleaving : Attr { + let Spellings = [CXX11<"intelfpga","max_interleaving">]; + let Args = [ExprArgument<"NExpr">]; + let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let HasCustomTypeTransform = 1; + let AdditionalMembers = [{ + static const char *getName() { + return "max_interleaving"; + } + }]; + let Documentation = [SYCLIntelFPGAMaxInterleavingAttrDocs]; +} + +def SYCLIntelFPGASpeculatedIterations : Attr { + let Spellings = [CXX11<"intelfpga","speculated_iterations">]; + let Args = [ExprArgument<"NExpr">]; + let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let HasCustomTypeTransform = 1; + let AdditionalMembers = [{ + static const char *getName() { + return "speculated_iterations"; + } + }]; + let Documentation = [SYCLIntelFPGASpeculatedIterationsAttrDocs]; +} + def IntelFPGALocalNonConstVar : SubsetSubjecthasLocalStorage() && S->getKind() != Decl::ImplicitParam && diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 58af06c66bb84..79e1f2a44077e 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2090,6 +2090,53 @@ be applied multiple times to the same loop. }]; } +def SYCLIntelFPGALoopCoalesceAttrDocs : Documentation { + let Category = DocCatVariable; + let Heading = "loop_coalesce"; + let Content = [{ +This attribute applies to a loop. Indicates that the loop nest should be +coalesced into a single loop without affecting functionality. Parameter N is +optional. If specified, it must be a positive integer, and indicates how many +of the nested loop levels should be coalesced. + }]; +} + +def SYCLIntelFPGADisableLoopPipeliningAttrDocs : Documentation { + let Category = DocCatVariable; + let Heading = "disable_loop_pipelining"; + let Content = [{ +This attribute applies to a loop. Disables pipelining of the loop data path, +causing the loop to be executed serially. Cannot be used on the same loop in +conjunction with max_interleaving, speculated_iterations, max_concurrency, ii +or ivdep. + }]; +} + +def SYCLIntelFPGAMaxInterleavingAttrDocs : Documentation { + let Category = DocCatVariable; + let Heading = "max_interleaving"; + let Content = [{ +This attribute applies to a loop. Places a maximum limit N on the number of +interleaved invocations of an inner loop by an outer loop (note, this does not +mean that this attribute can only be applied to inner loops in user code - outer +loops in user code may still be contained in an implicit loop due to NDRange). +Parameter N is mandatory, and may either b 0, or a positive integer. Cannot be +used on the same loop in conjunction with disable_loop_pipelining. + }]; +} + +def SYCLIntelFPGASpeculatedIterationsAttrDocs : Documentation { + let Category = DocCatVariable; + let Heading = "speculated_iterations"; + let Content = [{ +This attribute applies to a loop. Specifies the number of concurrent speculated +iterations that will be in flight (iterations that are in flight where the exit +condition for that iteration has not yet been evaluated) for a loop invocation. +Parameter N is mandatory, and may either be 0, or a positive integer. Cannot be +used on the same loop in conjunction with disable_loop_pipelining. + }]; +} + def SYCLDeviceIndirectlyCallableDocs : Documentation { let Category = DocCatFunction; let Heading = "intel::device_indirectly_callable"; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 353ca10894b92..d211214acc8b1 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1719,7 +1719,7 @@ class Sema final { Expr *Expr2); template FPGALoopAttrT *BuildSYCLIntelFPGALoopAttr(const AttributeCommonInfo &A, - Expr *E); + Expr *E = nullptr); LoopUnrollHintAttr *BuildLoopUnrollHintAttr(const AttributeCommonInfo &A, Expr *E); diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index 5a2ddad981931..2dc557596ff0e 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -524,6 +524,49 @@ MDNode *LoopInfo::createMetadata( LoopProperties.push_back(MDNode::get(Ctx, Vals)); } + if (Attrs.SYCLLoopCoalesceEnable) { + LLVMContext &Ctx = Header->getContext(); + Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.coalesce.enable")}; + LoopProperties.push_back(MDNode::get(Ctx, Vals)); + } + + if (Attrs.SYCLLoopCoalesceNLevels > 0) { + LLVMContext &Ctx = Header->getContext(); + Metadata *Vals[] = { + MDString::get(Ctx, "llvm.loop.coalesce.count"), + ConstantAsMetadata::get(ConstantInt::get( + llvm::Type::getInt32Ty(Ctx), Attrs.SYCLLoopCoalesceNLevels))}; + LoopProperties.push_back(MDNode::get(Ctx, Vals)); + } + + if (Attrs.SYCLLoopPipeliningDisable) { + LLVMContext &Ctx = Header->getContext(); + Metadata *Vals[] = { + MDString::get(Ctx, "llvm.loop.intel.pipelining.enable"), + ConstantAsMetadata::get(ConstantInt::get( + llvm::Type::getInt32Ty(Ctx), 0))}; + LoopProperties.push_back(MDNode::get(Ctx, Vals)); + } + + if (Attrs.SYCLMaxInterleavingEnable) { + LLVMContext &Ctx = Header->getContext(); + Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.max_interleaving.count"), + ConstantAsMetadata::get(ConstantInt::get( + llvm::Type::getInt32Ty(Ctx), + Attrs.SYCLMaxInterleavingNInvocations))}; + LoopProperties.push_back(MDNode::get(Ctx, Vals)); + } + + if (Attrs.SYCLSpeculatedIterationsEnable) { + LLVMContext &Ctx = Header->getContext(); + Metadata *Vals[] = { + MDString::get(Ctx, "llvm.loop.intel.speculated.iterations.count"), + ConstantAsMetadata::get( + ConstantInt::get(llvm::Type::getInt32Ty(Ctx), + Attrs.SYCLSpeculatedIterationsNIterations))}; + LoopProperties.push_back(MDNode::get(Ctx, Vals)); + } + LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(), AdditionalLoopProperties.end()); return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms); @@ -535,9 +578,13 @@ LoopAttributes::LoopAttributes(bool IsParallel) UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0), InterleaveCount(0), SYCLIInterval(0), SYCLMaxConcurrencyEnable(false), - SYCLMaxConcurrencyNThreads(0), UnrollCount(0), UnrollAndJamCount(0), - DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false), - PipelineInitiationInterval(0) {} + SYCLMaxConcurrencyNThreads(0), SYCLLoopCoalesceEnable(false), + SYCLLoopCoalesceNLevels(0), SYCLLoopPipeliningDisable(false), + SYCLMaxInterleavingEnable(false), SYCLMaxInterleavingNInvocations(0), + SYCLSpeculatedIterationsEnable(false), + SYCLSpeculatedIterationsNIterations(0), UnrollCount(0), + UnrollAndJamCount(0), DistributeEnable(LoopAttributes::Unspecified), + PipelineDisabled(false), PipelineInitiationInterval(0) {} void LoopAttributes::clear() { IsParallel = false; @@ -547,6 +594,13 @@ void LoopAttributes::clear() { SYCLIInterval = 0; SYCLMaxConcurrencyEnable = false; SYCLMaxConcurrencyNThreads = 0; + SYCLLoopCoalesceEnable = false; + SYCLLoopCoalesceNLevels = 0; + SYCLLoopPipeliningDisable = false; + SYCLMaxInterleavingEnable = false; + SYCLMaxInterleavingNInvocations = 0; + SYCLSpeculatedIterationsEnable = false; + SYCLSpeculatedIterationsNIterations = 0; InterleaveCount = 0; UnrollCount = 0; UnrollAndJamCount = 0; @@ -574,9 +628,16 @@ LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs, if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 && Attrs.InterleaveCount == 0 && !Attrs.GlobalSYCLIVDepInfo.hasValue() && Attrs.ArraySYCLIVDepInfo.empty() && Attrs.SYCLIInterval == 0 && - Attrs.SYCLMaxConcurrencyEnable == false && Attrs.UnrollCount == 0 && - Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled && - Attrs.PipelineInitiationInterval == 0 && + Attrs.SYCLMaxConcurrencyEnable == false && + Attrs.SYCLLoopCoalesceEnable == false && + Attrs.SYCLLoopCoalesceNLevels == 0 && + Attrs.SYCLLoopPipeliningDisable == false && + Attrs.SYCLMaxInterleavingEnable == false && + Attrs.SYCLMaxInterleavingNInvocations == 0 && + Attrs.SYCLSpeculatedIterationsEnable == false && + Attrs.SYCLSpeculatedIterationsNIterations == 0 && + Attrs.UnrollCount == 0 && Attrs.UnrollAndJamCount == 0 && + !Attrs.PipelineDisabled && Attrs.PipelineInitiationInterval == 0 && Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified && Attrs.VectorizeEnable == LoopAttributes::Unspecified && Attrs.UnrollEnable == LoopAttributes::Unspecified && @@ -877,6 +938,16 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, // n - 'llvm.loop.ii.count, i32 n' metadata will be emitted // For attribute max_concurrency: // n - 'llvm.loop.max_concurrency.count, i32 n' metadata will be emitted + // For attribute loop_coalesce: + // without parameter - 'lvm.loop.coalesce.enable' metadata will be emitted + // n - 'llvm.loop.coalesce.count, i32 n' metadata will be emitted + // For attribute disable_loop_pipelining: + // 'llvm.loop.intel.pipelining.enable, i32 0' metadata will be emitted + // For attribute max_interleaving: + // n - 'llvm.loop.max_interleaving.count, i32 n' metadata will be emitted + // For attribute speculated_iterations: + // n - 'llvm.loop.intel.speculated.iterations.count, i32 n' metadata will be + // emitted for (const auto *Attr : Attrs) { const SYCLIntelFPGAIVDepAttr *IntelFPGAIVDep = dyn_cast(Attr); @@ -884,8 +955,19 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, dyn_cast(Attr); const SYCLIntelFPGAMaxConcurrencyAttr *IntelFPGAMaxConcurrency = dyn_cast(Attr); - - if (!IntelFPGAIVDep && !IntelFPGAII && !IntelFPGAMaxConcurrency) + const SYCLIntelFPGALoopCoalesceAttr *IntelFPGALoopCoalesce = + dyn_cast(Attr); + const SYCLIntelFPGADisableLoopPipeliningAttr + *IntelFPGADisableLoopPipelining = + dyn_cast(Attr); + const SYCLIntelFPGAMaxInterleavingAttr *IntelFPGAMaxInterleaving = + dyn_cast(Attr); + const SYCLIntelFPGASpeculatedIterationsAttr *IntelFPGASpeculatedIterations = + dyn_cast(Attr); + + if (!IntelFPGAIVDep && !IntelFPGAII && !IntelFPGAMaxConcurrency && + !IntelFPGALoopCoalesce && !IntelFPGADisableLoopPipelining && + !IntelFPGAMaxInterleaving && !IntelFPGASpeculatedIterations) continue; if (IntelFPGAIVDep) { @@ -918,6 +1000,44 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, setSYCLMaxConcurrencyEnable(); setSYCLMaxConcurrencyNThreads(ArgVal.getSExtValue()); } + + if (IntelFPGALoopCoalesce) { + llvm::APSInt ArgVal(32); + if (auto *LCE = IntelFPGALoopCoalesce->getNExpr()) { + bool IsValid = LCE->isIntegerConstantExpr(ArgVal, Ctx); + assert(IsValid && "Not an integer constant expression"); + (void)IsValid; + setSYCLLoopCoalesceNLevels(ArgVal.getSExtValue()); + } else { + setSYCLLoopCoalesceEnable(); + } + } + + if (IntelFPGADisableLoopPipelining) { + setSYCLLoopPipeliningDisable(); + } + + if (IntelFPGAMaxInterleaving) { + llvm::APSInt ArgVal(32); + bool IsValid = + IntelFPGAMaxInterleaving->getNExpr()->isIntegerConstantExpr(ArgVal, + Ctx); + assert(IsValid && "Not an integer constant expression"); + (void)IsValid; + setSYCLMaxInterleavingEnable(); + setSYCLMaxInterleavingNInvocations(ArgVal.getSExtValue()); + } + + if (IntelFPGASpeculatedIterations) { + llvm::APSInt ArgVal(32); + bool IsValid = + IntelFPGASpeculatedIterations->getNExpr()->isIntegerConstantExpr( + ArgVal, Ctx); + assert(IsValid && "Not an integer constant expression"); + (void)IsValid; + setSYCLSpeculatedIterationsEnable(); + setSYCLSpeculatedIterationsNIterations(ArgVal.getSExtValue()); + } } /// Stage the attributes. diff --git a/clang/lib/CodeGen/CGLoopInfo.h b/clang/lib/CodeGen/CGLoopInfo.h index 690c4e68df1ce..2d128b62cc6d5 100644 --- a/clang/lib/CodeGen/CGLoopInfo.h +++ b/clang/lib/CodeGen/CGLoopInfo.h @@ -113,6 +113,27 @@ struct LoopAttributes { /// Value for llvm.loop.max_concurrency.count metadata. unsigned SYCLMaxConcurrencyNThreads; + /// Flag for llvm.loop.coalesce metadata. + bool SYCLLoopCoalesceEnable; + + /// Value for llvm.loop.coalesce.count metadata. + unsigned SYCLLoopCoalesceNLevels; + + /// Flag for llvm.loop.intel.pipelining.enable, i32 0 metadata. + bool SYCLLoopPipeliningDisable; + + /// Flag for llvm.loop.max_interleaving.count metadata. + bool SYCLMaxInterleavingEnable; + + /// Value for llvm.loop.max_interleaving.count metadata. + unsigned SYCLMaxInterleavingNInvocations; + + /// Flag for llvm.loop.intel.speculated.iterations.count metadata. + bool SYCLSpeculatedIterationsEnable; + + /// Value for llvm.loop.intel.speculated.iterations.count metadata. + unsigned SYCLSpeculatedIterationsNIterations; + /// llvm.unroll. unsigned UnrollCount; @@ -333,6 +354,41 @@ class LoopInfoStack { StagedAttrs.SYCLMaxConcurrencyNThreads = C; } + /// Set flag of loop_coalesce for the next loop pushed. + void setSYCLLoopCoalesceEnable() { + StagedAttrs.SYCLLoopCoalesceEnable = true; + } + + /// Set value of coalesced levels for the next loop pushed. + void setSYCLLoopCoalesceNLevels(unsigned C) { + StagedAttrs.SYCLLoopCoalesceNLevels = C; + } + + /// Set flag of disable_loop_pipelining for the next loop pushed. + void setSYCLLoopPipeliningDisable() { + StagedAttrs.SYCLLoopPipeliningDisable = true; + } + + /// Set flag of max_interleaving for the next loop pushed. + void setSYCLMaxInterleavingEnable() { + StagedAttrs.SYCLMaxInterleavingEnable = true; + } + + /// Set value of max interleaved invocations for the next loop pushed. + void setSYCLMaxInterleavingNInvocations(unsigned C) { + StagedAttrs.SYCLMaxInterleavingNInvocations = C; + } + + /// Set flag of speculated_iterations for the next loop pushed. + void setSYCLSpeculatedIterationsEnable() { + StagedAttrs.SYCLSpeculatedIterationsEnable = true; + } + + /// Set value of concurrent speculated iterations for the next loop pushed. + void setSYCLSpeculatedIterationsNIterations(unsigned C) { + StagedAttrs.SYCLSpeculatedIterationsNIterations = C; + } + /// Set the unroll count for the next loop pushed. void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; } diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index cc278410d6e4f..bfeab9df9bcff 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -2519,6 +2519,12 @@ bool Parser::ParseSYCLLoopAttributes(ParsedAttributes &Attrs) { if (Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGAIVDep && Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGAII && Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency && + Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGALoopCoalesce && + Attrs.begin()->getKind() != + ParsedAttr::AT_SYCLIntelFPGADisableLoopPipelining && + Attrs.begin()->getKind() != ParsedAttr::AT_SYCLIntelFPGAMaxInterleaving && + Attrs.begin()->getKind() != + ParsedAttr::AT_SYCLIntelFPGASpeculatedIterations && Attrs.begin()->getKind() != ParsedAttr::AT_LoopUnrollHint) return true; diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index c5f6730cf2c93..edf780b469481 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -86,13 +86,31 @@ static Attr *handleIntelFPGALoopAttr(Sema &S, const ParsedAttr &A) { if (NumArgs == 0) { if (A.getKind() == ParsedAttr::AT_SYCLIntelFPGAII || - A.getKind() == ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency) { + A.getKind() == ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency || + A.getKind() == ParsedAttr::AT_SYCLIntelFPGAMaxInterleaving || + A.getKind() == ParsedAttr::AT_SYCLIntelFPGASpeculatedIterations) { S.Diag(A.getLoc(), diag::warn_attribute_too_few_arguments) << A << 1; return nullptr; } } - return S.BuildSYCLIntelFPGALoopAttr(A, A.getArgAsExpr(0)); + return S.BuildSYCLIntelFPGALoopAttr( + A, A.getNumArgs() ? A.getArgAsExpr(0) : nullptr); +} + +template <> +Attr *handleIntelFPGALoopAttr( + Sema &S, const ParsedAttr &A) { + if (S.LangOpts.SYCLIsHost) + return nullptr; + + unsigned NumArgs = A.getNumArgs(); + if (NumArgs > 0) { + S.Diag(A.getLoc(), diag::warn_attribute_too_many_arguments) << A << 0; + return nullptr; + } + + return new (S.Context) SYCLIntelFPGADisableLoopPipeliningAttr(S.Context, A); } static bool checkSYCLIntelFPGAIVDepSafeLen(Sema &S, llvm::APSInt &Value, @@ -177,10 +195,10 @@ Sema::BuildSYCLIntelFPGAIVDepAttr(const AttributeCommonInfo &CI, Expr *Expr1, template FPGALoopAttrT *Sema::BuildSYCLIntelFPGALoopAttr(const AttributeCommonInfo &A, Expr *E) { - if (!E) + if (!E && !(A.getParsedKind() == ParsedAttr::AT_SYCLIntelFPGALoopCoalesce)) return nullptr; - if (!E->isInstantiationDependent()) { + if (E && !E->isInstantiationDependent()) { llvm::APSInt ArgVal(32); if (!E->isIntegerConstantExpr(ArgVal, getASTContext())) { @@ -192,17 +210,22 @@ FPGALoopAttrT *Sema::BuildSYCLIntelFPGALoopAttr(const AttributeCommonInfo &A, int Val = ArgVal.getSExtValue(); - if (A.getParsedKind() == ParsedAttr::AT_SYCLIntelFPGAII) { + if (A.getParsedKind() == ParsedAttr::AT_SYCLIntelFPGAII || + A.getParsedKind() == ParsedAttr::AT_SYCLIntelFPGALoopCoalesce) { if (Val <= 0) { Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) - << "'ii'" << /* positive */ 0; + << A.getAttrName() << /* positive */ 0; return nullptr; } } else if (A.getParsedKind() == - ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency) { + ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency || + A.getParsedKind() == + ParsedAttr::AT_SYCLIntelFPGAMaxInterleaving || + A.getParsedKind() == + ParsedAttr::AT_SYCLIntelFPGASpeculatedIterations) { if (Val < 0) { Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) - << "'max_concurrency'" << /* non-negative */ 1; + << A.getAttrName() << /* non-negative */ 1; return nullptr; } } else { @@ -521,13 +544,57 @@ static void CheckForDuplicationSYCLLoopAttribute( } } +/// Diagnose mutually exclusive attributes when present on a given +/// declaration. Returns true if diagnosed. +template +static void CheckMutualExclusionSYCLLoopAttribute( + Sema &S, const SmallVectorImpl &Attrs, SourceRange Range) { + const LoopAttrT *LoopAttr = nullptr; + const LoopAttrT2 *LoopAttr2 = nullptr; + + for (const auto *I : Attrs) { + if (isa(I)) + LoopAttr = cast(I); + if (isa(I)) + LoopAttr2 = cast(I); + if (LoopAttr && LoopAttr2) { + S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) + << "'" + std::string(LoopAttr->getName()) + "'" + << "'" + std::string(LoopAttr2->getName()) + "'"; + } + } +} + static void CheckForIncompatibleSYCLLoopAttributes( Sema &S, const SmallVectorImpl &Attrs, SourceRange Range) { CheckForDuplicationSYCLLoopAttribute(S, Attrs, Range); CheckForDuplicationSYCLLoopAttribute( S, Attrs, Range); + CheckForDuplicationSYCLLoopAttribute(S, Attrs, + Range); + CheckForDuplicationSYCLLoopAttribute( + S, Attrs, Range); + CheckForDuplicationSYCLLoopAttribute( + S, Attrs, Range); + CheckForDuplicationSYCLLoopAttribute( + S, Attrs, Range); CheckForDuplicationSYCLLoopAttribute(S, Attrs, Range, false); + CheckMutualExclusionSYCLLoopAttribute( + S, Attrs, Range); + CheckMutualExclusionSYCLLoopAttribute( + S, Attrs, Range); + CheckMutualExclusionSYCLLoopAttribute(S, Attrs, Range); + CheckMutualExclusionSYCLLoopAttribute(S, Attrs, + Range); + CheckMutualExclusionSYCLLoopAttribute( + S, Attrs, Range); + CheckRedundantSYCLIntelFPGAIVDepAttrs(S, Attrs); } @@ -638,6 +705,15 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, return handleIntelFPGALoopAttr(S, A); case ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency: return handleIntelFPGALoopAttr(S, A); + case ParsedAttr::AT_SYCLIntelFPGALoopCoalesce: + return handleIntelFPGALoopAttr(S, A); + case ParsedAttr::AT_SYCLIntelFPGADisableLoopPipelining: + return handleIntelFPGALoopAttr(S, + A); + case ParsedAttr::AT_SYCLIntelFPGAMaxInterleaving: + return handleIntelFPGALoopAttr(S, A); + case ParsedAttr::AT_SYCLIntelFPGASpeculatedIterations: + return handleIntelFPGALoopAttr(S, A); case ParsedAttr::AT_OpenCLUnrollHint: case ParsedAttr::AT_LoopUnrollHint: return handleLoopUnrollHint(S, St, A, Range); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 9b6f4f4cbd2d6..fec169893d86b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1058,6 +1058,14 @@ namespace { const SYCLIntelFPGAMaxConcurrencyAttr *MC); const LoopUnrollHintAttr * TransformLoopUnrollHintAttr(const LoopUnrollHintAttr *LU); + const SYCLIntelFPGALoopCoalesceAttr *TransformSYCLIntelFPGALoopCoalesceAttr( + const SYCLIntelFPGALoopCoalesceAttr *LC); + const SYCLIntelFPGAMaxInterleavingAttr * + TransformSYCLIntelFPGAMaxInterleavingAttr( + const SYCLIntelFPGAMaxInterleavingAttr *MI); + const SYCLIntelFPGASpeculatedIterationsAttr * + TransformSYCLIntelFPGASpeculatedIterationsAttr( + const SYCLIntelFPGASpeculatedIterationsAttr *SI); ExprResult TransformPredefinedExpr(PredefinedExpr *E); ExprResult TransformDeclRefExpr(DeclRefExpr *E); @@ -1524,6 +1532,31 @@ TemplateInstantiator::TransformSYCLIntelFPGAMaxConcurrencyAttr( *MC, TransformedExpr); } +const SYCLIntelFPGALoopCoalesceAttr * +TemplateInstantiator::TransformSYCLIntelFPGALoopCoalesceAttr( + const SYCLIntelFPGALoopCoalesceAttr *LC) { + Expr *TransformedExpr = getDerived().TransformExpr(LC->getNExpr()).get(); + return getSema().BuildSYCLIntelFPGALoopAttr( + *LC, TransformedExpr); +} + +const SYCLIntelFPGAMaxInterleavingAttr * +TemplateInstantiator::TransformSYCLIntelFPGAMaxInterleavingAttr( + const SYCLIntelFPGAMaxInterleavingAttr *MI) { + Expr *TransformedExpr = getDerived().TransformExpr(MI->getNExpr()).get(); + return getSema().BuildSYCLIntelFPGALoopAttr( + *MI, TransformedExpr); +} + +const SYCLIntelFPGASpeculatedIterationsAttr * +TemplateInstantiator::TransformSYCLIntelFPGASpeculatedIterationsAttr( + const SYCLIntelFPGASpeculatedIterationsAttr *SI) { + Expr *TransformedExpr = getDerived().TransformExpr(SI->getNExpr()).get(); + return getSema() + .BuildSYCLIntelFPGALoopAttr( + *SI, TransformedExpr); +} + const LoopUnrollHintAttr *TemplateInstantiator::TransformLoopUnrollHintAttr( const LoopUnrollHintAttr *LU) { Expr *TransformedExpr = diff --git a/clang/test/CodeGenSYCL/intel-fpga-loops.cpp b/clang/test/CodeGenSYCL/intel-fpga-loops.cpp index 4962f7200f0d4..9a049d5993f17 100644 --- a/clang/test/CodeGenSYCL/intel-fpga-loops.cpp +++ b/clang/test/CodeGenSYCL/intel-fpga-loops.cpp @@ -1,9 +1,26 @@ // RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -fsycl-is-device -emit-llvm %s -o - | FileCheck %s -// CHECK: br label %for.cond, !llvm.loop ![[MD_II:[0-9]+]] -// CHECK: br label %for.cond2, !llvm.loop ![[MD_II_2:[0-9]+]] -// CHECK: br label %for.cond, !llvm.loop ![[MD_MC:[0-9]+]] -// CHECK: br label %for.cond2, !llvm.loop ![[MD_MC_2:[0-9]+]] +// CHECK: br label %for.cond, !llvm.loop ![[MD_DLP:[0-9]+]] +// CHECK: br label %for.cond, !llvm.loop ![[MD_II:[0-9]+]] +// CHECK: br label %for.cond2, !llvm.loop ![[MD_II_2:[0-9]+]] +// CHECK: br label %for.cond, !llvm.loop ![[MD_MC:[0-9]+]] +// CHECK: br label %for.cond2, !llvm.loop ![[MD_MC_2:[0-9]+]] +// CHECK: br label %for.cond, !llvm.loop ![[MD_LC:[0-9]+]] +// CHECK: br label %for.cond2, !llvm.loop ![[MD_LC_2:[0-9]+]] +// CHECK: br label %for.cond12, !llvm.loop ![[MD_LC_3:[0-9]+]] +// CHECK: br label %for.cond, !llvm.loop ![[MD_MI:[0-9]+]] +// CHECK: br label %for.cond2, !llvm.loop ![[MD_MI_2:[0-9]+]] +// CHECK: br label %for.cond, !llvm.loop ![[MD_SI:[0-9]+]] +// CHECK: br label %for.cond2, !llvm.loop ![[MD_SI_2:[0-9]+]] + +void disable_loop_pipelining() { + int a[10]; + // CHECK: ![[MD_DLP]] = distinct !{![[MD_DLP]], ![[MD_dlp:[0-9]+]]} + // CHECK-NEXT: ![[MD_dlp]] = !{!"llvm.loop.intel.pipelining.enable", i32 0} + [[intelfpga::disable_loop_pipelining]] + for (int i = 0; i != 10; ++i) + a[i] = 0; +} template void ii() { @@ -35,6 +52,56 @@ void max_concurrency() { a[i] = 0; } +template +void loop_coalesce() { + int a[10]; + // CHECK: ![[MD_LC]] = distinct !{![[MD_LC]], ![[MD_loop_coalesce:[0-9]+]]} + // CHECK-NEXT: ![[MD_loop_coalesce]] = !{!"llvm.loop.coalesce.count", i32 2} + [[intelfpga::loop_coalesce(A)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // CHECK: ![[MD_LC_2]] = distinct !{![[MD_LC_2]], ![[MD_loop_coalesce_2:[0-9]+]]} + // CHECK-NEXT: ![[MD_loop_coalesce_2]] = !{!"llvm.loop.coalesce.count", i32 4} + [[intelfpga::loop_coalesce(4)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // CHECK: ![[MD_LC_3]] = distinct !{![[MD_LC_3]], ![[MD_loop_coalesce_3:[0-9]+]]} + // CHECK-NEXT: ![[MD_loop_coalesce_3]] = !{!"llvm.loop.coalesce.enable"} + [[intelfpga::loop_coalesce]] + for (int i = 0; i != 10; ++i) + a[i] = 0; +} + +template +void max_interleaving() { + int a[10]; + // CHECK: ![[MD_MI]] = distinct !{![[MD_MI]], ![[MD_max_interleaving:[0-9]+]]} + // CHECK-NEXT: ![[MD_max_interleaving]] = !{!"llvm.loop.max_interleaving.count", i32 3} + [[intelfpga::max_interleaving(A)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // CHECK: ![[MD_MI_2]] = distinct !{![[MD_MI_2]], ![[MD_max_interleaving_2:[0-9]+]]} + // CHECK-NEXT: ![[MD_max_interleaving_2]] = !{!"llvm.loop.max_interleaving.count", i32 2} + [[intelfpga::max_interleaving(2)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; +} + +template +void speculated_iterations() { + int a[10]; + // CHECK: ![[MD_SI]] = distinct !{![[MD_SI]], ![[MD_speculated_iterations:[0-9]+]]} + // CHECK-NEXT: ![[MD_speculated_iterations]] = !{!"llvm.loop.intel.speculated.iterations.count", i32 4} + [[intelfpga::speculated_iterations(A)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // CHECK: ![[MD_SI_2]] = distinct !{![[MD_SI_2]], ![[MD_speculated_iterations_2:[0-9]+]]} + // CHECK-NEXT: ![[MD_speculated_iterations_2]] = !{!"llvm.loop.intel.speculated.iterations.count", i32 5} + [[intelfpga::speculated_iterations(5)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; +} + template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { kernelFunc(); @@ -42,8 +109,12 @@ __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { int main() { kernel_single_task([]() { + disable_loop_pipelining(); ii<4>(); max_concurrency<0>(); + loop_coalesce<2>(); + max_interleaving<3>(); + speculated_iterations<4>(); }); return 0; } diff --git a/clang/test/SemaSYCL/intel-fpga-loops.cpp b/clang/test/SemaSYCL/intel-fpga-loops.cpp index 99150b1e63e8a..fa8a8832d442d 100644 --- a/clang/test/SemaSYCL/intel-fpga-loops.cpp +++ b/clang/test/SemaSYCL/intel-fpga-loops.cpp @@ -16,6 +16,15 @@ void foo() { [[intelfpga::ivdep(arr)]] int e[10]; // expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}} [[intelfpga::ivdep(arr, 2)]] int f[10]; + + // expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}} + [[intelfpga::disable_loop_pipelining]] int g[10]; + // expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}} + [[intelfpga::loop_coalesce(2)]] int h[10]; + // expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}} + [[intelfpga::max_interleaving(4)]] int i[10]; + // expected-error@+1 {{intelfpga loop attributes must be applied to for, while, or do statements}} + [[intelfpga::speculated_iterations(6)]] int j[10]; } // Test for incorrect number of arguments for Intel FPGA loop attributes @@ -52,12 +61,41 @@ void boo() { // expected-error@+1 {{unknown argument to 'ivdep'. Expected integer or array variable}} [[intelfpga::ivdep(2, 3.0)]] for (int i = 0; i != 10; ++i) a[i] = 0; + + // expected-warning@+1 {{'disable_loop_pipelining' attribute takes no more than 0 arguments - attribute ignored}} + [[intelfpga::disable_loop_pipelining(0)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-warning@+1 {{'loop_coalesce' attribute takes no more than 1 argument - attribute ignored}} + [[intelfpga::loop_coalesce(2,3)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-warning@+1 {{'max_interleaving' attribute takes at least 1 argument - attribute ignored}} + [[intelfpga::max_interleaving]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-warning@+1 {{'max_interleaving' attribute takes no more than 1 argument - attribute ignored}} + [[intelfpga::max_interleaving(2,4)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-warning@+1 {{'speculated_iterations' attribute takes at least 1 argument - attribute ignored}} + [[intelfpga::speculated_iterations]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-warning@+1 {{'speculated_iterations' attribute takes no more than 1 argument - attribute ignored}} + [[intelfpga::speculated_iterations(1,2)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; } // Test for incorrect argument value for Intel FPGA loop attributes void goo() { int a[10]; // no diagnostics are expected + [[intelfpga::disable_loop_pipelining]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // no diagnostics are expected [[intelfpga::max_concurrency(0)]] for (int i = 0; i != 10; ++i) a[i] = 0; @@ -71,6 +109,18 @@ void goo() { a[i] = 0; // expected-error@+1 {{'max_concurrency' attribute requires a non-negative integral compile time constant expression}} [[intelfpga::max_concurrency(-1)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'loop_coalesce' attribute requires a positive integral compile time constant expression}} + [[intelfpga::loop_coalesce(0)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'max_interleaving' attribute requires a non-negative integral compile time constant expression}} + [[intelfpga::max_interleaving(-1)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'speculated_iterations' attribute requires a non-negative integral compile time constant expression}} + [[intelfpga::speculated_iterations(-1)]] for (int i = 0; i != 10; ++i) a[i] = 0; // expected-error@+1 {{unknown argument to 'ivdep'. Expected integer or array variable}} @@ -83,6 +133,18 @@ void goo() { a[i] = 0; // expected-error@+1 {{'max_concurrency' attribute requires an integer constant}} [[intelfpga::max_concurrency("test123")]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'loop_coalesce' attribute requires an integer constant}} + [[intelfpga::loop_coalesce("test123")]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'max_interleaving' attribute requires an integer constant}} + [[intelfpga::max_interleaving("test123")]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'speculated_iterations' attribute requires an integer constant}} + [[intelfpga::speculated_iterations("test123")]] for (int i = 0; i != 10; ++i) a[i] = 0; // expected-error@+1 {{unknown argument to 'ivdep'. Expected integer or array variable}} @@ -136,6 +198,29 @@ void zoo() { // expected-error@-1 {{duplicate Intel FPGA loop attribute 'ii'}} [[intelfpga::max_concurrency(2)]] [[intelfpga::ii(2)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + [[intelfpga::disable_loop_pipelining]] + // expected-error@-1 {{duplicate Intel FPGA loop attribute 'disable_loop_pipelining'}} + [[intelfpga::disable_loop_pipelining]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + [[intelfpga::loop_coalesce(2)]] + // expected-error@-1 {{duplicate Intel FPGA loop attribute 'loop_coalesce'}} + [[intelfpga::max_interleaving(1)]] + [[intelfpga::loop_coalesce]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + [[intelfpga::max_interleaving(1)]] + // expected-error@-1 {{duplicate Intel FPGA loop attribute 'max_interleaving'}} + [[intelfpga::speculated_iterations(1)]] + [[intelfpga::max_interleaving(4)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + [[intelfpga::speculated_iterations(1)]] + // expected-error@-1 {{duplicate Intel FPGA loop attribute 'speculated_iterations'}} + [[intelfpga::loop_coalesce]] + [[intelfpga::speculated_iterations(2)]] for (int i = 0; i != 10; ++i) a[i] = 0; @@ -195,6 +280,41 @@ void zoo() { a[i] = 0; } +// Test for Intel FPGA loop attributes compatibility +void woo() { + int a[10]; + // no diagnostics are expected + [[intelfpga::disable_loop_pipelining]] + [[intelfpga::loop_coalesce]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'disable_loop_pipelining' and 'max_interleaving' attributes are not compatible}} + [[intelfpga::disable_loop_pipelining]] + [[intelfpga::max_interleaving(0)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'disable_loop_pipelining' and 'speculated_iterations' attributes are not compatible}} + [[intelfpga::speculated_iterations(0)]] + [[intelfpga::disable_loop_pipelining]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'disable_loop_pipelining' and 'max_concurrency' attributes are not compatible}} + [[intelfpga::disable_loop_pipelining]] + [[intelfpga::max_concurrency(0)]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'disable_loop_pipelining' and 'ii' attributes are not compatible}} + [[intelfpga::ii(10)]] + [[intelfpga::disable_loop_pipelining]] + for (int i = 0; i != 10; ++i) + a[i] = 0; + // expected-error@+1 {{'disable_loop_pipelining' and 'ivdep' attributes are not compatible}} + [[intelfpga::disable_loop_pipelining]] + [[intelfpga::ivdep]] + for (int i = 0; i != 10; ++i) + a[i] = 0; +} + template void ivdep_dependent() { int a[10]; @@ -270,6 +390,7 @@ int main() { boo(); goo(); zoo(); + woo(); ivdep_dependent<4, 2, 1>(); //expected-note@-1 +{{in instantiation of function template specialization}} ivdep_dependent<2, 4, -1>(); From c76a9cbe68e8816b7bdacaff9954d4e628d25486 Mon Sep 17 00:00:00 2001 From: Viktoria Maksimova Date: Fri, 13 Mar 2020 18:22:33 +0300 Subject: [PATCH 2/4] Apply clang format Signed-off-by: Viktoria Maksimova --- clang/lib/CodeGen/CGLoopInfo.cpp | 7 +- clang/test/CodeGenSYCL/intel-fpga-loops.cpp | 40 +++--- clang/test/SemaSYCL/intel-fpga-loops.cpp | 130 ++++++++------------ 3 files changed, 71 insertions(+), 106 deletions(-) diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index 2dc557596ff0e..e822cc873b52d 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -541,10 +541,9 @@ MDNode *LoopInfo::createMetadata( if (Attrs.SYCLLoopPipeliningDisable) { LLVMContext &Ctx = Header->getContext(); - Metadata *Vals[] = { - MDString::get(Ctx, "llvm.loop.intel.pipelining.enable"), - ConstantAsMetadata::get(ConstantInt::get( - llvm::Type::getInt32Ty(Ctx), 0))}; + Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.intel.pipelining.enable"), + ConstantAsMetadata::get( + ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 0))}; LoopProperties.push_back(MDNode::get(Ctx, Vals)); } diff --git a/clang/test/CodeGenSYCL/intel-fpga-loops.cpp b/clang/test/CodeGenSYCL/intel-fpga-loops.cpp index 9a049d5993f17..0556feadcf7a2 100644 --- a/clang/test/CodeGenSYCL/intel-fpga-loops.cpp +++ b/clang/test/CodeGenSYCL/intel-fpga-loops.cpp @@ -17,9 +17,8 @@ void disable_loop_pipelining() { int a[10]; // CHECK: ![[MD_DLP]] = distinct !{![[MD_DLP]], ![[MD_dlp:[0-9]+]]} // CHECK-NEXT: ![[MD_dlp]] = !{!"llvm.loop.intel.pipelining.enable", i32 0} - [[intelfpga::disable_loop_pipelining]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::disable_loop_pipelining]] for (int i = 0; i != 10; ++i) + a[i] = 0; } template @@ -57,19 +56,16 @@ void loop_coalesce() { int a[10]; // CHECK: ![[MD_LC]] = distinct !{![[MD_LC]], ![[MD_loop_coalesce:[0-9]+]]} // CHECK-NEXT: ![[MD_loop_coalesce]] = !{!"llvm.loop.coalesce.count", i32 2} - [[intelfpga::loop_coalesce(A)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::loop_coalesce(A)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // CHECK: ![[MD_LC_2]] = distinct !{![[MD_LC_2]], ![[MD_loop_coalesce_2:[0-9]+]]} // CHECK-NEXT: ![[MD_loop_coalesce_2]] = !{!"llvm.loop.coalesce.count", i32 4} - [[intelfpga::loop_coalesce(4)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::loop_coalesce(4)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // CHECK: ![[MD_LC_3]] = distinct !{![[MD_LC_3]], ![[MD_loop_coalesce_3:[0-9]+]]} // CHECK-NEXT: ![[MD_loop_coalesce_3]] = !{!"llvm.loop.coalesce.enable"} - [[intelfpga::loop_coalesce]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::loop_coalesce]] for (int i = 0; i != 10; ++i) + a[i] = 0; } template @@ -77,14 +73,12 @@ void max_interleaving() { int a[10]; // CHECK: ![[MD_MI]] = distinct !{![[MD_MI]], ![[MD_max_interleaving:[0-9]+]]} // CHECK-NEXT: ![[MD_max_interleaving]] = !{!"llvm.loop.max_interleaving.count", i32 3} - [[intelfpga::max_interleaving(A)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_interleaving(A)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // CHECK: ![[MD_MI_2]] = distinct !{![[MD_MI_2]], ![[MD_max_interleaving_2:[0-9]+]]} // CHECK-NEXT: ![[MD_max_interleaving_2]] = !{!"llvm.loop.max_interleaving.count", i32 2} - [[intelfpga::max_interleaving(2)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_interleaving(2)]] for (int i = 0; i != 10; ++i) + a[i] = 0; } template @@ -92,14 +86,12 @@ void speculated_iterations() { int a[10]; // CHECK: ![[MD_SI]] = distinct !{![[MD_SI]], ![[MD_speculated_iterations:[0-9]+]]} // CHECK-NEXT: ![[MD_speculated_iterations]] = !{!"llvm.loop.intel.speculated.iterations.count", i32 4} - [[intelfpga::speculated_iterations(A)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::speculated_iterations(A)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // CHECK: ![[MD_SI_2]] = distinct !{![[MD_SI_2]], ![[MD_speculated_iterations_2:[0-9]+]]} // CHECK-NEXT: ![[MD_speculated_iterations_2]] = !{!"llvm.loop.intel.speculated.iterations.count", i32 5} - [[intelfpga::speculated_iterations(5)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::speculated_iterations(5)]] for (int i = 0; i != 10; ++i) + a[i] = 0; } template diff --git a/clang/test/SemaSYCL/intel-fpga-loops.cpp b/clang/test/SemaSYCL/intel-fpga-loops.cpp index fa8a8832d442d..71709816b217b 100644 --- a/clang/test/SemaSYCL/intel-fpga-loops.cpp +++ b/clang/test/SemaSYCL/intel-fpga-loops.cpp @@ -63,38 +63,31 @@ void boo() { a[i] = 0; // expected-warning@+1 {{'disable_loop_pipelining' attribute takes no more than 0 arguments - attribute ignored}} - [[intelfpga::disable_loop_pipelining(0)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::disable_loop_pipelining(0)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-warning@+1 {{'loop_coalesce' attribute takes no more than 1 argument - attribute ignored}} - [[intelfpga::loop_coalesce(2,3)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::loop_coalesce(2, 3)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-warning@+1 {{'max_interleaving' attribute takes at least 1 argument - attribute ignored}} - [[intelfpga::max_interleaving]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_interleaving]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-warning@+1 {{'max_interleaving' attribute takes no more than 1 argument - attribute ignored}} - [[intelfpga::max_interleaving(2,4)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_interleaving(2, 4)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-warning@+1 {{'speculated_iterations' attribute takes at least 1 argument - attribute ignored}} - [[intelfpga::speculated_iterations]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::speculated_iterations]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-warning@+1 {{'speculated_iterations' attribute takes no more than 1 argument - attribute ignored}} - [[intelfpga::speculated_iterations(1,2)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::speculated_iterations(1, 2)]] for (int i = 0; i != 10; ++i) + a[i] = 0; } // Test for incorrect argument value for Intel FPGA loop attributes void goo() { int a[10]; // no diagnostics are expected - [[intelfpga::disable_loop_pipelining]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::disable_loop_pipelining]] for (int i = 0; i != 10; ++i) + a[i] = 0; // no diagnostics are expected [[intelfpga::max_concurrency(0)]] for (int i = 0; i != 10; ++i) @@ -108,21 +101,17 @@ void goo() { for (int i = 0; i != 10; ++i) a[i] = 0; // expected-error@+1 {{'max_concurrency' attribute requires a non-negative integral compile time constant expression}} - [[intelfpga::max_concurrency(-1)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_concurrency(-1)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'loop_coalesce' attribute requires a positive integral compile time constant expression}} - [[intelfpga::loop_coalesce(0)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::loop_coalesce(0)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'max_interleaving' attribute requires a non-negative integral compile time constant expression}} - [[intelfpga::max_interleaving(-1)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_interleaving(-1)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'speculated_iterations' attribute requires a non-negative integral compile time constant expression}} - [[intelfpga::speculated_iterations(-1)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::speculated_iterations(-1)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{unknown argument to 'ivdep'. Expected integer or array variable}} [[intelfpga::ivdep("test123")]] for (int i = 0; i != 10; ++i) @@ -132,21 +121,17 @@ void goo() { for (int i = 0; i != 10; ++i) a[i] = 0; // expected-error@+1 {{'max_concurrency' attribute requires an integer constant}} - [[intelfpga::max_concurrency("test123")]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_concurrency("test123")]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'loop_coalesce' attribute requires an integer constant}} - [[intelfpga::loop_coalesce("test123")]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::loop_coalesce("test123")]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'max_interleaving' attribute requires an integer constant}} - [[intelfpga::max_interleaving("test123")]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_interleaving("test123")]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'speculated_iterations' attribute requires an integer constant}} - [[intelfpga::speculated_iterations("test123")]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::speculated_iterations("test123")]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{unknown argument to 'ivdep'. Expected integer or array variable}} [[intelfpga::ivdep("test123")]] for (int i = 0; i != 10; ++i) a[i] = 0; @@ -197,32 +182,27 @@ void zoo() { [[intelfpga::ii(2)]] // expected-error@-1 {{duplicate Intel FPGA loop attribute 'ii'}} [[intelfpga::max_concurrency(2)]] - [[intelfpga::ii(2)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::ii(2)]] for (int i = 0; i != 10; ++i) + a[i] = 0; [[intelfpga::disable_loop_pipelining]] // expected-error@-1 {{duplicate Intel FPGA loop attribute 'disable_loop_pipelining'}} - [[intelfpga::disable_loop_pipelining]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::disable_loop_pipelining]] for (int i = 0; i != 10; ++i) + a[i] = 0; [[intelfpga::loop_coalesce(2)]] // expected-error@-1 {{duplicate Intel FPGA loop attribute 'loop_coalesce'}} [[intelfpga::max_interleaving(1)]] - [[intelfpga::loop_coalesce]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::loop_coalesce]] for (int i = 0; i != 10; ++i) + a[i] = 0; [[intelfpga::max_interleaving(1)]] // expected-error@-1 {{duplicate Intel FPGA loop attribute 'max_interleaving'}} [[intelfpga::speculated_iterations(1)]] - [[intelfpga::max_interleaving(4)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_interleaving(4)]] for (int i = 0; i != 10; ++i) + a[i] = 0; [[intelfpga::speculated_iterations(1)]] // expected-error@-1 {{duplicate Intel FPGA loop attribute 'speculated_iterations'}} [[intelfpga::loop_coalesce]] - [[intelfpga::speculated_iterations(2)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::speculated_iterations(2)]] for (int i = 0; i != 10; ++i) + a[i] = 0; [[intelfpga::ivdep]] // expected-warning@+2 {{ignoring redundant Intel FPGA loop attribute 'ivdep': safelen INF >= safelen INF}} @@ -285,34 +265,28 @@ void woo() { int a[10]; // no diagnostics are expected [[intelfpga::disable_loop_pipelining]] - [[intelfpga::loop_coalesce]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::loop_coalesce]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'disable_loop_pipelining' and 'max_interleaving' attributes are not compatible}} [[intelfpga::disable_loop_pipelining]] - [[intelfpga::max_interleaving(0)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_interleaving(0)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'disable_loop_pipelining' and 'speculated_iterations' attributes are not compatible}} [[intelfpga::speculated_iterations(0)]] - [[intelfpga::disable_loop_pipelining]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::disable_loop_pipelining]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'disable_loop_pipelining' and 'max_concurrency' attributes are not compatible}} [[intelfpga::disable_loop_pipelining]] - [[intelfpga::max_concurrency(0)]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::max_concurrency(0)]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'disable_loop_pipelining' and 'ii' attributes are not compatible}} [[intelfpga::ii(10)]] - [[intelfpga::disable_loop_pipelining]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::disable_loop_pipelining]] for (int i = 0; i != 10; ++i) + a[i] = 0; // expected-error@+1 {{'disable_loop_pipelining' and 'ivdep' attributes are not compatible}} [[intelfpga::disable_loop_pipelining]] - [[intelfpga::ivdep]] - for (int i = 0; i != 10; ++i) - a[i] = 0; + [[intelfpga::ivdep]] for (int i = 0; i != 10; ++i) + a[i] = 0; } template From 89e1d1e6f7a3503adb975ce7fcf182fb19c2dc13 Mon Sep 17 00:00:00 2001 From: Viktoria Maksimova Date: Tue, 24 Mar 2020 14:54:15 +0300 Subject: [PATCH 3/4] Apply suggestions Signed-off-by: Viktoria Maksimova --- clang/include/clang/Basic/AttrDocs.td | 8 ++++---- clang/lib/CodeGen/CGLoopInfo.cpp | 7 ------- clang/lib/Sema/SemaStmtAttr.cpp | 3 +-- clang/test/SemaSYCL/intel-fpga-loops.cpp | 10 +++++----- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 79e1f2a44077e..d445d7c0ad991 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2096,7 +2096,7 @@ def SYCLIntelFPGALoopCoalesceAttrDocs : Documentation { let Content = [{ This attribute applies to a loop. Indicates that the loop nest should be coalesced into a single loop without affecting functionality. Parameter N is -optional. If specified, it must be a positive integer, and indicates how many +optional. If specified, it shall be a positive integer, and indicates how many of the nested loop levels should be coalesced. }]; } @@ -2120,7 +2120,7 @@ This attribute applies to a loop. Places a maximum limit N on the number of interleaved invocations of an inner loop by an outer loop (note, this does not mean that this attribute can only be applied to inner loops in user code - outer loops in user code may still be contained in an implicit loop due to NDRange). -Parameter N is mandatory, and may either b 0, or a positive integer. Cannot be +Parameter N is mandatory, and shall be non-negative integer. Cannot be used on the same loop in conjunction with disable_loop_pipelining. }]; } @@ -2130,8 +2130,8 @@ def SYCLIntelFPGASpeculatedIterationsAttrDocs : Documentation { let Heading = "speculated_iterations"; let Content = [{ This attribute applies to a loop. Specifies the number of concurrent speculated -iterations that will be in flight (iterations that are in flight where the exit -condition for that iteration has not yet been evaluated) for a loop invocation. +iterations that will be in flight for a loop invocation (i.e. the exit +condition for these iterations will not have been evaluated yet). Parameter N is mandatory, and may either be 0, or a positive integer. Cannot be used on the same loop in conjunction with disable_loop_pipelining. }]; diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index e822cc873b52d..3f990f270cd1d 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -507,7 +507,6 @@ MDNode *LoopInfo::createMetadata( // Setting ii attribute with an initiation interval if (Attrs.SYCLIInterval > 0) { - LLVMContext &Ctx = Header->getContext(); Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.ii.count"), ConstantAsMetadata::get(ConstantInt::get( llvm::Type::getInt32Ty(Ctx), Attrs.SYCLIInterval))}; @@ -516,7 +515,6 @@ MDNode *LoopInfo::createMetadata( // Setting max_concurrency attribute with number of threads if (Attrs.SYCLMaxConcurrencyEnable) { - LLVMContext &Ctx = Header->getContext(); Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.max_concurrency.count"), ConstantAsMetadata::get(ConstantInt::get( llvm::Type::getInt32Ty(Ctx), @@ -525,13 +523,11 @@ MDNode *LoopInfo::createMetadata( } if (Attrs.SYCLLoopCoalesceEnable) { - LLVMContext &Ctx = Header->getContext(); Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.coalesce.enable")}; LoopProperties.push_back(MDNode::get(Ctx, Vals)); } if (Attrs.SYCLLoopCoalesceNLevels > 0) { - LLVMContext &Ctx = Header->getContext(); Metadata *Vals[] = { MDString::get(Ctx, "llvm.loop.coalesce.count"), ConstantAsMetadata::get(ConstantInt::get( @@ -540,7 +536,6 @@ MDNode *LoopInfo::createMetadata( } if (Attrs.SYCLLoopPipeliningDisable) { - LLVMContext &Ctx = Header->getContext(); Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.intel.pipelining.enable"), ConstantAsMetadata::get( ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 0))}; @@ -548,7 +543,6 @@ MDNode *LoopInfo::createMetadata( } if (Attrs.SYCLMaxInterleavingEnable) { - LLVMContext &Ctx = Header->getContext(); Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.max_interleaving.count"), ConstantAsMetadata::get(ConstantInt::get( llvm::Type::getInt32Ty(Ctx), @@ -557,7 +551,6 @@ MDNode *LoopInfo::createMetadata( } if (Attrs.SYCLSpeculatedIterationsEnable) { - LLVMContext &Ctx = Header->getContext(); Metadata *Vals[] = { MDString::get(Ctx, "llvm.loop.intel.speculated.iterations.count"), ConstantAsMetadata::get( diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index edf780b469481..941dcdcc3d441 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -559,8 +559,7 @@ static void CheckMutualExclusionSYCLLoopAttribute( LoopAttr2 = cast(I); if (LoopAttr && LoopAttr2) { S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) - << "'" + std::string(LoopAttr->getName()) + "'" - << "'" + std::string(LoopAttr2->getName()) + "'"; + << LoopAttr->getSpelling() << LoopAttr2->getSpelling(); } } } diff --git a/clang/test/SemaSYCL/intel-fpga-loops.cpp b/clang/test/SemaSYCL/intel-fpga-loops.cpp index 71709816b217b..a759a608ddf13 100644 --- a/clang/test/SemaSYCL/intel-fpga-loops.cpp +++ b/clang/test/SemaSYCL/intel-fpga-loops.cpp @@ -267,23 +267,23 @@ void woo() { [[intelfpga::disable_loop_pipelining]] [[intelfpga::loop_coalesce]] for (int i = 0; i != 10; ++i) a[i] = 0; - // expected-error@+1 {{'disable_loop_pipelining' and 'max_interleaving' attributes are not compatible}} + // expected-error@+1 {{disable_loop_pipelining and max_interleaving attributes are not compatible}} [[intelfpga::disable_loop_pipelining]] [[intelfpga::max_interleaving(0)]] for (int i = 0; i != 10; ++i) a[i] = 0; - // expected-error@+1 {{'disable_loop_pipelining' and 'speculated_iterations' attributes are not compatible}} + // expected-error@+1 {{disable_loop_pipelining and speculated_iterations attributes are not compatible}} [[intelfpga::speculated_iterations(0)]] [[intelfpga::disable_loop_pipelining]] for (int i = 0; i != 10; ++i) a[i] = 0; - // expected-error@+1 {{'disable_loop_pipelining' and 'max_concurrency' attributes are not compatible}} + // expected-error@+1 {{disable_loop_pipelining and max_concurrency attributes are not compatible}} [[intelfpga::disable_loop_pipelining]] [[intelfpga::max_concurrency(0)]] for (int i = 0; i != 10; ++i) a[i] = 0; - // expected-error@+1 {{'disable_loop_pipelining' and 'ii' attributes are not compatible}} + // expected-error@+1 {{disable_loop_pipelining and ii attributes are not compatible}} [[intelfpga::ii(10)]] [[intelfpga::disable_loop_pipelining]] for (int i = 0; i != 10; ++i) a[i] = 0; - // expected-error@+1 {{'disable_loop_pipelining' and 'ivdep' attributes are not compatible}} + // expected-error@+1 {{disable_loop_pipelining and ivdep attributes are not compatible}} [[intelfpga::disable_loop_pipelining]] [[intelfpga::ivdep]] for (int i = 0; i != 10; ++i) a[i] = 0; From 660d5d9efba3d9edeb36cc6568f65eba15d1ccd6 Mon Sep 17 00:00:00 2001 From: Viktoria Maksimova Date: Tue, 24 Mar 2020 17:49:20 +0300 Subject: [PATCH 4/4] Apply more suggestions Signed-off-by: Viktoria Maksimova --- clang/lib/CodeGen/CGLoopInfo.cpp | 2 ++ clang/test/SemaSYCL/intel-fpga-loops.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index 3f990f270cd1d..0f85c700aa442 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -535,6 +535,8 @@ MDNode *LoopInfo::createMetadata( LoopProperties.push_back(MDNode::get(Ctx, Vals)); } + // disable_loop_pipelining attribute corresponds to + // 'llvm.loop.intel.pipelining.enable, i32 0' metadata if (Attrs.SYCLLoopPipeliningDisable) { Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.intel.pipelining.enable"), ConstantAsMetadata::get( diff --git a/clang/test/SemaSYCL/intel-fpga-loops.cpp b/clang/test/SemaSYCL/intel-fpga-loops.cpp index a759a608ddf13..19111a163e127 100644 --- a/clang/test/SemaSYCL/intel-fpga-loops.cpp +++ b/clang/test/SemaSYCL/intel-fpga-loops.cpp @@ -261,7 +261,7 @@ void zoo() { } // Test for Intel FPGA loop attributes compatibility -void woo() { +void loop_attrs_compatibility() { int a[10]; // no diagnostics are expected [[intelfpga::disable_loop_pipelining]] @@ -364,7 +364,7 @@ int main() { boo(); goo(); zoo(); - woo(); + loop_attrs_compatibility(); ivdep_dependent<4, 2, 1>(); //expected-note@-1 +{{in instantiation of function template specialization}} ivdep_dependent<2, 4, -1>();