Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -2981,10 +2981,10 @@ 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", "predicate"], ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount", "Unroll", "UnrollCount", "UnrollAndJam", "UnrollAndJamCount", - "PipelineDisabled", "PipelineInitiationInterval", "Distribute"]>, + "PipelineDisabled", "PipelineInitiationInterval", "Distribute", "Predicate"]>, EnumArgument<"State", "LoopHintState", ["enable", "disable", "numeric", "assume_safety", "full"], ["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>, @@ -3004,6 +3004,7 @@ case PipelineDisabled: return "pipeline"; case PipelineInitiationInterval: return "pipeline_initiation_interval"; case Distribute: return "distribute"; + case Predicate: return "predicate"; } llvm_unreachable("Unhandled LoopHint option."); } Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1210,7 +1210,7 @@ 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, or distribute">; + "pipeline, pipeline_initiation_interval, predicate, or distribute">; def err_pragma_fp_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected contract">; 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.predicate metadata + LVEnableState PredicateEnable; + /// Value for llvm.loop.vectorize.width metadata. unsigned VectorizeWidth; @@ -162,6 +165,11 @@ createFullUnrollMetadata(const LoopAttributes &Attrs, llvm::ArrayRef LoopProperties, bool &HasUserTransforms); + + llvm::MDNode * + createPredicateMetadata(const LoopAttributes &Attrs, + llvm::ArrayRef LoopProperties, + bool &HasUserTransforms); /// @} /// Create a LoopID for this loop, including transformation-unspecific @@ -237,6 +245,12 @@ StagedAttrs.UnrollEnable = State; } + + void setPredicateState(const LoopAttributes::LVEnableState &State) { + StagedAttrs.PredicateEnable = 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::createPredicateMetadata(const LoopAttributes &Attrs, + ArrayRef LoopProperties, + bool &HasUserTransforms) { + LLVMContext &Ctx = Header->getContext(); + + if (Attrs.PredicateEnable != LoopAttributes::Enable) + return nullptr; + + SmallVector NewLoopProperties; + NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end()); + NewLoopProperties.push_back( + MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.predicate"))); + LoopProperties = NewLoopProperties; + return createLoopPropertiesMetadata(LoopProperties); +} + MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs, ArrayRef LoopProperties, bool &HasUserTransforms) { @@ -405,13 +421,19 @@ LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(), AdditionalLoopProperties.end()); + + MDNode *N = createPredicateMetadata(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), + PredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0), InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0), DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false), PipelineInitiationInterval(0) {} @@ -425,6 +447,7 @@ VectorizeEnable = LoopAttributes::Unspecified; UnrollEnable = LoopAttributes::Unspecified; UnrollAndJamEnable = LoopAttributes::Unspecified; + PredicateEnable = LoopAttributes::Unspecified; DistributeEnable = LoopAttributes::Unspecified; PipelineDisabled = false; PipelineInitiationInterval = 0; @@ -446,6 +469,7 @@ Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 && Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled && Attrs.PipelineInitiationInterval == 0 && + Attrs.PredicateEnable == LoopAttributes::Unspecified && Attrs.VectorizeEnable == LoopAttributes::Unspecified && Attrs.UnrollEnable == LoopAttributes::Unspecified && Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified && @@ -480,6 +504,7 @@ BeforeJam.InterleaveCount = Attrs.InterleaveCount; BeforeJam.VectorizeEnable = Attrs.VectorizeEnable; BeforeJam.DistributeEnable = Attrs.DistributeEnable; + BeforeJam.PredicateEnable = Attrs.PredicateEnable; switch (Attrs.UnrollEnable) { case LoopAttributes::Unspecified: @@ -495,6 +520,7 @@ break; } + AfterJam.PredicateEnable = Attrs.PredicateEnable; AfterJam.UnrollCount = Attrs.UnrollCount; AfterJam.PipelineDisabled = Attrs.PipelineDisabled; AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval; @@ -516,6 +542,7 @@ // add it manually. SmallVector BeforeLoopProperties; if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified || + BeforeJam.PredicateEnable != LoopAttributes::Unspecified || BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0) BeforeLoopProperties.push_back( MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized"))); @@ -603,6 +630,9 @@ case LoopHintAttr::UnrollAndJam: setUnrollAndJamState(LoopAttributes::Disable); break; + case LoopHintAttr::Predicate: + setPredicateState(LoopAttributes::Disable); + break; case LoopHintAttr::Distribute: setDistributeState(false); break; @@ -630,6 +660,9 @@ case LoopHintAttr::UnrollAndJam: setUnrollAndJamState(LoopAttributes::Enable); break; + case LoopHintAttr::Predicate: + setPredicateState(LoopAttributes::Enable); + break; case LoopHintAttr::Distribute: setDistributeState(true); break; @@ -653,6 +686,7 @@ break; case LoopHintAttr::Unroll: case LoopHintAttr::UnrollAndJam: + case LoopHintAttr::Predicate: case LoopHintAttr::UnrollCount: case LoopHintAttr::UnrollAndJamCount: case LoopHintAttr::VectorizeWidth: @@ -681,6 +715,7 @@ case LoopHintAttr::Distribute: case LoopHintAttr::PipelineDisabled: case LoopHintAttr::PipelineInitiationInterval: + case LoopHintAttr::Predicate: llvm_unreachable("Options cannot be used with 'full' hint."); break; } @@ -704,6 +739,7 @@ break; case LoopHintAttr::Unroll: case LoopHintAttr::UnrollAndJam: + case LoopHintAttr::Predicate: case LoopHintAttr::Vectorize: case LoopHintAttr::Interleave: case LoopHintAttr::Distribute: Index: clang/lib/Parse/ParsePragma.cpp =================================================================== --- clang/lib/Parse/ParsePragma.cpp +++ clang/lib/Parse/ParsePragma.cpp @@ -1071,6 +1071,7 @@ StateOption = llvm::StringSwitch(OptionInfo->getName()) .Case("vectorize", true) .Case("interleave", true) + .Case("predicate", true) .Default(false) || OptionUnroll || OptionUnrollAndJam || OptionDistribute || OptionPipelineDisabled; @@ -2823,6 +2824,7 @@ /// loop-hint: /// 'vectorize' '(' loop-hint-keyword ')' /// 'interleave' '(' loop-hint-keyword ')' +/// 'predicate' '(' loop-hint-keyword ')' /// 'unroll' '(' unroll-hint-keyword ')' /// 'vectorize_width' '(' loop-hint-value ')' /// 'interleave_count' '(' loop-hint-value ')' @@ -2883,6 +2885,7 @@ bool OptionValid = llvm::StringSwitch(OptionInfo->getName()) .Case("vectorize", true) .Case("interleave", true) + .Case("predicate", true) .Case("unroll", true) .Case("distribute", true) .Case("vectorize_width", true) Index: clang/lib/Sema/SemaStmtAttr.cpp =================================================================== --- clang/lib/Sema/SemaStmtAttr.cpp +++ clang/lib/Sema/SemaStmtAttr.cpp @@ -133,6 +133,7 @@ .Case("vectorize", LoopHintAttr::Vectorize) .Case("vectorize_width", LoopHintAttr::VectorizeWidth) .Case("interleave", LoopHintAttr::Interleave) + .Case("predicate", LoopHintAttr::Predicate) .Case("interleave_count", LoopHintAttr::InterleaveCount) .Case("unroll", LoopHintAttr::Unroll) .Case("unroll_count", LoopHintAttr::UnrollCount) @@ -151,6 +152,7 @@ State = LoopHintAttr::Numeric; } else if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave || + Option == LoopHintAttr::Predicate || Option == LoopHintAttr::Unroll || Option == LoopHintAttr::Distribute || Option == LoopHintAttr::PipelineDisabled) { @@ -189,7 +191,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(I); @@ -205,7 +208,8 @@ Unroll, UnrollAndJam, Distribute, - Pipeline + Pipeline, + Predicate } Category; switch (Option) { case LoopHintAttr::Vectorize: @@ -232,6 +236,9 @@ case LoopHintAttr::PipelineInitiationInterval: Category = Pipeline; break; + case LoopHintAttr::Predicate: + Category = Predicate; + break; }; assert(Category < sizeof(HintAttrs) / sizeof(HintAttrs[0])); @@ -240,6 +247,7 @@ if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll || Option == LoopHintAttr::UnrollAndJam || + Option == LoopHintAttr::Predicate || Option == LoopHintAttr::PipelineDisabled || Option == LoopHintAttr::Distribute) { // Enable|Disable|AssumeSafety hint. For example, vectorize(enable). Index: clang/test/AST/ast-print-pragmas.cpp =================================================================== --- clang/test/AST/ast-print-pragmas.cpp +++ clang/test/AST/ast-print-pragmas.cpp @@ -17,10 +17,12 @@ // CHECK: #pragma clang loop distribute(disable) // CHECK-NEXT: #pragma clang loop vectorize(enable) // CHECK-NEXT: #pragma clang loop interleave(disable) +// CHECK-NEXT: #pragma clang loop predicate(disable) #pragma clang loop distribute(disable) #pragma clang loop vectorize(enable) #pragma clang loop interleave(disable) +#pragma clang loop predicate(disable) // CHECK-NEXT: while (i - 1 < Length) while (i - 1 < Length) { List[i] = i * 2; @@ -30,10 +32,12 @@ // CHECK: #pragma clang loop distribute(enable) // CHECK-NEXT: #pragma clang loop vectorize(disable) // CHECK-NEXT: #pragma clang loop interleave(enable) +// CHECK-NEXT: #pragma clang loop predicate(enable) #pragma clang loop distribute(enable) #pragma clang loop vectorize(disable) #pragma clang loop interleave(enable) +#pragma clang loop predicate(enable) // CHECK-NEXT: while (i - 2 < Length) while (i - 2 < Length) { List[i] = i * 2; Index: clang/test/CodeGenCXX/pragma-loop.cpp =================================================================== --- clang/test/CodeGenCXX/pragma-loop.cpp +++ clang/test/CodeGenCXX/pragma-loop.cpp @@ -10,6 +10,7 @@ #pragma clang loop vectorize_width(4) #pragma clang loop unroll(full) #pragma clang loop distribute(enable) +#pragma clang loop predicate(enable) while (i < Length) { // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] List[i] = i * 2; @@ -56,7 +57,7 @@ // Verify disable pragma clang loop directive generates correct metadata void disable_test(int *List, int Length) { -#pragma clang loop vectorize(disable) unroll(disable) distribute(disable) +#pragma clang loop vectorize(disable) unroll(disable) distribute(disable) predicate(disable) for (int i = 0; i < Length; i++) { // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]] List[i] = i * 2; @@ -158,8 +159,11 @@ for_template_constant_expression_test(List, Length); } -// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]]} -// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: !2 = distinct !{!2, !3, !5} +// CHECK !3 = distinct !{!3, !4]} +// CHECK: !4 = !{!"llvm.loop.predicate"} +// CHECK-NOT: !{!"llvm.loop.predicate"} +// CHECK: !5 = !{!"llvm.loop.unroll.full"} // CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[UNROLL_DISABLE:.*]], ![[DISTRIBUTE_DISABLE:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]]} // CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} Index: clang/test/Parser/pragma-loop.cpp =================================================================== --- clang/test/Parser/pragma-loop.cpp +++ clang/test/Parser/pragma-loop.cpp @@ -81,6 +81,7 @@ #pragma clang loop vectorize(enable) #pragma clang loop interleave(enable) +#pragma clang loop predicate(enable) #pragma clang loop unroll(full) while (i + 1 < Length) { List[i] = i; @@ -95,6 +96,7 @@ #pragma clang loop vectorize(disable) #pragma clang loop interleave(disable) +#pragma clang loop predicate(disable) #pragma clang loop unroll(disable) while (i - 1 < Length) { List[i] = i; @@ -111,7 +113,7 @@ } int VList[Length]; -#pragma clang loop vectorize(disable) interleave(disable) unroll(disable) +#pragma clang loop vectorize(disable) interleave(disable) unroll(disable) predicate(disable) for (int j : VList) { VList[j] = List[j]; } @@ -130,11 +132,13 @@ /* expected-error {{expected '('}} */ #pragma clang loop vectorize /* expected-error {{expected '('}} */ #pragma clang loop interleave +/* expected-error {{expected '('}} */ #pragma clang loop predicate /* expected-error {{expected '('}} */ #pragma clang loop unroll /* expected-error {{expected '('}} */ #pragma clang loop distribute /* expected-error {{expected ')'}} */ #pragma clang loop vectorize(enable /* expected-error {{expected ')'}} */ #pragma clang loop interleave(enable +/* expected-error {{expected ')'}} */ #pragma clang loop predicate(enable /* expected-error {{expected ')'}} */ #pragma clang loop unroll(full /* expected-error {{expected ')'}} */ #pragma clang loop distribute(enable @@ -147,7 +151,7 @@ /* expected-error {{missing argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll() /* expected-error {{missing argument; expected 'enable' or 'disable'}} */ #pragma clang loop distribute() -/* expected-error {{missing option; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, pipeline, pipeline_initiation_interval, or distribute}} */ #pragma clang loop +/* expected-error {{missing option; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, pipeline, pipeline_initiation_interval, predicate, or distribute}} */ #pragma clang loop /* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword /* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword(enable) /* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop vectorize(enable) badkeyword(4) @@ -245,6 +249,8 @@ /* expected-error {{duplicate directives 'vectorize(enable)' and 'vectorize(disable)'}} */ #pragma clang loop vectorize(disable) #pragma clang loop interleave(enable) /* expected-error {{duplicate directives 'interleave(enable)' and 'interleave(disable)'}} */ #pragma clang loop interleave(disable) +#pragma clang loop predicate(enable) +/* expected-error {{duplicate directives 'predicate(enable)' and 'predicate(disable)'}} */ #pragma clang loop predicate(disable) #pragma clang loop unroll(full) /* expected-error {{duplicate directives 'unroll(full)' and 'unroll(disable)'}} */ #pragma clang loop unroll(disable) #pragma clang loop distribute(enable) @@ -281,3 +287,7 @@ #pragma clang loop interleave(enable) /* expected-error {{expected statement}} */ } + +void foo(void) { +#pragma clang loop predicate(enable) +/* expected-error {{expected statement}} */ } Index: clang/test/Parser/pragma-unroll-and-jam.cpp =================================================================== --- clang/test/Parser/pragma-unroll-and-jam.cpp +++ clang/test/Parser/pragma-unroll-and-jam.cpp @@ -67,7 +67,7 @@ } // pragma clang unroll_and_jam is disabled for the moment -/* expected-error {{invalid option 'unroll_and_jam'; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, pipeline, pipeline_initiation_interval, or distribute}} */ #pragma clang loop unroll_and_jam(4) +/* expected-error {{invalid option 'unroll_and_jam'; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, pipeline, pipeline_initiation_interval, predicate, or distribute}} */ #pragma clang loop unroll_and_jam(4) for (int i = 0; i < Length; i++) { for (int j = 0; j < Length; j++) { List[i * Length + j] = Value;