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

Reply via email to