OSDN Git Service

2008-06-15 Mark Shinwell <shinwell@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop-ivopts.c
index 7bcb981..41c3794 100644 (file)
@@ -1,5 +1,6 @@
 /* Induction variable optimizations.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software
+   Foundation, Inc.
    
 This file is part of GCC.
    
@@ -772,8 +773,7 @@ determine_base_object (tree expr)
   /* If this is a pointer casted to any type, we need to determine
      the base object for the pointer; so handle conversions before
      throwing away non-pointer expressions.  */
-  if (TREE_CODE (expr) == NOP_EXPR
-      || TREE_CODE (expr) == CONVERT_EXPR)
+  if (CONVERT_EXPR_P (expr))
     return determine_base_object (TREE_OPERAND (expr, 0));
 
   if (!POINTER_TYPE_P (TREE_TYPE (expr)))
@@ -914,7 +914,12 @@ find_bivs (struct ivopts_data *data)
       type = TREE_TYPE (PHI_RESULT (phi));
       base = fold_convert (type, base);
       if (step)
-       step = fold_convert (type, step);
+       {
+         if (POINTER_TYPE_P (type))
+           step = fold_convert (sizetype, step);
+         else
+           step = fold_convert (type, step);
+       }
 
       set_iv (data, PHI_RESULT (phi), base, step);
       found = true;
@@ -1254,7 +1259,8 @@ find_interesting_uses_cond (struct ivopts_data *data, tree stmt, tree *cond_p)
 }
 
 /* Returns true if expression EXPR is obviously invariant in LOOP,
-   i.e. if all its operands are defined outside of the LOOP.  */
+   i.e. if all its operands are defined outside of the LOOP.  LOOP
+   should not be the function body.  */
 
 bool
 expr_invariant_in_loop_p (struct loop *loop, tree expr)
@@ -1262,6 +1268,8 @@ expr_invariant_in_loop_p (struct loop *loop, tree expr)
   basic_block def_bb;
   unsigned i, len;
 
+  gcc_assert (loop_depth (loop) > 0);
+
   if (is_gimple_min_invariant (expr))
     return true;
 
@@ -1522,8 +1530,8 @@ may_be_nonaddressable_p (tree expr)
         and make them look addressable.  After some processing the
         non-addressability may be uncovered again, causing ADDR_EXPRs
         of inappropriate objects to be built.  */
-      if (AGGREGATE_TYPE_P (TREE_TYPE (expr))
-         && !AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0))))
+      if (is_gimple_reg (TREE_OPERAND (expr, 0))
+         || is_gimple_min_invariant (TREE_OPERAND (expr, 0)))
        return true;
 
       /* ... fall through ... */
@@ -1532,9 +1540,7 @@ may_be_nonaddressable_p (tree expr)
     case ARRAY_RANGE_REF:
       return may_be_nonaddressable_p (TREE_OPERAND (expr, 0));
 
-    case CONVERT_EXPR:
-    case NON_LVALUE_EXPR:
-    case NOP_EXPR:
+    CASE_CONVERT:
       return true;
 
     default:
@@ -2037,7 +2043,9 @@ add_candidate_1 (struct ivopts_data *data,
     {
       orig_type = TREE_TYPE (base);
       type = generic_type_for (orig_type);
-      if (type != orig_type)
+      /* Don't convert the base to the generic type for pointers as the generic
+        type is an integer type with the same size as the pointer type.  */
+      if (type != orig_type && !POINTER_TYPE_P (orig_type))
        {
          base = fold_convert (type, base);
          step = fold_convert (type, step);
@@ -2234,13 +2242,17 @@ add_iv_value_candidates (struct ivopts_data *data,
 {
   unsigned HOST_WIDE_INT offset;
   tree base;
+  tree basetype;
 
   add_candidate (data, iv->base, iv->step, false, use);
 
   /* The same, but with initial value zero.  Make such variable important,
      since it is generic enough so that possibly many uses may be based
      on it.  */
-  add_candidate (data, build_int_cst (TREE_TYPE (iv->base), 0),
+  basetype = TREE_TYPE (iv->base);
+  if (POINTER_TYPE_P (basetype))
+    basetype = sizetype;
+  add_candidate (data, build_int_cst (basetype, 0),
                 iv->step, true, use);
 
   /* Third, try removing the constant offset.  */
@@ -2671,8 +2683,7 @@ determine_common_wider_type (tree *a, tree *b)
   tree suba, subb;
   tree atype = TREE_TYPE (*a);
 
-  if ((TREE_CODE (*a) == NOP_EXPR
-       || TREE_CODE (*a) == CONVERT_EXPR))
+  if (CONVERT_EXPR_P (*a))
     {
       suba = TREE_OPERAND (*a, 0);
       wider_type = TREE_TYPE (suba);
@@ -2682,8 +2693,7 @@ determine_common_wider_type (tree *a, tree *b)
   else
     return atype;
 
-  if ((TREE_CODE (*b) == NOP_EXPR
-       || TREE_CODE (*b) == CONVERT_EXPR))
+  if (CONVERT_EXPR_P (*b))
     {
       subb = TREE_OPERAND (*b, 0);
       if (TYPE_PRECISION (wider_type) != TYPE_PRECISION (TREE_TYPE (subb)))
@@ -3038,7 +3048,7 @@ get_address_cost (bool symbol_present, bool var_present,
            {
              base = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (""));
              /* ??? We can run into trouble with some backends by presenting
-                it with symbols which havn't been properly passed through
+                it with symbols which haven't been properly passed through
                 targetm.encode_section_info.  By setting the local bit, we
                 enhance the probability of things working.  */
              SYMBOL_REF_FLAGS (base) = SYMBOL_FLAG_LOCAL;
@@ -3208,7 +3218,7 @@ force_expr_to_var_cost (tree expr)
   if (SSA_VAR_P (expr))
     return zero_cost;
 
-  if (TREE_INVARIANT (expr))
+  if (is_gimple_min_invariant (expr))
     {
       if (TREE_CODE (expr) == INTEGER_CST)
        return new_cost (integer_cost, 0);
@@ -3668,10 +3678,13 @@ cand_value_at (struct loop *loop, struct iv_cand *cand, tree at, tree niter,
   aff_tree step, delta, nit;
   struct iv *iv = cand->iv;
   tree type = TREE_TYPE (iv->base);
+  tree steptype = type;
+  if (POINTER_TYPE_P (type))
+    steptype = sizetype;
 
-  tree_to_aff_combination (iv->step, type, &step);
+  tree_to_aff_combination (iv->step, steptype, &step);
   tree_to_aff_combination (niter, TREE_TYPE (niter), &nit);
-  aff_combination_convert (&nit, type);
+  aff_combination_convert (&nit, steptype);
   aff_combination_mult (&nit, &step, &delta);
   if (stmt_after_increment (loop, cand, at))
     aff_combination_add (&delta, &step);
@@ -3966,7 +3979,7 @@ determine_iv_cost (struct ivopts_data *data, struct iv_cand *cand)
   cost = cost_step + cost_base.cost / AVG_LOOP_NITER (current_loop);
 
   /* Prefer the original ivs unless we may gain something by replacing it.
-     The reason is to makee debugging simpler; so this is not relevant for
+     The reason is to make debugging simpler; so this is not relevant for
      artificial ivs created by other optimization passes.  */
   if (cand->pos != IP_ORIGINAL
       || DECL_ARTIFICIAL (SSA_NAME_VAR (cand->var_before)))
@@ -5139,9 +5152,6 @@ get_ref_tag (tree ref, tree orig)
        break;
     }
 
-  if (aref && SSA_VAR_P (aref) && get_subvars_for_var (aref))
-    return aref;
-
   if (!var)
     return NULL_TREE;