Commit 85300b46 by Daniel Berlin Committed by Daniel Berlin

tree-ssa-pre.c (bb_value_sets_t): Add antic_safe_loads.

2006-02-06  Daniel Berlin  <dberlin@dberlin.org>

	* tree-ssa-pre.c (bb_value_sets_t): Add antic_safe_loads.
	(ANTIC_SAFE_LOADS): New macro.
	(find_or_generate_expression): Add prototype.
	(set_contains_value): Allow null set for sake of not always having
	to allocate ANTIC_SAFE_LOADS.
	(phi_translate): Move placement of AGGREGATE_TYPE_P check.
	Allow COMPONENT_REF too.
	(valid_in_set): Allow COMPONENT_REF.
	Check ANTIC_SAFE_LOADS too.
	(compute_antic_aux): Print out ANTIC_SAFE_LOADS.
	(compute_rvuse_and_antic_safe): Add ANTIC_SAFE computation, and
	rename.
	(can_PRE_operation): Add COMPONENT_REF.
	(create_component_ref_by_pieces): New function.
	(create_expression_by_pieces): Use create_component_ref_by_pieces.
	(insert_aux): Move AGGREGATE_TYPE_P check here.
	(compute_avail): Set bb local stmt uids.
	(pass_pre): Use TODO_update_ssa_only_virtuals.

2006-02-06  Daniel Berlin  <dberlin@dberlin.org>

	* gcc.dg/tree-ssa/loadpre10.c: New test.
	* gcc.dg/tree-ssa/loadpre11.c: Ditto.
	* gcc.dg/tree-ssa/loadpre6.c: Expect one more elimination.
	* gcc.dg/tree-ssa/loadpre4.c: This should pass now.

From-SVN: r110644
parent 8a46b94f
2006-02-06 Daniel Berlin <dberlin@dberlin.org>
* tree-ssa-pre.c (bb_value_sets_t): Add antic_safe_loads.
(ANTIC_SAFE_LOADS): New macro.
(find_or_generate_expression): Add prototype.
(set_contains_value): Allow null set for sake of not always having
to allocate ANTIC_SAFE_LOADS.
(phi_translate): Move placement of AGGREGATE_TYPE_P check.
Allow COMPONENT_REF too.
(valid_in_set): Allow COMPONENT_REF.
Check ANTIC_SAFE_LOADS too.
(compute_antic_aux): Print out ANTIC_SAFE_LOADS.
(compute_rvuse_and_antic_safe): Add ANTIC_SAFE computation, and
rename.
(can_PRE_operation): Add COMPONENT_REF.
(create_component_ref_by_pieces): New function.
(create_expression_by_pieces): Use create_component_ref_by_pieces.
(insert_aux): Move AGGREGATE_TYPE_P check here.
(compute_avail): Set bb local stmt uids.
(pass_pre): Use TODO_update_ssa_only_virtuals.
2006-02-06 Ben Elliston <bje@au.ibm.com> 2006-02-06 Ben Elliston <bje@au.ibm.com>
* configure.ac: Unconditionally disable decimal float by default. * configure.ac: Unconditionally disable decimal float by default.
......
2006-02-06 Daniel Berlin <dberlin@dberlin.org>
* gcc.dg/tree-ssa/loadpre10.c: New test.
* gcc.dg/tree-ssa/loadpre11.c: Ditto.
* gcc.dg/tree-ssa/loadpre6.c: Expect one more elimination.
* gcc.dg/tree-ssa/loadpre4.c: This should pass now.
2006-02-06 Francois-Xavier Coudert <coudert@clipper.ens.fr> 2006-02-06 Francois-Xavier Coudert <coudert@clipper.ens.fr>
PR libfortran/24685 PR libfortran/24685
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
struct tree_common
{
int code;
};
union tree_node
{
struct tree_common common;
};
typedef union tree_node *tree;
extern tree test (tree, int, int);
extern tree foo (void);
extern void abort (void) __attribute__ ((__noreturn__));
/* Redundant loads of expr->common.code */
tree
test (tree expr, int t, int D17630)
{
int __i;
L0:
if (expr->common.code != 142) goto L23; else goto L2;
L2:
__i = 0;
goto L10;
L10:
__i = __i + 1;
if (D17630 != __i) goto L8; else goto L19;
L8:
if (t) goto L15; else goto L10;
L15:
expr = foo ();
if (expr->common.code != 142) goto L23; else goto L0;
L19:
abort ();
L23:
return expr;
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre-stats" } */
int *t;
int g(int);
int f(int tt)
{
int *t1 = t;
if (*t1)
*t1 = 2;
return g(*t1);
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -7,8 +7,6 @@ int main(int *a, int argc) ...@@ -7,8 +7,6 @@ int main(int *a, int argc)
int i; int i;
int d, e; int d, e;
/* With smarter load PRE, we'd be able to recompute the value at the
kill point. arguably not worth it. */
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
e = *a; e = *a;
...@@ -17,5 +15,5 @@ int main(int *a, int argc) ...@@ -17,5 +15,5 @@ int main(int *a, int argc)
return d + e; return d + e;
} }
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -30,6 +30,8 @@ foo (void) ...@@ -30,6 +30,8 @@ foo (void)
abort (); abort ();
} }
/* There are some reloaded loads of *cell, and cell->common.chain on various
branches. */
void __attribute__((noinline)) void __attribute__((noinline))
remove_useless_vars (tree *unexpanded_var_list, int dump_file) remove_useless_vars (tree *unexpanded_var_list, int dump_file)
{ {
...@@ -69,6 +71,6 @@ main (void) ...@@ -69,6 +71,6 @@ main (void)
remove_useless_vars (&unexpanded_var_list, 0); remove_useless_vars (&unexpanded_var_list, 0);
return 0; return 0;
} }
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ /* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -53,6 +53,11 @@ Boston, MA 02110-1301, USA. */ ...@@ -53,6 +53,11 @@ Boston, MA 02110-1301, USA. */
we can repair later on. we can repair later on.
3. We can do back-substitution or smarter value numbering to catch 3. We can do back-substitution or smarter value numbering to catch
commutative expressions split up over multiple statements. commutative expressions split up over multiple statements.
4. ANTIC_SAFE_LOADS could be a lot smarter than it is now.
Right now, it is simply calculating loads that occur before
any store in a block, instead of loads that occur before
stores that affect them. This is relatively more expensive, and
it's not clear how much more it will buy us.
*/ */
/* For ease of terminology, "expression node" in the below refers to /* For ease of terminology, "expression node" in the below refers to
...@@ -258,6 +263,11 @@ typedef struct bb_value_sets ...@@ -258,6 +263,11 @@ typedef struct bb_value_sets
bitmap rvuse_out; bitmap rvuse_out;
bitmap rvuse_gen; bitmap rvuse_gen;
bitmap rvuse_kill; bitmap rvuse_kill;
/* For actually occuring loads, as long as they occur before all the
other stores in the block, we know they are antic at the top of
the block, regardless of RVUSE_KILL. */
value_set_t antic_safe_loads;
} *bb_value_sets_t; } *bb_value_sets_t;
#define EXP_GEN(BB) ((bb_value_sets_t) ((BB)->aux))->exp_gen #define EXP_GEN(BB) ((bb_value_sets_t) ((BB)->aux))->exp_gen
...@@ -270,6 +280,7 @@ typedef struct bb_value_sets ...@@ -270,6 +280,7 @@ typedef struct bb_value_sets
#define RVUSE_KILL(BB) ((bb_value_sets_t) ((BB)->aux))->rvuse_kill #define RVUSE_KILL(BB) ((bb_value_sets_t) ((BB)->aux))->rvuse_kill
#define RVUSE_OUT(BB) ((bb_value_sets_t) ((BB)->aux))->rvuse_out #define RVUSE_OUT(BB) ((bb_value_sets_t) ((BB)->aux))->rvuse_out
#define NEW_SETS(BB) ((bb_value_sets_t) ((BB)->aux))->new_sets #define NEW_SETS(BB) ((bb_value_sets_t) ((BB)->aux))->new_sets
#define ANTIC_SAFE_LOADS(BB) ((bb_value_sets_t) ((BB)->aux))->antic_safe_loads
/* This structure is used to keep track of statistics on what /* This structure is used to keep track of statistics on what
optimization PRE was able to perform. */ optimization PRE was able to perform. */
...@@ -302,6 +313,7 @@ static bitmap_set_t bitmap_set_new (void); ...@@ -302,6 +313,7 @@ static bitmap_set_t bitmap_set_new (void);
static value_set_t set_new (bool); static value_set_t set_new (bool);
static bool is_undefined_value (tree); static bool is_undefined_value (tree);
static tree create_expression_by_pieces (basic_block, tree, tree); static tree create_expression_by_pieces (basic_block, tree, tree);
static tree find_or_generate_expression (basic_block, tree, tree);
/* We can add and remove elements and entries to and from sets /* We can add and remove elements and entries to and from sets
...@@ -701,7 +713,7 @@ set_contains_value (value_set_t set, tree val) ...@@ -701,7 +713,7 @@ set_contains_value (value_set_t set, tree val)
if (is_gimple_min_invariant (val)) if (is_gimple_min_invariant (val))
return true; return true;
if (set->length == 0) if (!set || set->length == 0)
return false; return false;
return value_exists_in_set_bitmap (set, val); return value_exists_in_set_bitmap (set, val);
...@@ -1102,6 +1114,18 @@ phi_translate (tree expr, value_set_t set, basic_block pred, ...@@ -1102,6 +1114,18 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
tree newval; tree newval;
if (oldval) if (oldval)
{ {
/* This may seem like a weird place for this
check, but it's actually the easiest place to
do it. We can't do it lower on in the
recursion because it's valid for pieces of a
component ref to be of AGGREGATE_TYPE, as long
as the outermost one is not.
To avoid *that* case, we have a check for
AGGREGATE_TYPE_P in insert_aux. However, that
check will *not* catch this case because here
it occurs in the argument list. */
if (AGGREGATE_TYPE_P (TREE_TYPE (oldval)))
return NULL;
newval = phi_translate (find_leader (set, oldval), newval = phi_translate (find_leader (set, oldval),
set, pred, phiblock); set, pred, phiblock);
if (newval == NULL) if (newval == NULL)
...@@ -1160,7 +1184,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred, ...@@ -1160,7 +1184,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
VEC (tree, gc) * newvuses = NULL; VEC (tree, gc) * newvuses = NULL;
if (TREE_CODE (expr) != INDIRECT_REF if (TREE_CODE (expr) != INDIRECT_REF
|| AGGREGATE_TYPE_P (TREE_TYPE (expr))) && TREE_CODE (expr) != COMPONENT_REF)
return NULL; return NULL;
newop1 = phi_translate (find_leader (set, oldop1), newop1 = phi_translate (find_leader (set, oldop1),
...@@ -1435,12 +1459,11 @@ vuses_dies_in_block_x (VEC (tree, gc) *vuses, basic_block block) ...@@ -1435,12 +1459,11 @@ vuses_dies_in_block_x (VEC (tree, gc) *vuses, basic_block block)
for (i = 0; VEC_iterate (tree, vuses, i, vuse); i++) for (i = 0; VEC_iterate (tree, vuses, i, vuse); i++)
{ {
/* Any places where this is too conservative, are places /* Any places where this is too conservative, are places
where we created a new version and shouldn't have. */ where we created a new version and shouldn't have. */
if (!bitmap_bit_p (RVUSE_IN (block), SSA_NAME_VERSION (vuse)) if (!bitmap_bit_p (RVUSE_IN (block), SSA_NAME_VERSION (vuse))
|| bitmap_bit_p (RVUSE_KILL (block), SSA_NAME_VERSION || bitmap_bit_p (RVUSE_KILL (block), SSA_NAME_VERSION (vuse)))
(vuse)))
return true; return true;
} }
return false; return false;
...@@ -1501,7 +1524,8 @@ valid_in_set (value_set_t set, tree expr, basic_block block) ...@@ -1501,7 +1524,8 @@ valid_in_set (value_set_t set, tree expr, basic_block block)
case tcc_reference: case tcc_reference:
{ {
if (TREE_CODE (expr) == INDIRECT_REF) if (TREE_CODE (expr) == INDIRECT_REF
|| TREE_CODE (expr) == COMPONENT_REF)
{ {
tree op0 = TREE_OPERAND (expr, 0); tree op0 = TREE_OPERAND (expr, 0);
if (is_gimple_min_invariant (op0) if (is_gimple_min_invariant (op0)
...@@ -1509,8 +1533,12 @@ valid_in_set (value_set_t set, tree expr, basic_block block) ...@@ -1509,8 +1533,12 @@ valid_in_set (value_set_t set, tree expr, basic_block block)
{ {
bool retval = set_contains_value (set, op0); bool retval = set_contains_value (set, op0);
if (retval) if (retval)
return !vuses_dies_in_block_x (VALUE_HANDLE_VUSES (vh), {
return set_contains_value (ANTIC_SAFE_LOADS (block),
vh)
|| !vuses_dies_in_block_x (VALUE_HANDLE_VUSES (vh),
block); block);
}
return false; return false;
} }
} }
...@@ -1649,7 +1677,12 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge) ...@@ -1649,7 +1677,12 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
{ {
if (ANTIC_OUT) if (ANTIC_OUT)
print_value_set (dump_file, ANTIC_OUT, "ANTIC_OUT", block->index); print_value_set (dump_file, ANTIC_OUT, "ANTIC_OUT", block->index);
if (ANTIC_SAFE_LOADS (block))
print_value_set (dump_file, ANTIC_SAFE_LOADS (block),
"ANTIC_SAFE_LOADS", block->index);
print_value_set (dump_file, ANTIC_IN (block), "ANTIC_IN", block->index); print_value_set (dump_file, ANTIC_IN (block), "ANTIC_IN", block->index);
if (S) if (S)
print_value_set (dump_file, S, "S", block->index); print_value_set (dump_file, S, "S", block->index);
} }
...@@ -1803,16 +1836,37 @@ compute_vuse_representatives (void) ...@@ -1803,16 +1836,37 @@ compute_vuse_representatives (void)
VEC_free (tree, heap, phis); VEC_free (tree, heap, phis);
} }
/* Compute reaching vuses. This is a small bit of iterative dataflow /* Compute reaching vuses and antic safe loads. RVUSE computation is
to determine what virtual uses reach what blocks. Because we can't is a small bit of iterative dataflow to determine what virtual uses
generate overlapping virtual uses, and virtual uses *do* actually reach what blocks. Because we can't generate overlapping virtual
die, this ends up being faster in most cases than continually uses, and virtual uses *do* actually die, this ends up being faster
walking the virtual use/def chains to determine whether we are in most cases than continually walking the virtual use/def chains
inside a block where a given virtual is still available to be to determine whether we are inside a block where a given virtual is
used. */ still available to be used.
ANTIC_SAFE_LOADS are those loads that actually occur before any kill to
their vuses in the block,and thus, are safe at the top of the
block.
An example:
<block begin>
b = *a
*a = 9
<block end>
b = *a is an antic safe load because it still safe to consider it
ANTIC at the top of the block.
We currently compute a conservative approximation to
ANTIC_SAFE_LOADS. We compute those loads that occur before *any*
stores in the block. This is not because it is difficult to
compute the precise answer, but because it is expensive. More
testing is necessary to determine whether it is worth computing the
precise answer. */
static void static void
compute_rvuse (void) compute_rvuse_and_antic_safe (void)
{ {
size_t i; size_t i;
...@@ -1820,7 +1874,10 @@ compute_rvuse (void) ...@@ -1820,7 +1874,10 @@ compute_rvuse (void)
basic_block bb; basic_block bb;
int *postorder; int *postorder;
bool changed = true; bool changed = true;
unsigned int *first_store_uid;
first_store_uid = xcalloc (n_basic_blocks, sizeof (unsigned int));
compute_vuse_representatives (); compute_vuse_representatives ();
FOR_ALL_BB (bb) FOR_ALL_BB (bb)
...@@ -1829,9 +1886,9 @@ compute_rvuse (void) ...@@ -1829,9 +1886,9 @@ compute_rvuse (void)
RVUSE_GEN (bb) = BITMAP_ALLOC (&grand_bitmap_obstack); RVUSE_GEN (bb) = BITMAP_ALLOC (&grand_bitmap_obstack);
RVUSE_KILL (bb) = BITMAP_ALLOC (&grand_bitmap_obstack); RVUSE_KILL (bb) = BITMAP_ALLOC (&grand_bitmap_obstack);
RVUSE_OUT (bb) = BITMAP_ALLOC (&grand_bitmap_obstack); RVUSE_OUT (bb) = BITMAP_ALLOC (&grand_bitmap_obstack);
ANTIC_SAFE_LOADS (bb) = NULL;
} }
/* Mark live on entry */ /* Mark live on entry */
for (i = 0; i < num_ssa_names; i++) for (i = 0; i < num_ssa_names; i++)
{ {
...@@ -1854,10 +1911,18 @@ compute_rvuse (void) ...@@ -1854,10 +1911,18 @@ compute_rvuse (void)
def_operand_p defp; def_operand_p defp;
use_operand_p usep; use_operand_p usep;
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{ {
tree stmt = bsi_stmt (bsi); tree stmt = bsi_stmt (bsi);
if (first_store_uid[bb->index] == 0
&& !ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYUSE | SSA_OP_VMAYDEF
| SSA_OP_VMUSTDEF | SSA_OP_VMUSTKILL))
{
first_store_uid[bb->index] = stmt_ann (stmt)->uid;
}
FOR_EACH_SSA_USE_OPERAND (usep, stmt, iter, SSA_OP_VIRTUAL_KILLS FOR_EACH_SSA_USE_OPERAND (usep, stmt, iter, SSA_OP_VIRTUAL_KILLS
| SSA_OP_VMAYUSE) | SSA_OP_VMAYUSE)
{ {
...@@ -1950,6 +2015,40 @@ compute_rvuse (void) ...@@ -1950,6 +2015,40 @@ compute_rvuse (void)
dump_bitmap_of_names (dump_file, RVUSE_OUT (bb)); dump_bitmap_of_names (dump_file, RVUSE_OUT (bb));
} }
} }
FOR_EACH_BB (bb)
{
value_set_node_t node;
if (bitmap_empty_p (RVUSE_KILL (bb)))
continue;
for (node = EXP_GEN (bb)->head; node; node = node->next)
{
if (REFERENCE_CLASS_P (node->expr))
{
tree vh = get_value_handle (node->expr);
tree maybe = bitmap_find_leader (AVAIL_OUT (bb), vh);
if (maybe)
{
tree def = SSA_NAME_DEF_STMT (maybe);
if (bb_for_stmt (def) != bb)
continue;
if (TREE_CODE (def) == PHI_NODE
|| stmt_ann (def)->uid < first_store_uid[bb->index])
{
if (ANTIC_SAFE_LOADS (bb) == NULL)
ANTIC_SAFE_LOADS (bb) = set_new (true);
value_insert_into_set (ANTIC_SAFE_LOADS (bb),
node->expr);
}
}
}
}
}
free (first_store_uid);
} }
/* Return true if we can value number the call in STMT. This is true /* Return true if we can value number the call in STMT. This is true
...@@ -1991,6 +2090,7 @@ can_PRE_operation (tree op) ...@@ -1991,6 +2090,7 @@ can_PRE_operation (tree op)
|| BINARY_CLASS_P (op) || BINARY_CLASS_P (op)
|| COMPARISON_CLASS_P (op) || COMPARISON_CLASS_P (op)
|| TREE_CODE (op) == INDIRECT_REF || TREE_CODE (op) == INDIRECT_REF
|| TREE_CODE (op) == COMPONENT_REF
|| TREE_CODE (op) == CALL_EXPR; || TREE_CODE (op) == CALL_EXPR;
} }
...@@ -2005,6 +2105,70 @@ static VEC(tree,heap) *inserted_exprs; ...@@ -2005,6 +2105,70 @@ static VEC(tree,heap) *inserted_exprs;
to see which expressions need to be put into GC'able memory */ to see which expressions need to be put into GC'able memory */
static VEC(tree, heap) *need_creation; static VEC(tree, heap) *need_creation;
/* For COMPONENT_REF's, we can't have any intermediates for the
COMPONENT_REF or INDIRECT_REF portion, because we'd end up with
trying to rename aggregates into ssa form directly, which is a no
no.
Thus, this routine doesn't create temporaries, it just builds a
single access expression for the array, calling
find_or_generate_expression to build the innermost pieces.
This function is a subroutine of create_expression_by_pieces, and
should not be called on it's own unless you really know what you
are doing.
*/
static tree
create_component_ref_by_pieces (basic_block block, tree expr, tree stmts)
{
tree genop = expr;
tree folded;
if (TREE_CODE (genop) == VALUE_HANDLE)
{
tree found = bitmap_find_leader (AVAIL_OUT (block), expr);
if (found)
return found;
}
if (TREE_CODE (genop) == VALUE_HANDLE)
genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr;
switch TREE_CODE (genop)
{
case COMPONENT_REF:
{
tree op0;
tree op1;
op0 = create_component_ref_by_pieces (block,
TREE_OPERAND (genop, 0),
stmts);
op1 = VALUE_HANDLE_EXPR_SET (TREE_OPERAND (genop, 1))->head->expr;
folded = fold_build3 (COMPONENT_REF, TREE_TYPE (genop), op0, op1,
NULL_TREE);
return folded;
}
break;
case INDIRECT_REF:
{
tree op1 = TREE_OPERAND (genop, 0);
tree genop1 = find_or_generate_expression (block, op1, stmts);
folded = fold_build1 (TREE_CODE (genop), TREE_TYPE (genop),
genop1);
return folded;
}
break;
case VAR_DECL:
case PARM_DECL:
case SSA_NAME:
return genop;
default:
gcc_unreachable ();
}
return NULL_TREE;
}
/* Find a leader for an expression, or generate one using /* Find a leader for an expression, or generate one using
create_expression_by_pieces if it's ANTIC but create_expression_by_pieces if it's ANTIC but
...@@ -2093,13 +2257,19 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts) ...@@ -2093,13 +2257,19 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
} }
break; break;
case tcc_reference: case tcc_reference:
gcc_assert (TREE_CODE (expr) == INDIRECT_REF);
{ {
tree op1 = TREE_OPERAND (expr, 0); if (TREE_CODE (expr) == COMPONENT_REF)
tree genop1 = find_or_generate_expression (block, op1, stmts); {
folded = create_component_ref_by_pieces (block, expr, stmts);
folded = fold_build1 (TREE_CODE (expr), TREE_TYPE (expr), }
genop1); else
{
tree op1 = TREE_OPERAND (expr, 0);
tree genop1 = find_or_generate_expression (block, op1, stmts);
folded = fold_build1 (TREE_CODE (expr), TREE_TYPE (expr),
genop1);
}
break; break;
} }
...@@ -2404,7 +2574,8 @@ insert_aux (basic_block block) ...@@ -2404,7 +2574,8 @@ insert_aux (basic_block block)
node; node;
node = node->next) node = node->next)
{ {
if (can_PRE_operation (node->expr)) if (can_PRE_operation (node->expr)
&& !AGGREGATE_TYPE_P (TREE_TYPE (node->expr)))
{ {
tree *avail; tree *avail;
tree val; tree val;
...@@ -2746,7 +2917,7 @@ insert_extra_phis (basic_block block, basic_block dom) ...@@ -2746,7 +2917,7 @@ insert_extra_phis (basic_block block, basic_block dom)
FOR_EACH_EDGE (e, ei, block->preds) FOR_EACH_EDGE (e, ei, block->preds)
{ {
/* We cannot handle abnormal incomming edges correctly. */ /* We cannot handle abnormal incoming edges correctly. */
if (e->flags & EDGE_ABNORMAL) if (e->flags & EDGE_ABNORMAL)
return; return;
...@@ -3076,7 +3247,6 @@ compute_avail (void) ...@@ -3076,7 +3247,6 @@ compute_avail (void)
basic_block *worklist; basic_block *worklist;
size_t sp = 0; size_t sp = 0;
tree param; tree param;
/* For arguments with default definitions, we pretend they are /* For arguments with default definitions, we pretend they are
defined in the entry block. */ defined in the entry block. */
for (param = DECL_ARGUMENTS (current_function_decl); for (param = DECL_ARGUMENTS (current_function_decl);
...@@ -3121,6 +3291,7 @@ compute_avail (void) ...@@ -3121,6 +3291,7 @@ compute_avail (void)
block_stmt_iterator bsi; block_stmt_iterator bsi;
tree stmt, phi; tree stmt, phi;
basic_block dom; basic_block dom;
unsigned int stmt_uid = 1;
/* Pick a block from the worklist. */ /* Pick a block from the worklist. */
block = worklist[--sp]; block = worklist[--sp];
...@@ -3152,6 +3323,8 @@ compute_avail (void) ...@@ -3152,6 +3323,8 @@ compute_avail (void)
stmt = bsi_stmt (bsi); stmt = bsi_stmt (bsi);
ann = stmt_ann (stmt); ann = stmt_ann (stmt);
ann->uid = stmt_uid++;
/* For regular value numbering, we are only interested in /* For regular value numbering, we are only interested in
assignments of the form X_i = EXPR, where EXPR represents assignments of the form X_i = EXPR, where EXPR represents
...@@ -3597,7 +3770,7 @@ execute_pre (bool do_fre) ...@@ -3597,7 +3770,7 @@ execute_pre (bool do_fre)
if (!do_fre && n_basic_blocks < 4000) if (!do_fre && n_basic_blocks < 4000)
{ {
vuse_names = XCNEWVEC (bitmap, num_ssa_names); vuse_names = XCNEWVEC (bitmap, num_ssa_names);
compute_rvuse (); compute_rvuse_and_antic_safe ();
compute_antic (); compute_antic ();
insert (); insert ();
free (vuse_names); free (vuse_names);
...@@ -3655,7 +3828,7 @@ struct tree_opt_pass pass_pre = ...@@ -3655,7 +3828,7 @@ struct tree_opt_pass pass_pre =
0, /* properties_provided */ 0, /* properties_provided */
0, /* properties_destroyed */ 0, /* properties_destroyed */
0, /* todo_flags_start */ 0, /* todo_flags_start */
TODO_update_ssa | TODO_dump_func | TODO_ggc_collect TODO_update_ssa_only_virtuals | TODO_dump_func | TODO_ggc_collect
| TODO_verify_ssa, /* todo_flags_finish */ | TODO_verify_ssa, /* todo_flags_finish */
0 /* letter */ 0 /* letter */
}; };
......
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