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
This commit is contained in:
parent
8a46b94f6c
commit
85300b4692
7 changed files with 296 additions and 32 deletions
|
@ -1,3 +1,24 @@
|
|||
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>
|
||||
|
||||
* configure.ac: Unconditionally disable decimal float by default.
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
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>
|
||||
|
||||
PR libfortran/24685
|
||||
|
|
49
gcc/testsuite/gcc.dg/tree-ssa/loadpre10.c
Normal file
49
gcc/testsuite/gcc.dg/tree-ssa/loadpre10.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* { 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" } } */
|
||||
|
14
gcc/testsuite/gcc.dg/tree-ssa/loadpre11.c
Normal file
14
gcc/testsuite/gcc.dg/tree-ssa/loadpre11.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* { 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)
|
|||
int i;
|
||||
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++)
|
||||
{
|
||||
e = *a;
|
||||
|
@ -17,5 +15,5 @@ int main(int *a, int argc)
|
|||
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" } } */
|
||||
|
|
|
@ -30,6 +30,8 @@ foo (void)
|
|||
abort ();
|
||||
}
|
||||
|
||||
/* There are some reloaded loads of *cell, and cell->common.chain on various
|
||||
branches. */
|
||||
void __attribute__((noinline))
|
||||
remove_useless_vars (tree *unexpanded_var_list, int dump_file)
|
||||
{
|
||||
|
@ -69,6 +71,6 @@ main (void)
|
|||
remove_useless_vars (&unexpanded_var_list, 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" } } */
|
||||
|
||||
|
|
|
@ -53,6 +53,11 @@ Boston, MA 02110-1301, USA. */
|
|||
we can repair later on.
|
||||
3. We can do back-substitution or smarter value numbering to catch
|
||||
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
|
||||
|
@ -258,6 +263,11 @@ typedef struct bb_value_sets
|
|||
bitmap rvuse_out;
|
||||
bitmap rvuse_gen;
|
||||
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;
|
||||
|
||||
#define EXP_GEN(BB) ((bb_value_sets_t) ((BB)->aux))->exp_gen
|
||||
|
@ -270,6 +280,7 @@ typedef struct bb_value_sets
|
|||
#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 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
|
||||
optimization PRE was able to perform. */
|
||||
|
@ -302,6 +313,7 @@ static bitmap_set_t bitmap_set_new (void);
|
|||
static value_set_t set_new (bool);
|
||||
static bool is_undefined_value (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
|
||||
|
@ -701,7 +713,7 @@ set_contains_value (value_set_t set, tree val)
|
|||
if (is_gimple_min_invariant (val))
|
||||
return true;
|
||||
|
||||
if (set->length == 0)
|
||||
if (!set || set->length == 0)
|
||||
return false;
|
||||
|
||||
return value_exists_in_set_bitmap (set, val);
|
||||
|
@ -1102,6 +1114,18 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
|
|||
tree newval;
|
||||
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),
|
||||
set, pred, phiblock);
|
||||
if (newval == NULL)
|
||||
|
@ -1160,7 +1184,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
|
|||
VEC (tree, gc) * newvuses = NULL;
|
||||
|
||||
if (TREE_CODE (expr) != INDIRECT_REF
|
||||
|| AGGREGATE_TYPE_P (TREE_TYPE (expr)))
|
||||
&& TREE_CODE (expr) != COMPONENT_REF)
|
||||
return NULL;
|
||||
|
||||
newop1 = phi_translate (find_leader (set, oldop1),
|
||||
|
@ -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++)
|
||||
{
|
||||
/* 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. */
|
||||
|
||||
if (!bitmap_bit_p (RVUSE_IN (block), SSA_NAME_VERSION (vuse))
|
||||
|| bitmap_bit_p (RVUSE_KILL (block), SSA_NAME_VERSION
|
||||
(vuse)))
|
||||
|| bitmap_bit_p (RVUSE_KILL (block), SSA_NAME_VERSION (vuse)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1501,7 +1524,8 @@ valid_in_set (value_set_t set, tree expr, basic_block block)
|
|||
|
||||
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);
|
||||
if (is_gimple_min_invariant (op0)
|
||||
|
@ -1509,8 +1533,12 @@ valid_in_set (value_set_t set, tree expr, basic_block block)
|
|||
{
|
||||
bool retval = set_contains_value (set, op0);
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1649,7 +1677,12 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
|
|||
{
|
||||
if (ANTIC_OUT)
|
||||
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);
|
||||
|
||||
if (S)
|
||||
print_value_set (dump_file, S, "S", block->index);
|
||||
}
|
||||
|
@ -1803,16 +1836,37 @@ compute_vuse_representatives (void)
|
|||
VEC_free (tree, heap, phis);
|
||||
}
|
||||
|
||||
/* Compute reaching vuses. This is a small bit of iterative dataflow
|
||||
to determine what virtual uses reach what blocks. Because we can't
|
||||
generate overlapping virtual uses, and virtual uses *do* actually
|
||||
die, this ends up being faster in most cases than continually
|
||||
walking the virtual use/def chains to determine whether we are
|
||||
inside a block where a given virtual is still available to be
|
||||
used. */
|
||||
/* Compute reaching vuses and antic safe loads. RVUSE computation is
|
||||
is a small bit of iterative dataflow to determine what virtual uses
|
||||
reach what blocks. Because we can't generate overlapping virtual
|
||||
uses, and virtual uses *do* actually die, this ends up being faster
|
||||
in most cases than continually walking the virtual use/def chains
|
||||
to determine whether we are inside a block where a given virtual is
|
||||
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
|
||||
compute_rvuse (void)
|
||||
compute_rvuse_and_antic_safe (void)
|
||||
{
|
||||
|
||||
size_t i;
|
||||
|
@ -1820,7 +1874,10 @@ compute_rvuse (void)
|
|||
basic_block bb;
|
||||
int *postorder;
|
||||
bool changed = true;
|
||||
unsigned int *first_store_uid;
|
||||
|
||||
first_store_uid = xcalloc (n_basic_blocks, sizeof (unsigned int));
|
||||
|
||||
compute_vuse_representatives ();
|
||||
|
||||
FOR_ALL_BB (bb)
|
||||
|
@ -1829,9 +1886,9 @@ compute_rvuse (void)
|
|||
RVUSE_GEN (bb) = BITMAP_ALLOC (&grand_bitmap_obstack);
|
||||
RVUSE_KILL (bb) = BITMAP_ALLOC (&grand_bitmap_obstack);
|
||||
RVUSE_OUT (bb) = BITMAP_ALLOC (&grand_bitmap_obstack);
|
||||
ANTIC_SAFE_LOADS (bb) = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Mark live on entry */
|
||||
for (i = 0; i < num_ssa_names; i++)
|
||||
{
|
||||
|
@ -1854,10 +1911,18 @@ compute_rvuse (void)
|
|||
def_operand_p defp;
|
||||
use_operand_p usep;
|
||||
|
||||
|
||||
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&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
|
||||
| SSA_OP_VMAYUSE)
|
||||
{
|
||||
|
@ -1950,6 +2015,40 @@ compute_rvuse (void)
|
|||
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
|
||||
|
@ -1991,6 +2090,7 @@ can_PRE_operation (tree op)
|
|||
|| BINARY_CLASS_P (op)
|
||||
|| COMPARISON_CLASS_P (op)
|
||||
|| TREE_CODE (op) == INDIRECT_REF
|
||||
|| TREE_CODE (op) == COMPONENT_REF
|
||||
|| TREE_CODE (op) == CALL_EXPR;
|
||||
}
|
||||
|
||||
|
@ -2005,6 +2105,70 @@ static VEC(tree,heap) *inserted_exprs;
|
|||
to see which expressions need to be put into GC'able memory */
|
||||
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
|
||||
create_expression_by_pieces if it's ANTIC but
|
||||
|
@ -2093,13 +2257,19 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
|
|||
}
|
||||
break;
|
||||
case tcc_reference:
|
||||
gcc_assert (TREE_CODE (expr) == INDIRECT_REF);
|
||||
{
|
||||
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);
|
||||
if (TREE_CODE (expr) == COMPONENT_REF)
|
||||
{
|
||||
folded = create_component_ref_by_pieces (block, expr, stmts);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2404,7 +2574,8 @@ insert_aux (basic_block block)
|
|||
node;
|
||||
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 val;
|
||||
|
@ -2746,7 +2917,7 @@ insert_extra_phis (basic_block block, basic_block dom)
|
|||
|
||||
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)
|
||||
return;
|
||||
|
||||
|
@ -3076,7 +3247,6 @@ compute_avail (void)
|
|||
basic_block *worklist;
|
||||
size_t sp = 0;
|
||||
tree param;
|
||||
|
||||
/* For arguments with default definitions, we pretend they are
|
||||
defined in the entry block. */
|
||||
for (param = DECL_ARGUMENTS (current_function_decl);
|
||||
|
@ -3121,6 +3291,7 @@ compute_avail (void)
|
|||
block_stmt_iterator bsi;
|
||||
tree stmt, phi;
|
||||
basic_block dom;
|
||||
unsigned int stmt_uid = 1;
|
||||
|
||||
/* Pick a block from the worklist. */
|
||||
block = worklist[--sp];
|
||||
|
@ -3152,6 +3323,8 @@ compute_avail (void)
|
|||
|
||||
stmt = bsi_stmt (bsi);
|
||||
ann = stmt_ann (stmt);
|
||||
|
||||
ann->uid = stmt_uid++;
|
||||
|
||||
/* For regular value numbering, we are only interested in
|
||||
assignments of the form X_i = EXPR, where EXPR represents
|
||||
|
@ -3597,7 +3770,7 @@ execute_pre (bool do_fre)
|
|||
if (!do_fre && n_basic_blocks < 4000)
|
||||
{
|
||||
vuse_names = XCNEWVEC (bitmap, num_ssa_names);
|
||||
compute_rvuse ();
|
||||
compute_rvuse_and_antic_safe ();
|
||||
compute_antic ();
|
||||
insert ();
|
||||
free (vuse_names);
|
||||
|
@ -3655,7 +3828,7 @@ struct tree_opt_pass pass_pre =
|
|||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
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 */
|
||||
0 /* letter */
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue