On Fri, Nov 7, 2014 at 2:23 AM, Richard Biener <rguent...@suse.de> wrote: > On Thu, 6 Nov 2014, Andrew Pinski wrote: > >> On Thu, Nov 6, 2014 at 2:40 AM, Richard Biener <rguent...@suse.de> wrote: >> > On Thu, 6 Nov 2014, Richard Biener wrote: >> > >> >> On Wed, 5 Nov 2014, Andrew Pinski wrote: >> >> >> >> > Hi, >> >> > I was trying to hook up tree-ssa-phiopt to match-and-simplify using >> >> > either gimple_build (or rather using gimple_simplify depending on if >> >> > we want to produce cond_expr for conditional move). I ran into a >> >> > problem. >> >> > With the pattern below: >> >> > /* a ? 0 : 1 -> a if 0 and 1 are integral types. */ >> >> > (simplify >> >> > (cond_expr @0 integer_zerop integer_onep) >> >> > (if (INTEGRAL_TYPE_P (type)) >> >> > (convert @0))) >> >> >> >> Ok, so you are capturing a GENERIC expr here but nothing knows that. >> >> It would work if you'd do (ugh) >> >> >> >> (for op (lt le eq ne ge gt) >> >> (simplify >> >> (cond_expr (op @0 @1) integer_zerop integer_onep) >> >> (if (INTEGRAL_TYPE_P (type)) >> >> (convert (op @0 @1))))) >> >> (simplify >> >> (cond_expr SSA_NAME@0 integer_zerop integer_onep) >> >> (if (INTEGRAL_TYPE_P (type)) >> >> (convert @0)))) >> >> >> >> as a workaround. To make your version work will require (quite) >> >> some special-casing in the code generator or maybe the resimplify >> >> helper. Let me see if I can cook up a "simple" fix. >> > >> > Sth like below (for the real fix this has to be replicated in >> > all gimple_resimplifyN functions). I'm missing a testcase >> > where the pattern would apply (and not be already folded by fold), >> > so I didn't check if it actually works. >> >> You do need to check if seq is NULL though as gimple_build depends on >> seq not being NULL. But otherwise yes this works for me. > > Ok, here is a better and more complete fix. The optimization > whether a captured expression may be a GENERIC condition isn't > implemented so a lot of checks are emitted right now. Also > if gimple_build would fail this terminates the whole matching > process, not just matching of the current pattern (failing "late" > isn't supported with the style of code we emit - well, without > adding ugly gotos and labels). > > At least it avoids splitting up conditions if substituted into > a COND_EXPR, so simplifications of COND_EXPRs in-place (w/o seq) > should still work. > > Can you check whether this works for you?
This works for most cases but does not work for things like: /* a != b ? a : b -> a */ (simplify (cond_expr (ne @0 @1) @0 @1) @0) In gimple_simplify after it matches COND_EXPR. It does not look into the operand 0 to see if it matches NE_EXPR, it just sees if it was a SSA_NAME. In this case I was trying to do a simple replacement of value_replacement in tree-ssa-phiopt.c. But for my purpose right now this is sufficient and will be posting a patch which does not remove things from tree-ssa-phiopt.c just yet. Thanks, Andrew Pinski > > Thanks, > Richard. > > > > Index: gcc/genmatch.c > =================================================================== > --- gcc/genmatch.c (revision 217213) > +++ gcc/genmatch.c (working copy) > @@ -419,7 +419,8 @@ struct operand { > operand (enum op_type type_) : type (type_) {} > enum op_type type; > virtual void gen_transform (FILE *, const char *, bool, int, > - const char *, dt_operand ** = 0) > + const char *, dt_operand ** = 0, > + bool = true) > { gcc_unreachable (); } > }; > > @@ -449,7 +450,7 @@ struct expr : public operand > later lowered to two separate patterns. */ > bool is_commutative; > virtual void gen_transform (FILE *f, const char *, bool, int, > - const char *, dt_operand ** = 0); > + const char *, dt_operand ** = 0, bool = true); > }; > > /* An operator that is represented by native C code. This is always > @@ -479,7 +480,7 @@ struct c_expr : public operand > /* The identifier replacement vector. */ > vec<id_tab> ids; > virtual void gen_transform (FILE *f, const char *, bool, int, > - const char *, dt_operand **); > + const char *, dt_operand ** = 0, bool = true); > }; > > /* A wrapper around another operand that captures its value. */ > @@ -493,7 +494,7 @@ struct capture : public operand > /* The captured value. */ > operand *what; > virtual void gen_transform (FILE *f, const char *, bool, int, > - const char *, dt_operand ** = 0); > + const char *, dt_operand ** = 0, bool = true); > }; > > template<> > @@ -1358,7 +1359,7 @@ get_operand_type (id_base *op, const cha > > void > expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth, > - const char *in_type, dt_operand **indexes) > + const char *in_type, dt_operand **indexes, bool) > { > bool conversion_p = is_conversion (operation); > const char *type = expr_type; > @@ -1405,7 +1406,10 @@ expr::gen_transform (FILE *f, const char > const char *optype > = get_operand_type (operation, in_type, expr_type, > i == 0 ? NULL : op0type); > - ops[i]->gen_transform (f, dest, gimple, depth + 1, optype, indexes); > + ops[i]->gen_transform (f, dest, gimple, depth + 1, optype, indexes, > + ((!(*operation == COND_EXPR) > + && !(*operation == VEC_COND_EXPR)) > + || i != 0)); > } > > const char *opr; > @@ -1455,7 +1459,7 @@ expr::gen_transform (FILE *f, const char > > void > c_expr::gen_transform (FILE *f, const char *dest, > - bool, int, const char *, dt_operand **) > + bool, int, const char *, dt_operand **, bool) > { > if (dest && nr_stmts == 1) > fprintf (f, "%s = ", dest); > @@ -1524,7 +1528,8 @@ c_expr::gen_transform (FILE *f, const ch > > void > capture::gen_transform (FILE *f, const char *dest, bool gimple, int depth, > - const char *in_type, dt_operand **indexes) > + const char *in_type, dt_operand **indexes, > + bool expand_compares) > { > if (what && is_a<expr *> (what)) > { > @@ -1537,6 +1542,24 @@ capture::gen_transform (FILE *f, const c > } > > fprintf (f, "%s = captures[%u];\n", dest, where); > + > + /* ??? Stupid tcc_comparison GENERIC trees in COND_EXPRs. Deal > + with substituting a capture of that. > + ??? We can optimize this in the generator because we should > + know whether this capture is from a COND_EXPR condition. Also > + technically splitting the comparison up isn't required if we > + are substituting into a COND_EXPR condition (so simplification > + may unnecessarily fail if seq is NULL and a toplevel cond result). > + ??? Returning false here will also not allow any other patterns > + to match. */ > + if (gimple && expand_compares) > + fprintf (f, "if (COMPARISON_CLASS_P (%s))\n" > + " {\n" > + " if (!seq) return false;\n" > + " %s = gimple_build (seq, TREE_CODE (%s)," > + " TREE_TYPE (%s), TREE_OPERAND (%s, 0)," > + " TREE_OPERAND (%s, 1));\n" > + " }\n", dest, dest, dest, dest, dest, dest); > } > > /* Return the name of the operand representing the decision tree node. > @@ -1999,7 +2022,8 @@ capture_info::walk_match (operand *o, un > { > bool cond_p = conditional_p; > if (i == 0 > - && *e->operation == COND_EXPR) > + && (*e->operation == COND_EXPR > + || *e->operation == VEC_COND_EXPR)) > cond_p = true; > else if (*e->operation == TRUTH_ANDIF_EXPR > || *e->operation == TRUTH_ORIF_EXPR) > @@ -2046,7 +2070,8 @@ capture_info::walk_result (operand *o, b > { > bool cond_p = conditional_p; > if (i == 0 > - && *e->operation == COND_EXPR) > + && (*e->operation == COND_EXPR > + || *e->operation == VEC_COND_EXPR)) > cond_p = true; > else if (*e->operation == TRUTH_ANDIF_EXPR > || *e->operation == TRUTH_ORIF_EXPR) > @@ -2226,7 +2251,11 @@ dt_simplify::gen (FILE *f, bool gimple) > "type", e->expr_type, > j == 0 > ? NULL : "TREE_TYPE (res_ops[0])"); > - e->ops[j]->gen_transform (f, dest, true, 1, optype, indexes); > + e->ops[j]->gen_transform (f, dest, true, 1, optype, indexes, > + !is_predicate > + && ((!(*e->operation == COND_EXPR) > + && !(*e->operation == > VEC_COND_EXPR)) > + || j != 0)); > } > > /* Re-fold the toplevel result. It's basically an embedded > @@ -2238,8 +2267,21 @@ dt_simplify::gen (FILE *f, bool gimple) > else if (result->type == operand::OP_CAPTURE > || result->type == operand::OP_C_EXPR) > { > - result->gen_transform (f, "res_ops[0]", true, 1, "type", indexes); > - fprintf (f, "*res_code = TREE_CODE (res_ops[0]);\n"); > + result->gen_transform (f, "res_ops[0]", true, 1, "type", > + indexes, false); > + /* ??? Stupid tcc_comparison GENERIC trees in COND_EXPRs. Deal > + with substituting a capture of that. > + ??? We can optimize this in the generator because we should > + know whether this capture is from a COND_EXPR condition. */ > + fprintf (f, "if (COMPARISON_CLASS_P (res_ops[0]))\n" > + " {\n" > + " tree tem = res_ops[0];\n" > + " res_ops[0] = TREE_OPERAND (tem, 0);\n" > + " res_ops[1] = TREE_OPERAND (tem, 1);\n" > + " *res_code = TREE_CODE (tem);\n" > + " }\n" > + "else\n" > + " *res_code = TREE_CODE (res_ops[0]);\n"); > } > else > gcc_unreachable ();