On Tue, Aug 19, 2014 at 4:35 PM, Richard Biener <richard.guent...@gmail.com> wrote: > On Tue, Aug 19, 2014 at 12:18 PM, Prathamesh Kulkarni > <bilbotheelffri...@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");