>> 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 ?
In principle predicates are not different from expressions: (plus @0 INTEGER_CST) is similar to (plus @0 (INTEGER_CST)) that is, if INTEGER_CST is treated as zero-operand "expression". > 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. I don't understand. predicate is already derived from operand, so is capture. How would you write (plus @0 integer_zerop) differently? Here 'integer_zerop' is an operand of the plus expression. To me predicate (and capture without expression or predicate) differs from expression in that predicate is clearly a leaf of the expression tree while we have to recurse into expression operands. Now, if we want to support applying predicates to the midst of an expression, like (plus predicate(minus @0 @1) @2) (...) then this would no longer be true. At the moment you'd write (plus (minus@3 @0 @1) @2) if (predicate (@3)) (...) which makes it clearer IMHO (with the decision tree building you'd apply the predicates after matching the expression tree anyway I suppose, so code generation would be equivalent). One exception may be types of (sub-)expressions which we can also check cheaply (and eventually build into the decision tree) (cheaply == doesn't involve function calls). So for the if-expressions like (match_and_simplify (plus @0 (negate @1)) if (!TYPE_SATURATING (TREE_TYPE (@0))) (minus @0 @1)) we'd ideally want to group all patterns with the same type-related if-expression to improve the matching process. That eventually asks for sth like if (!TYPE_SATURATING (TREE_TYPE (@0))) { (match_and_simplify (plus @0 (negate @1)) (minus @0 @1)) (match_and_simplify (plus (negate @0) @1) (minus @1 @0) } thus have multiple patterns with a common "outer" if-expression. If you look into fold-const.c we have this kind of grouping used there to group for example cases valid only for !FLOAT_TYPE_P or INTEGRAL_TYPE_P. IMHO we can think about this when the individual if-expressions become too many. I don't like the idea of applying predicates to non-leafs in the match expression itself. Richard.