summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorpinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4>2006-03-20 21:00:18 +0000
committerpinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4>2006-03-20 21:00:18 +0000
commit0e8f5fdeb1aa5193f267b58b80e939ff6d9369af (patch)
tree62891f428e807856aeb41bc768c8ca8e04b03e7f /gcc
parentdd030c96a41618a3932db4c3f273449a2285c3d5 (diff)
downloadgcc-0e8f5fdeb1aa5193f267b58b80e939ff6d9369af.tar.gz
2006-03-20 Andrew Pinski <pinskia@physics.uc.edu>
PR tree-opt/26629 * tree-ssa-pre (phi_translate): Handle ARRAY_REF's operands. (valid_in_set): Handle ARRAY_REF. Change "if min_variant or VH" to asserts. (create_component_ref_by_pieces): Handle ARRAY_REF. (create_expression_by_pieces): Likewise. (can_PRE_operation): ARRAY_REFs can now be PRE'd. 2006-03-20 Andrew Pinski <pinskia@physics.uc.edu> PR tree-opt/26629 * gcc.dg/tree-ssa/loadpre12.c: New test. * gcc.dg/tree-ssa/loadpre13.c: New test. * gcc.dg/tree-ssa/loadpre14.c: New test. * gcc.dg/tree-ssa/loadpre15.c: New test. * gcc.dg/tree-ssa/loadpre16.c: New test. * gcc.dg/tree-ssa/loadpre17.c: New test. * gcc.dg/tree-ssa/loadpre18.c: New test. * gcc.dg/tree-ssa/loadpre19.c: New test. * gcc.dg/tree-ssa/loadpre20.c: New test. * gcc.dg/tree-ssa/loadpre21.c: New test. * gcc.dg/tree-ssa/loadpre22.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@112227 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/testsuite/ChangeLog15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre12.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre13.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre14.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre15.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre16.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre17.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre18.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre20.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre21.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c19
-rw-r--r--gcc/tree-ssa-pre.c134
14 files changed, 318 insertions, 25 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e31001c0c5..157a550c1bb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2006-03-20 Andrew Pinski <pinskia@physics.uc.edu>
+
+ PR tree-opt/26629
+ * tree-ssa-pre (phi_translate): Handle ARRAY_REF's operands.
+ (valid_in_set): Handle ARRAY_REF.
+ Change "if min_variant or VH" to asserts.
+ (create_component_ref_by_pieces): Handle ARRAY_REF.
+ (create_expression_by_pieces): Likewise.
+ (can_PRE_operation): ARRAY_REFs can now be PRE'd.
+
2006-03-20 David Edelsohn <edelsohn@gnu.org>
* genpreds.c (write_insn_extra_address_constraint): Argument `c'
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 736eca1d9b2..92e62fc66fa 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,18 @@
+2006-03-20 Andrew Pinski <pinskia@physics.uc.edu>
+
+ PR tree-opt/26629
+ * gcc.dg/tree-ssa/loadpre12.c: New test.
+ * gcc.dg/tree-ssa/loadpre13.c: New test.
+ * gcc.dg/tree-ssa/loadpre14.c: New test.
+ * gcc.dg/tree-ssa/loadpre15.c: New test.
+ * gcc.dg/tree-ssa/loadpre16.c: New test.
+ * gcc.dg/tree-ssa/loadpre17.c: New test.
+ * gcc.dg/tree-ssa/loadpre18.c: New test.
+ * gcc.dg/tree-ssa/loadpre19.c: New test.
+ * gcc.dg/tree-ssa/loadpre20.c: New test.
+ * gcc.dg/tree-ssa/loadpre21.c: New test.
+ * gcc.dg/tree-ssa/loadpre22.c: New test.
+
2006-03-19 Paul Thomas <pault@gcc.gnu.org>
PR fortran/26741
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre12.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre12.c
new file mode 100644
index 00000000000..4a79c802b13
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre12.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+type *t;
+int g(int);
+int f(int tt)
+{
+ type *t1 = t;
+ if ((*t1)[0])
+ (*t1)[0] = 2;
+ return g((*t1)[0]);
+}
+
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" { xfail *-*-* } } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre13.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre13.c
new file mode 100644
index 00000000000..420ad7162bc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre13.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+int t[2];
+int g(int);
+int f(int tt)
+{
+ if (t[0])
+ t[0] = 2;
+ return g(t[0]);
+}
+
+/* { 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/loadpre14.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre14.c
new file mode 100644
index 00000000000..f4c06f264d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre14.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc)
+{
+ type c = {0, 1};
+ int d, e;
+
+ /* Should be able to eliminate the second load of *a along the main path. */
+ d = (*a)[0];
+ if (argc)
+ {
+ a = &c;
+ }
+ e = (*a)[0];
+ return d + e;
+}
+/* { 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/loadpre15.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre15.c
new file mode 100644
index 00000000000..3e3ff7c4535
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre15.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc, int t)
+{
+ type c = {0, 1};
+ int d, e;
+
+ /* Should be able to eliminate the second load of *a along the main path. */
+ d = (*a)[t];
+ if (argc)
+ {
+ a = &c;
+ }
+ e = (*a)[t];
+ return d + e;
+}
+/* { 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/loadpre16.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre16.c
new file mode 100644
index 00000000000..3702440f3d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre16.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc)
+{
+ int d, e;
+
+ /* Should be able to eliminate the second load of *a along the main path. */
+ d = (*a)[0];
+ if (argc)
+ a++;
+ e = (*a)[0];
+ return d + e;
+}
+/* { 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/loadpre17.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre17.c
new file mode 100644
index 00000000000..93c530d5e57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre17.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc)
+{
+ int d, e;
+
+ /* Should be able to eliminate the second load of *a along the main path. */
+ d = (*a)[argc];
+ if (argc)
+ a++;
+ e = (*a)[argc];
+ return d + e;
+}
+/* { 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/loadpre18.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre18.c
new file mode 100644
index 00000000000..21a1d067008
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre18.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc)
+{
+ int d, e;
+
+ /* Should be able to eliminate the second load of *a along the main path. */
+ d = (*a)[argc];
+ if (argc)
+ argc++;
+ e = (*a)[argc];
+ return d + e;
+}
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" { xfail *-*-* } } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c
new file mode 100644
index 00000000000..62ded9a6d80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc)
+{
+ int d, e;
+
+ /* Should be able to eliminate the second load of *a along the main path. */
+ d = (*a)[argc];
+ if (!d)
+ argc++;
+ e = (*a)[argc];
+ return e;
+}
+/* { 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/loadpre20.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre20.c
new file mode 100644
index 00000000000..330b67a579f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre20.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc)
+{
+ int d, e;
+
+ /* Should be able to eliminate the second load of *a along the main path. */
+ d = (*a)[argc];
+ if (!d)
+ a++;
+ e = (*a)[argc];
+ return e;
+}
+/* { 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/loadpre21.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre21.c
new file mode 100644
index 00000000000..77caef6ded6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre21.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc)
+{
+ int b;
+ int i;
+ int d, e;
+
+ /* Should be able to hoist this out of the loop. */
+ for (i = 0; i < argc; i++)
+ {
+ e = (*a)[0];
+ }
+ return d + e;
+}
+
+/* { 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/loadpre22.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c
new file mode 100644
index 00000000000..3c03c9b12f6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+typedef int type[2];
+int main(type *a, int argc)
+{
+ int b;
+ int i;
+ int d, e;
+
+ /* Should be able to hoist this out of the loop. */
+ for (i = 0; i < argc; i++)
+ {
+ e = (*a)[argc];
+ }
+ return d + e;
+}
+
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 305ee3e938b..eea38c3bca1 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -1177,32 +1177,78 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
case tcc_reference:
{
- tree oldop1 = TREE_OPERAND (expr, 0);
- tree newop1;
+ tree oldop0 = TREE_OPERAND (expr, 0);
+ tree oldop1 = NULL;
+ tree newop0;
+ tree newop1 = NULL;
+ tree oldop2 = NULL;
+ tree newop2 = NULL;
+ tree oldop3 = NULL;
+ tree newop3 = NULL;
tree newexpr;
VEC (tree, gc) * oldvuses = NULL;
VEC (tree, gc) * newvuses = NULL;
if (TREE_CODE (expr) != INDIRECT_REF
- && TREE_CODE (expr) != COMPONENT_REF)
+ && TREE_CODE (expr) != COMPONENT_REF
+ && TREE_CODE (expr) != ARRAY_REF)
return NULL;
- newop1 = phi_translate (find_leader (set, oldop1),
+ newop0 = phi_translate (find_leader (set, oldop0),
set, pred, phiblock);
- if (newop1 == NULL)
+ if (newop0 == NULL)
return NULL;
+
+ if (TREE_CODE (expr) == ARRAY_REF)
+ {
+ oldop1 = TREE_OPERAND (expr, 1);
+ newop1 = phi_translate (find_leader (set, oldop1),
+ set, pred, phiblock);
+
+ if (newop1 == NULL)
+ return NULL;
+ oldop2 = TREE_OPERAND (expr, 2);
+ if (oldop2)
+ {
+ newop2 = phi_translate (find_leader (set, oldop2),
+ set, pred, phiblock);
+
+ if (newop2 == NULL)
+ return NULL;
+ }
+ oldop3 = TREE_OPERAND (expr, 3);
+ if (oldop3)
+ {
+ newop3 = phi_translate (find_leader (set, oldop3),
+ set, pred, phiblock);
+
+ if (newop3 == NULL)
+ return NULL;
+ }
+ }
oldvuses = VALUE_HANDLE_VUSES (get_value_handle (expr));
if (oldvuses)
newvuses = translate_vuses_through_block (oldvuses, pred);
-
- if (newop1 != oldop1 || newvuses != oldvuses)
+
+ if (newop0 != oldop0 || newvuses != oldvuses
+ || newop1 != oldop1
+ || newop2 != oldop2
+ || newop3 != oldop3)
{
tree t;
newexpr = pool_alloc (reference_node_pool);
memcpy (newexpr, expr, tree_size (expr));
- TREE_OPERAND (newexpr, 0) = get_value_handle (newop1);
+ TREE_OPERAND (newexpr, 0) = get_value_handle (newop0);
+ if (TREE_CODE (expr) == ARRAY_REF)
+ {
+ TREE_OPERAND (newexpr, 1) = get_value_handle (newop1);
+ if (newop2)
+ TREE_OPERAND (newexpr, 2) = get_value_handle (newop2);
+ if (newop3)
+ TREE_OPERAND (newexpr, 3) = get_value_handle (newop3);
+ }
t = fully_constant_expression (newexpr);
@@ -1525,22 +1571,38 @@ valid_in_set (value_set_t set, tree expr, basic_block block)
case tcc_reference:
{
if (TREE_CODE (expr) == INDIRECT_REF
- || TREE_CODE (expr) == COMPONENT_REF)
+ || TREE_CODE (expr) == COMPONENT_REF
+ || TREE_CODE (expr) == ARRAY_REF)
{
tree op0 = TREE_OPERAND (expr, 0);
- if (is_gimple_min_invariant (op0)
- || TREE_CODE (op0) == VALUE_HANDLE)
+ gcc_assert (is_gimple_min_invariant (op0)
+ || TREE_CODE (op0) == VALUE_HANDLE);
+ if (!set_contains_value (set, op0))
+ return false;
+ if (TREE_CODE (expr) == ARRAY_REF)
{
- bool retval = set_contains_value (set, op0);
- if (retval)
- {
- return set_contains_value (ANTIC_SAFE_LOADS (block),
- vh)
- || !vuses_dies_in_block_x (VALUE_HANDLE_VUSES (vh),
- block);
- }
- return false;
- }
+ tree op1 = TREE_OPERAND (expr, 1);
+ tree op2 = TREE_OPERAND (expr, 2);
+ tree op3 = TREE_OPERAND (expr, 3);
+ gcc_assert (is_gimple_min_invariant (op1)
+ || TREE_CODE (op1) == VALUE_HANDLE);
+ if (!set_contains_value (set, op1))
+ return false;
+ gcc_assert (!op2 || is_gimple_min_invariant (op2)
+ || TREE_CODE (op2) == VALUE_HANDLE);
+ if (op2
+ && !set_contains_value (set, op2))
+ return false;
+ gcc_assert (!op3 || is_gimple_min_invariant (op3)
+ || TREE_CODE (op3) == VALUE_HANDLE);
+ if (op3
+ && !set_contains_value (set, op3))
+ return false;
+ }
+ return set_contains_value (ANTIC_SAFE_LOADS (block),
+ vh)
+ || !vuses_dies_in_block_x (VALUE_HANDLE_VUSES (vh),
+ block);
}
}
return false;
@@ -2091,7 +2153,8 @@ can_PRE_operation (tree op)
|| COMPARISON_CLASS_P (op)
|| TREE_CODE (op) == INDIRECT_REF
|| TREE_CODE (op) == COMPONENT_REF
- || TREE_CODE (op) == CALL_EXPR;
+ || TREE_CODE (op) == CALL_EXPR
+ || TREE_CODE (op) == ARRAY_REF;
}
@@ -2105,8 +2168,8 @@ 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
+/* For COMPONENT_REF's and ARRAY_REF's, we can't have any intermediates for the
+ COMPONENT_REF or INDIRECT_REF or ARRAY_REF portion, because we'd end up with
trying to rename aggregates into ssa form directly, which is a no
no.
@@ -2136,6 +2199,26 @@ create_component_ref_by_pieces (basic_block block, tree expr, tree stmts)
switch TREE_CODE (genop)
{
+ case ARRAY_REF:
+ {
+ tree op0;
+ tree op1, op2, op3;
+ op0 = create_component_ref_by_pieces (block,
+ TREE_OPERAND (genop, 0),
+ stmts);
+ op1 = TREE_OPERAND (genop, 1);
+ if (TREE_CODE (op1) == VALUE_HANDLE)
+ op1 = find_or_generate_expression (block, op1, stmts);
+ op2 = TREE_OPERAND (genop, 2);
+ if (op2 && TREE_CODE (op2) == VALUE_HANDLE)
+ op2 = find_or_generate_expression (block, op2, stmts);
+ op3 = TREE_OPERAND (genop, 3);
+ if (op3 && TREE_CODE (op3) == VALUE_HANDLE)
+ op3 = find_or_generate_expression (block, op3, stmts);
+ folded = build4 (ARRAY_REF, TREE_TYPE (genop), op0, op1,
+ op2, op3);
+ return folded;
+ }
case COMPONENT_REF:
{
tree op0;
@@ -2259,7 +2342,8 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
break;
case tcc_reference:
{
- if (TREE_CODE (expr) == COMPONENT_REF)
+ if (TREE_CODE (expr) == COMPONENT_REF
+ || TREE_CODE (expr) == ARRAY_REF)
{
folded = create_component_ref_by_pieces (block, expr, stmts);
}