SjoerdMeijer created this revision.

https://reviews.llvm.org/D64744

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CGLoopInfo.cpp
  clang/lib/CodeGen/CGLoopInfo.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/CodeGenCXX/pragma-tail-predicate.cpp
  clang/test/Parser/pragma-tail-predicate.cpp

Index: clang/test/Parser/pragma-tail-predicate.cpp
===================================================================
--- /dev/null
+++ clang/test/Parser/pragma-tail-predicate.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+// Note that this puts the expected lines before the directives to work around
+// limitations in the -verify mode.
+
+int foo(int *a, int N) {
+  int sum = 0;
+
+  #pragma tail_predicate
+  for (int i = 0; i < N; i++)
+    sum += a[i];
+
+
+  #pragma tail_predicate
+  /* expected-error {{expected a for, while, or do-while loop to follow '#pragma tail_predicate'}} */ int b;
+
+  return sum;
+}
Index: clang/test/CodeGenCXX/pragma-tail-predicate.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/pragma-tail-predicate.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple arm-none-eabi -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK:  !{!"llvm.loop.tailpredicate"}
+
+int foo(int *a, int N) {
+  int sum = 0;
+
+  #pragma tail_predicate
+  for (int i = 0; i < N; i++)
+    sum += a[i];
+
+  return sum;
+}
Index: clang/lib/Sema/SemaStmtAttr.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAttr.cpp
+++ clang/lib/Sema/SemaStmtAttr.cpp
@@ -85,6 +85,7 @@
   StringRef PragmaName =
       llvm::StringSwitch<StringRef>(PragmaNameLoc->Ident->getName())
           .Cases("unroll", "nounroll", "unroll_and_jam", "nounroll_and_jam",
+                 "tail_predicate",
                  PragmaNameLoc->Ident->getName())
           .Default("clang loop");
 
@@ -118,6 +119,8 @@
       SetHints(LoopHintAttr::Unroll, LoopHintAttr::Enable);
   } else if (PragmaName == "nounroll_and_jam") {
     SetHints(LoopHintAttr::UnrollAndJam, LoopHintAttr::Disable);
+  } else if (PragmaName == "tail_predicate") {
+    SetHints(LoopHintAttr::TailPredicate, LoopHintAttr::Enable);
   } else if (PragmaName == "unroll_and_jam") {
     // #pragma unroll_and_jam N
     if (ValueExpr)
@@ -189,7 +192,8 @@
     const LoopHintAttr *StateAttr;
     const LoopHintAttr *NumericAttr;
   } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr},
-                   {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};
+                   {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr},
+                   {nullptr, nullptr}};
 
   for (const auto *I : Attrs) {
     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
@@ -205,7 +209,8 @@
       Unroll,
       UnrollAndJam,
       Distribute,
-      Pipeline
+      Pipeline,
+      TailPredicate
     } Category;
     switch (Option) {
     case LoopHintAttr::Vectorize:
@@ -232,6 +237,9 @@
     case LoopHintAttr::PipelineInitiationInterval:
       Category = Pipeline;
       break;
+    case LoopHintAttr::TailPredicate:
+      Category = TailPredicate;
+      break;
     };
 
     assert(Category < sizeof(HintAttrs) / sizeof(HintAttrs[0]));
@@ -240,6 +248,7 @@
     if (Option == LoopHintAttr::Vectorize ||
         Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
         Option == LoopHintAttr::UnrollAndJam ||
+        Option == LoopHintAttr::TailPredicate ||
         Option == LoopHintAttr::PipelineDisabled ||
         Option == LoopHintAttr::Distribute) {
       // Enable|Disable|AssumeSafety hint.  For example, vectorize(enable).
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -372,6 +372,10 @@
       llvm::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
   PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
 
+  TailPredicateHintHandler =
+      llvm::make_unique<PragmaUnrollHintHandler>("tail_predicate");
+  PP.AddPragmaHandler(TailPredicateHintHandler.get());
+
   NoUnrollAndJamHintHandler =
       llvm::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
   PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
@@ -479,6 +483,9 @@
   PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
   UnrollAndJamHintHandler.reset();
 
+  PP.RemovePragmaHandler(TailPredicateHintHandler.get());
+  TailPredicateHintHandler.reset();
+
   PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
   NoUnrollAndJamHintHandler.reset();
 
@@ -1006,17 +1013,13 @@
 } // end anonymous namespace
 
 static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
-  std::string PragmaString;
-  if (PragmaName.getIdentifierInfo()->getName() == "loop") {
-    PragmaString = "clang loop ";
-    PragmaString += Option.getIdentifierInfo()->getName();
-  } else if (PragmaName.getIdentifierInfo()->getName() == "unroll_and_jam") {
-    PragmaString = "unroll_and_jam";
-  } else {
-    assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
-           "Unexpected pragma name");
-    PragmaString = "unroll";
-  }
+  std::string PragmaString = PragmaName.getIdentifierInfo()->getName();
+  PragmaString = llvm::StringSwitch<std::string>(PragmaString)
+               .Case("loop", std::string("clang loop ") + PragmaString)
+               .Case("unroll_and_jam", PragmaString)
+               .Case("unroll", PragmaString)
+               .Default("");
+  assert(PragmaString.size() && "Unexpected pragma name");
   return PragmaString;
 }
 
@@ -1041,12 +1044,12 @@
 
   // Return a valid hint if pragma unroll or nounroll were specified
   // without an argument.
-  bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
-  bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
-  bool PragmaUnrollAndJam = PragmaNameInfo->getName() == "unroll_and_jam";
-  bool PragmaNoUnrollAndJam = PragmaNameInfo->getName() == "nounroll_and_jam";
-  if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll || PragmaUnrollAndJam ||
-                       PragmaNoUnrollAndJam)) {
+  const bool LoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
+                            .Cases("unroll", "nounroll", "unroll_and_jam",
+                                   "nounroll_and_jam", "tail_predicate", true)
+                            .Default(false);
+
+  if (Toks.empty() && LoopHint) {
     ConsumeAnnotationToken();
     Hint.Range = Info->PragmaName.getLocation();
     return true;
Index: clang/lib/CodeGen/CGLoopInfo.h
===================================================================
--- clang/lib/CodeGen/CGLoopInfo.h
+++ clang/lib/CodeGen/CGLoopInfo.h
@@ -51,6 +51,9 @@
   /// Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full).
   LVEnableState UnrollAndJamEnable;
 
+  /// Value for llvm.loop.tailpredicate metadata
+  LVEnableState TailPredicateEnable;
+
   /// Value for llvm.loop.vectorize.width metadata.
   unsigned VectorizeWidth;
 
@@ -162,6 +165,11 @@
   createFullUnrollMetadata(const LoopAttributes &Attrs,
                            llvm::ArrayRef<llvm::Metadata *> LoopProperties,
                            bool &HasUserTransforms);
+
+  llvm::MDNode *
+  createTailPredicateMetadata(const LoopAttributes &Attrs,
+                              llvm::ArrayRef<llvm::Metadata *> LoopProperties,
+                              bool &HasUserTransforms);
   /// @}
 
   /// Create a LoopID for this loop, including transformation-unspecific
@@ -237,6 +245,12 @@
     StagedAttrs.UnrollEnable = State;
   }
 
+
+  void setTailPredicateState(const LoopAttributes::LVEnableState &State) {
+    StagedAttrs.TailPredicateEnable = State;
+  }
+
+
   /// Set the next pushed loop unroll_and_jam state.
   void setUnrollAndJamState(const LoopAttributes::LVEnableState &State) {
     StagedAttrs.UnrollAndJamEnable = State;
Index: clang/lib/CodeGen/CGLoopInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGLoopInfo.cpp
+++ clang/lib/CodeGen/CGLoopInfo.cpp
@@ -342,6 +342,22 @@
   return LoopID;
 }
 
+MDNode *LoopInfo::createTailPredicateMetadata(const LoopAttributes &Attrs,
+                                              ArrayRef<Metadata *> LoopProperties,
+                                              bool &HasUserTransforms) {
+  LLVMContext &Ctx = Header->getContext();
+
+  if (Attrs.TailPredicateEnable != LoopAttributes::Enable)
+    return nullptr;
+
+  SmallVector<Metadata *, 4> NewLoopProperties;
+  NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
+  NewLoopProperties.push_back(
+        MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.tailpredicate")));
+  LoopProperties = NewLoopProperties;
+  return createLoopPropertiesMetadata(LoopProperties);
+}
+
 MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
                                            ArrayRef<Metadata *> LoopProperties,
                                            bool &HasUserTransforms) {
@@ -405,13 +421,20 @@
 
   LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
                         AdditionalLoopProperties.end());
+
+  MDNode *N =
+    createTailPredicateMetadata(Attrs, LoopProperties, HasUserTransforms);
+  if(N)
+    LoopProperties.push_back(N);
+
   return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
 }
 
 LoopAttributes::LoopAttributes(bool IsParallel)
     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
       UnrollEnable(LoopAttributes::Unspecified),
-      UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
+      UnrollAndJamEnable(LoopAttributes::Unspecified),
+      TailPredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
       InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
       DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
       PipelineInitiationInterval(0) {}
@@ -425,6 +448,7 @@
   VectorizeEnable = LoopAttributes::Unspecified;
   UnrollEnable = LoopAttributes::Unspecified;
   UnrollAndJamEnable = LoopAttributes::Unspecified;
+  TailPredicateEnable = LoopAttributes::Unspecified;
   DistributeEnable = LoopAttributes::Unspecified;
   PipelineDisabled = false;
   PipelineInitiationInterval = 0;
@@ -446,6 +470,7 @@
       Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
       Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
       Attrs.PipelineInitiationInterval == 0 &&
+      Attrs.TailPredicateEnable == LoopAttributes::Unspecified &&
       Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
       Attrs.UnrollEnable == LoopAttributes::Unspecified &&
       Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
@@ -603,6 +628,9 @@
       case LoopHintAttr::UnrollAndJam:
         setUnrollAndJamState(LoopAttributes::Disable);
         break;
+      case LoopHintAttr::TailPredicate:
+        setTailPredicateState(LoopAttributes::Disable);
+        break;
       case LoopHintAttr::Distribute:
         setDistributeState(false);
         break;
@@ -630,6 +658,9 @@
       case LoopHintAttr::UnrollAndJam:
         setUnrollAndJamState(LoopAttributes::Enable);
         break;
+      case LoopHintAttr::TailPredicate:
+        setTailPredicateState(LoopAttributes::Enable);
+        break;
       case LoopHintAttr::Distribute:
         setDistributeState(true);
         break;
@@ -653,6 +684,7 @@
         break;
       case LoopHintAttr::Unroll:
       case LoopHintAttr::UnrollAndJam:
+      case LoopHintAttr::TailPredicate:
       case LoopHintAttr::UnrollCount:
       case LoopHintAttr::UnrollAndJamCount:
       case LoopHintAttr::VectorizeWidth:
@@ -681,6 +713,7 @@
       case LoopHintAttr::Distribute:
       case LoopHintAttr::PipelineDisabled:
       case LoopHintAttr::PipelineInitiationInterval:
+      case LoopHintAttr::TailPredicate:
         llvm_unreachable("Options cannot be used with 'full' hint.");
         break;
       }
@@ -704,6 +737,7 @@
         break;
       case LoopHintAttr::Unroll:
       case LoopHintAttr::UnrollAndJam:
+      case LoopHintAttr::TailPredicate:
       case LoopHintAttr::Vectorize:
       case LoopHintAttr::Interleave:
       case LoopHintAttr::Distribute:
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -191,6 +191,7 @@
   std::unique_ptr<PragmaHandler> CUDAForceHostDeviceHandler;
   std::unique_ptr<PragmaHandler> OptimizeHandler;
   std::unique_ptr<PragmaHandler> LoopHintHandler;
+  std::unique_ptr<PragmaHandler> TailPredicateHintHandler;
   std::unique_ptr<PragmaHandler> UnrollHintHandler;
   std::unique_ptr<PragmaHandler> NoUnrollHintHandler;
   std::unique_ptr<PragmaHandler> UnrollAndJamHintHandler;
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2975,16 +2975,17 @@
 
   let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">,
                    Pragma<"", "nounroll">, Pragma<"", "unroll_and_jam">,
-                   Pragma<"", "nounroll_and_jam">];
+                   Pragma<"", "nounroll_and_jam">,
+                   Pragma<"", "tail_predicate">];
 
   /// State of the loop optimization specified by the spelling.
   let Args = [EnumArgument<"Option", "OptionType",
                           ["vectorize", "vectorize_width", "interleave", "interleave_count",
                            "unroll", "unroll_count", "unroll_and_jam", "unroll_and_jam_count",
-                           "pipeline", "pipeline_initiation_interval", "distribute"],
+                           "pipeline", "pipeline_initiation_interval", "distribute", "tail_predicate"],
                           ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
                            "Unroll", "UnrollCount", "UnrollAndJam", "UnrollAndJamCount",
-                           "PipelineDisabled", "PipelineInitiationInterval", "Distribute"]>,
+                           "PipelineDisabled", "PipelineInitiationInterval", "Distribute", "TailPredicate"]>,
               EnumArgument<"State", "LoopHintState",
                            ["enable", "disable", "numeric", "assume_safety", "full"],
                            ["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
@@ -3004,6 +3005,7 @@
     case PipelineDisabled: return "pipeline";
     case PipelineInitiationInterval: return "pipeline_initiation_interval";
     case Distribute: return "distribute";
+    case TailPredicate: return "tail_predicate";
     }
     llvm_unreachable("Unhandled LoopHint option.");
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to