cfganal.h (rev_post_order_and_mark_dfs_back_seme): Declare.

2018-08-27  Richard Biener  <rguenther@suse.de>

	* cfganal.h (rev_post_order_and_mark_dfs_back_seme): Declare.
	* cfganal.c (rev_post_order_and_mark_dfs_back_seme): New function.

	* tree-ssa-sccvn.h (struct vn_pval): New structure.
	(struct vn_nary_op_s): Add unwind_to member.  Add
	predicated_values flag and put result into a union together
	with a linked list of vn_pval.
	(struct vn_ssa_aux): Add name member to make maintaining
	a map of SSA name to vn_ssa_aux possible.  Remove no longer
	needed info, dfsnum, low, visited, on_sccstack, use_processed
	and range_info_anti_range_p members.
	(run_scc_vn, vn_eliminate, free_scc_vn, vn_valueize): Remove.
	(do_rpo_vn, run_rpo_vn, eliminate_with_rpo_vn, free_rpo_vn):
	New functions.
	(vn_valueize): New global.
	(vn_context_bb): Likewise.
	(VN_INFO_RANGE_INFO, VN_INFO_ANTI_RANGE_P, VN_INFO_RANGE_TYPE,
	VN_INFO_PTR_INFO): Remove.
	* tree-ssa-sccvn.c: ... (rewrite)
	(pass_fre::execute): For -O2+ initialize loops and run
	RPO VN in optimistic mode (iterating).  For -O1 and -Og
	run RPO VN in non-optimistic mode.
	* params.def (PARAM_SCCVN_MAX_SCC_SIZE): Remove.
	(PARAM_RPO_VN_MAX_LOOP_DEPTH): Add.
	* doc/invoke.texi (sccvn-max-scc-size): Remove.
	(rpo-vn-max-loop-depth): Document.
	* tree-ssa-alias.c (walk_non_aliased_vuses): Stop walking
	when valuezing the VUSE signals we walked out of the region.
	* tree-ssa-pre.c (phi_translate_1): Ignore predicated values.
	(phi_translate): Set VN context block to use for availability
	lookup.
	(compute_avail): Likewise.
	(pre_valueize): New function.
	(pass_pre::execute): Adjust to the RPO VN API.

	* tree-ssa-loop-ivcanon.c: Include tree-ssa-sccvn.h.
	(propagate_constants_for_unrolling): Remove.
	(tree_unroll_loops_completely): Perform value-numbering
	on the unrolled bodies loop parent.

	* g++.dg/torture/20180705-1.C: New testcase.
	* gcc.dg/tree-ssa/ssa-fre-67.c: Likewise.
	* gcc.dg/tree-ssa/ssa-ccp-14.c: Scan FRE dump.
	* gcc.dg/tree-ssa/ssa-fre-46.c: Use -O2.
	* gcc.dg/tree-ssa/vrp92.c: Disable FRE.
	* gcc.dg/pr83666.c: Drop --param=sccvn-max-scc-size option.
	* gcc.dg/pr85195.c: Likewise.
	* gcc.dg/pr85467.c: Likewise.
	* gcc.dg/torture/pr81790.c: Likewise.

	* gfortran.dg/reassoc_4.f: Change max-completely-peeled-insns
	param to current default.

From-SVN: r263875
This commit is contained in:
Richard Biener 2018-08-27 10:55:53 +00:00 committed by Richard Biener
parent 8d2d69eba4
commit 78ea9abc20
21 changed files with 2470 additions and 1720 deletions

View File

@ -1,3 +1,45 @@
2018-08-27 Richard Biener <rguenther@suse.de>
* cfganal.h (rev_post_order_and_mark_dfs_back_seme): Declare.
* cfganal.c (rev_post_order_and_mark_dfs_back_seme): New function.
* tree-ssa-sccvn.h (struct vn_pval): New structure.
(struct vn_nary_op_s): Add unwind_to member. Add
predicated_values flag and put result into a union together
with a linked list of vn_pval.
(struct vn_ssa_aux): Add name member to make maintaining
a map of SSA name to vn_ssa_aux possible. Remove no longer
needed info, dfsnum, low, visited, on_sccstack, use_processed
and range_info_anti_range_p members.
(run_scc_vn, vn_eliminate, free_scc_vn, vn_valueize): Remove.
(do_rpo_vn, run_rpo_vn, eliminate_with_rpo_vn, free_rpo_vn):
New functions.
(vn_valueize): New global.
(vn_context_bb): Likewise.
(VN_INFO_RANGE_INFO, VN_INFO_ANTI_RANGE_P, VN_INFO_RANGE_TYPE,
VN_INFO_PTR_INFO): Remove.
* tree-ssa-sccvn.c: ... (rewrite)
(pass_fre::execute): For -O2+ initialize loops and run
RPO VN in optimistic mode (iterating). For -O1 and -Og
run RPO VN in non-optimistic mode.
* params.def (PARAM_SCCVN_MAX_SCC_SIZE): Remove.
(PARAM_RPO_VN_MAX_LOOP_DEPTH): Add.
* doc/invoke.texi (sccvn-max-scc-size): Remove.
(rpo-vn-max-loop-depth): Document.
* tree-ssa-alias.c (walk_non_aliased_vuses): Stop walking
when valuezing the VUSE signals we walked out of the region.
* tree-ssa-pre.c (phi_translate_1): Ignore predicated values.
(phi_translate): Set VN context block to use for availability
lookup.
(compute_avail): Likewise.
(pre_valueize): New function.
(pass_pre::execute): Adjust to the RPO VN API.
* tree-ssa-loop-ivcanon.c: Include tree-ssa-sccvn.h.
(propagate_constants_for_unrolling): Remove.
(tree_unroll_loops_completely): Perform value-numbering
on the unrolled bodies loop parent.
2018-08-27 Richard Biener <rguenther@suse.de>
* tree-ssa-pre.c (compute_antic): Re-use inverted postorder

View File

@ -1057,8 +1057,121 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
return pre_order_num;
}
/* Unlike pre_and_rev_post_order_compute we fill rev_post_order backwards
so iterating in RPO order needs to start with rev_post_order[n - 1]
going to rev_post_order[0]. If FOR_ITERATION is true then try to
make CFG cycles fit into small contiguous regions of the RPO order.
When FOR_ITERATION is true this requires up-to-date loop structures. */
int
rev_post_order_and_mark_dfs_back_seme (struct function *fn, edge entry,
bitmap exit_bbs, bool for_iteration,
int *rev_post_order)
{
int pre_order_num = 0;
int rev_post_order_num = 0;
/* Allocate stack for back-tracking up CFG. Worst case we need
O(n^2) edges but the following should suffice in practice without
a need to re-allocate. */
auto_vec<edge, 20> stack (2 * n_basic_blocks_for_fn (fn));
int *pre = XNEWVEC (int, 2 * last_basic_block_for_fn (fn));
int *post = pre + last_basic_block_for_fn (fn);
/* BB flag to track nodes that have been visited. */
auto_bb_flag visited (fn);
/* BB flag to track which nodes have post[] assigned to avoid
zeroing post. */
auto_bb_flag post_assigned (fn);
/* Push the first edge on to the stack. */
stack.quick_push (entry);
while (!stack.is_empty ())
{
basic_block src;
basic_block dest;
/* Look at the edge on the top of the stack. */
int idx = stack.length () - 1;
edge e = stack[idx];
src = e->src;
dest = e->dest;
e->flags &= ~EDGE_DFS_BACK;
/* Check if the edge destination has been visited yet. */
if (! bitmap_bit_p (exit_bbs, dest->index)
&& ! (dest->flags & visited))
{
/* Mark that we have visited the destination. */
dest->flags |= visited;
pre[dest->index] = pre_order_num++;
if (EDGE_COUNT (dest->succs) > 0)
{
/* Since the DEST node has been visited for the first
time, check its successors. */
/* Push the edge vector in reverse to match previous behavior. */
stack.reserve (EDGE_COUNT (dest->succs));
for (int i = EDGE_COUNT (dest->succs) - 1; i >= 0; --i)
stack.quick_push (EDGE_SUCC (dest, i));
/* Generalize to handle more successors? */
if (for_iteration
&& EDGE_COUNT (dest->succs) == 2)
{
edge &e1 = stack[stack.length () - 2];
if (loop_exit_edge_p (e1->src->loop_father, e1))
std::swap (e1, stack.last ());
}
}
else
{
/* There are no successors for the DEST node so assign
its reverse completion number. */
post[dest->index] = rev_post_order_num;
dest->flags |= post_assigned;
rev_post_order[rev_post_order_num] = dest->index;
rev_post_order_num++;
}
}
else
{
if (dest->flags & visited
&& src != entry->src
&& pre[src->index] >= pre[dest->index]
&& !(dest->flags & post_assigned))
e->flags |= EDGE_DFS_BACK;
if (idx != 0 && stack[idx - 1]->src != src)
{
/* There are no more successors for the SRC node
so assign its reverse completion number. */
post[src->index] = rev_post_order_num;
src->flags |= post_assigned;
rev_post_order[rev_post_order_num] = src->index;
rev_post_order_num++;
}
stack.pop ();
}
}
XDELETEVEC (pre);
/* Clear the temporarily allocated flags. */
for (int i = 0; i < rev_post_order_num; ++i)
BASIC_BLOCK_FOR_FN (fn, rev_post_order[i])->flags
&= ~(post_assigned|visited);
return rev_post_order_num;
}
/* Compute the depth first search order on the _reverse_ graph and
store in the array DFS_ORDER, marking the nodes visited in VISITED.
store it in the array DFS_ORDER, marking the nodes visited in VISITED.
Returns the number of nodes visited.
The computation is split into three pieces:

View File

@ -67,6 +67,8 @@ extern void inverted_post_order_compute (vec<int> *postorder, sbitmap *start_poi
extern int pre_and_rev_post_order_compute_fn (struct function *,
int *, int *, bool);
extern int pre_and_rev_post_order_compute (int *, int *, bool);
extern int rev_post_order_and_mark_dfs_back_seme (struct function *, edge,
bitmap, bool, int *);
extern int dfs_enumerate_from (basic_block, int,
bool (*)(const_basic_block, const void *),
basic_block *, int, const void *);

View File

@ -11076,11 +11076,12 @@ parameter sets a limit on the length of the sets that are computed,
which prevents the runaway behavior. Setting a value of 0 for
this parameter allows an unlimited set length.
@item sccvn-max-scc-size
Maximum size of a strongly connected component (SCC) during SCCVN
processing. If this limit is hit, SCCVN processing for the whole
function is not done and optimizations depending on it are
disabled. The default maximum SCC size is 10000.
@item rpo-vn-max-loop-depth
Maximum loop depth that is value-numbered optimistically. The default
maximum loop depth is three. When the limit hits the innermost
@var{rpo-vn-max-loop-depth} loops and the outermost loop in the
loop nest are value-numbered optimistically and the remaining ones not.
The default maximum loop depth is seven.
@item sccvn-max-alias-queries-per-access
Maximum number of alias-oracle queries we perform when looking for

View File

@ -847,15 +847,15 @@ DEFPARAM (PARAM_MAX_PARTIAL_ANTIC_LENGTH,
"Maximum length of partial antic set when performing tree pre optimization.",
100, 0, 0)
/* The following is used as a stop-gap limit for cases where really huge
SCCs blow up memory and compile-time use too much. If we hit this limit,
SCCVN and such FRE and PRE will be not done at all for the current
function. */
/* The following is used as a stop-gap limit for cases where really deep
loop nests cause compile-time to blow up. If we hit this limit,
FRE and PRE will value-number outer loops (but the outermost) in a
loop nest non-optimistically. */
DEFPARAM (PARAM_SCCVN_MAX_SCC_SIZE,
"sccvn-max-scc-size",
"Maximum size of a SCC before SCCVN stops processing a function.",
10000, 10, 0)
DEFPARAM (PARAM_RPO_VN_MAX_LOOP_DEPTH,
"rpo-vn-max-loop-depth",
"Maximum depth of a loop nest to fully value-number optimistically.",
7, 2, 0)
/* The following is used as a stop-gap limit for cases where really huge
functions blow up compile-time use too much. It limits the number of

View File

@ -1,3 +1,18 @@
2018-08-27 Richard Biener <rguenther@suse.de>
* g++.dg/torture/20180705-1.C: New testcase.
* gcc.dg/tree-ssa/ssa-fre-67.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-14.c: Scan FRE dump.
* gcc.dg/tree-ssa/ssa-fre-46.c: Use -O2.
* gcc.dg/tree-ssa/vrp92.c: Disable FRE.
* gcc.dg/pr83666.c: Drop --param=sccvn-max-scc-size option.
* gcc.dg/pr85195.c: Likewise.
* gcc.dg/pr85467.c: Likewise.
* gcc.dg/torture/pr81790.c: Likewise.
* gfortran.dg/reassoc_4.f: Change max-completely-peeled-insns
param to current default.
2018-08-27 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/87065

View File

@ -0,0 +1,30 @@
// { dg-do compile }
typedef long unsigned int size_t;
extern void fancy_abort () __attribute__ ((__noreturn__));
class cpp_string_location_reader { };
class cpp_substring_ranges {
public:
void add_range ();
};
typedef unsigned char uchar;
void
cpp_interpret_string_1 (size_t count, cpp_string_location_reader *loc_readers, cpp_substring_ranges *ranges, uchar c, const uchar *p)
{
size_t i;
((void)(!((loc_readers != __null ) == (ranges != __null )) ? fancy_abort (), 0 : 0));
cpp_string_location_reader *loc_reader = __null;
for (i = 0; i < count; i++)
{
if (loc_readers) loc_reader = &loc_readers[i];
if (*p == 'R') continue;
for (;;)
{
switch (c) {
case 'x': if (ranges) ranges->add_range (); break;
case '7': ((void)(!((loc_reader != __null ) == (ranges != __null )) ? fancy_abort (), 0 : 0)); break;
}
p = 0;
}
}
}

View File

@ -1,6 +1,6 @@
/* PR debug/83666 */
/* { dg-do compile } */
/* { dg-options "-O2 -g --param=sccvn-max-scc-size=10 -Wno-psabi" } */
/* { dg-options "-O2 -g -Wno-psabi" } */
/* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
typedef int __attribute__ ((vector_size (64))) V;

View File

@ -1,6 +1,6 @@
/* PR middle-end/85195 */
/* { dg-do compile { target int128 } } */
/* { dg-options "-Wno-psabi -O -fno-tree-ccp --param=sccvn-max-scc-size=10" } */
/* { dg-options "-Wno-psabi -O -fno-tree-ccp" } */
typedef __int128 V __attribute__ ((vector_size (16)));

View File

@ -1,6 +1,6 @@
/* PR tree-optimization/85467 */
/* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-ccp --param=sccvn-max-scc-size=10" } */
/* { dg-options "-O2 -fno-tree-ccp" } */
#define TEST(N, T) \
typedef T V##N __attribute__ ((__vector_size__ (sizeof (T)))); \

View File

@ -1,5 +1,4 @@
/* { dg-do compile } */
/* { dg-additional-options "--param sccvn-max-scc-size=10" } */
typedef int a __attribute__ ((__vector_size__ (16)));
typedef struct

View File

@ -1,8 +1,5 @@
/* PR tree-optimization/29738. We used not to realize that "i" can never
become nonzero. */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-options "-O2 -fdump-tree-fre1 -fdump-tree-optimized" } */
int i;
@ -16,5 +13,7 @@ void bar (void)
foo ();
}
/* Everything except for the "i = 0" assignment should get removed. */
/* { dg-final { scan-tree-dump-times "if" 0 "optimized" { xfail *-*-* } } } */
/* Everything except for the "i = 0" assignment should get removed. Value
numbering already figures out the if in the loop is never true. */
/* { dg-final { scan-tree-dump-times "foo" 0 "fre1" } } */
/* { dg-final { scan-tree-dump-times "if" 0 "optimized" } } */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-fre1-details" } */
/* { dg-options "-O2 -fdump-tree-fre1-details" } */
int x[1024];
int foo (int a, int s, unsigned int k)

View File

@ -0,0 +1,16 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-fre1-stats" } */
int foo()
{
int i = 0;
do
{
i++;
}
while (i != 1);
return i;
}
/* { dg-final { scan-tree-dump "RPO iteration over 3 blocks visited 3 blocks" "fre1" } } */
/* { dg-final { scan-tree-dump "return 1;" "fre1" } } */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1-details -fdisable-tree-ethread" } */
/* { dg-options "-O2 -fdisable-tree-evrp -fno-tree-fre -fdump-tree-vrp1-details -fdisable-tree-ethread" } */
void bar (void);
int foo (int i, int j)

View File

@ -1,5 +1,5 @@
! { dg-do compile }
! { dg-options "-O3 -ffast-math -fdump-tree-reassoc1 --param max-completely-peeled-insns=400" }
! { dg-options "-O3 -ffast-math -fdump-tree-reassoc1 --param max-completely-peeled-insns=200" }
! { dg-additional-options "--param max-completely-peel-times=16" { target spu-*-* } }
subroutine anisonl(w,vo,anisox,s,ii1,jj1,weight)
integer ii1,jj1,i1,iii1,j1,jjj1,k1,l1,m1,n1

View File

@ -2783,7 +2783,14 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
break;
if (valueize)
vuse = valueize (vuse);
{
vuse = valueize (vuse);
if (!vuse)
{
res = NULL;
break;
}
}
def_stmt = SSA_NAME_DEF_STMT (vuse);
if (gimple_nop_p (def_stmt))
break;

View File

@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "tree-cfgcleanup.h"
#include "builtins.h"
#include "tree-ssa-sccvn.h"
/* Specifies types of loops that may be unrolled. */
@ -1318,50 +1319,6 @@ canonicalize_induction_variables (void)
return 0;
}
/* Propagate constant SSA_NAMEs defined in basic block BB. */
static void
propagate_constants_for_unrolling (basic_block bb)
{
/* Look for degenerate PHI nodes with constant argument. */
for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
{
gphi *phi = gsi.phi ();
tree result = gimple_phi_result (phi);
tree arg = gimple_phi_arg_def (phi, 0);
if (! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (result)
&& gimple_phi_num_args (phi) == 1
&& CONSTANT_CLASS_P (arg))
{
replace_uses_by (result, arg);
gsi_remove (&gsi, true);
release_ssa_name (result);
}
else
gsi_next (&gsi);
}
/* Look for assignments to SSA names with constant RHS. */
for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
{
gimple *stmt = gsi_stmt (gsi);
tree lhs;
if (is_gimple_assign (stmt)
&& TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_constant
&& (lhs = gimple_assign_lhs (stmt), TREE_CODE (lhs) == SSA_NAME)
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
{
replace_uses_by (lhs, gimple_assign_rhs1 (stmt));
gsi_remove (&gsi, true);
release_ssa_name (lhs);
}
else
gsi_next (&gsi);
}
}
/* Process loops from innermost to outer, stopping at the innermost
loop we unrolled. */
@ -1512,10 +1469,14 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
EXECUTE_IF_SET_IN_BITMAP (fathers, 0, i, bi)
{
loop_p father = get_loop (cfun, i);
basic_block *body = get_loop_body_in_dom_order (father);
for (unsigned j = 0; j < father->num_nodes; j++)
propagate_constants_for_unrolling (body[j]);
free (body);
bitmap exit_bbs = BITMAP_ALLOC (NULL);
loop_exit *exit = father->exits->next;
while (exit->e)
{
bitmap_set_bit (exit_bbs, exit->e->dest->index);
exit = exit->next;
}
do_rpo_vn (cfun, loop_preheader_edge (father), exit_bbs);
}
BITMAP_FREE (fathers);

View File

@ -677,10 +677,10 @@ get_expr_value_id (pre_expr expr)
return id;
}
/* Return a SCCVN valnum (SSA name or constant) for the PRE value-id VAL. */
/* Return a VN valnum (SSA name or constant) for the PRE value-id VAL. */
static tree
sccvn_valnum_from_value_id (unsigned int val)
vn_valnum_from_value_id (unsigned int val)
{
bitmap_iterator bi;
unsigned int i;
@ -1308,9 +1308,9 @@ get_representative_for (const pre_expr e, basic_block b = NULL)
??? We should be able to re-use this when we insert the statement
to compute it. */
name = make_temp_ssa_name (get_expr_type (e), gimple_build_nop (), "pretmp");
VN_INFO_GET (name)->value_id = value_id;
VN_INFO (name)->value_id = value_id;
VN_INFO (name)->valnum = valnum ? valnum : name;
/* ??? For now mark this SSA name for release by SCCVN. */
/* ??? For now mark this SSA name for release by VN. */
VN_INFO (name)->needs_insertion = true;
add_to_value (value_id, get_or_alloc_expr_for_name (name));
if (dump_file && (dump_flags & TDF_DETAILS))
@ -1404,7 +1404,22 @@ phi_translate_1 (bitmap_set_t dest,
constant = find_leader_in_sets (value_id, dest,
AVAIL_OUT (pred));
if (constant)
return constant;
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "simplifying ");
print_pre_expr (dump_file, expr);
fprintf (dump_file, " translated %d -> %d to ",
phiblock->index, pred->index);
PRE_EXPR_NARY (expr) = newnary;
print_pre_expr (dump_file, expr);
PRE_EXPR_NARY (expr) = nary;
fprintf (dump_file, " to ");
print_pre_expr (dump_file, constant);
fprintf (dump_file, "\n");
}
return constant;
}
}
}
else
@ -1426,7 +1441,7 @@ phi_translate_1 (bitmap_set_t dest,
expr = pre_expr_pool.allocate ();
expr->kind = NARY;
expr->id = 0;
if (nary)
if (nary && !nary->predicated_values)
{
PRE_EXPR_NARY (expr) = nary;
new_val_id = nary->value_id;
@ -1664,7 +1679,10 @@ phi_translate (bitmap_set_t dest, pre_expr expr,
}
/* Translate. */
basic_block saved_valueize_bb = vn_context_bb;
vn_context_bb = e->src;
phitrans = phi_translate_1 (dest, expr, set1, set2, e);
vn_context_bb = saved_valueize_bb;
if (slot)
{
@ -2923,7 +2941,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
if (forcedname != folded)
{
VN_INFO_GET (forcedname)->valnum = forcedname;
VN_INFO (forcedname)->valnum = forcedname;
VN_INFO (forcedname)->value_id = get_next_value_id ();
nameexpr = get_or_alloc_expr_for_name (forcedname);
add_to_value (VN_INFO (forcedname)->value_id, nameexpr);
@ -2949,8 +2967,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
the expression may have been represented. There is no harm in replacing
here. */
value_id = get_expr_value_id (expr);
VN_INFO_GET (name)->value_id = value_id;
VN_INFO (name)->valnum = sccvn_valnum_from_value_id (value_id);
VN_INFO (name)->value_id = value_id;
VN_INFO (name)->valnum = vn_valnum_from_value_id (value_id);
if (VN_INFO (name)->valnum == NULL_TREE)
VN_INFO (name)->valnum = name;
gcc_assert (VN_INFO (name)->valnum != NULL_TREE);
@ -3055,8 +3073,8 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
temp = make_temp_ssa_name (type, NULL, "prephitmp");
phi = create_phi_node (temp, block);
VN_INFO_GET (temp)->value_id = val;
VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
VN_INFO (temp)->value_id = val;
VN_INFO (temp)->valnum = vn_valnum_from_value_id (val);
if (VN_INFO (temp)->valnum == NULL_TREE)
VN_INFO (temp)->valnum = temp;
bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (temp));
@ -3300,8 +3318,8 @@ do_pre_regular_insertion (basic_block block, basic_block dom)
gimple_stmt_iterator gsi = gsi_after_labels (block);
gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
VN_INFO_GET (temp)->value_id = val;
VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
VN_INFO (temp)->value_id = val;
VN_INFO (temp)->valnum = vn_valnum_from_value_id (val);
if (VN_INFO (temp)->valnum == NULL_TREE)
VN_INFO (temp)->valnum = temp;
bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (temp));
@ -3742,6 +3760,7 @@ compute_avail (void)
/* Pick a block from the worklist. */
block = worklist[--sp];
vn_context_bb = block;
/* Initially, the set of available values in BLOCK is that of
its immediate dominator. */
@ -4043,6 +4062,7 @@ compute_avail (void)
son = next_dom_son (CDI_DOMINATORS, son))
worklist[sp++] = son;
}
vn_context_bb = NULL;
free (worklist);
}
@ -4133,6 +4153,34 @@ public:
}; // class pass_pre
/* Valueization hook for RPO VN when we are calling back to it
at ANTIC compute time. */
static tree
pre_valueize (tree name)
{
if (TREE_CODE (name) == SSA_NAME)
{
tree tem = VN_INFO (name)->valnum;
if (tem != VN_TOP && tem != name)
{
if (TREE_CODE (tem) != SSA_NAME
|| SSA_NAME_IS_DEFAULT_DEF (tem))
return tem;
/* We create temporary SSA names for representatives that
do not have a definition (yet) but are not default defs either
assume they are fine to use. */
basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (tem));
if (! def_bb
|| dominated_by_p (CDI_DOMINATORS, vn_context_bb, def_bb))
return tem;
/* ??? Now we could look for a leader. Ideally we'd somehow
expose RPO VN leaders and get rid of AVAIL_OUT as well... */
}
}
return name;
}
unsigned int
pass_pre::execute (function *fun)
{
@ -4141,16 +4189,18 @@ pass_pre::execute (function *fun)
do_partial_partial =
flag_tree_partial_pre && optimize_function_for_speed_p (fun);
/* This has to happen before SCCVN runs because
/* This has to happen before VN runs because
loop_optimizer_init may create new phis, etc. */
loop_optimizer_init (LOOPS_NORMAL);
split_critical_edges ();
scev_initialize ();
run_scc_vn (VN_WALK);
run_rpo_vn (VN_WALK);
init_pre ();
vn_valueize = pre_valueize;
/* Insert can get quite slow on an incredibly large number of basic
blocks due to some quadratic behavior. Until this behavior is
fixed, don't run it when he have an incredibly large number of
@ -4179,8 +4229,9 @@ pass_pre::execute (function *fun)
statistics_counter_event (fun, "HOIST inserted", pre_stats.hoist_insert);
statistics_counter_event (fun, "New PHIs", pre_stats.phis);
/* Remove all the redundant expressions. */
todo |= vn_eliminate (inserted_exprs);
todo |= eliminate_with_rpo_vn (inserted_exprs);
vn_valueize = NULL;
/* Because we don't follow exactly the standard PRE algorithm, and decide not
to insert PHI nodes sometimes, and because value numbering of casts isn't
@ -4193,9 +4244,6 @@ pass_pre::execute (function *fun)
scev_finalize ();
loop_optimizer_finalize ();
/* Restore SSA info before tail-merging as that resets it as well. */
scc_vn_restore_ssa_info ();
/* TODO: tail_merge_optimize may merge all predecessors of a block, in which
case we can merge the block with the remaining predecessor of the block.
It should either:
@ -4205,7 +4253,7 @@ pass_pre::execute (function *fun)
- share the cfg cleanup with fini_pre. */
todo |= tail_merge_optimize (todo);
free_scc_vn ();
free_rpo_vn ();
/* Tail merging invalidates the virtual SSA web, together with
cfg-cleanup opportunities exposed by PRE this will wreck the

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,18 @@ bool expressions_equal_p (tree, tree);
/* TOP of the VN lattice. */
extern tree VN_TOP;
/* A predicated value. */
struct vn_pval
{
vn_pval *next;
/* The value of the expression this is attached to is RESULT in
case the expression is computed dominated by one of the blocks
in valid_dominated_by_p. */
tree result;
unsigned n;
int valid_dominated_by_p[1];
};
/* N-ary operations in the hashtable consist of length operands, an
opcode, and a type. Result is the value number of the operation,
and hashcode is stored to avoid having to calculate it
@ -36,12 +48,19 @@ extern tree VN_TOP;
typedef struct vn_nary_op_s
{
vn_nary_op_s *next;
vn_nary_op_s *unwind_to;
/* Unique identify that all expressions with the same value have. */
unsigned int value_id;
ENUM_BITFIELD(tree_code) opcode : 16;
unsigned length : 16;
hashval_t hashcode;
tree result;
unsigned predicated_values : 1;
union {
/* If ! predicated_values this is the value of the expression. */
tree result;
/* If predicated_values this is a list of values of the expression. */
vn_pval *values;
} u;
tree type;
tree op[1];
} *vn_nary_op_t;
@ -176,36 +195,23 @@ vn_constant_eq_with_type (tree c1, tree c2)
typedef struct vn_ssa_aux
{
/* SSA name this vn_ssa_aux is associated with in the lattice. */
tree name;
/* Value number. This may be an SSA name or a constant. */
tree valnum;
/* Statements to insert if needs_insertion is true. */
gimple_seq expr;
/* Saved SSA name info. */
tree_ssa_name::ssa_name_info_type info;
/* Unique identifier that all expressions with the same value have. */
unsigned int value_id;
/* SCC information. */
unsigned int dfsnum;
unsigned int low;
/* Whether the SSA_NAME has been processed at least once. */
unsigned visited : 1;
unsigned on_sccstack : 1;
/* Whether the SSA_NAME has been value numbered already. This is
only saying whether visit_use has been called on it at least
once. It cannot be used to avoid visitation for SSA_NAME's
involved in non-singleton SCC's. */
unsigned use_processed : 1;
/* Whether the SSA_NAME has no defining statement and thus an
insertion of such with EXPR as definition is required before
a use can be created of it. */
unsigned needs_insertion : 1;
/* Whether range-info is anti-range. */
unsigned range_info_anti_range_p : 1;
} *vn_ssa_aux_t;
enum vn_lookup_kind { VN_NOWALK, VN_WALK, VN_WALKREWRITE };
@ -213,11 +219,7 @@ enum vn_lookup_kind { VN_NOWALK, VN_WALK, VN_WALKREWRITE };
/* Return the value numbering info for an SSA_NAME. */
bool has_VN_INFO (tree);
extern vn_ssa_aux_t VN_INFO (tree);
extern vn_ssa_aux_t VN_INFO_GET (tree);
tree vn_get_expr_for (tree);
void run_scc_vn (vn_lookup_kind);
unsigned int vn_eliminate (bitmap);
void free_scc_vn (void);
void scc_vn_restore_ssa_info (void);
tree vn_nary_op_lookup (tree, vn_nary_op_t *);
tree vn_nary_op_lookup_stmt (gimple *, vn_nary_op_t *);
@ -250,55 +252,17 @@ bool value_id_constant_p (unsigned int);
tree fully_constant_vn_reference_p (vn_reference_t);
tree vn_nary_simplify (vn_nary_op_t);
/* Valueize NAME if it is an SSA name, otherwise just return it. */
unsigned do_rpo_vn (function *, edge, bitmap);
void run_rpo_vn (vn_lookup_kind);
unsigned eliminate_with_rpo_vn (bitmap);
void free_rpo_vn (void);
static inline tree
vn_valueize (tree name)
{
if (TREE_CODE (name) == SSA_NAME)
{
tree tem = VN_INFO (name)->valnum;
return tem == VN_TOP ? name : tem;
}
return name;
}
/* Valueize NAME if it is an SSA name, otherwise just return it. This hook
is initialized by run_scc_vn. */
extern tree (*vn_valueize) (tree);
/* Get at the original range info for NAME. */
/* Context that valueization should operate on. */
extern basic_block vn_context_bb;
inline range_info_def *
VN_INFO_RANGE_INFO (tree name)
{
return (VN_INFO (name)->info.range_info
? VN_INFO (name)->info.range_info
: SSA_NAME_RANGE_INFO (name));
}
/* Whether the original range info of NAME is an anti-range. */
inline bool
VN_INFO_ANTI_RANGE_P (tree name)
{
return (VN_INFO (name)->info.range_info
? VN_INFO (name)->range_info_anti_range_p
: SSA_NAME_ANTI_RANGE_P (name));
}
/* Get at the original range info kind for NAME. */
inline value_range_type
VN_INFO_RANGE_TYPE (tree name)
{
return VN_INFO_ANTI_RANGE_P (name) ? VR_ANTI_RANGE : VR_RANGE;
}
/* Get at the original pointer info for NAME. */
inline ptr_info_def *
VN_INFO_PTR_INFO (tree name)
{
return (VN_INFO (name)->info.ptr_info
? VN_INFO (name)->info.ptr_info
: SSA_NAME_PTR_INFO (name));
}
#endif /* TREE_SSA_SCCVN_H */