OSDN Git Service

Backport from mainline
[pf3gnuchains/gcc-fork.git] / gcc / gimple-fold.c
index 08b7ccc..0210ccf 100644 (file)
@@ -1,5 +1,5 @@
 /* Statement simplification on GIMPLE.
-   Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc.
    Split out from tree-ssa-ccp.c.
 
 This file is part of GCC.
@@ -115,6 +115,7 @@ can_refer_decl_in_current_unit_p (tree decl)
 tree
 canonicalize_constructor_val (tree cval)
 {
+  tree orig_cval = cval;
   STRIP_NOPS (cval);
   if (TREE_CODE (cval) == POINTER_PLUS_EXPR
       && TREE_CODE (TREE_OPERAND (cval, 1)) == INTEGER_CST)
@@ -137,14 +138,21 @@ canonicalize_constructor_val (tree cval)
              || TREE_CODE (base) == FUNCTION_DECL)
          && !can_refer_decl_in_current_unit_p (base))
        return NULL_TREE;
-      if (cfun && gimple_referenced_vars (cfun)
-         && base && TREE_CODE (base) == VAR_DECL)
-       add_referenced_var (base);
+      if (base && TREE_CODE (base) == VAR_DECL)
+       {
+         TREE_ADDRESSABLE (base) = 1;
+         if (cfun && gimple_referenced_vars (cfun))
+           add_referenced_var (base);
+       }
       /* Fixup types in global initializers.  */
       if (TREE_TYPE (TREE_TYPE (cval)) != TREE_TYPE (TREE_OPERAND (cval, 0)))
        cval = build_fold_addr_expr (TREE_OPERAND (cval, 0));
+
+      if (!useless_type_conversion_p (TREE_TYPE (orig_cval), TREE_TYPE (cval)))
+       cval = fold_convert (TREE_TYPE (orig_cval), cval);
+      return cval;
     }
-  return cval;
+  return orig_cval;
 }
 
 /* If SYM is a constant variable with known value, return the value.
@@ -564,7 +572,7 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
              unlink_stmt_vdef (stmt);
              release_defs (stmt);
            }
-         gsi_remove (si_p, true);
+         gsi_replace (si_p, gimple_build_nop (), true);
          return;
        }
     }
@@ -588,8 +596,11 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
   for (i = gsi_last (stmts); !gsi_end_p (i); gsi_prev (&i))
     {
       new_stmt = gsi_stmt (i);
-      if (gimple_assign_single_p (new_stmt)
-         && !is_gimple_reg (gimple_assign_lhs (new_stmt)))
+      if ((gimple_assign_single_p (new_stmt)
+          && !is_gimple_reg (gimple_assign_lhs (new_stmt)))
+         || (is_gimple_call (new_stmt)
+             && (gimple_call_flags (new_stmt)
+                 & (ECF_NOVOPS | ECF_PURE | ECF_CONST | ECF_NORETURN)) == 0))
        {
          tree vdef;
          if (!laststore)
@@ -597,7 +608,7 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
          else
            vdef = make_ssa_name (gimple_vop (cfun), new_stmt);
          gimple_set_vdef (new_stmt, vdef);
-         if (TREE_CODE (vdef) == SSA_NAME)
+         if (vdef && TREE_CODE (vdef) == SSA_NAME)
            SSA_NAME_DEF_STMT (vdef) = new_stmt;
          laststore = new_stmt;
        }
@@ -665,13 +676,10 @@ get_maxval_strlen (tree arg, tree *length, bitmap visited, int type)
 
   if (TREE_CODE (arg) != SSA_NAME)
     {
-      if (TREE_CODE (arg) == COND_EXPR)
-        return get_maxval_strlen (COND_EXPR_THEN (arg), length, visited, type)
-               && get_maxval_strlen (COND_EXPR_ELSE (arg), length, visited, type);
       /* We can end up with &(*iftmp_1)[0] here as well, so handle it.  */
-      else if (TREE_CODE (arg) == ADDR_EXPR
-              && TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF
-              && integer_zerop (TREE_OPERAND (TREE_OPERAND (arg, 0), 1)))
+      if (TREE_CODE (arg) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF
+         && integer_zerop (TREE_OPERAND (TREE_OPERAND (arg, 0), 1)))
        {
          tree aop0 = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
          if (TREE_CODE (aop0) == INDIRECT_REF
@@ -731,6 +739,13 @@ get_maxval_strlen (tree arg, tree *length, bitmap visited, int type)
             tree rhs = gimple_assign_rhs1 (def_stmt);
             return get_maxval_strlen (rhs, length, visited, type);
           }
+       else if (gimple_assign_rhs_code (def_stmt) == COND_EXPR)
+         {
+           tree op2 = gimple_assign_rhs2 (def_stmt);
+           tree op3 = gimple_assign_rhs3 (def_stmt);
+           return get_maxval_strlen (op2, length, visited, type)
+                  && get_maxval_strlen (op3, length, visited, type);
+          }
         return false;
 
       case GIMPLE_PHI:
@@ -831,6 +846,7 @@ gimple_fold_builtin (gimple stmt)
     case BUILT_IN_MEMMOVE_CHK:
     case BUILT_IN_MEMSET_CHK:
     case BUILT_IN_STRNCPY_CHK:
+    case BUILT_IN_STPNCPY_CHK:
       arg_idx = 2;
       type = 2;
       break;
@@ -937,12 +953,14 @@ gimple_fold_builtin (gimple stmt)
       break;
 
     case BUILT_IN_STRNCPY_CHK:
+    case BUILT_IN_STPNCPY_CHK:
       if (val[2] && is_gimple_val (val[2]) && nargs == 4)
-       result = fold_builtin_strncpy_chk (loc, gimple_call_arg (stmt, 0),
+       result = fold_builtin_stxncpy_chk (loc, gimple_call_arg (stmt, 0),
                                            gimple_call_arg (stmt, 1),
                                            gimple_call_arg (stmt, 2),
                                            gimple_call_arg (stmt, 3),
-                                          val[2]);
+                                          val[2], ignore,
+                                          DECL_FUNCTION_CODE (callee));
       break;
 
     case BUILT_IN_SNPRINTF_CHK:
@@ -1105,23 +1123,12 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
        }
     }
 
-  /* Check whether propagating into the function address made the
-     call direct, and thus possibly non-inlineable.
-     ???  This asks for a more conservative setting of the non-inlinable
-     flag, namely true for all indirect calls.  But that would require
-     that we can re-compute the flag conservatively, thus it isn't
-     ever initialized from something else than return/argument type
-     checks .  */
-  callee = gimple_call_fndecl (stmt);
-  if (callee
-      && !gimple_check_call_matching_types (stmt, callee))
-    gimple_call_set_cannot_inline (stmt, true);
-
   if (inplace)
     return changed;
 
   /* Check for builtins that CCP can handle using information not
      available in the generic fold routines.  */
+  callee = gimple_call_fndecl (stmt);
   if (callee && DECL_BUILT_IN (callee))
     {
       tree result = gimple_fold_builtin (stmt);
@@ -1252,6 +1259,18 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
                  changed = true;
                }
            }
+         else if (val
+                  && TREE_CODE (val) == ADDR_EXPR)
+           {
+             tree ref = TREE_OPERAND (val, 0);
+             tree tem = maybe_fold_reference (ref, false);
+             if (tem)
+               {
+                 tem = build_fold_addr_expr_with_type (tem, TREE_TYPE (val));
+                 gimple_debug_bind_set_value (stmt, tem);
+                 changed = true;
+               }
+           }
        }
       break;
 
@@ -2525,8 +2544,10 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
              if (CONVERT_EXPR_CODE_P (subcode)
                  && POINTER_TYPE_P (TREE_TYPE (lhs))
                  && POINTER_TYPE_P (TREE_TYPE (op0))
-                 && (TYPE_ADDR_SPACE (TREE_TYPE (lhs))
-                     == TYPE_ADDR_SPACE (TREE_TYPE (op0))))
+                 && TYPE_ADDR_SPACE (TREE_TYPE (lhs))
+                    == TYPE_ADDR_SPACE (TREE_TYPE (op0))
+                 && TYPE_MODE (TREE_TYPE (lhs))
+                    == TYPE_MODE (TREE_TYPE (op0)))
                return op0;
 
               return
@@ -2689,6 +2710,10 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
       if (!DECL_INITIAL (base)
          && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
         return error_mark_node;
+      /* Do not return an error_mark_node DECL_INITIAL.  LTO uses this
+         as special marker (_not_ zero ...) for its own purposes.  */
+      if (DECL_INITIAL (base) == error_mark_node)
+       return NULL_TREE;
       return DECL_INITIAL (base);
 
     case ARRAY_REF:
@@ -3089,7 +3114,7 @@ gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
   offset += token * size;
   fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), DECL_INITIAL (v),
                            offset, size);
-  if (!fn)
+  if (!fn || integer_zerop (fn))
     return NULL_TREE;
   gcc_assert (TREE_CODE (fn) == ADDR_EXPR
              || TREE_CODE (fn) == FDESC_EXPR);