OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop-ivopts.c
index d1adbab..508f781 100644 (file)
@@ -88,6 +88,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-scalar-evolution.h"
 #include "cfgloop.h"
 #include "params.h"
+#include "langhooks.h"
 
 /* The infinite cost.  */
 #define INFTY 10000000
@@ -1840,6 +1841,22 @@ strip_offset (tree expr, bool inside_addr, unsigned HOST_WIDE_INT *offset)
   return fold_convert (orig_type, expr);
 }
 
+/* Returns variant of TYPE that can be used as base for different uses.
+   For integer types, we return unsigned variant of the type, which
+   avoids problems with overflows.  For pointer types, we return void *.  */
+
+static tree
+generic_type_for (tree type)
+{
+  if (POINTER_TYPE_P (type))
+    return ptr_type_node;
+
+  if (TYPE_UNSIGNED (type))
+    return type;
+
+  return unsigned_type_for (type);
+}
+
 /* Adds a candidate BASE + STEP * i.  Important field is set to IMPORTANT and
    position to POS.  If USE is not NULL, the candidate is set as related to
    it.  If both BASE and STEP are NULL, we add a pseudocandidate for the
@@ -1852,14 +1869,14 @@ add_candidate_1 (struct ivopts_data *data,
 {
   unsigned i;
   struct iv_cand *cand = NULL;
-  tree type;
+  tree type, orig_type;
   
   if (base)
     {
-      type = TREE_TYPE (base);
-      if (!TYPE_UNSIGNED (type))
+      orig_type = TREE_TYPE (base);
+      type = generic_type_for (orig_type);
+      if (type != orig_type)
        {
-         type = unsigned_type_for (type);
          base = fold_convert (type, base);
          if (step)
            step = fold_convert (type, step);
@@ -1980,23 +1997,28 @@ add_candidate (struct ivopts_data *data,
     add_candidate_1 (data, base, step, important, IP_END, use, NULL_TREE);
 }
 
+/* Add a standard "0 + 1 * iteration" iv candidate for a
+   type with SIZE bits.  */
+
+static void
+add_standard_iv_candidates_for_size (struct ivopts_data *data,
+                                    unsigned int size)
+{
+  tree type = lang_hooks.types.type_for_size (size, true);
+  add_candidate (data, build_int_cst (type, 0), build_int_cst (type, 1),
+                true, NULL);
+}
+
 /* Adds standard iv candidates.  */
 
 static void
 add_standard_iv_candidates (struct ivopts_data *data)
 {
-  /* Add 0 + 1 * iteration candidate.  */
-  add_candidate (data,
-                build_int_cst (unsigned_intSI_type_node, 0),
-                build_int_cst (unsigned_intSI_type_node, 1),
-                true, NULL);
+  add_standard_iv_candidates_for_size (data, INT_TYPE_SIZE);
 
-  /* The same for a long type if it is still fast enough.  */
-  if (BITS_PER_WORD > 32)
-    add_candidate (data,
-                  build_int_cst (unsigned_intDI_type_node, 0),
-                  build_int_cst (unsigned_intDI_type_node, 1),
-                  true, NULL);
+  /* The same for a double-integer type if it is still fast enough.  */
+  if (BITS_PER_WORD >= INT_TYPE_SIZE * 2)
+    add_standard_iv_candidates_for_size (data, INT_TYPE_SIZE * 2);
 }
 
 
@@ -2348,8 +2370,8 @@ static rtx
 produce_memory_decl_rtl (tree obj, int *regno)
 {
   rtx x;
-  if (!obj)
-    abort ();
+  
+  gcc_assert (obj);
   if (TREE_STATIC (obj) || DECL_EXTERNAL (obj))
     {
       const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (obj));
@@ -2427,7 +2449,8 @@ computation_cost (tree expr)
   rtx seq, rslt;
   tree type = TREE_TYPE (expr);
   unsigned cost;
-  int regno = 0;
+  /* Avoid using hard regs in ways which may be unsupported.  */
+  int regno = LAST_VIRTUAL_REGISTER + 1;
 
   walk_tree (&expr, prepare_decl_rtl, &regno, NULL);
   start_sequence ();
@@ -3680,8 +3703,11 @@ determine_iv_cost (struct ivopts_data *data, struct iv_cand *cand)
 
   cand->cost = cost_step + cost_base / AVG_LOOP_NITER (current_loop);
 
-  /* Prefer the original iv unless we may gain something by replacing it.  */
-  if (cand->pos == IP_ORIGINAL)
+  /* Prefer the original iv unless we may gain something by replacing it;
+     this is not really relevant for artificial ivs created by other
+     passes.  */
+  if (cand->pos == IP_ORIGINAL
+      && !DECL_ARTIFICIAL (SSA_NAME_VAR (cand->var_before)))
     cand->cost--;
   
   /* Prefer not to insert statements into latch unless there are some
@@ -4016,7 +4042,7 @@ iv_ca_delta_add (struct iv_use *use, struct cost_pair *old_cp,
 }
 
 /* Joins two lists of changes L1 and L2.  Destructive -- old lists
-   are rewritten.   */
+   are rewritten.  */
 
 static struct iv_ca_delta *
 iv_ca_delta_join (struct iv_ca_delta *l1, struct iv_ca_delta *l2)
@@ -4651,7 +4677,7 @@ remove_statement (tree stmt, bool including_defined_name)
          /* Prevent the ssa name defined by the statement from being removed.  */
          SET_PHI_RESULT (stmt, NULL);
        }
-      remove_phi_node (stmt, NULL_TREE, bb_for_stmt (stmt));
+      remove_phi_node (stmt, NULL_TREE);
     }
   else
     {
@@ -4825,6 +4851,7 @@ rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with)
       new_name = make_ssa_name (new_var, copy);
     }
   TREE_OPERAND (copy, 0) = new_name;
+  update_stmt (copy);
   bsi_insert_before (bsi, copy, BSI_SAME_STMT);
   with = new_name;
 
@@ -4877,16 +4904,18 @@ rewrite_use_compare (struct ivopts_data *data,
   
   if (may_eliminate_iv (data, use, cand, &compare, &bound))
     {
+      tree var = var_at_stmt (data->current_loop, cand, use->stmt);
+      tree var_type = TREE_TYPE (var);
+
+      bound = fold_convert (var_type, bound);
       op = force_gimple_operand (unshare_expr (bound), &stmts,
                                 true, NULL_TREE);
 
       if (stmts)
        bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
 
-      *use->op_p = build2 (compare, boolean_type_node,
-                         var_at_stmt (data->current_loop,
-                                      cand, use->stmt), op);
-      modify_stmt (use->stmt);
+      *use->op_p = build2 (compare, boolean_type_node, var, op);
+      update_stmt (use->stmt);
       return;
     }
 
@@ -4984,22 +5013,27 @@ compute_phi_arg_on_exit (edge exit, tree stmts, tree op)
   block_stmt_iterator bsi;
   tree phi, stmt, def, next;
 
-  if (EDGE_COUNT (exit->dest->preds) > 1)
+  if (!single_pred_p (exit->dest))
     split_loop_exit_edge (exit);
 
+  /* Ensure there is label in exit->dest, so that we can
+     insert after it.  */
+  tree_block_label (exit->dest);
+  bsi = bsi_after_labels (exit->dest);
+
   if (TREE_CODE (stmts) == STATEMENT_LIST)
     {
       for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
-       protect_loop_closed_ssa_form (exit, tsi_stmt (tsi));
+        {
+         bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_NEW_STMT);
+         protect_loop_closed_ssa_form (exit, bsi_stmt (bsi));
+       }
     }
   else
-    protect_loop_closed_ssa_form (exit, stmts);
-
-  /* Ensure there is label in exit->dest, so that we can
-     insert after it.  */
-  tree_block_label (exit->dest);
-  bsi = bsi_after_labels (exit->dest);
-  bsi_insert_after (&bsi, stmts, BSI_CONTINUE_LINKING);
+    {
+      bsi_insert_after (&bsi, stmts, BSI_NEW_STMT);
+      protect_loop_closed_ssa_form (exit, bsi_stmt (bsi));
+    }
 
   if (!op)
     return;
@@ -5118,7 +5152,7 @@ rewrite_use (struct ivopts_data *data,
       default:
        gcc_unreachable ();
     }
-  modify_stmt (use->stmt);
+  update_stmt (use->stmt);
 }
 
 /* Rewrite the uses using the selected induction variables.  */