OSDN Git Service

* config/darwin.c (indirect_data): Fix typo in strncmp logic.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ccp.c
index c530ede..26e1a2e 100644 (file)
@@ -1,5 +1,6 @@
 /* Conditional constant propagation pass for the GNU compiler.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   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>
 
@@ -330,16 +331,6 @@ likely_value (tree stmt)
 }
 
 
-/* Function indicating whether we ought to include information for VAR
-   when calculating immediate uses.  */
-
-static bool
-need_imm_uses_for (tree var)
-{
-  return get_value (var)->lattice_val != VARYING;
-}
-
-
 /* Initialize local data structures for CCP.  */
 
 static void
@@ -429,9 +420,6 @@ ccp_initialize (void)
     }
 
   sbitmap_free (is_may_def);
-
-  /* Compute immediate uses for variables we care about.  */
-  compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, need_imm_uses_for);
 }
 
 
@@ -590,7 +578,7 @@ substitute_and_fold (void)
              if (maybe_clean_eh_stmt (stmt))
                tree_purge_dead_eh_edges (bb);
 
-             modify_stmt (stmt);
+             update_stmt (stmt);
            }
 
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -937,6 +925,7 @@ ccp_fold (tree stmt)
       if (NUM_USES (uses) != 0)
        {
          tree *orig;
+         tree fndecl, arglist;
          size_t i;
 
          /* Preserve the original values of every operand.  */
@@ -946,7 +935,9 @@ ccp_fold (tree stmt)
 
          /* Substitute operands with their values and try to fold.  */
          replace_uses_in (stmt, NULL);
-         retval = fold_builtin (rhs, false);
+         fndecl = get_callee_fndecl (rhs);
+         arglist = TREE_OPERAND (rhs, 1);
+         retval = fold_builtin (fndecl, arglist, false);
 
          /* Restore operands to their original form.  */
          for (i = 0; i < NUM_USES (uses); i++)
@@ -1059,9 +1050,7 @@ visit_assignment (tree stmt, tree *output_p)
       val = evaluate_stmt (stmt);
 
   /* If the original LHS was a VIEW_CONVERT_EXPR, modify the constant
-     value to be a VIEW_CONVERT_EXPR of the old constant value.  This is
-     valid because a VIEW_CONVERT_EXPR is valid everywhere an operand of
-     aggregate type is valid.
+     value to be a VIEW_CONVERT_EXPR of the old constant value.
 
      ??? Also, if this was a definition of a bitfield, we need to widen
      the constant value into the type of the destination variable.  This
@@ -1072,10 +1061,18 @@ visit_assignment (tree stmt, tree *output_p)
     if (TREE_CODE (orig_lhs) == VIEW_CONVERT_EXPR
        && val.lattice_val == CONSTANT)
       {
-       val.const_val = build1 (VIEW_CONVERT_EXPR,
-                               TREE_TYPE (TREE_OPERAND (orig_lhs, 0)),
-                               val.const_val);
+       tree w = fold (build1 (VIEW_CONVERT_EXPR,
+                              TREE_TYPE (TREE_OPERAND (orig_lhs, 0)),
+                              val.const_val));
+
        orig_lhs = TREE_OPERAND (orig_lhs, 1);
+       if (w && is_gimple_min_invariant (w))
+         val.const_val = w;
+       else
+         {
+           val.lattice_val = VARYING;
+           val.const_val = NULL;
+         }
       }
 
     if (val.lattice_val == CONSTANT
@@ -1284,9 +1281,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 = build (BIT_AND_EXPR, TREE_TYPE (var), val, 
-                       fold_convert (TREE_TYPE (var),
-                                     build_int_cst (NULL_TREE, mask)));
+      wide_val = build2 (BIT_AND_EXPR, TREE_TYPE (var), val, 
+                        build_int_cst (TREE_TYPE (var), mask));
     }
   else
     {
@@ -1296,9 +1292,8 @@ 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 = build (BIT_IOR_EXPR, TREE_TYPE (var), val,
-                       fold_convert (TREE_TYPE (var),
-                                     build_int_cst (NULL_TREE, mask)));
+      wide_val = build2 (BIT_IOR_EXPR, TREE_TYPE (var), val,
+                        build_int_cst (TREE_TYPE (var), mask));
     }
 
   return fold (wide_val);
@@ -1449,45 +1444,39 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
        continue;
 
       field_type = TREE_TYPE (f);
-      if (cmp < 0)
-       {
-         /* Don't care about offsets into the middle of scalars.  */
-         if (!AGGREGATE_TYPE_P (field_type))
-           continue;
-
-         /* Check for array at the end of the struct.  This is often
-            used as for flexible array members.  We should be able to
-            turn this into an array access anyway.  */
-         if (TREE_CODE (field_type) == ARRAY_TYPE)
-           tail_array_field = f;
-
-         /* Check the end of the field against the offset.  */
-         if (!DECL_SIZE_UNIT (f)
-             || TREE_CODE (DECL_SIZE_UNIT (f)) != INTEGER_CST)
-           continue;
-         t = int_const_binop (MINUS_EXPR, offset, DECL_FIELD_OFFSET (f), 1);
-         if (!tree_int_cst_lt (t, DECL_SIZE_UNIT (f)))
-           continue;
-
-         /* If we matched, then set offset to the displacement into
-            this field.  */
-         offset = t;
-       }
 
       /* Here we exactly match the offset being checked.  If the types match,
         then we can return that field.  */
-      else if (lang_hooks.types_compatible_p (orig_type, field_type))
+      if (cmp == 0
+         && lang_hooks.types_compatible_p (orig_type, field_type))
        {
          if (base_is_ptr)
            base = build1 (INDIRECT_REF, record_type, base);
          t = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
          return t;
        }
+      
+      /* Don't care about offsets into the middle of scalars.  */
+      if (!AGGREGATE_TYPE_P (field_type))
+       continue;
 
-      /* Don't care about type-punning of scalars.  */
-      else if (!AGGREGATE_TYPE_P (field_type))
-       return NULL_TREE;
+      /* Check for array at the end of the struct.  This is often
+        used as for flexible array members.  We should be able to
+        turn this into an array access anyway.  */
+      if (TREE_CODE (field_type) == ARRAY_TYPE)
+       tail_array_field = f;
 
+      /* Check the end of the field against the offset.  */
+      if (!DECL_SIZE_UNIT (f)
+         || TREE_CODE (DECL_SIZE_UNIT (f)) != INTEGER_CST)
+       continue;
+      t = int_const_binop (MINUS_EXPR, offset, field_offset, 1);
+      if (!tree_int_cst_lt (t, DECL_SIZE_UNIT (f)))
+       continue;
+
+      /* If we matched, then set offset to the displacement into
+        this field.  */
+      offset = t;
       goto found;
     }
 
@@ -1496,6 +1485,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
 
   f = tail_array_field;
   field_type = TREE_TYPE (f);
+  offset = int_const_binop (MINUS_EXPR, offset, byte_position (f), 1);
 
  found:
   /* If we get here, we've got an aggregate field, and a possibly 
@@ -1579,7 +1569,7 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
       /* We can get here for out-of-range string constant accesses, 
         such as "_"[3].  Bail out of the entire substitution search
         and arrange for the entire statement to be replaced by a
-        call to __builtin_trap.  In all likelyhood this will all be
+        call to __builtin_trap.  In all likelihood this will all be
         constant-folded away, but in the meantime we can't leave with
         something that get_expr_operands can't understand.  */
 
@@ -1929,7 +1919,9 @@ ccp_fold_builtin (tree stmt, tree fn)
 
   /* First try the generic builtin folder.  If that succeeds, return the
      result directly.  */
-  result = fold_builtin (fn, ignore);
+  callee = get_callee_fndecl (fn);
+  arglist = TREE_OPERAND (fn, 1);
+  result = fold_builtin (callee, arglist, ignore);
   if (result)
   {
     if (ignore)
@@ -1938,13 +1930,11 @@ ccp_fold_builtin (tree stmt, tree fn)
   }
 
   /* Ignore MD builtins.  */
-  callee = get_callee_fndecl (fn);
   if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
     return NULL_TREE;
 
   /* If the builtin could not be folded, and it has no argument list,
      we're done.  */
-  arglist = TREE_OPERAND (fn, 1);
   if (!arglist)
     return NULL_TREE;
 
@@ -1965,7 +1955,7 @@ ccp_fold_builtin (tree stmt, tree fn)
     }
 
   /* Try to use the dataflow information gathered by the CCP process.  */
-  visited = BITMAP_XMALLOC ();
+  visited = BITMAP_ALLOC (NULL);
 
   memset (strlen_val, 0, sizeof (strlen_val));
   for (i = 0, a = arglist;
@@ -1978,7 +1968,7 @@ ccp_fold_builtin (tree stmt, tree fn)
          strlen_val[i] = NULL_TREE;
       }
 
-  BITMAP_XFREE (visited);
+  BITMAP_FREE (visited);
 
   result = NULL_TREE;
   switch (DECL_FUNCTION_CODE (callee))
@@ -1999,12 +1989,20 @@ ccp_fold_builtin (tree stmt, tree fn)
 
     case BUILT_IN_STRCPY:
       if (strlen_val[1] && is_gimple_val (strlen_val[1]))
-        result = fold_builtin_strcpy (fn, strlen_val[1]);
+       {
+         tree fndecl = get_callee_fndecl (fn);
+         tree arglist = TREE_OPERAND (fn, 1);
+         result = fold_builtin_strcpy (fndecl, arglist, strlen_val[1]);
+       }
       break;
 
     case BUILT_IN_STRNCPY:
       if (strlen_val[1] && is_gimple_val (strlen_val[1]))
-       result = fold_builtin_strncpy (fn, strlen_val[1]);
+       {
+         tree fndecl = get_callee_fndecl (fn);
+         tree arglist = TREE_OPERAND (fn, 1);
+         result = fold_builtin_strncpy (fndecl, arglist, strlen_val[1]);
+       }
       break;
 
     case BUILT_IN_FPUTS:
@@ -2193,10 +2191,14 @@ execute_fold_all_builtins (void)
          if (!set_rhs (stmtp, result))
            {
              result = convert_to_gimple_builtin (&i, result);
-             if (result && !set_rhs (stmtp, result))
-               abort ();
+             if (result)
+               {
+                 bool ok = set_rhs (stmtp, result);
+                 
+                 gcc_assert (ok);
+               }
            }
-         modify_stmt (*stmtp);
+         update_stmt (*stmtp);
          if (maybe_clean_eh_stmt (*stmtp)
              && tree_purge_dead_eh_edges (bb))
            cfg_changed = true;