mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-18 14:31:48 +08:00
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:
parent
8d2d69eba4
commit
78ea9abc20
@ -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
|
||||
|
115
gcc/cfganal.c
115
gcc/cfganal.c
@ -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:
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
30
gcc/testsuite/g++.dg/torture/20180705-1.C
Normal file
30
gcc/testsuite/g++.dg/torture/20180705-1.C
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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)));
|
||||
|
||||
|
@ -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)))); \
|
||||
|
@ -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
|
||||
|
@ -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" } } */
|
||||
|
@ -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)
|
||||
|
16
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-67.c
Normal file
16
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-67.c
Normal 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" } } */
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
3663
gcc/tree-ssa-sccvn.c
3663
gcc/tree-ssa-sccvn.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user