[PATCH] Add loop unroll pragma support
Aaron Ballman
aaron.ballman at gmail.com
Tue Jun 10 16:04:39 PDT 2014
> Index: lib/Parse/ParsePragma.cpp
> ===================================================================
> --- lib/Parse/ParsePragma.cpp
> +++ lib/Parse/ParsePragma.cpp
> @@ -1641,8 +1641,10 @@
> /// loop-hint:
> /// 'vectorize' '(' loop-hint-keyword ')'
> /// 'interleave' '(' loop-hint-keyword ')'
> +/// 'unroll' '(' loop-hint-keyword ')'
> /// 'vectorize_width' '(' loop-hint-value ')'
> /// 'interleave_count' '(' loop-hint-value ')'
> +/// 'unroll_count' '(' loop-hint-value ')'
> ///
> /// loop-hint-keyword:
> /// 'enable'
> @@ -1661,6 +1663,13 @@
> /// possible and profitable, and 0 is invalid. The loop vectorizer currently
> /// only works on inner loops.
> ///
> +/// The unroll and unroll_count directives control the concatenation
> +/// unroller. Specifying unroll(enable) instructs llvm to try to
> +/// unroll the loop completely, and unroll(disable) disables unrolling
> +/// for the loop. Specifying unroll_count(_value_) instructs llvm to
> +/// try to unroll the loop the number of times indicated by the value.
> +/// If unroll(enable) and unroll_count are both specified only
> +/// unroll_count takes effect.
> void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
> PragmaIntroducerKind Introducer,
> Token &Tok) {
> @@ -1680,8 +1689,9 @@
> IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
>
> if (!OptionInfo->isStr("vectorize") && !OptionInfo->isStr("interleave") &&
> - !OptionInfo->isStr("vectorize_width") &&
> - !OptionInfo->isStr("interleave_count")) {
> + !OptionInfo->isStr("unroll") && !OptionInfo->isStr("vectorize_width") &&
> + !OptionInfo->isStr("interleave_count") &&
> + !OptionInfo->isStr("unroll_count")) {
At this point, I think a StringSwitch would make more sense.
> Index: lib/Sema/SemaStmtAttr.cpp
> ===================================================================
> --- lib/Sema/SemaStmtAttr.cpp
> +++ lib/Sema/SemaStmtAttr.cpp
> @@ -67,10 +67,13 @@
> .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
> .Case("interleave", LoopHintAttr::Interleave)
> .Case("interleave_count", LoopHintAttr::InterleaveCount)
> + .Case("unroll", LoopHintAttr::Unroll)
> + .Case("unroll_count", LoopHintAttr::UnrollCount)
> .Default(LoopHintAttr::Vectorize);
>
> int ValueInt;
> - if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave) {
> + if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave ||
> + Option == LoopHintAttr::Unroll) {
> if (!ValueInfo) {
> S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
> << /*MissingKeyword=*/true << "";
> @@ -87,7 +90,8 @@
> return nullptr;
> }
> } else if (Option == LoopHintAttr::VectorizeWidth ||
> - Option == LoopHintAttr::InterleaveCount) {
> + Option == LoopHintAttr::InterleaveCount ||
> + Option == LoopHintAttr::UnrollCount) {
> // FIXME: We should support template parameters for the loop hint value.
> // See bug report #19610.
> llvm::APSInt ValueAPS;
> @@ -111,10 +115,26 @@
>
> static void
> CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
> - int PrevOptionValue[4] = {-1, -1, -1, -1};
> - int OptionId[4] = {LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth,
> - LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount};
> + // There are 3 categories of loop hints: vectorize, interleave, and
> + // unroll. Each comes in two variants: an enable/disable form and a
> + // form which takes a numeric argument. For example:
> + // unroll(enable|disable) and unroll_count(N). The following arrays
> + // accumulate the hints encountered while iterating through the
> + // attributes to check for compatibility
> + //
> + // Accumulated state of enable|disable hints for each hint category.
> + bool EnabledIsSet[3] = {false, false, false};
> + int EnabledValue[3];
> + // Accumulated state of numeric hints for each hint category.
> + bool NumericValueIsSet[3] = {false, false, false};
> + int NumericValue[3];
>
> + int EnableOptionId[3] = {LoopHintAttr::Vectorize, LoopHintAttr::Interleave,
> + LoopHintAttr::Unroll};
> + int NumericOptionId[3] = {LoopHintAttr::VectorizeWidth,
> + LoopHintAttr::InterleaveCount,
> + LoopHintAttr::UnrollCount};
I agree with Reid's comments about perhaps making this into a struct
instead of parallel arrays. Also, the array size isn't needed.
Aside from these nits, LGTM, thanks!
~Aaron
On Tue, Jun 10, 2014 at 2:54 PM, Mark Heffernan <meheff at google.com> wrote:
> Hi TylerNowicki, eliben, aaron.ballman, rsmith,
>
> Piggy-backing on the support for "#pragma clang loop vectorize..." which was added recently by Tyler. This patch adds support for loop unrolling pragmas. The pragmas must immediately precede a loop statement and take the following forms:
>
> #pragma clang loop unroll(enable) // unroll the loop completely
> #pragma clang loop unroll(disable) // do not unroll the loop.
> #pragma clang loop unroll_count(N) // unroll the loop N times
>
> if both unroll(enable) and unroll_count(N) are specified then the unroll_count takes precedence (ie, unroll the loop N times).
>
> Tyler, I changed the logic a bit in CheckForIncompatibleAttributes, specifically it now rejects any combination of the disable form of the pragma and the numeric form (eg, vectorize(disable) and vectorize_width(N)). As a special case, it previously allowed this combination if the numeric value is 1. The logic seems cleaner without that special case. Lemme know if that's reasonable.
>
> I'll be sending out a LLVM patch which consumes the generated metadata right after this.
>
> http://reviews.llvm.org/D4089
>
> Files:
> include/clang/Basic/Attr.td
> include/clang/Basic/DiagnosticParseKinds.td
> lib/CodeGen/CGStmt.cpp
> lib/Parse/ParsePragma.cpp
> lib/Sema/SemaStmtAttr.cpp
> test/CodeGen/pragma-loop.cpp
> test/PCH/pragma-loop.cpp
> test/Parser/pragma-loop.cpp
More information about the cfe-commits
mailing list