OSDN Git Service

PR c++/55877
[pf3gnuchains/gcc-fork.git] / gcc / graphite-scop-detection.c
index 5fae5aa..42dfbc6 100644 (file)
@@ -22,34 +22,23 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "ggc.h"
-#include "tree.h"
-#include "rtl.h"
-#include "basic-block.h"
-#include "diagnostic.h"
 #include "tree-flow.h"
-#include "toplev.h"
-#include "tree-dump.h"
-#include "timevar.h"
 #include "cfgloop.h"
 #include "tree-chrec.h"
 #include "tree-data-ref.h"
 #include "tree-scalar-evolution.h"
 #include "tree-pass.h"
-#include "domwalk.h"
-#include "value-prof.h"
-#include "pointer-set.h"
-#include "gimple.h"
 #include "sese.h"
 
 #ifdef HAVE_cloog
 #include "ppl_c.h"
 #include "graphite-ppl.h"
-#include "graphite.h"
 #include "graphite-poly.h"
 #include "graphite-scop-detection.h"
 
+/* Forward declarations.  */
+static void make_close_phi_nodes_unique (basic_block);
+
 /* The type of the analyzed basic block.  */
 
 typedef enum gbb_type {
@@ -277,7 +266,9 @@ stmt_has_simple_data_refs_p (loop_p outermost_loop, gimple stmt)
   bool res = true;
   VEC (data_reference_p, heap) *drs = VEC_alloc (data_reference_p, heap, 5);
 
-  graphite_find_data_references_in_stmt (outermost_loop, stmt, &drs);
+  graphite_find_data_references_in_stmt (outermost_loop,
+                                        loop_containing_stmt (stmt),
+                                        stmt, &drs);
 
   FOR_EACH_VEC_ELT (data_reference_p, drs, j, dr)
     for (i = 0; i < DR_NUM_DIMENSIONS (dr); i++)
@@ -899,9 +890,7 @@ create_single_entry_edge (sd_region *region)
        single edge pointing from outside into the loop.  */
     gcc_unreachable ();
 
-#ifdef ENABLE_CHECKING
-  gcc_assert (find_single_entry_edge (region));
-#endif
+  gcc_checking_assert (find_single_entry_edge (region));
 }
 
 /* Check if the sd_region, mentioned in EDGE, has no exit bb.  */
@@ -967,9 +956,7 @@ create_single_exit_edge (sd_region *region)
     if (e->aux)
       ((sd_region *) e->aux)->exit = forwarder->dest;
 
-#ifdef ENABLE_CHECKING
-  gcc_assert (find_single_exit_edge (region));
-#endif
+  gcc_checking_assert (find_single_exit_edge (region));
 }
 
 /* Unmark the exit edges of all REGIONS.
@@ -1217,6 +1204,73 @@ limit_scops (VEC (scop_p, heap) **scops)
   VEC_free (sd_region, heap, regions);
 }
 
+/* Returns true when P1 and P2 are close phis with the same
+   argument.  */
+
+static inline bool
+same_close_phi_node (gimple p1, gimple p2)
+{
+  return operand_equal_p (gimple_phi_arg_def (p1, 0),
+                         gimple_phi_arg_def (p2, 0), 0);
+}
+
+/* Remove the close phi node at GSI and replace its rhs with the rhs
+   of PHI.  */
+
+static void
+remove_duplicate_close_phi (gimple phi, gimple_stmt_iterator *gsi)
+{
+  gimple use_stmt;
+  use_operand_p use_p;
+  imm_use_iterator imm_iter;
+  tree res = gimple_phi_result (phi);
+  tree def = gimple_phi_result (gsi_stmt (*gsi));
+
+  gcc_assert (same_close_phi_node (phi, gsi_stmt (*gsi)));
+
+  FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def)
+    {
+      FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
+       SET_USE (use_p, res);
+
+      update_stmt (use_stmt);
+      
+      /* It is possible that we just created a duplicate close-phi
+        for an already-processed containing loop.  Check for this
+        case and clean it up.  */
+      if (gimple_code (use_stmt) == GIMPLE_PHI
+         && gimple_phi_num_args (use_stmt) == 1)
+       make_close_phi_nodes_unique (gimple_bb (use_stmt));
+    }
+
+  remove_phi_node (gsi, true);
+}
+
+/* Removes all the close phi duplicates from BB.  */
+
+static void
+make_close_phi_nodes_unique (basic_block bb)
+{
+  gimple_stmt_iterator psi;
+
+  for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
+    {
+      gimple_stmt_iterator gsi = psi;
+      gimple phi = gsi_stmt (psi);
+
+      /* At this point, PHI should be a close phi in normal form.  */
+      gcc_assert (gimple_phi_num_args (phi) == 1);
+
+      /* Iterate over the next phis and remove duplicates.  */
+      gsi_next (&gsi);
+      while (!gsi_end_p (gsi))
+       if (same_close_phi_node (phi, gsi_stmt (gsi)))
+         remove_duplicate_close_phi (phi, &gsi);
+       else
+         gsi_next (&gsi);
+    }
+}
+
 /* Transforms LOOP to the canonical loop closed SSA form.  */
 
 static void
@@ -1231,7 +1285,10 @@ canonicalize_loop_closed_ssa (loop_p loop)
   bb = e->dest;
 
   if (VEC_length (edge, bb->preds) == 1)
-    split_block_after_labels (bb);
+    {
+      e = split_block_after_labels (bb);
+      make_close_phi_nodes_unique (e->src);
+    }
   else
     {
       gimple_stmt_iterator psi;
@@ -1266,7 +1323,13 @@ canonicalize_loop_closed_ssa (loop_p loop)
                update_stmt (phi);
              }
        }
+
+      make_close_phi_nodes_unique (close);
     }
+
+  /* The code above does not properly handle changes in the post dominance
+     information (yet).  */
+  free_dominance_info (CDI_POST_DOMINATORS);
 }
 
 /* Converts the current loop closed SSA form to a canonical form
@@ -1286,6 +1349,8 @@ canonicalize_loop_closed_ssa (loop_p loop)
 
    - the basic block containing the close phi nodes does not contain
    other statements.
+
+   - there exist only one phi node per definition in the loop.
 */
 
 static void