summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGLoopInfo.cpp37
-rw-r--r--clang/lib/Parse/ParseDecl.cpp4
-rw-r--r--clang/lib/Parse/ParseStmt.cpp18
-rw-r--r--clang/lib/Sema/SemaStmtAttr.cpp48
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
OpenPOWER on IntegriCloud