===================================================================
@@ -107,6 +107,19 @@ along with GCC; see the file COPYING3.
(abs @0))
+/* From fold_unary. */
+
+/* (T1)(~(T2) X) -> ~(T1) X */
+(simplify
+ (convert (bit_not@0 (convert @1)))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1)))
+ (bit_not (convert (bit_not @0)))))
+
+
#include "match-plusminus.pd"
#include "match-bitwise.pd"
#include "match-rotate.pd"
===================================================================
@@ -238,14 +238,14 @@ struct operand {
enum op_type { OP_PREDICATE, OP_EXPR, OP_CAPTURE, OP_C_EXPR };
operand (enum op_type type_) : type (type_) {}
enum op_type type;
- virtual void gen_transform (FILE *f, const char *, bool, int) = 0;
+ virtual void gen_transform (FILE *f, const char *, bool, int, const char *) = 0;
};
struct predicate : public operand
{
predicate (const char *ident_) : operand (OP_PREDICATE), ident (ident_) {}
const char *ident;
- virtual void gen_transform (FILE *, const char *, bool, int)
+ virtual void gen_transform (FILE *, const char *, bool, int, const char *)
{ gcc_unreachable (); }
};
@@ -263,7 +263,7 @@ struct expr : public operand
void append_op (operand *op) { ops.safe_push (op); }
e_operation *operation;
vec<operand *> ops;
- virtual void gen_transform (FILE *f, const char *, bool, int);
+ virtual void gen_transform (FILE *f, const char *, bool, int, const char *);
};
struct c_expr : public operand
@@ -286,7 +286,7 @@ struct c_expr : public operand
char *fname;
vec<id_tab> ids;
- virtual void gen_transform (FILE *f, const char *, bool, int);
+ virtual void gen_transform (FILE *f, const char *, bool, int, const char *);
void output_code (FILE *f, bool);
};
@@ -296,7 +296,7 @@ struct capture : public operand
: operand (OP_CAPTURE), where (where_), what (what_) {}
const char *where;
operand *what;
- virtual void gen_transform (FILE *f, const char *, bool, int);
+ virtual void gen_transform (FILE *f, const char *, bool, int, const char *);
};
template<>
@@ -860,32 +860,71 @@ check_no_user_id (simplify *s)
/* Code gen off the AST. */
void
-expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth)
+expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth,
+ const char *in_type)
{
+ bool is_conversion = false;
+ if (*operation->op == CONVERT_EXPR
+ || *operation->op == NOP_EXPR
+ || *operation->op == FLOAT_EXPR
+ || *operation->op == FIX_TRUNC_EXPR)
+ is_conversion = true;
+
+ const char *type;
+ char optype[20];
+ if (is_conversion)
+ /* For conversions we need to build the expression using the
+ outer type passed in. */
+ type = in_type;
+ else
+ {
+ /* Other operations are of the same type as their first operand. */
+ sprintf (optype, "TREE_TYPE (ops%d[0])", depth);
+ type = optype;
+ }
+ if (!type)
+ fatal ("two conversions in a row");
+
fprintf (f, "{\n");
fprintf (f, " tree ops%d[%u], res;\n", depth, ops.length ());
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);
+ ops[i]->gen_transform (f, dest, gimple, depth + 1,
+ is_conversion
+ /* 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));
}
+
if (gimple)
{
/* ??? 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])",
- operation->op->id, depth);
+ " res = gimple_simplify (%s, %s",
+ operation->op->id, type);
for (unsigned i = 0; i < ops.length (); ++i)
fprintf (f, ", ops%d[%u]", depth, i);
fprintf (f, ", seq, valueize);\n");
fprintf (f, " if (!res) return false;\n");
fprintf (f, " }\n");
fprintf (f, " else\n");
- fprintf (f, " res = gimple_build (seq, UNKNOWN_LOCATION, %s, "
- "TREE_TYPE (ops%d[0])", operation->op->id, depth);
+ fprintf (f, " res = gimple_build (seq, UNKNOWN_LOCATION, %s, %s",
+ operation->op->id, type);
for (unsigned i = 0; i < ops.length (); ++i)
fprintf (f, ", ops%d[%u]", depth, i);
fprintf (f, ", valueize);\n");
@@ -893,8 +932,8 @@ expr::gen_transform (FILE *f, const char
else
{
if (operation->op->kind == id_base::CODE)
- fprintf (f, " res = fold_build%d (%s, TREE_TYPE (ops%d[0])",
- ops.length(), operation->op->id, depth);
+ fprintf (f, " res = fold_build%d (%s, %s",
+ ops.length(), operation->op->id, type);
else
fprintf (f, " res = build_call_expr (builtin_decl_implicit (%s), %d",
operation->op->id, ops.length());
@@ -965,7 +1004,7 @@ c_expr::output_code (FILE *f, bool for_f
void
-c_expr::gen_transform (FILE *f, const char *dest, bool, int)
+c_expr::gen_transform (FILE *f, const char *dest, bool, int, const char *)
{
/* If this expression has an outlined function variant, call it. */
if (fname)
@@ -985,7 +1024,7 @@ c_expr::gen_transform (FILE *f, const ch
}
void
-capture::gen_transform (FILE *f, const char *dest, bool, int)
+capture::gen_transform (FILE *f, const char *dest, bool, int, const char *)
{
fprintf (f, "%s = captures[%s];\n", dest, where);
}
@@ -1673,7 +1712,7 @@ dt_simplify::gen_gimple (FILE *f)
for (unsigned i = s->ifexpr_vec.length (); i; --i)
{
fprintf (f, "(");
- s->ifexpr_vec[i - 1]->gen_transform (f, NULL, true, 1);
+ s->ifexpr_vec[i - 1]->gen_transform (f, NULL, true, 1, "type");
fprintf (f, ")");
if (i > 1)
fprintf (f, " && ");
@@ -1691,7 +1730,7 @@ dt_simplify::gen_gimple (FILE *f)
{
char dest[32];
snprintf (dest, 32, " res_ops[%d]", j);
- e->ops[j]->gen_transform (f, dest, true, 1);
+ e->ops[j]->gen_transform (f, dest, true, 1, "type");
}
/* Re-fold the toplevel result. It's basically an embedded
gimple_build w/o actually building the stmt. */
@@ -1701,7 +1740,7 @@ dt_simplify::gen_gimple (FILE *f)
else if (s->result->type == operand::OP_CAPTURE
|| s->result->type == operand::OP_C_EXPR)
{
- s->result->gen_transform (f, "res_ops[0]", true, 1);
+ s->result->gen_transform (f, "res_ops[0]", true, 1, "type");
fprintf (f, "*res_code = TREE_CODE (res_ops[0]);\n");
}
else
@@ -1738,7 +1777,7 @@ dt_simplify::gen_generic (FILE *f)
for (unsigned i = s->ifexpr_vec.length (); i; --i)
{
fprintf (f, "(");
- s->ifexpr_vec[i - 1]->gen_transform (f, NULL, false, 1);
+ s->ifexpr_vec[i - 1]->gen_transform (f, NULL, false, 1, "type");
fprintf (f, ")");
if (i > 1)
fprintf (f, " && ");
@@ -1757,7 +1796,7 @@ dt_simplify::gen_generic (FILE *f)
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);
+ e->ops[j]->gen_transform (f, dest, false, 1, "type");
}
/* Re-fold the toplevel result. */
if (e->operation->op->kind == id_base::CODE)
@@ -1774,7 +1813,7 @@ dt_simplify::gen_generic (FILE *f)
|| s->result->type == operand::OP_C_EXPR)
{
fprintf (f, " tree res;\n");
- s->result->gen_transform (f, " res", false, 1);
+ s->result->gen_transform (f, " res", false, 1, "type");
fprintf (f, " return res;\n");
}
else