OSDN Git Service

2005-12-02 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ccp.c
index 8bf8242..133d00a 100644 (file)
@@ -273,6 +273,32 @@ debug_lattice_value (prop_value_t val)
 }
 
 
+/* The regular is_gimple_min_invariant does a shallow test of the object.
+   It assumes that full gimplification has happened, or will happen on the
+   object.  For a value coming from DECL_INITIAL, this is not true, so we
+   have to be more strict outselves.  */
+
+static bool
+ccp_decl_initial_min_invariant (tree t)
+{
+  if (!is_gimple_min_invariant (t))
+    return false;
+  if (TREE_CODE (t) == ADDR_EXPR)
+    {
+      /* Inline and unroll is_gimple_addressable.  */
+      while (1)
+       {
+         t = TREE_OPERAND (t, 0);
+         if (is_gimple_id (t))
+           return true;
+         if (!handled_component_p (t))
+           return false;
+       }
+    }
+  return true;
+}
+
+
 /* Compute a default value for variable VAR and store it in the
    CONST_VAL array.  The following rules are used to get default
    values:
@@ -317,7 +343,7 @@ get_default_value (tree var)
   else if (TREE_STATIC (sym)
           && TREE_READONLY (sym)
           && DECL_INITIAL (sym)
-          && is_gimple_min_invariant (DECL_INITIAL (sym)))
+          && ccp_decl_initial_min_invariant (DECL_INITIAL (sym)))
     {
       /* Globals and static variables declared 'const' take their
         initial value.  */
@@ -473,6 +499,9 @@ likely_value (tree stmt)
       && TREE_CODE (stmt) != SWITCH_EXPR)
     return VARYING;
 
+  if (is_gimple_min_invariant (get_rhs (stmt)))
+    return CONSTANT;
+
   found_constant = false;
   FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE|SSA_OP_VUSE)
     {
@@ -658,7 +687,8 @@ ccp_lattice_meet (prop_value_t *val1, prop_value_t *val2)
           && val2->lattice_val == CONSTANT
           && simple_cst_equal (val1->value, val2->value) == 1
           && (!do_store_ccp
-              || simple_cst_equal (val1->mem_ref, val2->mem_ref) == 1))
+              || (val1->mem_ref && val2->mem_ref
+                  && operand_equal_p (val1->mem_ref, val2->mem_ref, 0))))
     {
       /* Ci M Cj = Ci          if (i == j)
         Ci M Cj = VARYING      if (i != j)
@@ -826,7 +856,8 @@ ccp_fold (tree stmt)
       /* If the RHS is a memory load, see if the VUSEs associated with
         it are a valid constant for that memory load.  */
       prop_value_t *val = get_value_loaded_by (stmt, const_val);
-      if (val && simple_cst_equal (val->mem_ref, rhs) == 1)
+      if (val && val->mem_ref
+         && operand_equal_p (val->mem_ref, rhs, 0))
        return val->value;
       else
        return NULL_TREE;
@@ -848,6 +879,10 @@ ccp_fold (tree stmt)
            op0 = get_value (op0, true)->value;
        }
 
+      if ((code == NOP_EXPR || code == CONVERT_EXPR)
+         && tree_ssa_useless_type_conversion_1 (TREE_TYPE (rhs),
+                                                TREE_TYPE (op0)))
+       return op0;
       return fold_unary (code, TREE_TYPE (rhs), op0);
     }
 
@@ -936,7 +971,9 @@ static tree
 fold_const_aggregate_ref (tree t)
 {
   prop_value_t *value;
-  tree base, ctor, idx, field, elt;
+  tree base, ctor, idx, field;
+  unsigned HOST_WIDE_INT cnt;
+  tree cfield, cval;
 
   switch (TREE_CODE (t))
     {
@@ -993,13 +1030,9 @@ fold_const_aggregate_ref (tree t)
        }
 
       /* Whoo-hoo!  I'll fold ya baby.  Yeah!  */
-      for (elt = CONSTRUCTOR_ELTS (ctor);
-          (elt && !tree_int_cst_equal (TREE_PURPOSE (elt), idx));
-          elt = TREE_CHAIN (elt))
-       ;
-
-      if (elt)
-       return TREE_VALUE (elt);
+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+       if (tree_int_cst_equal (cfield, idx))
+         return cval;
       break;
 
     case COMPONENT_REF:
@@ -1035,13 +1068,22 @@ fold_const_aggregate_ref (tree t)
 
       field = TREE_OPERAND (t, 1);
 
-      for (elt = CONSTRUCTOR_ELTS (ctor); elt; elt = TREE_CHAIN (elt))
-       if (TREE_PURPOSE (elt) == field
+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+       if (cfield == field
            /* FIXME: Handle bit-fields.  */
-           && ! DECL_BIT_FIELD (TREE_PURPOSE (elt)))
-         return TREE_VALUE (elt);
+           && ! DECL_BIT_FIELD (cfield))
+         return cval;
       break;
 
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      {
+       tree c = fold_const_aggregate_ref (TREE_OPERAND (t, 0));
+       if (c && TREE_CODE (c) == COMPLEX_CST)
+         return fold_build1 (TREE_CODE (t), TREE_TYPE (t), c);
+       break;
+      }
+    
     default:
       break;
     }
@@ -1087,7 +1129,11 @@ evaluate_stmt (tree stmt)
       /* The statement produced a nonconstant value.  If the statement
         had UNDEFINED operands, then the result of the statement
         should be UNDEFINED.  Otherwise, the statement is VARYING.  */
-      val.lattice_val = (likelyvalue == UNDEFINED) ? UNDEFINED : VARYING;
+      if (likelyvalue == UNDEFINED || likelyvalue == UNKNOWN_VAL)
+       val.lattice_val = likelyvalue;
+      else
+       val.lattice_val = VARYING;
+
       val.value = NULL_TREE;
     }
 
@@ -1124,7 +1170,8 @@ visit_assignment (tree stmt, tree *output_p)
         we can propagate the value on the RHS.  */
       prop_value_t *nval = get_value_loaded_by (stmt, const_val);
 
-      if (nval && simple_cst_equal (nval->mem_ref, rhs) == 1)
+      if (nval && nval->mem_ref
+         && operand_equal_p (nval->mem_ref, rhs, 0))
        val = *nval;
       else
        val = evaluate_stmt (stmt);
@@ -1434,8 +1481,8 @@ widen_bitfield (tree val, tree field, tree var)
       for (i = 0, mask = 0; i < field_size; i++)
        mask |= ((HOST_WIDE_INT) 1) << i;
 
-      wide_val = build2 (BIT_AND_EXPR, TREE_TYPE (var), val, 
-                        build_int_cst (TREE_TYPE (var), mask));
+      wide_val = fold_build2 (BIT_AND_EXPR, TREE_TYPE (var), val, 
+                             build_int_cst (TREE_TYPE (var), mask));
     }
   else
     {
@@ -1445,11 +1492,11 @@ widen_bitfield (tree val, tree field, tree var)
       for (i = 0, mask = 0; i < (var_size - field_size); i++)
        mask |= ((HOST_WIDE_INT) 1) << (var_size - i - 1);
 
-      wide_val = build2 (BIT_IOR_EXPR, TREE_TYPE (var), val,
-                        build_int_cst (TREE_TYPE (var), mask));
+      wide_val = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (var), val,
+                             build_int_cst (TREE_TYPE (var), mask));
     }
 
-  return fold (wide_val);
+  return wide_val;
 }
 
 
@@ -1542,9 +1589,9 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
   if (!integer_zerop (elt_offset))
     idx = int_const_binop (PLUS_EXPR, idx, elt_offset, 0);
 
-  return build (ARRAY_REF, orig_type, base, idx, min_idx,
-               size_int (tree_low_cst (elt_size, 1)
-                         / (TYPE_ALIGN_UNIT (elt_type))));
+  return build4 (ARRAY_REF, orig_type, base, idx, min_idx,
+                size_int (tree_low_cst (elt_size, 1)
+                          / (TYPE_ALIGN_UNIT (elt_type))));
 }
 
 
@@ -1605,7 +1652,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
        {
          if (base_is_ptr)
            base = build1 (INDIRECT_REF, record_type, base);
-         t = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
+         t = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
          return t;
        }
       
@@ -1645,7 +1692,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
      nonzero offset into them.  Recurse and hope for a valid match.  */
   if (base_is_ptr)
     base = build1 (INDIRECT_REF, record_type, base);
-  base = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
+  base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
 
   t = maybe_fold_offset_to_array_ref (base, offset, orig_type);
   if (t)
@@ -1695,7 +1742,7 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
 
       /* Fold away CONST_DECL to its value, if the type is scalar.  */
       if (TREE_CODE (base) == CONST_DECL
-         && is_gimple_min_invariant (DECL_INITIAL (base)))
+         && ccp_decl_initial_min_invariant (DECL_INITIAL (base)))
        return DECL_INITIAL (base);
 
       /* Try folding *(&B+O) to B[X].  */
@@ -2234,7 +2281,7 @@ ccp_fold_builtin (tree stmt, tree fn)
 }
 
 
-/* Fold the statement pointed by STMT_P.  In some cases, this function may
+/* Fold the statement pointed to by STMT_P.  In some cases, this function may
    replace the whole statement with a new one.  Returns true iff folding
    makes any changes.  */
 
@@ -2337,6 +2384,7 @@ fold_stmt_inplace (tree stmt)
     return changed;
 
   new_rhs = fold (rhs);
+  STRIP_USELESS_TYPE_CONVERSION (new_rhs);
   if (new_rhs == rhs)
     return changed;
 
@@ -2442,7 +2490,7 @@ execute_fold_all_builtins (void)
                  gcc_assert (ok);
                }
            }
-         update_stmt (*stmtp);
+         mark_new_vars_to_rename (*stmtp);
          if (maybe_clean_or_replace_eh_stmt (old_stmt, *stmtp)
              && tree_purge_dead_eh_edges (bb))
            cfg_changed = true;