diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGLoopInfo.cpp | 37 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmtAttr.cpp | 48 |
4 files changed, 97 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index 0afe7dbb9f1..f10cfcfa7cb 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -115,20 +115,41 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, // Identify loop hint attributes from Attrs. for (const auto *Attr : Attrs) { const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr); + const OpenCLUnrollHintAttr *OpenCLHint = + dyn_cast<OpenCLUnrollHintAttr>(Attr); // Skip non loop hint attributes - if (!LH) + if (!LH && !OpenCLHint) { continue; + } - auto *ValueExpr = LH->getValue(); + LoopHintAttr::OptionType Option = LoopHintAttr::Unroll; + LoopHintAttr::LoopHintState State = LoopHintAttr::Disable; unsigned ValueInt = 1; - if (ValueExpr) { - llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx); - ValueInt = ValueAPS.getSExtValue(); - } + // Translate opencl_unroll_hint attribute argument to + // equivalent LoopHintAttr enums. + // OpenCL v2.0 s6.11.5: + // 0 - full unroll (no argument). + // 1 - disable unroll. + // other positive integer n - unroll by n. + if (OpenCLHint) { + ValueInt = OpenCLHint->getUnrollHint(); + if (ValueInt == 0) { + State = LoopHintAttr::Full; + } else if (ValueInt != 1) { + Option = LoopHintAttr::UnrollCount; + State = LoopHintAttr::Numeric; + } + } else if (LH) { + auto *ValueExpr = LH->getValue(); + if (ValueExpr) { + llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx); + ValueInt = ValueAPS.getSExtValue(); + } - LoopHintAttr::OptionType Option = LH->getOption(); - LoopHintAttr::LoopHintState State = LH->getState(); + Option = LH->getOption(); + State = LH->getState(); + } switch (State) { case LoopHintAttr::Disable: switch (Option) { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 64f00bfcfa5..24db6814b81 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -670,7 +670,7 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { } } -void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) { +void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) { // Treat these like attributes while (Tok.is(tok::kw___kernel)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); @@ -3098,7 +3098,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // OpenCL single token adornments. case tok::kw___kernel: - ParseOpenCLAttributes(DS.getAttributes()); + ParseOpenCLKernelAttributes(DS.getAttributes()); continue; // Nullability type specifiers. diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 71904f0cc22..085319f9bdd 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -107,6 +107,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, ParsedAttributesWithRange Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true); + if (!MaybeParseOpenCLUnrollHintAttribute(Attrs)) + return StmtError(); StmtResult Res = ParseStatementOrDeclarationAfterAttributes( Stmts, Allowed, TrailingElseLoc, Attrs); @@ -2208,3 +2210,19 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { } Braces.consumeClose(); } + +bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) { + MaybeParseGNUAttributes(Attrs); + + if (Attrs.empty()) + return true; + + if (Attrs.getList()->getKind() != AttributeList::AT_OpenCLUnrollHint) + return true; + + if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) { + Diag(Tok, diag::err_opencl_unroll_hint_on_non_loop); + return false; + } + return true; +} diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 984bd078fa0..0279441ee20 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -203,6 +203,52 @@ CheckForIncompatibleAttributes(Sema &S, } } +static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A, + SourceRange Range) { + // OpenCL v2.0 s6.11.5 - opencl_unroll_hint can have 0 arguments (compiler + // determines unrolling factor) or 1 argument (the unroll factor provided + // by the user). + + if (S.getLangOpts().OpenCLVersion < 200) { + S.Diag(A.getLoc(), diag::err_attribute_requires_opencl_version) + << A.getName() << "2.0"; + return nullptr; + } + + unsigned NumArgs = A.getNumArgs(); + + if (NumArgs > 1) { + S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A.getName() + << 1; + return nullptr; + } + + unsigned UnrollFactor = 0; + + if (NumArgs == 1) { + Expr *E = A.getArgAsExpr(0); + llvm::APSInt ArgVal(32); + + if (!E->isIntegerConstantExpr(ArgVal, S.Context)) { + S.Diag(A.getLoc(), diag::err_attribute_argument_type) + << A.getName() << AANT_ArgumentIntegerConstant << E->getSourceRange(); + return nullptr; + } + + int Val = ArgVal.getSExtValue(); + + if (Val <= 0) { + S.Diag(A.getRange().getBegin(), + diag::err_attribute_requires_positive_integer) + << A.getName(); + return nullptr; + } + UnrollFactor = Val; + } + + return OpenCLUnrollHintAttr::CreateImplicit(S.Context, UnrollFactor); +} + static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, SourceRange Range) { switch (A.getKind()) { @@ -215,6 +261,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, return handleFallThroughAttr(S, St, A, Range); case AttributeList::AT_LoopHint: return handleLoopHintAttr(S, St, A, Range); + case AttributeList::AT_OpenCLUnrollHint: + return handleOpenCLUnrollHint(S, St, A, Range); default: // if we're here, then we parsed a known attribute, but didn't recognize // it as a statement attribute => it is declaration attribute |