Hi nadav, aschwaighofer, rsmith,
So, I have progressed a little bit, but I got stuck again on something a little
more fundamental: where in Stmt to store the vectorizer information to add as a
metadata later?
I've done:
1. Added the PragmaVectorizeHandler to read the #pragma and create a Token
with the information
2. Added HandlePragmaVectorize and ActOnPragmaVectorize to transform this into
Sema's context
3. Added VectorizeTraits to Stmt, so that loops, functions and blocks can get
their metadata
My assumptions:
1. Every time a pragma is encountered, the pragma handler is called, and
Sema's vectorizer context gets filled with data
2. Whenever the loop/function/block which the pragma is associated
(ActOnCompoundStmt), I should check this statement, populate the vectorizer
traits (VectorizerTraitsBitfields), so when the IR is lowered, I know what
metadata to fill in.
My questions are:
1. Are my assumptions correct?
2. Is VectorizerTraitsBitfields the correct way to pass this information down?
Thanks!
PS: For now, I'm not allowing two #pragma lines to refer to the same
loop/block, but this could become important, and will depend on the syntax of
the #pragma, which I'll handle later.
http://llvm-reviews.chandlerc.com/D2420
Files:
include/clang/AST/Stmt.h
include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/TokenKinds.def
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
lib/Parse/ParsePragma.cpp
lib/Parse/ParsePragma.h
lib/Parse/ParseStmt.cpp
lib/Parse/Parser.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaAttr.cpp
lib/Sema/SemaStmt.cpp
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h
+++ include/clang/AST/Stmt.h
@@ -286,6 +286,22 @@
unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
};
+ class VectorizerTraitsBitfields {
+ unsigned : NumExprBits;
+
+ /// \brief Forced enable.
+ unsigned Enabled : 1;
+
+ /// \brief Forced disable.
+ unsigned Disabled : 1;
+
+ /// \brief Forced width (in log(bytes), up to 64 - Width = 2^WidthFactor).
+ unsigned WidthFactor : 3;
+
+ /// \brief Forced disable (in log(lanes), up to 16 - Same as Width).
+ unsigned UnrollFactor : 2;
+ };
+
union {
// FIXME: this is wasteful on 64-bit platforms.
void *Aligner;
@@ -304,6 +320,7 @@
ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
InitListExprBitfields InitListExprBits;
TypeTraitExprBitfields TypeTraitExprBits;
+ VectorizerTraitsBitfields VectorizerTraitsBits;
};
friend class ASTStmtReader;
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -788,6 +788,8 @@
"missing '(' after '#pragma %0' - ignoring">;
def warn_pragma_expected_rparen : Warning<
"missing ')' after '#pragma %0' - ignoring">;
+def err_pragma_expected_numeric_constant : Error<
+ "expected numeric constant in #pragma %0">;
def warn_pragma_expected_identifier : Warning<
"expected identifier in '#pragma %0' - ignored">;
def warn_pragma_ms_struct : Warning<
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def
+++ include/clang/Basic/TokenKinds.def
@@ -681,6 +681,9 @@
ANNOTATION(pragma_openmp)
ANNOTATION(pragma_openmp_end)
+// Annotation for #pragma vectorize ...
+ANNOTATION(pragma_vectorize)
+
// Annotations for module import translated from #include etc.
ANNOTATION(module_include)
ANNOTATION(module_begin)
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -152,6 +152,7 @@
OwningPtr<PragmaHandler> OpenCLExtensionHandler;
OwningPtr<CommentHandler> CommentSemaHandler;
OwningPtr<PragmaHandler> OpenMPHandler;
+ OwningPtr<PragmaHandler> VectorizeHandler;
OwningPtr<PragmaHandler> MSCommentHandler;
OwningPtr<PragmaHandler> MSDetectMismatchHandler;
@@ -464,6 +465,10 @@
void HandlePragmaOpenCLExtension();
/// \brief Handle the annotation token produced for
+ /// #pragma vectorize...
+ void HandlePragmaVectorize();
+
+ /// \brief Handle the annotation token produced for
/// #pragma clang __debug captured
StmtResult HandlePragmaCaptured();
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -266,6 +266,21 @@
/// VisContext - Manages the stack for \#pragma GCC visibility.
void *VisContext; // Really a "PragmaVisStack*"
+ enum PragmaVectKind {
+ PVK_ENABLE, // #pragma vectorize enable/disable
+ PVK_WIDTH, // #pragma vectorize width(N)
+ PVK_UNROLL // #pragma vectorize unroll(N)
+ };
+
+ struct PragmaVectContext {
+ PragmaVectKind Kind;
+ bool Enable;
+ Token Value;
+ SourceLocation Loc;
+ };
+ /// VectorizeContext - Manages \#pragma vectorize context
+ PragmaVectContext *VectorizeContext;
+
/// \brief Flag indicating if Sema is building a recovery call expression.
///
/// This flag is used to avoid building recovery call expressions
@@ -6952,6 +6967,10 @@
PCK_User // #pragma comment(user, ...)
};
+ /// ActOnPragmaVectorize - Called on well formed \#pragma vectorize.
+ void ActOnPragmaVectorize(PragmaVectKind Kind, bool Enable, Token &Value,
+ SourceLocation PragmaLoc);
+
/// ActOnPragmaPack - Called on well formed \#pragma pack(...).
void ActOnPragmaPack(PragmaPackKind Kind,
IdentifierInfo *Name,
@@ -7033,6 +7052,9 @@
/// FreeVisContext - Deallocate and null out VisContext.
void FreeVisContext();
+ /// FreeVectorizeContext - Deallocate and null out VectorizeContext.
+ void FreeVectorizeContext();
+
/// AddCFAuditedAttribute - Check whether we're currently within
/// '\#pragma clang arc_cf_code_audited' and, if so, consider adding
/// the appropriate attribute.
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -180,7 +180,24 @@
}
}
-
+void Parser::HandlePragmaVectorize() {
+ assert(Tok.is(tok::annot_pragma_vectorize));
+ Sema::PragmaVectContext *Info =
+ static_cast<Sema::PragmaVectContext *>(Tok.getAnnotationValue());
+ SourceLocation PragmaLoc = ConsumeToken();
+ if (Info->Kind == Sema::PVK_WIDTH ||
+ Info->Kind == Sema::PVK_UNROLL) {
+ ExprResult Value;
+ if (Info->Value.is(tok::numeric_constant)) {
+ Value = Actions.ActOnNumericConstant(Info->Value);
+ if (Value.isInvalid())
+ return;
+ } else
+ return;
+ }
+ Actions.ActOnPragmaVectorize(Info->Kind, Info->Enable, Info->Value,
+ PragmaLoc);
+}
// #pragma GCC visibility comes in two variants:
// 'push' '(' [visibility] ')'
@@ -799,6 +816,85 @@
/*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
}
+/// \brief Handle '#pragma vectorize ...'.
+///
+void
+PragmaVectorizeHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &FirstTok) {
+ Token Tok;
+ PP.LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
+ "VECTORIZE";
+ return;
+ }
+
+ IdentifierInfo *ename = Tok.getIdentifierInfo();
+ SourceLocation Loc = Tok.getLocation();
+ Sema::PragmaVectContext *Info =
+ (Sema::PragmaVectContext*) PP.getPreprocessorAllocator().Allocate(
+ sizeof(Sema::PragmaVectContext), llvm::alignOf<Sema::PragmaVectContext>());
+ new (Info) Sema::PragmaVectContext();
+
+ if (ename->isStr("enable")) {
+ Info->Kind = Sema::PVK_ENABLE;
+ Info->Enable = true;
+ } else if (ename->isStr("disable")) {
+ Info->Kind = Sema::PVK_ENABLE;
+ Info->Enable = false;
+ } else if (ename->isStr("width")) {
+ Info->Kind = Sema::PVK_WIDTH;
+ Info->Enable = true;
+ } else if (ename->isStr("unroll")) {
+ Info->Kind = Sema::PVK_UNROLL;
+ Info->Enable = true;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
+ "VECTORIZE";
+ return;
+ }
+
+ // Parse argument for witdh (N), unroll (N)
+ if (Info->Kind == Sema::PVK_UNROLL || Info->Kind == Sema::PVK_WIDTH) {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << ename;
+ return;
+ }
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::numeric_constant)) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_expected_numeric_constant)
+ << ename;
+ return;
+ }
+ Info->Value = Tok;
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << ename;
+ return;
+ }
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eod)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
+ "VECTORIZE";
+ return;
+ }
+
+ Token *Toks =
+ (Token*) PP.getPreprocessorAllocator().Allocate(
+ sizeof(Token), llvm::alignOf<Token>());
+ new (Toks) Token();
+ Toks[0].startToken();
+ Toks[0].setKind(tok::annot_pragma_vectorize);
+ Toks[0].setLocation(Loc);
+ Toks[0].setAnnotationValue(static_cast<void*>(Info));
+ PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
+ /*OwnsTokens=*/false);
+}
+
/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
///
/// The syntax is:
Index: lib/Parse/ParsePragma.h
===================================================================
--- lib/Parse/ParsePragma.h
+++ lib/Parse/ParsePragma.h
@@ -113,6 +113,14 @@
Token &FirstToken);
};
+/// PragmaVectorizeHandler - "\#pragma vectorize ...".
+class PragmaVectorizeHandler : public PragmaHandler {
+public:
+ PragmaVectorizeHandler() : PragmaHandler("vectorize") { }
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
/// PragmaCommentHandler - "\#pragma comment ...".
class PragmaCommentHandler : public PragmaHandler {
public:
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -345,6 +345,10 @@
ProhibitAttributes(Attrs);
return ParseOpenMPDeclarativeOrExecutableDirective();
+ case tok::annot_pragma_vectorize:
+ ProhibitAttributes(Attrs);
+ HandlePragmaVectorize();
+ return StmtEmpty();
}
// If we reached this code, the statement must end in a semicolon.
@@ -826,6 +830,9 @@
case tok::annot_pragma_fp_contract:
HandlePragmaFPContract();
break;
+ case tok::annot_pragma_vectorize:
+ HandlePragmaVectorize();
+ break;
default:
checkForPragmas = false;
break;
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -109,6 +109,9 @@
PP.AddPragmaHandler(MSDetectMismatchHandler.get());
}
+ VectorizeHandler.reset(new PragmaVectorizeHandler());
+ PP.AddPragmaHandler(VectorizeHandler.get());
+
CommentSemaHandler.reset(new ActionCommentHandler(actions));
PP.addCommentHandler(CommentSemaHandler.get());
@@ -479,6 +482,9 @@
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
FPContractHandler.reset();
+ PP.RemovePragmaHandler(VectorizeHandler.get());
+ VectorizeHandler.reset();
+
PP.removeCommentHandler(CommentSemaHandler.get());
PP.clearCodeCompletionHandler();
@@ -693,6 +699,9 @@
case tok::annot_pragma_openmp:
ParseOpenMPDeclarativeDirective();
return DeclGroupPtrTy();
+ case tok::annot_pragma_vectorize:
+ HandlePragmaVectorize();
+ return DeclGroupPtrTy();
case tok::semi:
// Either a C++11 empty-declaration or attribute-declaration.
SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -76,7 +76,7 @@
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
CollectStats(false), CodeCompleter(CodeCompleter),
CurContext(0), OriginalLexicalContext(0),
- PackContext(0), MSStructPragmaOn(false), VisContext(0),
+ PackContext(0), MSStructPragmaOn(false), VisContext(0), VectorizeContext(0),
IsBuildingRecoveryCallExpr(false),
ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
@@ -184,6 +184,7 @@
delete I->second;
if (PackContext) FreePackedContext();
if (VisContext) FreeVisContext();
+ if (VectorizeContext) FreeVectorizeContext();
delete TheTargetAttributesSema;
MSStructPragmaOn = false;
// Kill all the active scopes.
Index: lib/Sema/SemaAttr.cpp
===================================================================
--- lib/Sema/SemaAttr.cpp
+++ lib/Sema/SemaAttr.cpp
@@ -260,6 +260,28 @@
}
}
+void Sema::ActOnPragmaVectorize(PragmaVectKind Kind, bool Enable, Token &Value,
+ SourceLocation PragmaLoc) {
+ // There can be only one
+ if (VectorizeContext) FreeVectorizeContext();
+
+ // Update the current metadata to be used in the next lexical block
+ PragmaVectContext* Context = new (VectorizeContext) PragmaVectContext;
+ Context->Kind = Kind;
+ Context->Enable = Enable;
+ Context->Value = Value;
+ Context->Loc = PragmaLoc;
+
+ // Lexical block actions interested in this metadata should check for
+ // this context and apply it where the vectorizer will look for.
+}
+
+/// FreeVectorizeContext - Deallocate and null out VectorizeContext.
+void Sema::FreeVectorizeContext() {
+ delete static_cast<PragmaVectContext*>(VectorizeContext);
+ VectorizeContext = 0;
+}
+
void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
MSStructPragmaOn = (Kind == PMSST_ON);
}
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -331,7 +331,13 @@
DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]);
}
- return Owned(new (Context) CompoundStmt(Context, Elts, L, R));
+ CompoundStmt* Stmt = new (Context) CompoundStmt(Context, Elts, L, R);
+
+ // Propagates #pragma vectorize annotation
+ if (VectorizeContext) {
+ // FIXME: Add here the logic to set the flags
+ }
+ return Owned(Stmt);
}
StmtResult
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits