summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-16 01:12:07 +0000
committerdberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-16 01:12:07 +0000
commitf0c13a343d486f428f8c7eb41d0e1c8a7f0b2f86 (patch)
tree9ae1ca4cfd3a16282eccd4a1235eecbb784104c3
parente3feb2af3138cba10396fab975f553e986304d08 (diff)
downloadgcc-f0c13a343d486f428f8c7eb41d0e1c8a7f0b2f86.tar.gz
2005-05-15 Daniel Berlin <dberlin@dberlin.org>
Fix PR tree-optimization/21576 * tree-ssa-pre.c (expression_node_pool): New pool. (comparison_node_pool): Ditto. (list_node_pool): Ditto. (pool_copy_list): New function. (phi_translate): Handle CALL_EXPR. (valid_in_set): Ditto. (create_expression_by_pieces): Ditto. (insert_into_preds_of_block): Ditto. (insert_aux): Ditto. (compute_avail): Ditto. (create_value_expr_from): Handle TREE_LIST and CALL_EXPR. (can_value_number_call): New function. (find_leader): Update comment. (init_pre): Create new pools. (fini_pre): Free new pools. (pass_pre): Add TODO_update_ssa for the future when we are going to need vops. * tree-vn.c (expressions_equal_p): Handle TREE_LIST. (set_value_handle): Ditto. (get_value_handle): Ditto. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99759 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-10.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-11.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-12.c27
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-13.c26
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-9.c13
-rw-r--r--gcc/tree-ssa-pre.c281
-rw-r--r--gcc/tree-vn.c26
9 files changed, 419 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ef16d8ba29e..24444470364 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@
+2005-05-15 Daniel Berlin <dberlin@dberlin.org>
+
+ Fix PR tree-optimization/21576
+
+ * tree-ssa-pre.c (expression_node_pool): New pool.
+ (comparison_node_pool): Ditto.
+ (list_node_pool): Ditto.
+ (pool_copy_list): New function.
+ (phi_translate): Handle CALL_EXPR.
+ (valid_in_set): Ditto.
+ (create_expression_by_pieces): Ditto.
+ (insert_into_preds_of_block): Ditto.
+ (insert_aux): Ditto.
+ (compute_avail): Ditto.
+ (create_value_expr_from): Handle TREE_LIST and CALL_EXPR.
+ (can_value_number_call): New function.
+ (find_leader): Update comment.
+ (init_pre): Create new pools.
+ (fini_pre): Free new pools.
+ (pass_pre): Add TODO_update_ssa for the future when we are going
+ to need vops.
+ * tree-vn.c (expressions_equal_p): Handle TREE_LIST.
+ (set_value_handle): Ditto.
+ (get_value_handle): Ditto.
+
2005-05-15 Richard Earnshaw <richard.earnshaw@arm.com>
* arm.c (thumb_unexpanded_epilogue): Delete unused variable 'mode'.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-1.c
index 82687d71913..5bbfd3d17fb 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom1-details" } */
+/* { dg-options "-O2 -fdump-tree-fre-details" } */
int t(int a) __attribute__ ((const));
void q (void);
void
@@ -12,5 +12,5 @@ threading(int a,int b)
}
}
/* We should thread the jump twice and eliminate it. */
-/* { dg-final { scan-tree-dump-times "Replaced.* t " 1 "dom1"} } */
-/* { dg-final { cleanup-tree-dump "dom1" } } */
+/* { dg-final { scan-tree-dump-times "Replaced.* t " 1 "fre"} } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-10.c
new file mode 100644
index 00000000000..127caa6cd6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-10.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-fre-stats" } */
+double cos (double);
+void link_error();
+void f(double a)
+{
+ double b = cos (a);
+ double c = cos (a);
+ if (b != c)
+ link_error();
+}
+
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "fre"} } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-11.c
new file mode 100644
index 00000000000..26c47b1830b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-11.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+double cos (double);
+double f(double a)
+{
+ double b;
+ double c,d;
+ if (a < 2.0)
+ {
+ c = cos (a);
+ }
+ else
+ {
+ c = 1.0;
+ }
+ d = cos (a);
+ return d + c;
+}
+
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-12.c
new file mode 100644
index 00000000000..fd80e3d8d50
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-12.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+double cos (double) __attribute__ ((const));
+double sin (double) __attribute__ ((const));
+double f(double a)
+{
+ double b;
+ double c,d;
+ double (*fp) (double) __attribute__ ((const));
+ /* Fully redundant call, but we need a phi node to merge the results. */
+ if (a < 2.0)
+ {
+ fp = sin;
+ c = fp (a);
+ }
+ else
+ {
+ c = 1.0;
+ fp = cos;
+ c = fp (a);
+ }
+ d = fp (a);
+ return d + c;
+}
+
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-13.c
new file mode 100644
index 00000000000..dfce46b9907
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-13.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+double cos (double) __attribute__ ((const));
+double sin (double) __attribute__ ((const));
+double f(double a)
+{
+ double b;
+ double c,d;
+ double (*fp) (double) __attribute__ ((const));
+ /* Partially redundant call */
+ if (a < 2.0)
+ {
+ fp = sin;
+ c = fp (a);
+ }
+ else
+ {
+ c = 1.0;
+ fp = cos;
+ }
+ d = fp (a);
+ return d + c;
+}
+
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-9.c
new file mode 100644
index 00000000000..32e37b99703
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-9.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-fre-stats" } */
+int
+foo (unsigned long a)
+{
+ int b = __builtin_clzl (a);
+ int c = __builtin_clzl (a);
+ if (b == c)
+ return 1;
+ return 0;
+}
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "fre"} } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 0494774b608..859bf096210 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -305,6 +305,9 @@ static alloc_pool value_set_node_pool;
static alloc_pool binary_node_pool;
static alloc_pool unary_node_pool;
static alloc_pool reference_node_pool;
+static alloc_pool comparison_node_pool;
+static alloc_pool expression_node_pool;
+static alloc_pool list_node_pool;
static bitmap_obstack grand_bitmap_obstack;
/* Set of blocks with statements that have had its EH information
@@ -855,6 +858,35 @@ fully_constant_expression (tree t)
return t;
}
+/* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.
+ For example, this can copy a list made of TREE_LIST nodes.
+ Allocates the nodes in list_node_pool*/
+
+static tree
+pool_copy_list (tree list)
+{
+ tree head;
+ tree prev, next;
+
+ if (list == 0)
+ return 0;
+ head = pool_alloc (list_node_pool);
+
+ memcpy (head, list, tree_size (list));
+ prev = head;
+
+ next = TREE_CHAIN (list);
+ while (next)
+ {
+ TREE_CHAIN (prev) = pool_alloc (list_node_pool);
+ memcpy (TREE_CHAIN (prev), next, tree_size (next));
+ prev = TREE_CHAIN (prev);
+ next = TREE_CHAIN (next);
+ }
+ return head;
+}
+
+
/* Translate EXPR using phis in PHIBLOCK, so that it has the values of
the phis in PRED. Return NULL if we can't find a leader for each
part of the translated expression. */
@@ -879,6 +911,89 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
+ case tcc_expression:
+ {
+ if (TREE_CODE (expr) != CALL_EXPR)
+ return NULL;
+ else
+ {
+ tree oldop0 = TREE_OPERAND (expr, 0);
+ tree oldarglist = TREE_OPERAND (expr, 1);
+ tree oldop2 = TREE_OPERAND (expr, 2);
+ tree newop0;
+ tree newarglist;
+ tree newop2 = NULL;
+ tree oldwalker;
+ tree newwalker;
+ tree newexpr;
+ bool listchanged = false;
+
+ /* Call expressions are kind of weird because they have an
+ argument list. We don't want to value number the list
+ as one value number, because that doesn't make much
+ sense, and just breaks the support functions we call,
+ which expect TREE_OPERAND (call_expr, 2) to be a
+ TREE_LIST. */
+
+ newop0 = phi_translate (find_leader (set, oldop0),
+ set, pred, phiblock);
+ if (newop0 == NULL)
+ return NULL;
+ if (oldop2)
+ {
+ newop2 = phi_translate (find_leader (set, oldop2),
+ set, pred, phiblock);
+ if (newop2 == NULL)
+ return NULL;
+ }
+
+ /* phi translate the argument list piece by piece.
+
+ We could actually build the list piece by piece here,
+ but it's likely to not be worth the memory we will save,
+ unless you have millions of call arguments. */
+
+ newarglist = pool_copy_list (oldarglist);
+ for (oldwalker = oldarglist, newwalker = newarglist;
+ oldwalker && newwalker;
+ oldwalker = TREE_CHAIN (oldwalker),
+ newwalker = TREE_CHAIN (newwalker))
+ {
+
+ tree oldval = TREE_VALUE (oldwalker);
+ tree newval;
+ if (oldval)
+ {
+ newval = phi_translate (find_leader (set, oldval),
+ set, pred, phiblock);
+ if (newval == NULL)
+ return NULL;
+ if (newval != oldval)
+ {
+ listchanged = true;
+ TREE_VALUE (newwalker) = get_value_handle (newval);
+ }
+ }
+ }
+ if (listchanged)
+ vn_lookup_or_add (newarglist, NULL);
+
+ if (listchanged || (newop0 != oldop0) || (oldop2 != newop2))
+ {
+ newexpr = pool_alloc (expression_node_pool);
+ memcpy (newexpr, expr, tree_size (expr));
+ TREE_OPERAND (newexpr, 0) = newop0 == oldop0 ? oldop0 : get_value_handle (newop0);
+ TREE_OPERAND (newexpr, 1) = listchanged ? newarglist : oldarglist;
+ TREE_OPERAND (newexpr, 2) = newop2 == oldop2 ? oldop2 : get_value_handle (newop2);
+ create_tree_ann (newexpr);
+ vn_lookup_or_add (newexpr, NULL);
+ expr = newexpr;
+ phi_trans_add (oldexpr, newexpr, pred);
+ }
+ }
+ }
+ return expr;
+
case tcc_reference:
/* XXX: Until we have PRE of loads working, none will be ANTIC. */
return NULL;
@@ -1084,10 +1199,10 @@ find_leader (value_set_t set, tree val)
we have a leader for each part of the expression (if it consists of
values), or the expression is an SSA_NAME.
- NB: We never should run into a case where we have SSA_NAME +
+ NB: We never should run into a case where we have SSA_NAME +
SSA_NAME or SSA_NAME + value. The sets valid_in_set is called on,
- the ANTIC sets, will only ever have SSA_NAME's or binary value
- expression (IE VALUE1 + VALUE2) */
+ the ANTIC sets, will only ever have SSA_NAME's or value expressions
+ (IE VALUE1 + VALUE2, *VALUE1, VALUE1 < VALUE2) */
static bool
valid_in_set (value_set_t set, tree expr)
@@ -1107,7 +1222,31 @@ valid_in_set (value_set_t set, tree expr)
tree op1 = TREE_OPERAND (expr, 0);
return set_contains_value (set, op1);
}
+
+ case tcc_expression:
+ {
+ if (TREE_CODE (expr) == CALL_EXPR)
+ {
+ tree op0 = TREE_OPERAND (expr, 0);
+ tree arglist = TREE_OPERAND (expr, 1);
+ tree op2 = TREE_OPERAND (expr, 2);
+ /* Check the non-list operands first. */
+ if (!set_contains_value (set, op0)
+ || (op2 && !set_contains_value (set, op2)))
+ return false;
+
+ /* Now check the operands. */
+ for (; arglist; arglist = TREE_CHAIN (arglist))
+ {
+ if (!set_contains_value (set, TREE_VALUE (arglist)))
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
case tcc_reference:
/* XXX: Until PRE of loads works, no reference nodes are ANTIC. */
return false;
@@ -1189,7 +1328,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
translate through. */
else if (single_succ_p (block))
{
- phi_translate_set (ANTIC_OUT, ANTIC_IN(single_succ (block)),
+ phi_translate_set (ANTIC_OUT, ANTIC_IN (single_succ (block)),
block, single_succ (block));
}
/* If we have multiple successors, we take the intersection of all of
@@ -1359,6 +1498,42 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
+ case tcc_expression:
+ {
+ tree op0, op2;
+ tree arglist;
+ tree genop0, genop2;
+ tree genarglist;
+ tree walker, genwalker;
+
+ gcc_assert (TREE_CODE (expr) == CALL_EXPR);
+ genop2 = NULL;
+
+ op0 = TREE_OPERAND (expr, 0);
+ arglist = TREE_OPERAND (expr, 1);
+ op2 = TREE_OPERAND (expr, 2);
+
+ genop0 = find_or_generate_expression (block, op0, stmts);
+ genarglist = copy_list (arglist);
+ for (walker = arglist, genwalker = genarglist;
+ genwalker && walker;
+ genwalker = TREE_CHAIN (genwalker), walker = TREE_CHAIN (walker))
+ {
+ TREE_VALUE (genwalker) = find_or_generate_expression (block,
+ TREE_VALUE (walker),
+ stmts);
+ }
+
+ if (op2)
+ genop2 = find_or_generate_expression (block, op2, stmts);
+ folded = fold (build (TREE_CODE (expr), TREE_TYPE (expr),
+ genop0, genarglist, genop2));
+ break;
+
+
+ }
+ break;
+
case tcc_binary:
case tcc_comparison:
{
@@ -1499,7 +1674,8 @@ insert_into_preds_of_block (basic_block block, value_set_node_t node,
eprime = avail[bprime->index];
if (BINARY_CLASS_P (eprime)
|| COMPARISON_CLASS_P (eprime)
- || UNARY_CLASS_P (eprime))
+ || UNARY_CLASS_P (eprime)
+ || TREE_CODE (eprime) == CALL_EXPR)
{
builtexpr = create_expression_by_pieces (bprime,
eprime,
@@ -1613,7 +1789,8 @@ insert_aux (basic_block block)
{
if (BINARY_CLASS_P (node->expr)
|| COMPARISON_CLASS_P (node->expr)
- || UNARY_CLASS_P (node->expr))
+ || UNARY_CLASS_P (node->expr)
+ || TREE_CODE (node->expr) == CALL_EXPR)
{
tree *avail;
tree val;
@@ -1817,17 +1994,55 @@ create_value_expr_from (tree expr, basic_block block, tree stmt)
gcc_assert (TREE_CODE_CLASS (code) == tcc_unary
|| TREE_CODE_CLASS (code) == tcc_binary
|| TREE_CODE_CLASS (code) == tcc_comparison
- || TREE_CODE_CLASS (code) == tcc_reference);
+ || TREE_CODE_CLASS (code) == tcc_reference
+ || TREE_CODE_CLASS (code) == tcc_expression
+ || TREE_CODE_CLASS (code) == tcc_exceptional);
if (TREE_CODE_CLASS (code) == tcc_unary)
pool = unary_node_pool;
else if (TREE_CODE_CLASS (code) == tcc_reference)
pool = reference_node_pool;
- else
+ else if (TREE_CODE_CLASS (code) == tcc_binary)
pool = binary_node_pool;
+ else if (TREE_CODE_CLASS (code) == tcc_comparison)
+ pool = comparison_node_pool;
+ else if (TREE_CODE_CLASS (code) == tcc_exceptional)
+ {
+ gcc_assert (code == TREE_LIST);
+ pool = list_node_pool;
+ }
+ else
+ {
+ gcc_assert (code == CALL_EXPR);
+ pool = expression_node_pool;
+ }
vexpr = pool_alloc (pool);
memcpy (vexpr, expr, tree_size (expr));
+
+ /* This case is only for TREE_LIST's that appear as part of
+ CALL_EXPR's. Anything else is a bug, but we can't easily verify
+ this, hence tihs comment. TREE_LIST is not handled by the
+ general case below is because they don't have a fixed length, or
+ operands, so you can't access purpose/value/chain through
+ TREE_OPERAND macros. */
+
+ if (code == TREE_LIST)
+ {
+ tree temp = NULL_TREE;
+ if (TREE_CHAIN (vexpr))
+ temp = create_value_expr_from (TREE_CHAIN (vexpr), block, stmt);
+ TREE_CHAIN (vexpr) = temp ? temp : TREE_CHAIN (vexpr);
+
+ /* This is the equivalent of inserting op into EXP_GEN like we
+ do below */
+ if (!is_undefined_value (TREE_VALUE (vexpr)))
+ value_insert_into_set (EXP_GEN (block), TREE_VALUE (vexpr));
+
+ TREE_VALUE (vexpr) = vn_lookup_or_add (TREE_VALUE (vexpr), NULL);
+
+ return vexpr;
+ }
for (i = 0; i < TREE_CODE_LENGTH (code); i++)
{
@@ -1846,18 +2061,32 @@ create_value_expr_from (tree expr, basic_block block, tree stmt)
return NULL;
}
- /* Recursively value-numberize reference ops */
+ /* Recursively value-numberize reference ops and tree lists. */
if (REFERENCE_CLASS_P (op))
{
tree tempop = create_value_expr_from (op, block, stmt);
op = tempop ? tempop : op;
val = vn_lookup_or_add (op, stmt);
}
+ else if (TREE_CODE (op) == TREE_LIST)
+ {
+ tree tempop;
+
+ gcc_assert (TREE_CODE (expr) == CALL_EXPR);
+ tempop = create_value_expr_from (op, block, stmt);
+
+ op = tempop ? tempop : op;
+ vn_lookup_or_add (op, NULL);
+ /* Unlike everywhere else, we do *not* want to replace the
+ TREE_LIST itself with a value number, because support
+ functions we call will blow up. */
+ val = op;
+ }
else
/* Create a value handle for OP and add it to VEXPR. */
val = vn_lookup_or_add (op, NULL);
- if (!is_undefined_value (op))
+ if (!is_undefined_value (op) && TREE_CODE (op) != TREE_LIST)
value_insert_into_set (EXP_GEN (block), op);
if (TREE_CODE (val) == VALUE_HANDLE)
@@ -1870,6 +2099,22 @@ create_value_expr_from (tree expr, basic_block block, tree stmt)
}
+/* Return true if we can value number a call. This is true if we have
+ a pure or constant call. */
+static bool
+can_value_number_call (tree stmt)
+{
+ tree call = get_call_expr_in (stmt);
+
+ /* This is a temporary restriction until we translate vuses through
+ phi nodes. */
+ if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+ return false;
+ if (call_expr_flags (call) & (ECF_PURE | ECF_CONST))
+ return true;
+ return false;
+}
+
/* Compute the AVAIL set for all basic blocks.
This function performs value numbering of the statements in each basic
@@ -1964,7 +2209,9 @@ compute_avail (void)
if (UNARY_CLASS_P (rhs)
|| BINARY_CLASS_P (rhs)
|| COMPARISON_CLASS_P (rhs)
- || REFERENCE_CLASS_P (rhs))
+ || REFERENCE_CLASS_P (rhs)
+ || (TREE_CODE (rhs) == CALL_EXPR
+ && can_value_number_call (stmt)))
{
/* For binary, unary, and reference expressions,
create a duplicate expression with the operands
@@ -2245,6 +2492,12 @@ init_pre (bool do_fre)
tree_code_size (NEGATE_EXPR), 30);
reference_node_pool = create_alloc_pool ("Reference tree nodes",
tree_code_size (ARRAY_REF), 30);
+ expression_node_pool = create_alloc_pool ("Expression tree nodes",
+ tree_code_size (CALL_EXPR), 30);
+ list_node_pool = create_alloc_pool ("List tree nodes",
+ tree_code_size (TREE_LIST), 30);
+ comparison_node_pool = create_alloc_pool ("Comparison tree nodes",
+ tree_code_size (EQ_EXPR), 30);
FOR_ALL_BB (bb)
{
EXP_GEN (bb) = set_new (true);
@@ -2273,6 +2526,9 @@ fini_pre (bool do_fre)
free_alloc_pool (binary_node_pool);
free_alloc_pool (reference_node_pool);
free_alloc_pool (unary_node_pool);
+ free_alloc_pool (list_node_pool);
+ free_alloc_pool (expression_node_pool);
+ free_alloc_pool (comparison_node_pool);
htab_delete (phi_translate_table);
remove_fake_exit_edges ();
@@ -2398,7 +2654,8 @@ struct tree_opt_pass pass_pre =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */
+ TODO_update_ssa | TODO_dump_func | TODO_ggc_collect
+ | TODO_verify_ssa, /* todo_flags_finish */
0 /* letter */
};
diff --git a/gcc/tree-vn.c b/gcc/tree-vn.c
index 5f003720e4d..e46fafaf308 100644
--- a/gcc/tree-vn.c
+++ b/gcc/tree-vn.c
@@ -119,9 +119,25 @@ expressions_equal_p (tree e1, tree e2)
te1 = TREE_TYPE (e1);
te2 = TREE_TYPE (e2);
- if (TREE_CODE (e1) == TREE_CODE (e2)
- && (te1 == te2 || lang_hooks.types_compatible_p (te1, te2))
- && operand_equal_p (e1, e2, OEP_PURE_SAME))
+ if (TREE_CODE (e1) == TREE_LIST && TREE_CODE (e2) == TREE_LIST)
+ {
+ tree lop1 = e1;
+ tree lop2 = e2;
+ for (lop1 = e1, lop2 = e2;
+ lop1 || lop2;
+ lop1 = TREE_CHAIN (lop1), lop2 = TREE_CHAIN (lop2))
+ {
+ if (!lop1 || !lop2)
+ return false;
+ if (!expressions_equal_p (TREE_VALUE (lop1), TREE_VALUE (lop2)))
+ return false;
+ }
+ return true;
+
+ }
+ else if (TREE_CODE (e1) == TREE_CODE (e2)
+ && (te1 == te2 || lang_hooks.types_compatible_p (te1, te2))
+ && operand_equal_p (e1, e2, OEP_PURE_SAME))
return true;
return false;
@@ -166,7 +182,7 @@ set_value_handle (tree e, tree v)
{
if (TREE_CODE (e) == SSA_NAME)
SSA_NAME_VALUE (e) = v;
- else if (EXPR_P (e) || DECL_P (e))
+ else if (EXPR_P (e) || DECL_P (e) || TREE_CODE (e) == TREE_LIST)
get_tree_ann (e)->common.value_handle = v;
else
/* Do nothing. Constants are their own value handles. */
@@ -271,7 +287,7 @@ get_value_handle (tree expr)
if (TREE_CODE (expr) == SSA_NAME)
return SSA_NAME_VALUE (expr);
- else if (EXPR_P (expr) || DECL_P (expr))
+ else if (EXPR_P (expr) || DECL_P (expr) || TREE_CODE (expr) == TREE_LIST)
{
tree_ann_t ann = tree_ann (expr);
return ((ann) ? ann->common.value_handle : NULL_TREE);