kitaisreal created this revision.
kitaisreal added a reviewer: aaron.ballman.
kitaisreal added projects: All, LLVM.
Herald added a subscriber: hiraditya.
kitaisreal requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, wangpc.
Herald added a project: clang.

Add pragma force_vectorize to emit error if loop is not vectorized.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156910

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/CodeGen/CGLoopInfo.cpp
  clang/lib/CodeGen/CGLoopInfo.h
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  llvm/include/llvm/IR/DiagnosticInfo.h
  llvm/lib/IR/DiagnosticInfo.cpp
  llvm/lib/Transforms/Scalar/WarnMissedTransforms.cpp
  llvm/lib/Transforms/Utils/LoopUtils.cpp

Index: llvm/lib/Transforms/Utils/LoopUtils.cpp
===================================================================
--- llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -389,6 +389,11 @@
 }
 
 TransformationMode llvm::hasVectorizeTransformation(const Loop *L) {
+  std::optional<bool> EnableForceVectorize =
+      getOptionalBoolLoopAttribute(L, "llvm.loop.vectorize.force_vectorize");
+  if (EnableForceVectorize == true)
+    return TM_ForcedByUser;
+
   std::optional<bool> Enable =
       getOptionalBoolLoopAttribute(L, "llvm.loop.vectorize.enable");
 
Index: llvm/lib/Transforms/Scalar/WarnMissedTransforms.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/WarnMissedTransforms.cpp
+++ llvm/lib/Transforms/Scalar/WarnMissedTransforms.cpp
@@ -19,8 +19,8 @@
 
 #define DEBUG_TYPE "transform-warning"
 
-/// Emit warnings for forced (i.e. user-defined) loop transformations which have
-/// still not been performed.
+/// Emit warnings or errors for forced (i.e. user-defined) loop transformations
+/// which have still not been performed.
 static void warnAboutLeftoverTransformations(Loop *L,
                                              OptimizationRemarkEmitter *ORE) {
   if (hasUnrollTransformation(L) == TM_ForcedByUser) {
@@ -51,8 +51,19 @@
         getOptionalElementCountLoopAttribute(L);
     std::optional<int> InterleaveCount =
         getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count");
+    std::optional<bool> ForceVectorize =
+        getOptionalBoolLoopAttribute(L, "llvm.loop.vectorize.force_vectorize");
 
-    if (!VectorizeWidth || VectorizeWidth->isVector())
+    if (ForceVectorize == true)
+      ORE->emit(
+          DiagnosticInfoOptimizationFailure(
+              DEBUG_TYPE, "FailedRequestedForceVectorization", L->getStartLoc(),
+              L->getHeader(), DS_Error)
+          << "loop not force vectorized: the optimizer was unable to perform "
+             "the "
+             "requested transformation; the transformation might be disabled "
+             "or specified as part of an unsupported transformation ordering");
+    else if (!VectorizeWidth || VectorizeWidth->isVector())
       ORE->emit(
           DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
                                             "FailedRequestedVectorization",
Index: llvm/lib/IR/DiagnosticInfo.cpp
===================================================================
--- llvm/lib/IR/DiagnosticInfo.cpp
+++ llvm/lib/IR/DiagnosticInfo.cpp
@@ -351,14 +351,14 @@
 
 DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(
     const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
-    const Value *CodeRegion)
+    const Value *CodeRegion, DiagnosticSeverity Severity)
     : DiagnosticInfoIROptimization(
-          DK_OptimizationFailure, DS_Warning, PassName, RemarkName,
+          DK_OptimizationFailure, Severity, PassName, RemarkName,
           *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
 
 bool DiagnosticInfoOptimizationFailure::isEnabled() const {
-  // Only print warnings.
-  return getSeverity() == DS_Warning;
+  // Only print warnings and errors.
+  return getSeverity() == DS_Warning || getSeverity() == DS_Error;
 }
 
 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {
Index: llvm/include/llvm/IR/DiagnosticInfo.h
===================================================================
--- llvm/include/llvm/IR/DiagnosticInfo.h
+++ llvm/include/llvm/IR/DiagnosticInfo.h
@@ -341,7 +341,7 @@
 
   /// Return the absolute path tot the file.
   std::string getAbsolutePath() const;
-  
+
   const Function &getFunction() const { return Fn; }
   DiagnosticLocation getLocation() const { return Loc; }
 
@@ -983,9 +983,10 @@
   /// of the diagnostic.
   DiagnosticInfoOptimizationFailure(const Function &Fn,
                                     const DiagnosticLocation &Loc,
-                                    const Twine &Msg)
-      : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
-                                     nullptr, Fn, Loc, Msg) {}
+                                    const Twine &Msg,
+                                    DiagnosticSeverity Severity = DS_Warning)
+      : DiagnosticInfoIROptimization(DK_OptimizationFailure, Severity, nullptr,
+                                     Fn, Loc, Msg) {}
 
   /// \p PassName is the name of the pass emitting this diagnostic.  \p
   /// RemarkName is a textual identifier for the remark (single-word,
@@ -994,7 +995,8 @@
   /// supported).
   DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
                                     const DiagnosticLocation &Loc,
-                                    const Value *CodeRegion);
+                                    const Value *CodeRegion,
+                                    DiagnosticSeverity Severity = DS_Warning);
 
   static bool classof(const DiagnosticInfo *DI) {
     return DI->getKind() == DK_OptimizationFailure;
Index: clang/lib/Sema/SemaStmtAttr.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAttr.cpp
+++ clang/lib/Sema/SemaStmtAttr.cpp
@@ -123,6 +123,7 @@
     Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
                  OptionLoc->Ident->getName())
                  .Case("vectorize", LoopHintAttr::Vectorize)
+                 .Case("force_vectorize", LoopHintAttr::ForceVectorize)
                  .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
                  .Case("interleave", LoopHintAttr::Interleave)
                  .Case("vectorize_predicate", LoopHintAttr::VectorizePredicate)
@@ -151,6 +152,7 @@
         return nullptr;
       State = LoopHintAttr::Numeric;
     } else if (Option == LoopHintAttr::Vectorize ||
+               Option == LoopHintAttr::ForceVectorize ||
                Option == LoopHintAttr::Interleave ||
                Option == LoopHintAttr::VectorizePredicate ||
                Option == LoopHintAttr::Unroll ||
@@ -375,8 +377,10 @@
 
     CategoryType Category = CategoryType::NumberOfCategories;
     LoopHintAttr::OptionType Option = LH->getOption();
+
     switch (Option) {
     case LoopHintAttr::Vectorize:
+    case LoopHintAttr::ForceVectorize:
     case LoopHintAttr::VectorizeWidth:
       Category = Vectorize;
       break;
@@ -409,6 +413,7 @@
     auto &CategoryState = HintAttrs[Category];
     const LoopHintAttr *PrevAttr;
     if (Option == LoopHintAttr::Vectorize ||
+        Option == LoopHintAttr::ForceVectorize ||
         Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
         Option == LoopHintAttr::UnrollAndJam ||
         Option == LoopHintAttr::VectorizePredicate ||
@@ -425,7 +430,7 @@
 
     PrintingPolicy Policy(S.Context.getLangOpts());
     SourceLocation OptionLoc = LH->getRange().getBegin();
-    if (PrevAttr)
+    if (PrevAttr && Option != LoopHintAttr::ForceVectorize)
       // Cannot specify same type of attribute twice.
       S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
           << /*Duplicate=*/true << PrevAttr->getDiagnosticName(Policy)
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -1375,6 +1375,7 @@
     OptionPipelineDisabled = OptionInfo->isStr("pipeline");
     StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
                       .Case("vectorize", true)
+                      .Case("force_vectorize", true)
                       .Case("interleave", true)
                       .Case("vectorize_predicate", true)
                       .Default(false) ||
@@ -3522,6 +3523,7 @@
 
     bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
                            .Case("vectorize", true)
+                           .Case("force_vectorize", true)
                            .Case("interleave", true)
                            .Case("unroll", true)
                            .Case("distribute", true)
Index: clang/lib/CodeGen/CodeGenAction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -745,9 +745,10 @@
 
 void BackendConsumer::EmitOptimizationMessage(
     const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) {
-  // We only support warnings and remarks.
+  // We only support warnings, remarks and errors.
   assert(D.getSeverity() == llvm::DS_Remark ||
-         D.getSeverity() == llvm::DS_Warning);
+         D.getSeverity() == llvm::DS_Warning ||
+         D.getSeverity() == llvm::DS_Error);
 
   StringRef Filename;
   unsigned Line, Column;
@@ -840,7 +841,11 @@
 
 void BackendConsumer::OptimizationFailureHandler(
     const llvm::DiagnosticInfoOptimizationFailure &D) {
-  EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
+  unsigned DiagID = diag::warn_fe_backend_optimization_failure;
+  if (D.getSeverity() == DiagnosticSeverity::DS_Error)
+    DiagID = diag::err_fe_backend_optimization_failure;
+
+  EmitOptimizationMessage(D, DiagID);
 }
 
 void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) {
Index: clang/lib/CodeGen/CGLoopInfo.h
===================================================================
--- clang/lib/CodeGen/CGLoopInfo.h
+++ clang/lib/CodeGen/CGLoopInfo.h
@@ -46,6 +46,9 @@
   /// Value for llvm.loop.vectorize.enable metadata.
   LVEnableState VectorizeEnable;
 
+  /// Value for llvm.loop.vectorize.force_vectorize.enable metadata.
+  LVEnableState ForceVectorizeEnable;
+
   /// Value for llvm.loop.unroll.* metadata (enable, disable, or full).
   LVEnableState UnrollEnable;
 
@@ -237,6 +240,12 @@
         Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
   }
 
+  /// Set the next pushed loop 'force_vectorize.enable'
+  void setForceVectorizeEnable(bool Enable = true) {
+    StagedAttrs.ForceVectorizeEnable =
+        Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
+  }
+
   /// Set the next pushed loop as a distribution candidate.
   void setDistributeState(bool Enable = true) {
     StagedAttrs.DistributeEnable =
Index: clang/lib/CodeGen/CGLoopInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGLoopInfo.cpp
+++ clang/lib/CodeGen/CGLoopInfo.cpp
@@ -217,6 +217,7 @@
   if (Attrs.VectorizeEnable == LoopAttributes::Disable)
     Enabled = false;
   else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
+           Attrs.ForceVectorizeEnable != LoopAttributes::Unspecified ||
            Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
            Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||
            Attrs.VectorizeScalable != LoopAttributes::Unspecified)
@@ -265,6 +266,14 @@
     Args.push_back(MDNode::get(Ctx, Vals));
   }
 
+  if (Attrs.ForceVectorizeEnable == LoopAttributes::Enable) {
+    Metadata *Vals[] = {
+        MDString::get(Ctx, "llvm.loop.vectorize.force_vectorize"),
+        ConstantAsMetadata::get(
+            ConstantInt::get(llvm::Type::getInt1Ty(Ctx), true))};
+    Args.push_back(MDNode::get(Ctx, Vals));
+  }
+
   // Setting vectorize.width
   if (Attrs.VectorizeWidth > 0) {
     Metadata *Vals[] = {
@@ -644,8 +653,11 @@
         setVectorizeWidth(1);
         setVectorizeScalable(LoopAttributes::Unspecified);
         break;
+      case LoopHintAttr::ForceVectorize:
+        setForceVectorizeEnable(false);
+        break;
       case LoopHintAttr::Interleave:
-        // Disable interleaving by speciyfing a count of 1.
+        // Disable interleaving by specifying a count of 1.
         setInterleaveCount(1);
         break;
       case LoopHintAttr::Unroll:
@@ -678,6 +690,9 @@
       case LoopHintAttr::Interleave:
         setVectorizeEnable(true);
         break;
+      case LoopHintAttr::ForceVectorize:
+        setForceVectorizeEnable(true);
+        break;
       case LoopHintAttr::Unroll:
         setUnrollState(LoopAttributes::Enable);
         break;
@@ -703,6 +718,7 @@
     case LoopHintAttr::AssumeSafety:
       switch (Option) {
       case LoopHintAttr::Vectorize:
+      case LoopHintAttr::ForceVectorize:
       case LoopHintAttr::Interleave:
         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
         setParallel(true);
@@ -731,6 +747,7 @@
         setUnrollAndJamState(LoopAttributes::Full);
         break;
       case LoopHintAttr::Vectorize:
+      case LoopHintAttr::ForceVectorize:
       case LoopHintAttr::Interleave:
       case LoopHintAttr::UnrollCount:
       case LoopHintAttr::UnrollAndJamCount:
@@ -777,6 +794,7 @@
       case LoopHintAttr::UnrollAndJam:
       case LoopHintAttr::VectorizePredicate:
       case LoopHintAttr::Vectorize:
+      case LoopHintAttr::ForceVectorize:
       case LoopHintAttr::VectorizeWidth:
       case LoopHintAttr::Interleave:
       case LoopHintAttr::Distribute:
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1550,8 +1550,8 @@
   "'enable'%select{|, 'full'}1%select{|, 'assume_safety'}2 or 'disable'}0">;
 def err_pragma_loop_invalid_option : Error<
   "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
-  "vectorize_width, interleave, interleave_count, unroll, unroll_count, "
-  "pipeline, pipeline_initiation_interval, vectorize_predicate, or distribute">;
+  "force_vectorize, vectorize_width, interleave, interleave_count, unroll, "
+  "unroll_count, pipeline, pipeline_initiation_interval, vectorize_predicate, or distribute">;
 def err_pragma_loop_invalid_vectorize_option : Error<
   "vectorize_width loop hint malformed; use vectorize_width(X, fixed) or "
   "vectorize_width(X, scalable) where X is an integer, or vectorize_width('fixed' or 'scalable')">;
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -3687,6 +3687,7 @@
 def LoopHint : Attr {
   /// #pragma clang loop <option> directive
   /// vectorize: vectorizes loop operations if State == Enable.
+  /// force_vectorize: force vectorizes loop operations if State == Enable.
   /// vectorize_width: vectorize loop operations with width 'Value'.
   /// interleave: interleave multiple loop iterations if State == Enable.
   /// interleave_count: interleaves 'Value' loop iterations.
@@ -3709,11 +3710,11 @@
 
   /// State of the loop optimization specified by the spelling.
   let Args = [EnumArgument<"Option", "OptionType",
-                          ["vectorize", "vectorize_width", "interleave", "interleave_count",
+                          ["vectorize", "force_vectorize", "vectorize_width", "interleave", "interleave_count",
                            "unroll", "unroll_count", "unroll_and_jam", "unroll_and_jam_count",
                            "pipeline", "pipeline_initiation_interval", "distribute",
                            "vectorize_predicate"],
-                          ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
+                          ["Vectorize", "ForceVectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
                            "Unroll", "UnrollCount", "UnrollAndJam", "UnrollAndJamCount",
                            "PipelineDisabled", "PipelineInitiationInterval", "Distribute",
                            "VectorizePredicate"]>,
@@ -3728,6 +3729,7 @@
   static const char *getOptionName(int Option) {
     switch(Option) {
     case Vectorize: return "vectorize";
+    case ForceVectorize: return "force_vectorize";
     case VectorizeWidth: return "vectorize_width";
     case Interleave: return "interleave";
     case InterleaveCount: return "interleave_count";
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to