[PATCH] Support constant expressions, including non-type template parameters, in pragma loop hints

Aaron Ballman aaron at aaronballman.com
Mon Jul 28 14:03:04 PDT 2014


On Mon, Jul 28, 2014 at 4:41 PM, Tyler Nowicki <tnowicki at apple.com> wrote:
> Hi,
>
> My internship finishes up this week, and Aaron informed me he won’t be able
> to respond until next week. Would someone be able to review the patches
> these patches so I can get them in before I leave?

Not to make a liar of you (I really am on "vacation"), but I don't
want you to get stuck waiting on me. :-)

Minor comments, but with fixing them up, LGTM!

> Index: include/clang/Basic/Attr.td
> ===================================================================
> --- include/clang/Basic/Attr.td (revision 214099)
> +++ include/clang/Basic/Attr.td (working copy)
> @@ -1815,12 +1815,6 @@
>      llvm_unreachable("Unhandled LoopHint option.");
>    }
>
> -  static StringRef getValueName(int Value) {
> -    if (Value)
> -      return "enable";
> -    return "disable";
> -  }
> -

Good catch here, but will this conflict with Mark's upcoming patch? I
don't think it will, but better to ask now. ;-)


>    void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
>      unsigned SpellingIndex = getSpellingListIndex();
>      // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
> @@ -1829,52 +1823,46 @@
>        OS << "\n";
>        return;
>      }
> -    if (SpellingIndex == Pragma_unroll) {
> -      if (option == UnrollCount)
> -        printArgument(OS);
> -      OS << "\n";
> +    else if (SpellingIndex == Pragma_unroll) {
> +      OS << getValueString(Policy) << "\n";
>        return;
>      }
> +
>      assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
> -    OS << getOptionName(option);
> -    printArgument(OS);
> -    OS << "\n";
> +    OS << getOptionName(option) << getValueString(Policy) << "\n";
>    }
>
> -  // Prints the loop hint argument including the enclosing parentheses to OS.
> -  void printArgument(raw_ostream &OS) const {
> +  // Return a string containing the loop hint argument including the
> +  // enclosing parentheses.
> +  std::string getValueString(const PrintingPolicy &Policy) const {
> +    std::string ValueName;
> +    llvm::raw_string_ostream OS(ValueName);

I don't see the benefit of using a raw_string_ostream here since it's
just string concats. Just use a std::string instead?

>      OS << "(";
>      if (option == VectorizeWidth || option == InterleaveCount ||
>          option == UnrollCount)
>        OS << value;
> -    else if (option == Unroll && value)
> -      // Unroll loop hint does not use the keyword "enable". Instead, a nonzero value
> -      // indicates full unrolling which uses the keyword "full".
> -      OS << "full";
> -    else if (value)
> -      OS << "enable";
> -    else
> +    else if (value < 0) {
> +      return "";
> +    } else if (value > 0) {
> +      OS << (option == Unroll ? "full" : "enable");

No curly braces for single statements.

> +    } else {
> +      assert(value == 0 && "Unexpected loop hint value.");

I don't think this assert adds value since it's the only thing value
could possibly be in the else clause.

>        OS << "disable";
> +    }
>      OS << ")";
> +    return OS.str();
>    }
>
>    // Return a string suitable for identifying this attribute in diagnostics.
> -  std::string getDiagnosticName() const {
> -    std::string DiagnosticName;
> -    llvm::raw_string_ostream OS(DiagnosticName);
> +  std::string getDiagnosticName(const PrintingPolicy &Policy) const {
>      unsigned SpellingIndex = getSpellingListIndex();
>      if (SpellingIndex == Pragma_nounroll)
> -      OS << "#pragma nounroll";
> -    else if (SpellingIndex == Pragma_unroll) {
> -      OS << "#pragma unroll";
> -      if (option == UnrollCount)
> -        printArgument(OS);
> -    } else {
> -      assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
> -      OS << getOptionName(option);
> -      printArgument(OS);
> -    }
> -    return OS.str();
> +      return "#pragma nounroll";
> +    else if (SpellingIndex == Pragma_unroll)
> +      return "#pragma unroll" + getValueString(Policy);
> +
> +    assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
> +    return std::string(getOptionName(option)) + getValueString(Policy);

I think getOptionName() should return a const char *, then you don't
need the cast here, or the StringRef construction there. But I don't
feel strongly about it.

>    }
>    }];
>
> Index: lib/Sema/SemaStmtAttr.cpp
> ===================================================================
> --- lib/Sema/SemaStmtAttr.cpp (revision 214099)
> +++ lib/Sema/SemaStmtAttr.cpp (working copy)
> @@ -90,7 +90,7 @@
>    int ValueInt;
>    if (Option == LoopHintAttr::Unroll &&
>        Spelling == LoopHintAttr::Pragma_unroll) {
> -    ValueInt = 1;
> +    ValueInt = (!ValueInfo ? -1 : (ValueInfo->isStr("disable") ? 0 : 1));

Clever, but kind of hard to follow the logic. Why not initialize
ValueInt to -1, then hoist the ValueInfo check? Eg)

int ValueInt = -1;
if (ValueInfo && Option == LoopHintAttr::Unroll && Spelling ==
LoopHintAttr::Pragma_unroll)

>    } else if (Option == LoopHintAttr::Unroll &&
>               Spelling == LoopHintAttr::Pragma_nounroll) {
>      ValueInt = 0;
> @@ -174,7 +174,6 @@
>      };
>
>      auto &CategoryState = HintAttrs[Category];
> -    SourceLocation OptionLoc = LH->getRange().getBegin();
>      const LoopHintAttr *PrevAttr;
>      if (Option == LoopHintAttr::Vectorize ||
>          Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
> @@ -187,11 +186,13 @@
>        CategoryState.NumericAttr = LH;
>      }
>
> +    PrintingPolicy Policy(S.Context.getLangOpts());
> +    SourceLocation OptionLoc = LH->getRange().getBegin();
>      if (PrevAttr)
>        // Cannot specify same type of attribute twice.
>        S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
> -          << /*Duplicate=*/true << PrevAttr->getDiagnosticName()
> -          << LH->getDiagnosticName();
> +          << /*Duplicate=*/true << PrevAttr->getDiagnosticName(Policy)
> +          << LH->getDiagnosticName(Policy);
>
>      if (CategoryState.EnableAttr && CategoryState.NumericAttr &&
>          (Category == Unroll || !CategoryState.EnableAttr->getValue())) {
> @@ -200,8 +201,8 @@
>        // compatible with "enable" form of the unroll pragma, unroll(full).
>        S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
>            << /*Duplicate=*/false
> -          << CategoryState.EnableAttr->getDiagnosticName()
> -          << CategoryState.NumericAttr->getDiagnosticName();
> +          << CategoryState.EnableAttr->getDiagnosticName(Policy)
> +          << CategoryState.NumericAttr->getDiagnosticName(Policy);
>      }
>    }
>  }
>

~Aaron




More information about the cfe-commits mailing list