This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][match-and-simplify] Fix comparison operator type handling
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 16 Sep 2014 11:10:06 +0200 (CEST)
- Subject: [PATCH][match-and-simplify] Fix comparison operator type handling
- Authentication-results: sourceware.org; auth=none
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard.
2014-09-16 Richard Biener <rguenther@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)