OSDN Git Service

2006-03-20 Andrew Pinski <pinskia@physics.uc.edu>
authorpinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 20 Mar 2006 21:00:18 +0000 (21:00 +0000)
committerpinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 20 Mar 2006 21:00:18 +0000 (21:00 +0000)
        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

14 files changed:
gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/loadpre12.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre13.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre14.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre15.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre16.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre17.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre18.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre20.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre21.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c [new file with mode: 0644]
gcc/tree-ssa-pre.c

index 9e31001..157a550 100644 (file)
@@ -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'
index 736eca1..92e62fc 100644 (file)
@@ -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 (file)
index 0000000..4a79c80
--- /dev/null
@@ -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 (file)
index 0000000..420ad71
--- /dev/null
@@ -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 (file)
index 0000000..f4c06f2
--- /dev/null
@@ -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 (file)
index 0000000..3e3ff7c
--- /dev/null
@@ -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 (file)
index 0000000..3702440
--- /dev/null
@@ -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 (file)
index 0000000..93c530d
--- /dev/null
@@ -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 (file)
index 0000000..21a1d06
--- /dev/null
@@ -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 (file)
index 0000000..62ded9a
--- /dev/null
@@ -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 (file)
index 0000000..330b67a
--- /dev/null
@@ -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 (file)
index 0000000..77caef6
--- /dev/null
@@ -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 (file)
index 0000000..3c03c9b
--- /dev/null
@@ -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" } } */
index 305ee3e..eea38c3 100644 (file)
@@ -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);
          }