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