Commit 50f0aa20 by Richard Biener Committed by Richard Biener

re PR tree-optimization/61034 (Optimizing takes too many passes)

2014-05-07  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/61034
	* tree-ssa-alias.c (call_may_clobber_ref_p_1): Export.
	(maybe_skip_until): Use translate to take into account
	lattices when trying to do disambiguations.
	(get_continuation_for_phi_1): Likewise.
	(get_continuation_for_phi): Adjust for added translate
	arguments.
	(walk_non_aliased_vuses): Likewise.
	* tree-ssa-alias.h (get_continuation_for_phi): Adjust
	prototype.
	(walk_non_aliased_vuses): Likewise.
	(call_may_clobber_ref_p_1): Declare.
	* tree-ssa-sccvn.c (vn_reference_lookup_3): Also
	disambiguate against calls.  Stop early if we are
	only supposed to disambiguate.
	* tree-ssa-pre.c (translate_vuse_through_block): Adjust.

	* g++.dg/tree-ssa/pr61034.C: New testcase.

From-SVN: r210160
parent 2588652e
2014-05-07 Richard Biener <rguenther@suse.de>
PR tree-optimization/61034
* tree-ssa-alias.c (call_may_clobber_ref_p_1): Export.
(maybe_skip_until): Use translate to take into account
lattices when trying to do disambiguations.
(get_continuation_for_phi_1): Likewise.
(get_continuation_for_phi): Adjust for added translate
arguments.
(walk_non_aliased_vuses): Likewise.
* tree-ssa-alias.h (get_continuation_for_phi): Adjust
prototype.
(walk_non_aliased_vuses): Likewise.
(call_may_clobber_ref_p_1): Declare.
* tree-ssa-sccvn.c (vn_reference_lookup_3): Also
disambiguate against calls. Stop early if we are
only supposed to disambiguate.
* tree-ssa-pre.c (translate_vuse_through_block): Adjust.
2014-05-07 Joern Rennecke <joern.rennecke@embecosm.com> 2014-05-07 Joern Rennecke <joern.rennecke@embecosm.com>
* config/epiphany/epiphany.c (epiphany_handle_interrupt_attribute): * config/epiphany/epiphany.c (epiphany_handle_interrupt_attribute):
......
2014-05-07 Richard Biener <rguenther@suse.de>
PR tree-optimization/61034
* g++.dg/tree-ssa/pr61034.C: New testcase.
2014-05-07 Joern Rennecke <joern.rennecke@embecosm.com> 2014-05-07 Joern Rennecke <joern.rennecke@embecosm.com>
* gcc.target/epiphany/isr-arg.c: New file. * gcc.target/epiphany/isr-arg.c: New file.
......
// { dg-do compile }
// { dg-options "-O3 -fdump-tree-fre2" }
#define assume(x) if(!(x))__builtin_unreachable()
inline void* operator new(__SIZE_TYPE__ n){ return __builtin_malloc(n); }
inline void operator delete(void *p) { __builtin_free(p); }
struct O {
double num;
int count;
};
struct I {
O *o;
I(double d = 0) : o (new O) { o->num = d; o->count = 1; }
I(I const&i) { assume(i.o->count >= 1); o = i.o; ++o->count; }
I& operator=(I const&i) { I(i).swap(*this); return *this; }
~I() { if (--o->count == 0) delete o; }
void swap(I& i) { O *tmp = o; o = i.o; i.o = tmp; }
I& operator*= (I const&i) {
if (o->count > 1) *this = I(o->num);
o->num *= i.o->num;
return *this;
}
I& operator-= (I const&i) {
if (o->count > 1) *this = I(o->num);
o->num -= i.o->num;
return *this;
}
};
inline I operator* (I a, I const&b) { return a *= b; }
inline I operator- (I a, I const&b) { return a -= b; }
inline bool operator< (I const&a, I const&b) { return a.o->num < b.o->num; }
bool f(I a, I b, I c, I d) {
return (a * d - b * c) * (a * b - c * d) < 42;
}
// We should be able to CSE most references to count and thus remove
// a bunch of conditional free()s and unreachable()s.
// This works only if everything is inlined into 'f'.
// { dg-final { scan-tree-dump-times ";; Function" 1 "fre2" } }
// { dg-final { scan-tree-dump-times "free" 19 "fre2" } }
// { dg-final { scan-tree-dump-times "unreachable" 11 "fre2" } }
// { dg-final { cleanup-tree-dump "fre2" } }
...@@ -1835,7 +1835,7 @@ ref_maybe_used_by_stmt_p (gimple stmt, tree ref) ...@@ -1835,7 +1835,7 @@ ref_maybe_used_by_stmt_p (gimple stmt, tree ref)
/* If the call in statement CALL may clobber the memory reference REF /* If the call in statement CALL may clobber the memory reference REF
return true, otherwise return false. */ return true, otherwise return false. */
static bool bool
call_may_clobber_ref_p_1 (gimple call, ao_ref *ref) call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
{ {
tree base; tree base;
...@@ -2318,7 +2318,9 @@ stmt_kills_ref_p (gimple stmt, tree ref) ...@@ -2318,7 +2318,9 @@ stmt_kills_ref_p (gimple stmt, tree ref)
static bool static bool
maybe_skip_until (gimple phi, tree target, ao_ref *ref, maybe_skip_until (gimple phi, tree target, ao_ref *ref,
tree vuse, unsigned int *cnt, bitmap *visited, tree vuse, unsigned int *cnt, bitmap *visited,
bool abort_on_visited) bool abort_on_visited,
void *(*translate)(ao_ref *, tree, void *, bool),
void *data)
{ {
basic_block bb = gimple_bb (phi); basic_block bb = gimple_bb (phi);
...@@ -2338,7 +2340,8 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref, ...@@ -2338,7 +2340,8 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt)))) if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
return !abort_on_visited; return !abort_on_visited;
vuse = get_continuation_for_phi (def_stmt, ref, cnt, vuse = get_continuation_for_phi (def_stmt, ref, cnt,
visited, abort_on_visited); visited, abort_on_visited,
translate, data);
if (!vuse) if (!vuse)
return false; return false;
continue; continue;
...@@ -2350,7 +2353,13 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref, ...@@ -2350,7 +2353,13 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
/* A clobbering statement or the end of the IL ends it failing. */ /* A clobbering statement or the end of the IL ends it failing. */
++*cnt; ++*cnt;
if (stmt_may_clobber_ref_p_1 (def_stmt, ref)) if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
return false; {
if (translate
&& (*translate) (ref, vuse, data, true) == NULL)
;
else
return false;
}
} }
/* If we reach a new basic-block see if we already skipped it /* If we reach a new basic-block see if we already skipped it
in a previous walk that ended successfully. */ in a previous walk that ended successfully. */
...@@ -2372,7 +2381,9 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref, ...@@ -2372,7 +2381,9 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
static tree static tree
get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1, get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
ao_ref *ref, unsigned int *cnt, ao_ref *ref, unsigned int *cnt,
bitmap *visited, bool abort_on_visited) bitmap *visited, bool abort_on_visited,
void *(*translate)(ao_ref *, tree, void *, bool),
void *data)
{ {
gimple def0 = SSA_NAME_DEF_STMT (arg0); gimple def0 = SSA_NAME_DEF_STMT (arg0);
gimple def1 = SSA_NAME_DEF_STMT (arg1); gimple def1 = SSA_NAME_DEF_STMT (arg1);
...@@ -2386,7 +2397,7 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1, ...@@ -2386,7 +2397,7 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
gimple_bb (def1), gimple_bb (def0)))) gimple_bb (def1), gimple_bb (def0))))
{ {
if (maybe_skip_until (phi, arg0, ref, arg1, cnt, if (maybe_skip_until (phi, arg0, ref, arg1, cnt,
visited, abort_on_visited)) visited, abort_on_visited, translate, data))
return arg0; return arg0;
} }
else if (gimple_nop_p (def1) else if (gimple_nop_p (def1)
...@@ -2394,7 +2405,7 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1, ...@@ -2394,7 +2405,7 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
gimple_bb (def0), gimple_bb (def1))) gimple_bb (def0), gimple_bb (def1)))
{ {
if (maybe_skip_until (phi, arg1, ref, arg0, cnt, if (maybe_skip_until (phi, arg1, ref, arg0, cnt,
visited, abort_on_visited)) visited, abort_on_visited, translate, data))
return arg1; return arg1;
} }
/* Special case of a diamond: /* Special case of a diamond:
...@@ -2414,8 +2425,12 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1, ...@@ -2414,8 +2425,12 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
&& common_vuse == gimple_vuse (def1)) && common_vuse == gimple_vuse (def1))
{ {
*cnt += 2; *cnt += 2;
if (!stmt_may_clobber_ref_p_1 (def0, ref) if ((!stmt_may_clobber_ref_p_1 (def0, ref)
&& !stmt_may_clobber_ref_p_1 (def1, ref)) || (translate
&& (*translate) (ref, arg0, data, true) == NULL))
&& (!stmt_may_clobber_ref_p_1 (def1, ref)
|| (translate
&& (*translate) (ref, arg1, data, true) == NULL)))
return common_vuse; return common_vuse;
} }
...@@ -2432,7 +2447,9 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1, ...@@ -2432,7 +2447,9 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
tree tree
get_continuation_for_phi (gimple phi, ao_ref *ref, get_continuation_for_phi (gimple phi, ao_ref *ref,
unsigned int *cnt, bitmap *visited, unsigned int *cnt, bitmap *visited,
bool abort_on_visited) bool abort_on_visited,
void *(*translate)(ao_ref *, tree, void *, bool),
void *data)
{ {
unsigned nargs = gimple_phi_num_args (phi); unsigned nargs = gimple_phi_num_args (phi);
...@@ -2470,7 +2487,8 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, ...@@ -2470,7 +2487,8 @@ get_continuation_for_phi (gimple phi, ao_ref *ref,
{ {
arg1 = PHI_ARG_DEF (phi, i); arg1 = PHI_ARG_DEF (phi, i);
arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref, arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref,
cnt, visited, abort_on_visited); cnt, visited, abort_on_visited,
translate, data);
if (!arg0) if (!arg0)
return NULL_TREE; return NULL_TREE;
} }
...@@ -2502,7 +2520,8 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, ...@@ -2502,7 +2520,8 @@ get_continuation_for_phi (gimple phi, ao_ref *ref,
void * void *
walk_non_aliased_vuses (ao_ref *ref, tree vuse, walk_non_aliased_vuses (ao_ref *ref, tree vuse,
void *(*walker)(ao_ref *, tree, unsigned int, void *), void *(*walker)(ao_ref *, tree, unsigned int, void *),
void *(*translate)(ao_ref *, tree, void *), void *data) void *(*translate)(ao_ref *, tree, void *, bool),
void *data)
{ {
bitmap visited = NULL; bitmap visited = NULL;
void *res; void *res;
...@@ -2532,7 +2551,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse, ...@@ -2532,7 +2551,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
break; break;
else if (gimple_code (def_stmt) == GIMPLE_PHI) else if (gimple_code (def_stmt) == GIMPLE_PHI)
vuse = get_continuation_for_phi (def_stmt, ref, &cnt, vuse = get_continuation_for_phi (def_stmt, ref, &cnt,
&visited, translated); &visited, translated, translate, data);
else else
{ {
cnt++; cnt++;
...@@ -2540,7 +2559,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse, ...@@ -2540,7 +2559,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
{ {
if (!translate) if (!translate)
break; break;
res = (*translate) (ref, vuse, data); res = (*translate) (ref, vuse, data, false);
/* Failed lookup and translation. */ /* Failed lookup and translation. */
if (res == (void *)-1) if (res == (void *)-1)
{ {
......
...@@ -110,13 +110,17 @@ extern bool stmt_may_clobber_global_p (gimple); ...@@ -110,13 +110,17 @@ extern bool stmt_may_clobber_global_p (gimple);
extern bool stmt_may_clobber_ref_p (gimple, tree); extern bool stmt_may_clobber_ref_p (gimple, tree);
extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *); extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
extern bool call_may_clobber_ref_p (gimple, tree); extern bool call_may_clobber_ref_p (gimple, tree);
extern bool call_may_clobber_ref_p_1 (gimple, ao_ref *);
extern bool stmt_kills_ref_p (gimple, tree); extern bool stmt_kills_ref_p (gimple, tree);
extern tree get_continuation_for_phi (gimple, ao_ref *, extern tree get_continuation_for_phi (gimple, ao_ref *,
unsigned int *, bitmap *, bool); unsigned int *, bitmap *, bool,
void *(*)(ao_ref *, tree, void *, bool),
void *);
extern void *walk_non_aliased_vuses (ao_ref *, tree, extern void *walk_non_aliased_vuses (ao_ref *, tree,
void *(*)(ao_ref *, tree, void *(*)(ao_ref *, tree,
unsigned int, void *), unsigned int, void *),
void *(*)(ao_ref *, tree, void *), void *); void *(*)(ao_ref *, tree, void *, bool),
void *);
extern unsigned int walk_aliased_vdefs (ao_ref *, tree, extern unsigned int walk_aliased_vdefs (ao_ref *, tree,
bool (*)(ao_ref *, tree, void *), bool (*)(ao_ref *, tree, void *),
void *, bitmap *); void *, bitmap *);
......
...@@ -1308,7 +1308,8 @@ translate_vuse_through_block (vec<vn_reference_op_s> operands, ...@@ -1308,7 +1308,8 @@ translate_vuse_through_block (vec<vn_reference_op_s> operands,
unsigned int cnt; unsigned int cnt;
/* Try to find a vuse that dominates this phi node by skipping /* Try to find a vuse that dominates this phi node by skipping
non-clobbering statements. */ non-clobbering statements. */
vuse = get_continuation_for_phi (phi, &ref, &cnt, &visited, false); vuse = get_continuation_for_phi (phi, &ref, &cnt, &visited, false,
NULL, NULL);
if (visited) if (visited)
BITMAP_FREE (visited); BITMAP_FREE (visited);
} }
......
...@@ -1542,7 +1542,8 @@ vn_reference_lookup_or_insert_for_pieces (tree vuse, ...@@ -1542,7 +1542,8 @@ vn_reference_lookup_or_insert_for_pieces (tree vuse,
of VUSE. */ of VUSE. */
static void * static void *
vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_) vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
bool disambiguate_only)
{ {
vn_reference_t vr = (vn_reference_t)vr_; vn_reference_t vr = (vn_reference_t)vr_;
gimple def_stmt = SSA_NAME_DEF_STMT (vuse); gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
...@@ -1580,6 +1581,39 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_) ...@@ -1580,6 +1581,39 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
lhs_ref_ok = true; lhs_ref_ok = true;
} }
} }
else if (gimple_call_builtin_p (def_stmt, BUILT_IN_NORMAL)
&& gimple_call_num_args (def_stmt) <= 4)
{
/* For builtin calls valueize its arguments and call the
alias oracle again. Valueization may improve points-to
info of pointers and constify size and position arguments.
Originally this was motivated by PR61034 which has
conditional calls to free falsely clobbering ref because
of imprecise points-to info of the argument. */
tree oldargs[4];
bool valueized_anything;
for (unsigned i = 0; i < gimple_call_num_args (def_stmt); ++i)
{
oldargs[i] = gimple_call_arg (def_stmt, i);
if (TREE_CODE (oldargs[i]) == SSA_NAME
&& VN_INFO (oldargs[i])->valnum != oldargs[i])
{
gimple_call_set_arg (def_stmt, i, VN_INFO (oldargs[i])->valnum);
valueized_anything = true;
}
}
if (valueized_anything)
{
bool res = call_may_clobber_ref_p_1 (def_stmt, ref);
for (unsigned i = 0; i < gimple_call_num_args (def_stmt); ++i)
gimple_call_set_arg (def_stmt, i, oldargs[i]);
if (!res)
return NULL;
}
}
if (disambiguate_only)
return (void *)-1;
base = ao_ref_base (ref); base = ao_ref_base (ref);
offset = ref->offset; offset = ref->offset;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment