This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [match-and-simplify] express conversions in transform ?
- From: Prathamesh Kulkarni <bilbotheelffriend at gmail dot com>
- To: Richard Biener <richard dot guenther at gmail dot com>
- Cc: gcc <gcc at gcc dot gnu dot org>
- Date: Thu, 21 Aug 2014 14:12:16 +0530
- Subject: Re: [match-and-simplify] express conversions in transform ?
- Authentication-results: sourceware.org; auth=none
- References: <CAJXstsDabCQdw9EmdYSdE5puCdrEv6jLArwPRPbLbnJatJ_BkQ at mail dot gmail dot com> <CAFiYyc2SUmOYdUYEwA1g3WaSRi_-cmEAbXvGVhCqXWv_YTxr_w at mail dot gmail dot com>
On Tue, Aug 19, 2014 at 4:35 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Tue, Aug 19, 2014 at 12:18 PM, Prathamesh Kulkarni
> <bilbotheelffriend@gmail.com> wrote:
>> I was wondering how to write transform that involves conversions
>> (without using c_expr) ?
>> for eg:
>> (T1)(~(T2) X) -> ~(T1) X
>> // T1, T2 has same precision and X is an integral type not narrower than T1, T2
>>
>> this could be written as:
>> (simplify
>> (convert (bit_not (convert@0 integral_op_p@1)))
>> if-expr
>> transform)
>>
>> How would the transform be written ?
>> with c_expr we could probably write as: (is that correct?)
>> (bit_not { fold_convert (type, @1); })
>
> No, unfortunately while that's correct for GENERIC it doesn't work
> for GIMPLE code-gen. c_exprs are required to evaluate to
> "atomics", that is, non-expressions.
>
>> I was wondering whether we should have an explicit support for
>> conversions (something equivalent of "casting") ?
>> sth like:
>> (bit_not (cast type @0))
>
> Indeed simply writing
>
> (bit_not (convert @1))
>
> will make the code-generator "convert" @0 to its own type
> (I knew the hack to simply use the first operands type is not
> going to work in all cases... ;). Other conversion operators
> include FIX_TRUNC_EXPR (float -> int), FLOAT_EXPR
> (int -> float).
>
> For most cases it works by accident as the outermost expression
> knows its type via 'type'.
>
> In the cases where we need to specify a type I'd like to avoid
> making the type-converting operators take an additional operand.
> Instead can we make it use a operator flag-with-argument? Like
>
> (bit_not (convert:type @1))
>
> or for the type of a capture (convert:t@2 @1).
>
> We can also put in some more intelligence in automatically
> determining the type to convert to. In your example we
> know the bit_not is of type 'type' and this has to match
> the type of its operands thus the 'convert' needs to convert
> to 'type' as well. I'm sure there are cases we can't
> auto-compute though, like chains of conversions (but not sure
> they matter in practice).
>
> So let's try that - Micha will like more intelligence in the generator ;)
>
> I suggest to add a predicate to the generator conversion_op_p
> to catch the various converting operators and then assert that
> during code-gen we are going to create it with 'type' (outermost
> type), not TREE_TYPE (ops[0]). Then start from the cases
> we want to support and special-case (which requires passing
> down the type of the enclosing expression).
Um sorry, I am not sure if I understood that correctly.
How would conversion_op_p know when to use 'type' and not TREE_TYPE (ops[0]) ?
conversion_op_p would be used somewhat similar to in the attached
patch (illustrate only) ?
Thanks,
Prathamesh
>
> Thanks,
> Richard.
>
>> in case we want to cast to a type of another capture
>> we could use:
>> (foo (cast (type @0) @1)) ? // cast @1 to @0's type
>> here type would be an operator that extracts type of the capture.
>>
>> Another use of having type as an operator I guess would be for
>> type-matching (not sure if it's useful).
>> for instance:
>> (foo (bar @0 @1) @(type @0)@1)
>> that checks if @0, @1 have same types.
>>
>> I was wondering on the same lines if we could introduce new
>> keyword "precision" analogous to type ?
>> (precision @0) would be short-hand for
>> TYPE_PRECISION (TREE_TYPE (@0))
>>
>> So far I found couple patterns in fold_unary_loc with conversions
>> in transform:
>> (T1)(X p+ Y) into ((T1)X p+ Y)
>> (T1)(~(T2) X) -> ~(T1) X
>> (T1) (X * Y) -> (T1) X * (T1) Y
>>
>> Thanks,
>> Prathamesh
Index: genmatch.c
===================================================================
--- genmatch.c (revision 214258)
+++ genmatch.c (working copy)
@@ -859,6 +859,18 @@ check_no_user_id (simplify *s)
/* Code gen off the AST. */
+bool
+conversion_op_p (e_operation *oper)
+{
+ if (strcmp (oper->op->id, "CONVERT_EXPR") != 0
+ && strcmp (oper->op->id, "FIX_TRUNC_EXPR") != 0
+ && strcmp (oper->op->id, "FLOAT_EXPR") != 0)
+ return false;
+
+ // ??? how to assert convert should use 'type'
+ return false;
+}
+
void
expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth)
{
@@ -875,9 +887,13 @@ expr::gen_transform (FILE *f, const char
/* ??? Have another helper that is like gimple_build but may
fail if seq == NULL. */
fprintf (f, " if (!seq)\n"
- " {\n"
- " res = gimple_simplify (%s, TREE_TYPE (ops%d[0])",
+ " {\n");
+ if (!conversion_op_p (operation))
+ fprintf (f, " res = gimple_simplify (%s, TREE_TYPE (ops%d[0])",
operation->op->id, depth);
+ else
+ fprintf (f, " res = gimple_simplify (%s, type", operation->op->id);
+
for (unsigned i = 0; i < ops.length (); ++i)
fprintf (f, ", ops%d[%u]", depth, i);
fprintf (f, ", seq, valueize);\n");