OSDN Git Service

* system.h: Poison PARAMS.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop-manip.c
index 19b0ca2..cbc1e69 100644 (file)
@@ -1,5 +1,5 @@
 /* High-level loop manipulation functions.
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
    
 This file is part of GCC.
    
@@ -37,6 +37,84 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "cfglayout.h"
 #include "tree-scalar-evolution.h"
 
+/* Creates an induction variable with value BASE + STEP * iteration in LOOP.
+   It is expected that neither BASE nor STEP are shared with other expressions
+   (unless the sharing rules allow this).  Use VAR as a base var_decl for it
+   (if NULL, a new temporary will be created).  The increment will occur at
+   INCR_POS (after it if AFTER is true, before it otherwise).  INCR_POS and 
+   AFTER can be computed using standard_iv_increment_position.  The ssa versions
+   of the variable before and after increment will be stored in VAR_BEFORE and
+   VAR_AFTER (unless they are NULL).  */
+
+void
+create_iv (tree base, tree step, tree var, struct loop *loop,
+          block_stmt_iterator *incr_pos, bool after,
+          tree *var_before, tree *var_after)
+{
+  tree stmt, initial, step1, stmts;
+  tree vb, va;
+  enum tree_code incr_op = PLUS_EXPR;
+
+  if (!var)
+    {
+      var = create_tmp_var (TREE_TYPE (base), "ivtmp");
+      add_referenced_tmp_var (var);
+    }
+
+  vb = make_ssa_name (var, NULL_TREE);
+  if (var_before)
+    *var_before = vb;
+  va = make_ssa_name (var, NULL_TREE);
+  if (var_after)
+    *var_after = va;
+
+  /* For easier readability of the created code, produce MINUS_EXPRs
+     when suitable.  */
+  if (TREE_CODE (step) == INTEGER_CST)
+    {
+      if (TYPE_UNSIGNED (TREE_TYPE (step)))
+       {
+         step1 = fold (build1 (NEGATE_EXPR, TREE_TYPE (step), step));
+         if (tree_int_cst_lt (step1, step))
+           {
+             incr_op = MINUS_EXPR;
+             step = step1;
+           }
+       }
+      else
+       {
+         if (!tree_expr_nonnegative_p (step)
+             && may_negate_without_overflow_p (step))
+           {
+             incr_op = MINUS_EXPR;
+             step = fold (build1 (NEGATE_EXPR, TREE_TYPE (step), step));
+           }
+       }
+    }
+
+  stmt = build2 (MODIFY_EXPR, void_type_node, va,
+                build2 (incr_op, TREE_TYPE (base),
+                        vb, step));
+  SSA_NAME_DEF_STMT (va) = stmt;
+  if (after)
+    bsi_insert_after (incr_pos, stmt, BSI_NEW_STMT);
+  else
+    bsi_insert_before (incr_pos, stmt, BSI_NEW_STMT);
+
+  initial = force_gimple_operand (base, &stmts, true, var);
+  if (stmts)
+    {
+      edge pe = loop_preheader_edge (loop);
+
+      bsi_insert_on_edge_immediate_loop (pe, stmts);
+    }
+
+  stmt = create_phi_node (vb, loop->header);
+  SSA_NAME_DEF_STMT (vb) = stmt;
+  add_phi_arg (stmt, initial, loop_preheader_edge (loop));
+  add_phi_arg (stmt, va, loop_latch_edge (loop));
+}
+
 /* Add exit phis for the USE on EXIT.  */
 
 static void
@@ -46,10 +124,11 @@ add_exit_phis_edge (basic_block exit, tree use)
   basic_block def_bb = bb_for_stmt (def_stmt);
   struct loop *def_loop;
   edge e;
+  edge_iterator ei;
 
   /* Check that some of the edges entering the EXIT block exits a loop in
      that USE is defined.  */
-  for (e = exit->pred; e; e = e->pred_next)
+  FOR_EACH_EDGE (e, ei, exit->preds)
     {
       def_loop = find_common_loop (def_bb->loop_father, e->src->loop_father);
       if (!flow_bb_inside_loop_p (def_loop, e->dest))
@@ -61,8 +140,8 @@ add_exit_phis_edge (basic_block exit, tree use)
 
   phi = create_phi_node (use, exit);
 
-  for (e = exit->pred; e; e = e->pred_next)
-    add_phi_arg (&phi, use, e);
+  FOR_EACH_EDGE (e, ei, exit->preds)
+    add_phi_arg (phi, use, e);
 
   SSA_NAME_DEF_STMT (use) = def_stmt;
 }
@@ -74,18 +153,21 @@ static void
 add_exit_phis_var (tree var, bitmap livein, bitmap exits)
 {
   bitmap def;
-  int index;
+  unsigned index;
   basic_block def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (var));
+  bitmap_iterator bi;
 
   bitmap_clear_bit (livein, def_bb->index);
 
-  def = BITMAP_XMALLOC ();
+  def = BITMAP_ALLOC (NULL);
   bitmap_set_bit (def, def_bb->index);
   compute_global_livein (livein, def);
-  BITMAP_XFREE (def);
+  BITMAP_FREE (def);
 
-  EXECUTE_IF_AND_IN_BITMAP (exits, livein, 0, index,
-                           add_exit_phis_edge (BASIC_BLOCK (index), var));
+  EXECUTE_IF_AND_IN_BITMAP (exits, livein, 0, index, bi)
+    {
+      add_exit_phis_edge (BASIC_BLOCK (index), var);
+    }
 }
 
 /* Add exit phis for the names marked in NAMES_TO_RENAME.
@@ -96,11 +178,12 @@ static void
 add_exit_phis (bitmap names_to_rename, bitmap *use_blocks, bitmap loop_exits)
 {
   unsigned i;
+  bitmap_iterator bi;
 
-  EXECUTE_IF_SET_IN_BITMAP (names_to_rename, 0, i,
+  EXECUTE_IF_SET_IN_BITMAP (names_to_rename, 0, i, bi)
     {
       add_exit_phis_var (ssa_name (i), use_blocks[i], loop_exits);
-    });
+    }
 }
 
 /* Returns a bitmap of all loop exit edge targets.  */
@@ -108,13 +191,14 @@ add_exit_phis (bitmap names_to_rename, bitmap *use_blocks, bitmap loop_exits)
 static bitmap
 get_loops_exits (void)
 {
-  bitmap exits = BITMAP_XMALLOC ();
+  bitmap exits = BITMAP_ALLOC (NULL);
   basic_block bb;
   edge e;
+  edge_iterator ei;
 
   FOR_EACH_BB (bb)
     {
-      for (e = bb->pred; e; e = e->pred_next)
+      FOR_EACH_EDGE (e, ei, bb->preds)
        if (e->src != ENTRY_BLOCK_PTR
            && !flow_bb_inside_loop_p (e->src->loop_father, bb))
          {
@@ -151,7 +235,7 @@ find_uses_to_rename_use (basic_block bb, tree use, bitmap *use_blocks)
     return;
 
   if (!use_blocks[ver])
-    use_blocks[ver] = BITMAP_XMALLOC ();
+    use_blocks[ver] = BITMAP_ALLOC (NULL);
   bitmap_set_bit (use_blocks[ver], bb->index);
 
   if (!flow_bb_inside_loop_p (def_loop, bb))
@@ -165,50 +249,62 @@ find_uses_to_rename_use (basic_block bb, tree use, bitmap *use_blocks)
 static void
 find_uses_to_rename_stmt (tree stmt, bitmap *use_blocks)
 {
-  use_optype uses;
-  vuse_optype vuses;
-  v_may_def_optype v_may_defs;
-  stmt_ann_t ann;
-  unsigned i;
+  ssa_op_iter iter;
+  tree var;
   basic_block bb = bb_for_stmt (stmt);
 
   get_stmt_operands (stmt);
-  ann = stmt_ann (stmt);
 
-  uses = USE_OPS (ann);
-  for (i = 0; i < NUM_USES (uses); i++)
-    find_uses_to_rename_use (bb, USE_OP (uses, i), use_blocks);
+  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES | SSA_OP_ALL_KILLS)
+    find_uses_to_rename_use (bb, var, use_blocks);
+}
 
-  vuses = VUSE_OPS (ann);
-  for (i = 0; i < NUM_VUSES (vuses); i++)
-    find_uses_to_rename_use (bb, VUSE_OP (vuses, i),use_blocks);
+/* Marks names that are used in BB and outside of the loop they are
+   defined in for rewrite.  Records the set of blocks in that the ssa
+   names are defined to USE_BLOCKS.  */
 
-  v_may_defs = V_MAY_DEF_OPS (ann);
-  for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
-    find_uses_to_rename_use (bb, V_MAY_DEF_OP (v_may_defs, i), use_blocks);
-}
+static void
+find_uses_to_rename_bb (basic_block bb, bitmap *use_blocks)
+{
+  block_stmt_iterator bsi;
+  edge e;
+  edge_iterator ei;
+  tree phi;
 
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
+      find_uses_to_rename_use (bb, PHI_ARG_DEF_FROM_EDGE (phi, e),
+                              use_blocks);
+  for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+    find_uses_to_rename_stmt (bsi_stmt (bsi), use_blocks);
+}
+     
 /* Marks names that are used outside of the loop they are defined in
    for rewrite.  Records the set of blocks in that the ssa
-   names are defined to USE_BLOCKS.  */
+   names are defined to USE_BLOCKS.  If CHANGED_BBS is not NULL,
+   scan only blocks in this set.  */
 
 static void
-find_uses_to_rename (bitmap *use_blocks)
+find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks)
 {
   basic_block bb;
-  block_stmt_iterator bsi;
-  tree phi;
-  unsigned i;
+  unsigned index;
+  bitmap_iterator bi;
 
-  FOR_EACH_BB (bb)
+  if (changed_bbs)
     {
-      for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
-       for (i = 0; i < (unsigned) PHI_NUM_ARGS (phi); i++)
-         find_uses_to_rename_use (PHI_ARG_EDGE (phi, i)->src,
-                                  PHI_ARG_DEF (phi, i), use_blocks);
-
-      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-       find_uses_to_rename_stmt (bsi_stmt (bsi), use_blocks);
+      EXECUTE_IF_SET_IN_BITMAP (changed_bbs, 0, index, bi)
+       {
+         find_uses_to_rename_bb (BASIC_BLOCK (index), use_blocks);
+       }
+    }
+  else
+    {
+      FOR_EACH_BB (bb)
+       {
+         find_uses_to_rename_bb (bb, use_blocks);
+       }
     }
 }
 
@@ -236,23 +332,32 @@ find_uses_to_rename (bitmap *use_blocks)
 
       Looking from the outer loop with the normal SSA form, the first use of k
       is not well-behaved, while the second one is an induction variable with
-      base 99 and step 1.  */
+      base 99 and step 1.
+      
+      If CHANGED_BBS is not NULL, we look for uses outside loops only in
+      the basic blocks in this set.  */
 
 void
-rewrite_into_loop_closed_ssa (void)
+rewrite_into_loop_closed_ssa (bitmap changed_bbs)
 {
   bitmap loop_exits = get_loops_exits ();
   bitmap *use_blocks;
   unsigned i;
   bitmap names_to_rename;
 
-  if (any_marked_for_rewrite_p ())
-    abort ();
+  gcc_assert (!any_marked_for_rewrite_p ());
 
   use_blocks = xcalloc (num_ssa_names, sizeof (bitmap));
 
   /* Find the uses outside loops.  */
-  find_uses_to_rename (use_blocks);
+  find_uses_to_rename (changed_bbs, use_blocks);
+
+  if (!any_marked_for_rewrite_p ())
+    {
+      free (use_blocks);
+      BITMAP_FREE (loop_exits);
+      return;
+    }
 
   /* Add the phi nodes on exits of the loops for the names we need to
      rewrite.  */
@@ -260,10 +365,10 @@ rewrite_into_loop_closed_ssa (void)
   add_exit_phis (names_to_rename, use_blocks, loop_exits);
 
   for (i = 0; i < num_ssa_names; i++)
-    BITMAP_XFREE (use_blocks[i]);
+    BITMAP_FREE (use_blocks[i]);
   free (use_blocks);
-  BITMAP_XFREE (loop_exits);
-  BITMAP_XFREE (names_to_rename);
+  BITMAP_FREE (loop_exits);
+  BITMAP_FREE (names_to_rename);
 
   /* Do the rewriting.  */
   rewrite_ssa_into_ssa ();
@@ -282,9 +387,8 @@ check_loop_closed_ssa_use (basic_block bb, tree use)
 
   def = SSA_NAME_DEF_STMT (use);
   def_bb = bb_for_stmt (def);
-  if (def_bb
-      && !flow_bb_inside_loop_p (def_bb->loop_father, bb))
-    abort ();
+  gcc_assert (!def_bb
+             || flow_bb_inside_loop_p (def_bb->loop_father, bb));
 }
 
 /* Checks invariants of loop closed ssa form in statement STMT in BB.  */
@@ -292,26 +396,13 @@ check_loop_closed_ssa_use (basic_block bb, tree use)
 static void
 check_loop_closed_ssa_stmt (basic_block bb, tree stmt)
 {
-  use_optype uses;
-  vuse_optype vuses;
-  v_may_def_optype v_may_defs;
-  stmt_ann_t ann;
-  unsigned i;
+  ssa_op_iter iter;
+  tree var;
 
   get_stmt_operands (stmt);
-  ann = stmt_ann (stmt);
-
-  uses = USE_OPS (ann);
-  for (i = 0; i < NUM_USES (uses); i++)
-    check_loop_closed_ssa_use (bb, USE_OP (uses, i));
 
-  vuses = VUSE_OPS (ann);
-  for (i = 0; i < NUM_VUSES (vuses); i++)
-    check_loop_closed_ssa_use (bb, VUSE_OP (vuses, i));
-
-  v_may_defs = V_MAY_DEF_OPS (ann);
-  for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
-    check_loop_closed_ssa_use (bb, V_MAY_DEF_OP (v_may_defs, i));
+  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES)
+    check_loop_closed_ssa_use (bb, var);
 }
 
 /* Checks that invariants of the loop closed ssa form are preserved.  */
@@ -324,11 +415,11 @@ verify_loop_closed_ssa (void)
   tree phi;
   unsigned i;
 
-  verify_ssa ();
+  verify_ssa (false);
 
   FOR_EACH_BB (bb)
     {
-      for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
        for (i = 0; i < (unsigned) PHI_NUM_ARGS (phi); i++)
          check_loop_closed_ssa_use (PHI_ARG_EDGE (phi, i)->src,
                                     PHI_ARG_DEF (phi, i));
@@ -337,3 +428,252 @@ verify_loop_closed_ssa (void)
        check_loop_closed_ssa_stmt (bb, bsi_stmt (bsi));
     }
 }
+
+/* Split loop exit edge EXIT.  The things are a bit complicated by a need to
+   preserve the loop closed ssa form.  */
+
+void
+split_loop_exit_edge (edge exit)
+{
+  basic_block dest = exit->dest;
+  basic_block bb = loop_split_edge_with (exit, NULL);
+  tree phi, new_phi, new_name, name;
+  use_operand_p op_p;
+
+  for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
+    {
+      op_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (bb));
+
+      name = USE_FROM_PTR (op_p);
+
+      /* If the argument of the phi node is a constant, we do not need
+        to keep it inside loop.  */
+      if (TREE_CODE (name) != SSA_NAME)
+       continue;
+
+      /* Otherwise create an auxiliary phi node that will copy the value
+        of the ssa name out of the loop.  */
+      new_name = duplicate_ssa_name (name, NULL);
+      new_phi = create_phi_node (new_name, bb);
+      SSA_NAME_DEF_STMT (new_name) = new_phi;
+      add_phi_arg (new_phi, name, exit);
+      SET_USE (op_p, new_name);
+    }
+}
+
+/* Insert statement STMT to the edge E and update the loop structures.
+   Returns the newly created block (if any).  */
+
+basic_block
+bsi_insert_on_edge_immediate_loop (edge e, tree stmt)
+{
+  basic_block src, dest, new_bb;
+  struct loop *loop_c;
+
+  src = e->src;
+  dest = e->dest;
+
+  loop_c = find_common_loop (src->loop_father, dest->loop_father);
+
+  new_bb = bsi_insert_on_edge_immediate (e, stmt);
+
+  if (!new_bb)
+    return NULL;
+
+  add_bb_to_loop (new_bb, loop_c);
+  if (dest->loop_father->latch == src)
+    dest->loop_father->latch = new_bb;
+
+  return new_bb;
+}
+
+/* Returns the basic block in that statements should be emitted for induction
+   variables incremented at the end of the LOOP.  */
+
+basic_block
+ip_end_pos (struct loop *loop)
+{
+  return loop->latch;
+}
+
+/* Returns the basic block in that statements should be emitted for induction
+   variables incremented just before exit condition of a LOOP.  */
+
+basic_block
+ip_normal_pos (struct loop *loop)
+{
+  tree last;
+  basic_block bb;
+  edge exit;
+
+  if (!single_pred_p (loop->latch))
+    return NULL;
+
+  bb = single_pred (loop->latch);
+  last = last_stmt (bb);
+  if (TREE_CODE (last) != COND_EXPR)
+    return NULL;
+
+  exit = EDGE_SUCC (bb, 0);
+  if (exit->dest == loop->latch)
+    exit = EDGE_SUCC (bb, 1);
+
+  if (flow_bb_inside_loop_p (loop, exit->dest))
+    return NULL;
+
+  return bb;
+}
+
+/* Stores the standard position for induction variable increment in LOOP
+   (just before the exit condition if it is available and latch block is empty,
+   end of the latch block otherwise) to BSI.  INSERT_AFTER is set to true if
+   the increment should be inserted after *BSI.  */
+
+void
+standard_iv_increment_position (struct loop *loop, block_stmt_iterator *bsi,
+                               bool *insert_after)
+{
+  basic_block bb = ip_normal_pos (loop), latch = ip_end_pos (loop);
+  tree last = last_stmt (latch);
+
+  if (!bb
+      || (last && TREE_CODE (last) != LABEL_EXPR))
+    {
+      *bsi = bsi_last (latch);
+      *insert_after = true;
+    }
+  else
+    {
+      *bsi = bsi_last (bb);
+      *insert_after = false;
+    }
+}
+
+/* Copies phi node arguments for duplicated blocks.  The index of the first
+   duplicated block is FIRST_NEW_BLOCK.  */
+
+static void
+copy_phi_node_args (unsigned first_new_block)
+{
+  unsigned i;
+
+  for (i = first_new_block; i < (unsigned) last_basic_block; i++)
+    BASIC_BLOCK (i)->rbi->duplicated = 1;
+
+  for (i = first_new_block; i < (unsigned) last_basic_block; i++)
+    add_phi_args_after_copy_bb (BASIC_BLOCK (i));
+
+  for (i = first_new_block; i < (unsigned) last_basic_block; i++)
+    BASIC_BLOCK (i)->rbi->duplicated = 0;
+}
+
+/* Renames variables in the area copied by tree_duplicate_loop_to_header_edge.
+   FIRST_NEW_BLOCK is the first block in the copied area.   DEFINITIONS is
+   a bitmap of all ssa names defined inside the loop.  */
+
+static void
+rename_variables (unsigned first_new_block, bitmap definitions)
+{
+  unsigned i, copy_number = 0;
+  basic_block bb;
+  htab_t ssa_name_map = NULL;
+
+  for (i = first_new_block; i < (unsigned) last_basic_block; i++)
+    {
+      bb = BASIC_BLOCK (i);
+
+      /* We assume that first come all blocks from the first copy, then all
+        blocks from the second copy, etc.  */
+      if (copy_number != (unsigned) bb->rbi->copy_number)
+       {
+         allocate_ssa_names (definitions, &ssa_name_map);
+         copy_number = bb->rbi->copy_number;
+       }
+
+      rewrite_to_new_ssa_names_bb (bb, ssa_name_map);
+    }
+
+  htab_delete (ssa_name_map);
+}
+
+/* Sets SSA_NAME_DEF_STMT for results of all phi nodes in BB.  */
+
+static void
+set_phi_def_stmts (basic_block bb)
+{
+  tree phi;
+
+  for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+    SSA_NAME_DEF_STMT (PHI_RESULT (phi)) = phi;
+}
+
+/* The same as cfgloopmanip.c:duplicate_loop_to_header_edge, but also updates
+   ssa.  In order to achieve this, only loops whose exits all lead to the same
+   location are handled.
+   
+   FIXME: we create some degenerate phi nodes that could be avoided by copy
+   propagating them instead.  Unfortunately this is not completely
+   straightforward due to problems with constant folding.  */
+
+bool
+tree_duplicate_loop_to_header_edge (struct loop *loop, edge e,
+                                   struct loops *loops,
+                                   unsigned int ndupl, sbitmap wont_exit,
+                                   edge orig, edge *to_remove,
+                                   unsigned int *n_to_remove, int flags)
+{
+  unsigned first_new_block;
+  basic_block bb;
+  unsigned i;
+  bitmap definitions;
+
+  if (!(loops->state & LOOPS_HAVE_SIMPLE_LATCHES))
+    return false;
+  if (!(loops->state & LOOPS_HAVE_PREHEADERS))
+    return false;
+
+#ifdef ENABLE_CHECKING
+  verify_loop_closed_ssa ();
+#endif
+
+  gcc_assert (!any_marked_for_rewrite_p ());
+
+  first_new_block = last_basic_block;
+  if (!duplicate_loop_to_header_edge (loop, e, loops, ndupl, wont_exit,
+                                     orig, to_remove, n_to_remove, flags))
+    return false;
+
+  /* Readd the removed phi args for e.  */
+  flush_pending_stmts (e);
+
+  /* Copy the phi node arguments.  */
+  copy_phi_node_args (first_new_block);
+
+  /* Rename the variables.  */
+  definitions = marked_ssa_names ();
+  rename_variables (first_new_block, definitions);
+  unmark_all_for_rewrite ();
+  BITMAP_FREE (definitions);
+
+  /* For some time we have the identical ssa names as results in multiple phi
+     nodes.  When phi node is resized, it sets SSA_NAME_DEF_STMT of its result
+     to the new copy.  This means that we cannot easily ensure that the ssa
+     names defined in those phis are pointing to the right one -- so just
+     recompute SSA_NAME_DEF_STMT for them.  */ 
+
+  for (i = first_new_block; i < (unsigned) last_basic_block; i++)
+    {
+      bb = BASIC_BLOCK (i);
+      set_phi_def_stmts (bb);
+      if (bb->rbi->copy_number == 1)
+       set_phi_def_stmts (bb->rbi->original);
+    }
+
+  scev_reset ();
+#ifdef ENABLE_CHECKING
+  verify_loop_closed_ssa ();
+#endif
+
+  return true;
+}
+