OSDN Git Service

Add dbg count support for ccp
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ccp.c
index d68337f..c7df588 100644 (file)
@@ -1,5 +1,5 @@
 /* Conditional constant propagation pass for the GNU compiler.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Adapted from original RTL SSA-CCP by Daniel Berlin <dberlin@dberlin.org>
    Adapted to GIMPLE trees by Diego Novillo <dnovillo@redhat.com>
@@ -208,6 +208,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "target.h"
 #include "toplev.h"
+#include "dbgcnt.h"
 
 
 /* Possible lattice values.  */
@@ -287,10 +288,11 @@ get_symbol_constant_value (tree sym)
         have zero as the initializer if they may not be
         overridden at link or run time.  */
       if (!val
+         && !DECL_EXTERNAL (sym)
          && targetm.binds_local_p (sym)
           && (INTEGRAL_TYPE_P (TREE_TYPE (sym))
               || SCALAR_FLOAT_TYPE_P (TREE_TYPE (sym))))
-        return fold_convert (TREE_TYPE (sym), integer_zero_node);
+       return fold_convert (TREE_TYPE (sym), integer_zero_node);
     }
 
   return NULL_TREE;
@@ -319,52 +321,45 @@ get_default_value (tree var)
 {
   tree sym = SSA_NAME_VAR (var);
   prop_value_t val = { UNINITIALIZED, NULL_TREE };
-  tree cst_val;
-  
-  if (!is_gimple_reg (var))
-    {
-      /* Short circuit for regular CCP.  We are not interested in any
-        non-register when DO_STORE_CCP is false.  */
-      val.lattice_val = VARYING;
-    }
-  else if ((cst_val = get_symbol_constant_value (sym)) != NULL_TREE)
+  gimple stmt;
+
+  stmt = SSA_NAME_DEF_STMT (var);
+
+  if (gimple_nop_p (stmt))
     {
-      /* Globals and static variables declared 'const' take their
-        initial value.  */
-      val.lattice_val = CONSTANT;
-      val.value = cst_val;
+      /* Variables defined by an empty statement are those used
+        before being initialized.  If VAR is a local variable, we
+        can assume initially that it is UNDEFINED, otherwise we must
+        consider it VARYING.  */
+      if (is_gimple_reg (sym) && TREE_CODE (sym) != PARM_DECL)
+       val.lattice_val = UNDEFINED;
+      else
+       val.lattice_val = VARYING;
     }
-  else
-    {
-      gimple stmt = SSA_NAME_DEF_STMT (var);
-
-      if (gimple_nop_p (stmt))
+  else if (is_gimple_assign (stmt)
+          /* Value-returning GIMPLE_CALL statements assign to
+             a variable, and are treated similarly to GIMPLE_ASSIGN.  */
+          || (is_gimple_call (stmt)
+              && gimple_call_lhs (stmt) != NULL_TREE)
+          || gimple_code (stmt) == GIMPLE_PHI)
+    {
+      tree cst;
+      if (gimple_assign_single_p (stmt)
+         && DECL_P (gimple_assign_rhs1 (stmt))
+         && (cst = get_symbol_constant_value (gimple_assign_rhs1 (stmt))))
        {
-         /* Variables defined by an empty statement are those used
-            before being initialized.  If VAR is a local variable, we
-            can assume initially that it is UNDEFINED, otherwise we must
-            consider it VARYING.  */
-         if (is_gimple_reg (sym) && TREE_CODE (sym) != PARM_DECL)
-           val.lattice_val = UNDEFINED;
-         else
-           val.lattice_val = VARYING;
-       }
-      else if (is_gimple_assign (stmt)
-               /* Value-returning GIMPLE_CALL statements assign to
-                  a variable, and are treated similarly to GIMPLE_ASSIGN.  */
-               || (is_gimple_call (stmt)
-                   && gimple_call_lhs (stmt) != NULL_TREE)
-              || gimple_code (stmt) == GIMPLE_PHI)
-        {
-         /* Any other variable defined by an assignment or a PHI node
-            is considered UNDEFINED.  */
-         val.lattice_val = UNDEFINED;
+         val.lattice_val = CONSTANT;
+         val.value = cst;
        }
       else
-       {
-         /* Otherwise, VAR will never take on a constant value.  */
-         val.lattice_val = VARYING;
-       }
+       /* Any other variable defined by an assignment or a PHI node
+          is considered UNDEFINED.  */
+       val.lattice_val = UNDEFINED;
+    }
+  else
+    {
+      /* Otherwise, VAR will never take on a constant value.  */
+      val.lattice_val = VARYING;
     }
 
   return val;
@@ -500,6 +495,7 @@ likely_value (gimple stmt)
   bool has_constant_operand, has_undefined_operand, all_undefined_operands;
   tree use;
   ssa_op_iter iter;
+  unsigned i;
 
   enum gimple_code code = gimple_code (stmt);
 
@@ -515,33 +511,11 @@ likely_value (gimple stmt)
   if (gimple_has_volatile_ops (stmt))
     return VARYING;
 
-  /* If we are not doing store-ccp, statements with loads
-     and/or stores will never fold into a constant.  */
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
-    return VARYING;
-
-  /* Note that only a GIMPLE_SINGLE_RHS assignment can satisfy
-     is_gimple_min_invariant, so we do not consider calls or
-     other forms of assignment.  */
-  if (gimple_assign_single_p (stmt)
-      && is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
-    return CONSTANT;
-
-  if (code == GIMPLE_COND
-      && is_gimple_min_invariant (gimple_cond_lhs (stmt))
-      && is_gimple_min_invariant (gimple_cond_rhs (stmt)))
-    return CONSTANT;
-
-  if (code == GIMPLE_SWITCH
-      && is_gimple_min_invariant (gimple_switch_index (stmt)))
-    return CONSTANT;
-
   /* Arrive here for more complex cases.  */
-
   has_constant_operand = false;
   has_undefined_operand = false;
   all_undefined_operands = true;
-  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
+  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
     {
       prop_value_t *val = get_value (use);
 
@@ -554,6 +528,17 @@ likely_value (gimple stmt)
        has_constant_operand = true;
     }
 
+  /* There may be constants in regular rhs operands.  */
+  for (i = is_gimple_call (stmt) + gimple_has_lhs (stmt);
+       i < gimple_num_ops (stmt); ++i)
+    {
+      tree op = gimple_op (stmt, i);
+      if (!op || TREE_CODE (op) == SSA_NAME)
+       continue;
+      if (is_gimple_min_invariant (op))
+       has_constant_operand = true;
+    }
+
   /* If the operation combines operands like COMPLEX_EXPR make sure to
      not mark the result UNDEFINED if only one part of the result is
      undefined.  */
@@ -584,11 +569,11 @@ likely_value (gimple stmt)
   if (has_undefined_operand)
     return VARYING;
 
+  /* We do not consider virtual operands here -- load from read-only
+     memory may have only VARYING virtual operands, but still be
+     constant.  */
   if (has_constant_operand
-      /* We do not consider virtual operands here -- load from read-only
-        memory may have only VARYING virtual operands, but still be
-        constant.  */
-      || ZERO_SSA_OPERANDS (stmt, SSA_OP_USE))
+      || gimple_references_memory_p (stmt))
     return CONSTANT;
 
   return VARYING;
@@ -604,9 +589,6 @@ surely_varying_stmt_p (gimple stmt)
   if (gimple_has_volatile_ops (stmt))
     return true;
 
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
-    return true;
-
   /* If it is a call and does not return a value or is not a
      builtin and not an indirect call, it is varying.  */
   if (is_gimple_call (stmt))
@@ -618,6 +600,10 @@ surely_varying_stmt_p (gimple stmt)
        return true;
     }
 
+  /* Any other store operation is not interesting.  */
+  else if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+    return true;
+
   /* Anything other than assignments and conditional jumps are not
      interesting for CCP.  */
   if (gimple_code (stmt) != GIMPLE_ASSIGN
@@ -656,10 +642,7 @@ ccp_initialize (void)
              /* If the statement will not produce a constant, mark
                 all its outputs VARYING.  */
              FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
-               {
-                 if (is_varying)
-                   set_value_varying (def);
-               }
+               set_value_varying (def);
            }
           prop_set_simulate_again (stmt, !is_varying);
        }
@@ -684,6 +667,24 @@ ccp_initialize (void)
     }
 }
 
+/* Debug count support. Reset the values of ssa names
+   VARYING when the total number ssa names analyzed is
+   beyond the debug count specified.  */
+
+static void
+do_dbg_cnt (void)
+{
+  unsigned i;
+  for (i = 0; i < num_ssa_names; i++)
+    {
+      if (!dbg_cnt (ccp))
+        {
+          const_val[i].lattice_val = VARYING;
+          const_val[i].value = NULL_TREE;
+        }
+    }
+}
+
 
 /* Do final substitution of propagated values, cleanup the flowgraph and
    free allocated storage.  
@@ -693,8 +694,11 @@ ccp_initialize (void)
 static bool
 ccp_finalize (void)
 {
+  bool something_changed;
+
+  do_dbg_cnt ();
   /* Perform substitutions based on the known constant values.  */
-  bool something_changed = substitute_and_fold (const_val, false);
+  something_changed = substitute_and_fold (const_val, false);
 
   free (const_val);
   const_val = NULL;
@@ -860,6 +864,10 @@ may_propagate_address_into_dereference (tree addr, tree deref)
   gcc_assert (INDIRECT_REF_P (deref)
              && TREE_CODE (addr) == ADDR_EXPR);
 
+  /* Don't propagate if ADDR's operand has incomplete type.  */
+  if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_OPERAND (addr, 0))))
+    return false;
+
   /* If the address is invariant then we do not need to preserve restrict
      qualifications.  But we do need to preserve volatile qualifiers until
      we can annotate the folded dereference itself properly.  */
@@ -948,6 +956,16 @@ ccp_fold (gimple stmt)
                        return fold_unary (VIEW_CONVERT_EXPR,
                                           TREE_TYPE (rhs), val->value);
                    }
+                 else if (TREE_CODE (rhs) == INDIRECT_REF
+                          && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
+                   {
+                     prop_value_t *val = get_value (TREE_OPERAND (rhs, 0));
+                     if (val->lattice_val == CONSTANT
+                         && TREE_CODE (val->value) == ADDR_EXPR
+                         && useless_type_conversion_p (TREE_TYPE (rhs),
+                                                       TREE_TYPE (TREE_TYPE (val->value))))
+                       rhs = TREE_OPERAND (val->value, 0);
+                   }
                  return fold_const_aggregate_ref (rhs);
                }
               else if (kind == tcc_declaration)
@@ -962,7 +980,6 @@ ccp_fold (gimple stmt)
                  so this should almost always return a simplified RHS.  */
               tree lhs = gimple_assign_lhs (stmt);
               tree op0 = gimple_assign_rhs1 (stmt);
-             tree res;
 
               /* Simplify the operand down to a constant.  */
               if (TREE_CODE (op0) == SSA_NAME)
@@ -998,20 +1015,8 @@ ccp_fold (gimple stmt)
                  return op0;
                }
 
-              res = fold_unary (subcode, gimple_expr_type (stmt), op0);
-
-             /* If the operation was a conversion do _not_ mark a
-                resulting constant with TREE_OVERFLOW if the original
-                constant was not.  These conversions have implementation
-                defined behavior and retaining the TREE_OVERFLOW flag
-                here would confuse later passes such as VRP.  */
-             if (res
-                 && TREE_CODE (res) == INTEGER_CST
-                 && TREE_CODE (op0) == INTEGER_CST
-                 && CONVERT_EXPR_CODE_P (subcode))
-               TREE_OVERFLOW (res) = TREE_OVERFLOW (op0);
-
-             return res;
+              return fold_unary_ignore_overflow (subcode,
+                                                gimple_expr_type (stmt), op0);
             }
 
           case GIMPLE_BINARY_RHS:
@@ -1152,6 +1157,9 @@ fold_const_aggregate_ref (tree t)
   unsigned HOST_WIDE_INT cnt;
   tree cfield, cval;
 
+  if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
+    return get_symbol_constant_value (t);
+
   switch (TREE_CODE (t))
     {
     case ARRAY_REF:
@@ -1950,8 +1958,7 @@ maybe_fold_offset_to_address (tree addr, tree offset, tree orig_type)
           || (TREE_CODE (orig) == COMPONENT_REF
               && TREE_CODE (TREE_TYPE (TREE_OPERAND (orig, 1))) == ARRAY_TYPE))
          && (TREE_CODE (t) == ARRAY_REF
-             || (TREE_CODE (t) == COMPONENT_REF
-                 && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 1))) == ARRAY_TYPE))
+             || TREE_CODE (t) == COMPONENT_REF)
          && !operand_equal_p (TREE_CODE (orig) == ARRAY_REF
                               ? TREE_OPERAND (orig, 0) : orig,
                               TREE_CODE (t) == ARRAY_REF