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

Richard Smith richard at metafoo.co.uk
Tue Jul 1 18:09:52 PDT 2014


Thanks, this looks like the right approach.


+def err_pragma_loop_invalid_expression : Error<
+  "invalid argument; expected a constant integer expression">;

The appropriate term is "integer constant expression".


+    if (ValueExpr) {
+      llvm::APSInt ValueAPS;
+      bool IsICE = ValueExpr->isIntegerConstantExpr(ValueAPS,
CGM.getContext());
+      (void)IsICE; // So release build do not warn about unused variables
+      assert(IsICE &&
+             "Loop hint argument is not an integer constant expression");

Use 'ValueExpr->EvaluateKnownConstInt' here.


+      ValueInt = ValueAPS.getSExtValue();
+    }

What if the value doesn't fit in 64 bits? Asserting is not a friendly
response. Since you're looking for a 32-bit int anyway, maybe saturate at
0xFFFFF'FFFF?


 struct PragmaLoopHintInfo {
   Token Loop;
-  Token Value;
   Token Option;
+  std::pair<Token *, size_t> Values;

Either use ArrayRef or split this out into two separate members with names
that indicate that one is the size of the other.


+  if (!Info)
+    return LoopHint(); // Uninitialized loop hints are ignored.

Why do we even create an annotation token in this case?


+    // Suppress diagnostic messages so we can report and invalid
expression if
+    // ParseConstantExpression fails.

Typo 'and'. But I don't think this is a good idea. If
ParseConstantExpression fails, you should just let it report its diagnostic
and bail out. It gives better diagnostics than you do.


+    PP.EnterTokenStream(Args, ArgSize, false, false);

You'll need to add a terminator token here to stop us falling off the end
of the tokens of the expression into whatever follows, in cases like

    #pragma clang loop vectorize_width(1 +)
    1
     for (...) {}

We usually add a tok::eof token after the saved tokens for this purpose.
Please also add /*comments*/ explaining what the 'false's mean in this call.


+    QualType QT = R.get()->getType();
+    if (!QT->isIntegerType() || QT->isBooleanType() || QT->isCharType()) {
+      Diag(Args[0].getLocation(),
diag::err_pragma_loop_invalid_expression);
+      return LoopHint(); // Uninitialized loop hints are ignored.
+    }

This should be in Sema, not here. (In particular, you need to allow a
dependent type here and repeat this check after instantiation.)


+    Token *TokenArray = new Token[ValueList.size()];

Allocate this on the Preprocessor's block allocator, instead of leaking it.


-    if (!Hint.LoopLoc || !Hint.OptionLoc || !Hint.ValueLoc)
+    if (!Hint.LoopLoc || !Hint.OptionLoc ||
+        !(Hint.EnabledLoc || Hint.ValueExpr))
       continue;

Maybe create a LoopHint::isInvalid() and put this there? Do you really need
to check the loop and option locations here?


+bool Sema::DiagnoseLoopHintValue(Expr *ValueExpr) {

Should be 'CheckLoopHintValue', since it doesn't always diagnose.


+  if (!ValueExpr->isIntegerConstantExpr(ValueAPS, getASTContext()) ||

Use VerifyIntegerConstantExpression here; it gives much better diagnostics.


+  // Only transform non-type template parameters.
+  if (!LH->getValue() || !LH->getValue()->isValueDependent())

This is not correct. You need to transform LH if the value is
instantiation-dependent too (also the comment is wrong...). The way we
usually deal with this is:

Expr *TransformedExpr = getDerived().TransformExpr(LH->getValue()).get();
if (TransformedExpr == LH->getValue().get())
  return LH;


+  /// \brief Transform the given attribute.
+  ///
+  /// By default, this routine transforms a statement by delegating to the
+  /// appropriate TransformXXXAttr function to transform a specific kind
+  /// of attribute. Subclasses may override this function to transform
+  /// attributed statements using some other mechanism.
+  ///
+  /// \returns the transformed attribute
+  const Attr *TransformAttr(const Attr *S);

I don't like that this gives us two completely different ways to
instantiate attributes (TreeTransform::transformAttrs /
Sema::InstantiateAttrs and this new function). I'm OK with this as a
stopgap measure if you're prepared to clean this duplication up afterwards,
but this is not reasonable as a long-term situation.

Please add tests for the case where the value is type-dependent.

On Mon, Jun 30, 2014 at 3:07 PM, Hal Finkel <hfinkel at anl.gov> wrote:

> Tyler,
>
> Thanks for working on this!
>
> First, this patch contains a few things that looks like unrelated cleanup
> (formatting changes and extra CHECK lines in the tests). Please separate
> these out (and commit them separately).
>
> Except, not the formatting part of this change (because it makes the lines
> too long):
>
> -  /// State of the loop optimization specified by the spelling.
>
>    let Args = [EnumArgument<"Option", "OptionType",
>
> -                          ["vectorize", "vectorize_width", "interleave",
> "interleave_count",
>
> -                           "unroll", "unroll_count"],
>
> -                          ["Vectorize", "VectorizeWidth", "Interleave",
> "InterleaveCount",
>
> -                           "Unroll", "UnrollCount"]>,
>
> -              DefaultIntArgument<"Value", 1>];
>
> +                          ["vectorize", "vectorize_width", "interleave",
> "interleave_count", "unroll", "unroll_count"],
>
> +                          ["Vectorize", "VectorizeWidth", "Interleave",
> "InterleaveCount", "Unroll", "UnrollCount"]>,
>
> +              DefaultBoolArgument<"Enabled", 0>,
>
> +              ExprArgument<"Value", 0>];
>
> And, regarding errors like this:
> +/* expected-error {{invalid argument; expected a positive integer value}}
> */ #pragma clang loop interleave_count(10 / 5 - 2)
>
> I think it is important that we provide the evaluated integer value in the
> error message (it is obvious in this example, but if the numbers some from
> preprocessor macros and/or template parameters, it likely won't be
> obvious). Similarly, if we're given something of the wrong type (like a
> floating-point value), we should provide the name of the bad type.
>
> Thanks again,
> Hal
>
> ----- Original Message -----
> > From: "Tyler Nowicki" <tnowicki at apple.com>
> > To: "llvm cfe" <cfe-commits at cs.uiuc.edu>, "Hal Finkel" <hfinkel at anl.gov>,
> "Aaron Ballman" <aaron.ballman at gmail.com>,
> > "Richard Smith" <richard at metafoo.co.uk>
> > Cc: "Nadav Rotem" <nrotem at apple.com>
> > Sent: Friday, June 27, 2014 4:11:17 PM
> > Subject: [PATCH] Support constant expressions, including non-type
> template parameters, in pragma loop hints
> >
> > Hi Hal, Aaron, Richard,
> >
> > This patch adds support for constant expressions, including non-type
> > template parameters, in pragma loop hints.
> >
> > Support for constant expressions is done using
> > ParseConstantExpression() in the pragma parser, modifying the
> > LoopHintAttr to hold an Expr, and transforming the LoopHintAttr
> > expression during template instantiation.
> >
> > Previously it was suggested that I also split the LoopHintAttr into
> > an Attr for enable/disable loop hints and an Attr for loop hints
> > with an expression. I gave it a try but it caused a lot of
> > duplication without much of a reduction in the complexity of loop
> > hint handling. I am willing to give it another look if you think it
> > would be better in the long run.
> >
> > Tyler
> >
> >
> >
>
> --
> Hal Finkel
> Assistant Computational Scientist
> Leadership Computing Facility
> Argonne National Laboratory
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140701/63cf7145/attachment.html>


More information about the cfe-commits mailing list