This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [GSoC] writing test-case


On Wed, May 14, 2014 at 4:33 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Wed, May 14, 2014 at 12:30 PM, Richard Biener
> <richard.guenther@gmail.com> wrote:
>> On Wed, May 14, 2014 at 12:24 PM, Richard Biener
>> <richard.guenther@gmail.com> wrote:
>>> On Tue, May 13, 2014 at 11:06 PM, Prathamesh Kulkarni
>>> <bilbotheelffriend@gmail.com> wrote:
>>>> On Tue, May 13, 2014 at 2:36 PM, Richard Biener
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Sun, May 11, 2014 at 5:00 PM, Prathamesh Kulkarni
>>>>> <bilbotheelffriend@gmail.com> wrote:
>>>>>> On Sun, May 11, 2014 at 8:10 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>>>>>>> Prathamesh Kulkarni <bilbotheelffriend@gmail.com> writes:
>>>>>>>
>>>>>>>> a) I am not able to follow why 3 slashes are required here
>>>>>>>> in x_.\\\(D\\\) ? Why does x_.\(D\) not work ?
>>>>>>>
>>>>>>> Two of the three backslashes are eaten by the tcl parser.  But actually
>>>>>>> only two backslashes are needed, since the parens are not special to tcl
>>>>>>> (but are special to the regexp engine, so you want a single backslash
>>>>>>> surviving the tcl parser).
>>>>>>>
>>>>>>>> b) The expression after folding would be of the form:
>>>>>>>> t2_<digit> = x_<digit>(D) - y_<digit>(D)
>>>>>>>> I have used the operator "." in the pattern to match digit.
>>>>>>>> While that works in the above case, I think a better
>>>>>>>> idea would be to match using [0-9].
>>>>>>>> I tried the following but it does not work:
>>>>>>>> t_[0-9] = x_[0-9]\\\(D\\\) - y_[0-9]\\\(D\\\)
>>>>>>>> Neither does \\\[ and \\\] work.
>>>>>>>
>>>>>>> Brackets are special in tcl (including inside double quotes), so they
>>>>>>> need to be quoted.  But you want the brackets to appear unquoted to the
>>>>>>> regexp engine, so a single backslash will do the Right Thing.
>>>>>>>
>>>>>>> See tcl(n) for the tcl parsing rules.
>>>>>>>
>>>>>> Thanks. Now I get it, the double backslash \\ is an escape sequence
>>>>>> for \, and special characters like (, [
>>>>>> retain their meaning in quotes, so to match input text: (D), the
>>>>>> pattern has to be written as: "\\(D\\)".
>>>>>> I believe "\(D\)" would only match D in the input ?
>>>>>> I have modified the test-case. Is this version correct ?
>>>>>
>>>>> I usually verify that by running the testcase in isolation on a GCC version
>>>>> that should FAIL it and on one that should PASS it (tcl quoting is also
>>>>> try-and-error for me most of the time...).
>>>>>
>>>>> Thus I do
>>>>>
>>>>> gcc/> make check-gcc RUNTESTFLAGS="tree-ssa.exp=match-2.c"
>>>>> <test should FAIL>
>>>>> <patch source tree>
>>>>> gcc/> make cc1
>>>>> ... compiles cc1 ...
>>>>> gcc/> make check-gcc RUNTESTFLAGS="tree-ssa.exp=match-2.c"
>>>>> <test should PASS>
>>>>>
>>>>> A more complete matching for an SSA name would be (allowing
>>>>> for SSA name versions > 9) _\\d\+ with \\(D\\) appended if
>>>>> suitable (that's usually known from the testcase).  \\d\+ should match
>>>>> at least one decimal digit.
>>>> I thought that SSA name version wouldn't exceed 9 for that test-case,
>>>> so I decided for matching only one digit. I will change it to match
>>>> one or more digits.
>>>>
>>>> * I have written test-cases for patterns in match.pd (attached patch), which
>>>> result in PASS. Could you review them for me ?
>>>> I couldn't write for following ones:
>>>>
>>>> 1] Patterns involving COMPLEX_EXPR, REALPART_EXPR, IMAGPART_EXPR
>>>> (match_and_simplify
>>>>   (complex (realpart @0) (imagpart @0))
>>>>   @0)
>>>> (match_and_simplify
>>>>   (realpart (complex @0 @1))
>>>>   @0)
>>>> (match_and_simplify
>>>>   (imagpart (complex @0 @1))
>>>>   @1)
>>>>
>>>> Sorry to be daft, but I couldn't understand what these patterns meant
>>>> (I know complex numbers).
>>>> Could you give an example that matches one of these patterns ?
>>>> Thanks.
>>>
>>> The existing match-1.c testcase has some ideas.  For the first
>>> pattern I'd do
>>>
>>> _Complex double foo (_Complex double z)
>>> {
>>>   double r = __real z;
>>>   double i = __imag z;
>>>   return r + 1.0iF * i;
>>> }
>>>
>>> where the return expression is folded (yeah ...) to a COMPLEX_EXPR.
>>>
>>> For the other two patterns sth like
>>>
>>> double foo (double r)
>>> {
>>>   _Complex double z = r;
>>>   return __real z;
>>> }
>>>
>>> and
>>>
>>> double foo (double i)
>>> {
>>>   _Complex double z = 1.0iF * i;
>>>   return __imag z;
>>> }
>>>
>>> should work.
>>>
>>>> 2] Test-case for FMA_EXPR. I am not sure how to generate FMA_EXPR from C code.
>>>> (match_and_simplify
>>>>   (fma INTEGER_CST_P@0 INTEGER_CST_P@1 @3)
>>>>   (plus (mult @0 @1) @3))
>>>
>>> I believe it's not possible.  FMA is matched by the optimize_widen_mult
>>> pass which runs quite late, after the last forwprop pass.  So I don't think
>>> it's possible to write a testcase that triggers with the existing compiler.
>>>
>>>> 3] Test-case for COND_EXPR
>>>> (match_and_simplify
>>>>   (cond (bit_not @0) @1 @2)
>>>>   (cond @0 @2 @1))
>>>>
>>>> I believe cond corresponds to C's ternary operator ?
>>>> However c-expression of the form:
>>>> t2 = (x ? y : z)
>>>> gets translated to gimple as an if-else statement, with "x" being condition,
>>>> "y" being then-statement, and "z" being else-statement.
>>>> So I guess we need to handle this case specially in genmatch ?
>>>> Or am I mistaken ?
>>>
>>> One idea was to also match if-then-else as COND_EXPR (something
>>> to explore later), but you can also see COND_EXPRs in the GIMPLE IL,
>>> for example they are created by if-conversion which runs before
>>> vectorization.  But as above, it's difficult to create a testcase to
>>> match on a forwprop transform (those patterns are more likely to
>>> match from the various passes code-generation which need to be
>>> updated to use the gimple_build interface provided on the breanch).
>>>
>>> As of the if-then-else idea, for example
>>>
>>> int foo (int x)
>>> {
>>>   return x ? 3 : 5;
>>> }
>>>
>>> is seen as
>>>
>>>   <bb 2>:
>>>   if (x_2(D) != 0)
>>>     goto <bb 4>;
>>>   else
>>>     goto <bb 3>;
>>>
>>>   <bb 3>:
>>>
>>>   <bb 4>:
>>>   # iftmp_1 = PHI <1(2), 0(3)>
>>>   return iftmp_1;
>>>
>>> in GIMPLE SSA form.  Thus the COND_EXPR is translated
>>> to a PHI node and a controling predicate.
>>>
>>> But as said, I'd say we should defer this to a later stage if
>>> time permits.
>>>
>>>> * I added few patterns from TODO list in match.pd. I am
>>>> not sure how to write pattern for the following transform:
>>>> (T) (P + A) - (T) P -> (T) A
>>>
>>> This tries to match C pointer difference GIMPLE which is carried
>>> out using integer types.  You'd write sth like
>>>
>>> (match_and_simplify
>>>   (minus (convert (pointer_plus @0 @1))
>>>              (convert @0))
>>>   (convert @1))
>>>
>>> where a few issues show up.
>>>
>>> First, in GIMPLE we can
>>> have both NOP_EXPR and CONVERT_EXPR which mean the
>>> same (and are generally tested with CONVERT_EXRP_P).
>>> So the in the patterns we should prefer one of both (I'd say
>>> convert) but the code generator has to match both (actually
>>> NOP_EXPR appears way more often).
>>>
>>> Second, for the simplified pattern we generate a convert - but
>>> generally we'd want to supply a type to convert to (the current
>>> code will simply pick the type of the original expression which
>>> is the correct one in this case).  So for other cases I would
>>> expect we'd need to write
>>>
>>> (match_and_simplify
>>>   (minus (convert@2 (pointer_plus @0 @1))
>>>              (convert @0))
>>>   { fold_convert (TREE_TYPE (@2), @1); })
>>>
>>> thus use C code because there isn't (yet) a way to specify a
>>> type for a to generate expression.  I don't expect this to
>>> show up very often and thus I didn't look after a syntax
>>> to specify types for expression generation or matching
>>> as there exists a workaround (by using C expressions for
>>> the generation part and an appropriate if-expression for the
>>> matching part).
>>>
>>>> * ICE for transform sqrt (x * x) -> x
>>>> The following pattern results in ICE (gimple-match-head.c:546)
>>>> (match_and_simplify
>>>>   (built_in_sqrt (mult @0 @0))
>>>>   @0)
>>>>
>>>> I triggered the pattern with this test-case:
>>>> double foo(double x)
>>>> {
>>>>   double t1, t2;
>>>>   t1 = x * x;
>>>>   t2 = sqrt (t1);
>>>>   return t2;
>>>> }
>>>>
>>>> This happens because the following assert fails in
>>>> bool gimple_match_and_simplify (gimple_stmt_iterator *gsi, tree
>>>> (*valueize)(tree)): line 546:
>>>> gcc_assert (gimple_seq_singleton_p (tail));
>>>>
>>>> I guess that happens because for the above pattern
>>>> maybe_push_res_to_seq() returns ops[0], and tail remains NULL.
>>>>
>>>> if (TREE_CODE_LENGTH ((tree_code) rcode) == 0
>>>>    && is_gimple_val (ops[0]))
>>>>      return ops[0];
>>>>
>>>> Unfortunately, I couldn't find a fix.
>>>
>>> Ah, at this point we have a call which we'd like to replace with
>>> a SSA name result.  But maybe_push_res_to_seq only pushes
>>> if necessary (and for an SSA name or a constant it is not so),
>>> but here it's always necessary.
>>>
>>>> I have a couple of questions regarding gimple-match-head.c
>>>>
>>>> a) Why do we return if the above condition is true ?
>>>> I mean why don't we want gimple_build_assign_with_ops to be called
>>>> if that's true ?
>>>
>>> Because in all other callers this results in more optimal code.
>>>
>>>> Removing that condition in maybe_push_res_to_seq or calling
>>>> gimple_build_assign_with_ops (rcode, lhs, ops[0], NULL_TREE, NULL_TREE,
>>>>                                              NULL_TREE);
>>>> from gimple_match_and_simplify (if maybe_push_res_to_seq returns ops[0]),
>>>> resulted in verify_ssa failed: missing definition.
>>>
>>> Yeah, I have a fix for that as well.  The call handling code is pretty
>>> new and likely needs some fixes.  I'll be available to fix up the
>>> details there (they can be tricky).
>>>
>>> Fix in svn now, btw.
>>>
>>>> b) In
>>>> static bool
>>>> gimple_match_and_simplify (gimple stmt,
>>>>                            code_helper *rcode, tree *ops,
>>>>                            gimple_seq *seq, tree (*valueize)(tree))
>>>>
>>>> why do we return false by default (line 491), if number of args is
>>>> greater than 1 ?
>>>
>>> Because I didn't implement support for that yet ;)  Support for
>>> two arguments is the case 1 cut&pasted and all code handling
>>> arg1 duplicated for arg2 as well (and the call to
>>> gimple_match_and_simplify gets an additional argument).
>>> Not sure if the code generation part is in place yet though.
>>>
>>> As said above - call handling was written quickly and only late.
>>>
>>> I'll see to add the two-argument case.
>>
>> Btw, I have a hard time to find a builtin function where handling more than
>> one argument would be useful.  nextafter(3) and friends maybe, but all
>> other "mathematical" builtins have a single argument or use further
>> arguments for extra return values (which we can't handle).
>>
>> So I'll leave it as a single argument for now.
>
> pow (x, y) of course.  Added support and also a testcase for it.
>
> So I came along the need to add another predicate for REAL_CST
> leafs which makes me wonder if we should support tree codes
> as predicates.  Thus instead of writing
>
> (match_and_simplify
>   (plus (plus @0 INTEGER_CST_P@1) INTEGER_CST_P@2)
>   (plus @0 (plus @1 @2)))
>
> write
>
> (match_and_simplify
>   (plus (plus @0 INTEGER_CST@1) INTEGER_CST@2)
>   (plus @0 (plus @1 @2)))
>
> we have conveniently choosen lower-case without _EXPR for
> expression codes thus the uppercase original form is available
> to be used as pre-defined predicate (code generated is
> TREE_CODE (x) == <predicate-name>).
>
> Just an idea ...
It appears to be good. However would we want predicates that are
slightly more complex ?
For example, integer_onep @0 ?
I was wondering if it would be a good idea to make predicate an
attribute of operand (expr, capture)
rather than keep predicate as a separate operand ? (since predicates
are only used for checking the operand they are
applied to).

The hierarchy be something like:

struct predicate_operand: public operand
{
  predicate_operand (const char *ident_, enum operand::type ty) :
operand (ty), ident (ident_) {}
  const char *ident;
  virtual void gen_gimple_match (FILE *f, const char *, const char *);
  virtual void gen_gimple_transform (FILE *, const char *) = 0;
};

struct capture : public predicate_operand
{
  capture (const char *where_, operand *what_, const char *pred = 0)
      : predicate_operand (pred, OP_CAPTURE), where (where_), what (what_) {}
  const char *where;
  operand *what;
  virtual void gen_gimple_match (FILE *f, const char *, const char *);
  virtual void gen_gimple_transform (FILE *f, const char *);
};
And make capture::gen_gimple_match call
predicate_operand::gen_gimple_match if ident is non-null.
similarly for expr.


>
> Richard.
>
>> Richard.
>>
>>> I'll review the testcase patch separately.
>>>
>>> Thanks,
>>> Richard.
>>>
>>>> Thanks and Regards,
>>>> Prathamesh
>>>>>
>>>>> Richard.
>>>>>
>>>>>> Thanks and Regards,
>>>>>> Prathamesh
>>>>>>
>>>>>>
>>>>>>> Andreas.
>>>>>>>
>>>>>>> --
>>>>>>> Andreas Schwab, schwab@linux-m68k.org
>>>>>>> GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
>>>>>>> "And now for something completely different."


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]