Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard.
2014-09-16 Richard Biener <rguent...@suse.de> * genmatch.c (operator_id): Add tcc member. (get_operand_type): New function, split out from ... (expr::gen_transform): ... here. Treat comparisons properly. (dt_simplify::gen): Use get_operand_type. Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 215264) +++ gcc/genmatch.c (working copy) @@ -171,12 +171,14 @@ id_base::id_base (id_kind kind_, const c struct operator_id : public id_base { - operator_id (enum tree_code code_, const char *id_, unsigned nargs_) + operator_id (enum tree_code code_, const char *id_, unsigned nargs_, + const char *tcc_) : id_base (id_base::CODE, id_), - code (code_), nargs (nargs_) {} + code (code_), nargs (nargs_), tcc (tcc_) {} unsigned get_required_nargs () const { return nargs; } enum tree_code code; unsigned nargs; + const char *tcc; }; struct fn_id : public id_base @@ -215,7 +217,7 @@ add_operator (enum tree_code code, const /* To have INTEGER_CST and friends as "predicate operators". */ && strcmp (tcc, "tcc_constant") != 0) return; - operator_id *op = new operator_id (code, id, nargs); + operator_id *op = new operator_id (code, id, nargs, tcc); id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); if (*slot) fatal ("duplicate id definition"); @@ -890,6 +892,38 @@ is_conversion (id_base *op) || *op == VIEW_CONVERT_EXPR); } +/* Get the type to be used for generating operands of OP from the + various sources. */ + +static const char * +get_operand_type (id_base *op, const char *in_type, + const char *expr_type, + const char *other_oprnd_type) +{ + /* Generally operands whose type does not match the type of the + expression generated need to know their types but match and + thus can fall back to 'other_oprnd_type'. */ + if (is_conversion (op)) + return other_oprnd_type; + else if (*op == REALPART_EXPR + || *op == IMAGPART_EXPR) + return other_oprnd_type; + else if (is_a <operator_id *> (op) + && strcmp (as_a <operator_id *> (op)->tcc, "tcc_comparison") == 0) + return other_oprnd_type; + else + { + /* Otherwise all types should match - choose one in order of + preference. */ + if (expr_type) + return expr_type; + else if (in_type) + return in_type; + else + return other_oprnd_type; + } +} + /* Code gen off the AST. */ void @@ -912,8 +946,14 @@ expr::gen_transform (FILE *f, const char /* __real and __imag use the component type of its operand. */ sprintf (optype, "TREE_TYPE (TREE_TYPE (ops%d[0]))", depth); type = optype; - /* Avoid passing in_type / type to operand creation. */ - conversion_p = true; + } + else if (is_a <operator_id *> (operation->op) + && strcmp (as_a <operator_id *> (operation->op)->tcc, "tcc_comparison") == 0) + { + /* comparisons use boolean_type_node (or what gets in), but + their operands need to figure out the types themselves. */ + sprintf (optype, "boolean_type_node"); + type = optype; } else { @@ -926,26 +966,16 @@ expr::gen_transform (FILE *f, const char fprintf (f, "{\n"); fprintf (f, " tree ops%d[%u], res;\n", depth, ops.length ()); + char op0type[64]; + snprintf (op0type, 64, "TREE_TYPE (ops%d[0])", depth); for (unsigned i = 0; i < ops.length (); ++i) { char dest[32]; snprintf (dest, 32, " ops%d[%u]", depth, i); - ops[i]->gen_transform (f, dest, gimple, depth + 1, - conversion_p - /* If this op is a conversion its single - operand has to know its type itself. */ - ? NULL - /* For other ops the type is the type - we got passed in, or if that is from - a conversion we can at most use the - first operand type for all further - operands. So (convert (plus @1 (convert @2)) - is possible while - (convert (plus (convert @1) @2)) - is not unless we somehow discover what - operand we can generate first and do it - in the appropriate order. */ - : (i == 0 ? in_type : type)); + const char *optype + = get_operand_type (operation->op, in_type, expr_type, + i == 0 ? NULL : op0type); + ops[i]->gen_transform (f, dest, gimple, depth + 1, optype); } if (gimple) @@ -1804,9 +1834,12 @@ dt_simplify::gen (FILE *f, bool gimple) { char dest[32]; snprintf (dest, 32, " res_ops[%d]", j); - e->ops[j]->gen_transform (f, dest, true, 1, - is_conversion (e->operation->op) - ? NULL : "type"); + const char *optype + = get_operand_type (e->operation->op, + "type", e->expr_type, + j == 0 + ? NULL : "TREE_TYPE (res_ops[0])"); + e->ops[j]->gen_transform (f, dest, true, 1, optype); } /* Re-fold the toplevel result. It's basically an embedded gimple_build w/o actually building the stmt. */ @@ -1833,9 +1866,12 @@ dt_simplify::gen (FILE *f, bool gimple) fprintf (f, " tree res_op%d;\n", j); char dest[32]; snprintf (dest, 32, " res_op%d", j); - e->ops[j]->gen_transform (f, dest, false, 1, - is_conversion (e->operation->op) - ? NULL : "type"); + const char *optype + = get_operand_type (e->operation->op, + "type", e->expr_type, + j == 0 + ? NULL : "TREE_TYPE (res_op0)"); + e->ops[j]->gen_transform (f, dest, false, 1, optype); } /* Re-fold the toplevel result. */ if (e->operation->op->kind == id_base::CODE)