genmatch.c (verbose): New global.

2015-07-30  Richard Biener  <rguenther@suse.de>

	* genmatch.c (verbose): New global.
	(warning_at): Add overload with source_location.
	(capture_info::capture_info): Add bool whether generating gimple
	or generic.  Add gimple member.
	(capture_info::cinfo): Add capture member.
	(capture_info::walk_match): Record capture.  Warn on
	non-captured leafs.
	(capture_info::walk_c_expr): Add more fragments captures cannot
	escape through.  Warn on escaped captures.
	(dt_simplify::gen_1): Warn on operands we force to have no
	side-effects.
	(main): Initialize verbose.
	* match.pd: Add integer_nonzerop and HONOR_NANS predicates.

From-SVN: r226386
This commit is contained in:
Richard Biener 2015-07-30 07:56:23 +00:00 committed by Richard Biener
parent f501d5cd99
commit 53a19317f4
3 changed files with 92 additions and 21 deletions

View File

@ -1,3 +1,19 @@
2015-07-30 Richard Biener <rguenther@suse.de>
* genmatch.c (verbose): New global.
(warning_at): Add overload with source_location.
(capture_info::capture_info): Add bool whether generating gimple
or generic. Add gimple member.
(capture_info::cinfo): Add capture member.
(capture_info::walk_match): Record capture. Warn on
non-captured leafs.
(capture_info::walk_c_expr): Add more fragments captures cannot
escape through. Warn on escaped captures.
(dt_simplify::gen_1): Warn on operands we force to have no
side-effects.
(main): Initialize verbose.
* match.pd: Add integer_nonzerop and HONOR_NANS predicates.
2015-07-30 Richard Biener <rguenther@suse.de>
PR middle-end/67053

View File

@ -43,6 +43,12 @@ void ggc_free (void *)
}
/* Global state. */
/* Verboseness. 0 is quiet, 1 adds some warnings, 2 is for debugging. */
unsigned verbose;
/* libccp helpers. */
static struct line_maps *line_table;
@ -126,6 +132,18 @@ warning_at (const cpp_token *tk, const char *msg, ...)
va_end (ap);
}
static void
#if GCC_VERSION >= 4001
__attribute__((format (printf, 2, 3)))
#endif
warning_at (source_location loc, const char *msg, ...)
{
va_list ap;
va_start (ap, msg);
error_cb (NULL, CPP_DL_WARNING, 0, loc, 0, msg, &ap);
va_end (ap);
}
/* Like fprintf, but print INDENT spaces at the beginning. */
static void
@ -1599,7 +1617,7 @@ decision_tree::print (FILE *f)
struct capture_info
{
capture_info (simplify *s, operand *);
capture_info (simplify *s, operand *, bool);
void walk_match (operand *o, unsigned toplevel_arg, bool, bool);
bool walk_result (operand *o, bool, operand *);
void walk_c_expr (c_expr *);
@ -1614,16 +1632,20 @@ struct capture_info
unsigned long toplevel_msk;
int result_use_count;
unsigned same_as;
capture *c;
};
auto_vec<cinfo> info;
unsigned long force_no_side_effects;
bool gimple;
};
/* Analyze captures in S. */
capture_info::capture_info (simplify *s, operand *result)
capture_info::capture_info (simplify *s, operand *result, bool gimple_)
{
gimple = gimple_;
expr *e;
if (s->kind == simplify::MATCH)
{
@ -1661,6 +1683,8 @@ capture_info::walk_match (operand *o, unsigned toplevel_arg,
info[where].toplevel_msk |= 1 << toplevel_arg;
info[where].force_no_side_effects_p |= conditional_p;
info[where].cond_expr_cond_p |= cond_expr_cond_p;
if (!info[where].c)
info[where].c = c;
if (!c->what)
return;
/* Recurse to exprs and captures. */
@ -1710,6 +1734,10 @@ capture_info::walk_match (operand *o, unsigned toplevel_arg,
{
/* Mark non-captured leafs toplevel arg for checking. */
force_no_side_effects |= 1 << toplevel_arg;
if (verbose >= 1
&& !gimple)
warning_at (o->location,
"forcing no side-effects on possibly lost leaf");
}
else
gcc_unreachable ();
@ -1801,15 +1829,25 @@ capture_info::walk_result (operand *o, bool conditional_p, operand *result)
void
capture_info::walk_c_expr (c_expr *e)
{
/* Give up for C exprs mentioning captures not inside TREE_TYPE (). */
/* Give up for C exprs mentioning captures not inside TREE_TYPE,
TREE_REAL_CST, TREE_CODE or a predicate where they cannot
really escape through. */
unsigned p_depth = 0;
for (unsigned i = 0; i < e->code.length (); ++i)
{
const cpp_token *t = &e->code[i];
const cpp_token *n = i < e->code.length () - 1 ? &e->code[i+1] : NULL;
id_base *id;
if (t->type == CPP_NAME
&& strcmp ((const char *)CPP_HASHNODE
(t->val.node.node)->ident.str, "TREE_TYPE") == 0
&& (strcmp ((const char *)CPP_HASHNODE
(t->val.node.node)->ident.str, "TREE_TYPE") == 0
|| strcmp ((const char *)CPP_HASHNODE
(t->val.node.node)->ident.str, "TREE_CODE") == 0
|| strcmp ((const char *)CPP_HASHNODE
(t->val.node.node)->ident.str, "TREE_REAL_CST") == 0
|| ((id = get_operator ((const char *)CPP_HASHNODE
(t->val.node.node)->ident.str))
&& is_a <predicate_id *> (id)))
&& n->type == CPP_OPEN_PAREN)
p_depth++;
else if (t->type == CPP_CLOSE_PAREN
@ -1828,6 +1866,9 @@ capture_info::walk_c_expr (c_expr *e)
id = (const char *)CPP_HASHNODE (n->val.node.node)->ident.str;
unsigned where = *e->capture_ids->get(id);
info[info[where].same_as].force_no_side_effects_p = true;
if (verbose >= 1
&& !gimple)
warning_at (t, "capture escapes");
}
}
}
@ -2662,25 +2703,37 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
/* Analyze captures and perform early-outs on the incoming arguments
that cover cases we cannot handle. */
capture_info cinfo (s, result);
capture_info cinfo (s, result, gimple);
if (s->kind == simplify::SIMPLIFY)
{
if (!gimple)
{
for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i)
if (cinfo.force_no_side_effects & (1 << i))
fprintf_indent (f, indent,
"if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n",
i);
{
fprintf_indent (f, indent,
"if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n",
i);
if (verbose >= 1)
warning_at (as_a <expr *> (s->match)->ops[i]->location,
"forcing toplevel operand to have no "
"side-effects");
}
for (int i = 0; i <= s->capture_max; ++i)
if (cinfo.info[i].cse_p)
;
else if (cinfo.info[i].force_no_side_effects_p
&& (cinfo.info[i].toplevel_msk
& cinfo.force_no_side_effects) == 0)
fprintf_indent (f, indent,
"if (TREE_SIDE_EFFECTS (captures[%d])) "
"return NULL_TREE;\n", i);
{
fprintf_indent (f, indent,
"if (TREE_SIDE_EFFECTS (captures[%d])) "
"return NULL_TREE;\n", i);
if (verbose >= 1)
warning_at (cinfo.info[i].c->location,
"forcing captured operand to have no "
"side-effects");
}
else if ((cinfo.info[i].toplevel_msk
& cinfo.force_no_side_effects) != 0)
/* Mark capture as having no side-effects if we had to verify
@ -4165,7 +4218,6 @@ main (int argc, char **argv)
return 1;
bool gimple = true;
bool verbose = false;
char *input = argv[argc-1];
for (int i = 1; i < argc - 1; ++i)
{
@ -4174,11 +4226,13 @@ main (int argc, char **argv)
else if (strcmp (argv[i], "--generic") == 0)
gimple = false;
else if (strcmp (argv[i], "-v") == 0)
verbose = true;
verbose = 1;
else if (strcmp (argv[i], "-vv") == 0)
verbose = 2;
else
{
fprintf (stderr, "Usage: genmatch "
"[--gimple] [--generic] [-v] input\n");
"[--gimple] [--generic] [-v[v]] input\n");
return 1;
}
}
@ -4235,7 +4289,7 @@ add_operator (VIEW_CONVERT2, "VIEW_CONVERT2", "tcc_unary", 1);
predicate_id *pred = p.user_predicates[i];
lower (pred->matchers, gimple);
if (verbose)
if (verbose == 2)
for (unsigned i = 0; i < pred->matchers.length (); ++i)
print_matches (pred->matchers[i]);
@ -4243,7 +4297,7 @@ add_operator (VIEW_CONVERT2, "VIEW_CONVERT2", "tcc_unary", 1);
for (unsigned i = 0; i < pred->matchers.length (); ++i)
dt.insert (pred->matchers[i], i);
if (verbose)
if (verbose == 2)
dt.print (stderr);
write_predicate (stdout, pred, dt, gimple);
@ -4252,7 +4306,7 @@ add_operator (VIEW_CONVERT2, "VIEW_CONVERT2", "tcc_unary", 1);
/* Lower the main simplifiers and generate code for them. */
lower (p.simplifiers, gimple);
if (verbose)
if (verbose == 2)
for (unsigned i = 0; i < p.simplifiers.length (); ++i)
print_matches (p.simplifiers[i]);
@ -4260,7 +4314,7 @@ add_operator (VIEW_CONVERT2, "VIEW_CONVERT2", "tcc_unary", 1);
for (unsigned i = 0; i < p.simplifiers.length (); ++i)
dt.insert (p.simplifiers[i], i);
if (verbose)
if (verbose == 2)
dt.print (stderr);
if (gimple)

View File

@ -26,11 +26,12 @@ along with GCC; see the file COPYING3. If not see
/* Generic tree predicates we inherit. */
(define_predicates
integer_onep integer_zerop integer_all_onesp integer_minus_onep
integer_each_onep integer_truep
integer_each_onep integer_truep integer_nonzerop
real_zerop real_onep real_minus_onep
CONSTANT_CLASS_P
tree_expr_nonnegative_p
integer_pow2p)
integer_pow2p
HONOR_NANS)
/* Operator lists. */
(define_operator_list tcc_comparison