OSDN Git Service

* gimplify.c (gimplify_call_expr): Don't set CALL_CANNOT_INLINE_P
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index bb38ba3..8ed4263 100644 (file)
@@ -1,6 +1,6 @@
 /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
    tree representation into the GIMPLE form.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Major work done by Sebastian Pop <s.pop@laposte.net>,
    Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
@@ -565,7 +565,7 @@ create_tmp_var (tree type, const char *prefix)
 static inline tree
 create_tmp_from_val (tree val)
 {
-  return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val));
+  return create_tmp_var (TREE_TYPE (val), get_name (val));
 }
 
 /* Create a temporary to hold the value of VAL.  If IS_FORMAL, try to reuse
@@ -656,13 +656,8 @@ static bool
 is_gimple_mem_or_call_rhs (tree t)
 {
   /* If we're dealing with a renamable type, either source or dest must be
-     a renamed variable.  Also force a temporary if the type doesn't need
-     to be stored in memory, since it's cheap and prevents erroneous
-     tailcalls (PR 17526).  */
-  if (is_gimple_reg_type (TREE_TYPE (t))
-      || (TYPE_MODE (TREE_TYPE (t)) != BLKmode
-         && (TREE_CODE (t) != CALL_EXPR
-              || ! aggregate_value_p (t, t))))
+     a renamed variable.  */
+  if (is_gimple_reg_type (TREE_TYPE (t)))
     return is_gimple_val (t);
   else
     return is_gimple_formal_tmp_or_call_rhs (t);
@@ -772,7 +767,7 @@ declare_vars (tree vars, gimple scope, bool debug_info)
 
       temps = nreverse (last);
 
-      block = gimple_block (scope);
+      block = gimple_bind_block (scope);
       gcc_assert (!block || TREE_CODE (block) == BLOCK);
       if (!block || !debug_info)
        {
@@ -1245,6 +1240,9 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
            omp_add_variable (gimplify_omp_ctxp, t, GOVD_LOCAL | GOVD_SEEN);
 
          DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
+
+         if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
+           cfun->has_local_explicit_reg_vars = true;
        }
 
       /* Preliminarily mark non-addressed complex variables as eligible
@@ -2238,10 +2236,11 @@ maybe_with_size_expr (tree *expr_p)
 
 
 /* Helper for gimplify_call_expr.  Gimplify a single argument *ARG_P
-   Store any side-effects in PRE_P.  */
+   Store any side-effects in PRE_P.  CALL_LOCATION is the location of
+   the CALL_EXPR.  */
 
 static enum gimplify_status
-gimplify_arg (tree *arg_p, gimple_seq *pre_p)
+gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
 {
   bool (*test) (tree);
   fallback_t fb;
@@ -2259,6 +2258,10 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p)
   /* If this is a variable sized type, we must remember the size.  */
   maybe_with_size_expr (arg_p);
 
+  /* Make sure arguments have the same location as the function call
+     itself.  */
+  protected_set_expr_location (*arg_p, call_location);
+
   /* There is a sequence point before a function call.  Side effects in
      the argument list must occur before the actual call. So, when
      gimplifying arguments, force gimplify_expr to use an internal
@@ -2347,56 +2350,14 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
   else if (POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_FN (*expr_p))))
     parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*expr_p))));
 
-  /* Verify if the type of the argument matches that of the function
-     declaration.  If we cannot verify this or there is a mismatch,
-     mark the call expression so it doesn't get inlined later.  */
   if (fndecl && DECL_ARGUMENTS (fndecl))
-    {
-      for (i = 0, p = DECL_ARGUMENTS (fndecl);
-          i < nargs;
-          i++, p = TREE_CHAIN (p))
-       {
-         /* We cannot distinguish a varargs function from the case
-            of excess parameters, still deferring the inlining decision
-            to the callee is possible.  */
-         if (!p)
-           break;
-         if (p == error_mark_node
-             || CALL_EXPR_ARG (*expr_p, i) == error_mark_node
-             || !fold_convertible_p (DECL_ARG_TYPE (p),
-                                     CALL_EXPR_ARG (*expr_p, i)))
-           {
-             CALL_CANNOT_INLINE_P (*expr_p) = 1;
-             break;
-           }
-       }
-    }
+    p = DECL_ARGUMENTS (fndecl);
   else if (parms)
-    {
-      for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p))
-       {
-         /* If this is a varargs function defer inlining decision
-            to callee.  */
-         if (!p)
-           break;
-         if (TREE_VALUE (p) == error_mark_node
-             || CALL_EXPR_ARG (*expr_p, i) == error_mark_node
-             || TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
-             || !fold_convertible_p (TREE_VALUE (p),
-                                     CALL_EXPR_ARG (*expr_p, i)))
-           {
-             CALL_CANNOT_INLINE_P (*expr_p) = 1;
-             break;
-           }
-       }
-    }
+    p = parms;
   else
-    {
-      if (nargs != 0)
-       CALL_CANNOT_INLINE_P (*expr_p) = 1;
-      i = 0;
-      p = NULL_TREE;
-    }
+    p = NULL_TREE;
+  for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
+    ;
 
   /* If the last argument is __builtin_va_arg_pack () and it is not
      passed as a named argument, decrease the number of CALL_EXPR
@@ -2448,7 +2409,8 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
              be the plain PARM_DECL.  */
           if ((i != 1) || !builtin_va_start_p)
             {
-              t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p);
+              t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
+                               EXPR_LOCATION (*expr_p));
 
               if (t == GS_ERROR)
                 ret = GS_ERROR;
@@ -3095,10 +3057,10 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
   from = TREE_OPERAND (*expr_p, 1);
 
   from_ptr = build_fold_addr_expr (from);
-  gimplify_arg (&from_ptr, seq_p);
+  gimplify_arg (&from_ptr, seq_p, EXPR_LOCATION (*expr_p));
 
   to_ptr = build_fold_addr_expr (to);
-  gimplify_arg (&to_ptr, seq_p);
+  gimplify_arg (&to_ptr, seq_p, EXPR_LOCATION (*expr_p));
 
   t = implicit_built_in_decls[BUILT_IN_MEMCPY];
 
@@ -3145,7 +3107,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
   to = TREE_OPERAND (*expr_p, 0);
 
   to_ptr = build_fold_addr_expr (to);
-  gimplify_arg (&to_ptr, seq_p);
+  gimplify_arg (&to_ptr, seq_p, EXPR_LOCATION (*expr_p));
   t = implicit_built_in_decls[BUILT_IN_MEMSET];
 
   gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
@@ -3563,7 +3525,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        if (valid_const_initializer
            && num_nonzero_elements > 1
            && TREE_READONLY (object)
-           && TREE_CODE (object) == VAR_DECL)
+           && TREE_CODE (object) == VAR_DECL
+           && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)))
          {
            if (notify_temp_creation)
              return GS_ERROR;
@@ -3619,8 +3582,13 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
           be dropped to memory, and then memcpy'd out.  Don't do this
           for sparse arrays, though, as it's more efficient to follow
           the standard CONSTRUCTOR behavior of memset followed by
-          individual element initialization.  */
-       if (valid_const_initializer && !cleared)
+          individual element initialization.  Also don't do this for small
+          all-zero initializers (which aren't big enough to merit
+          clearing), and don't try to make bitwise copies of
+          TREE_ADDRESSABLE types.  */
+       if (valid_const_initializer
+           && !(cleared || num_nonzero_elements == 0)
+           && !TREE_ADDRESSABLE (type))
          {
            HOST_WIDE_INT size = int_size_in_bytes (type);
            unsigned int align;
@@ -3642,7 +3610,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            else
              align = TYPE_ALIGN (type);
 
-           if (size > 0 && !can_move_by_pieces (size, align))
+           if (size > 0
+               && num_nonzero_elements > 1
+               && !can_move_by_pieces (size, align))
              {
                tree new_tree;
 
@@ -5334,6 +5304,20 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
       goto do_outer;
     }
 
+  if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
+      && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
+      && DECL_SIZE (decl)
+      && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
+    {
+      splay_tree_node n2;
+      tree t = DECL_VALUE_EXPR (decl);
+      gcc_assert (TREE_CODE (t) == INDIRECT_REF);
+      t = TREE_OPERAND (t, 0);
+      gcc_assert (DECL_P (t));
+      n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
+      n2->value |= GOVD_SEEN;
+    }
+
   shared = ((flags | n->value) & GOVD_SHARED) != 0;
   ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
 
@@ -6059,12 +6043,27 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
+    case tcc_comparison:
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
                                     lhs_var);
     case tcc_unary:
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
                                     lhs_var);
       break;
+    case tcc_expression:
+      switch (TREE_CODE (expr))
+       {
+       case TRUTH_ANDIF_EXPR:
+       case TRUTH_ORIF_EXPR:
+         saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
+                                        lhs_addr, lhs_var);
+         saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+                                        lhs_addr, lhs_var);
+         break;
+       default:
+         break;
+       }
+      break;
     default:
       break;
     }
@@ -6978,7 +6977,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  && code != ASM_EXPR
                  && code != BIND_EXPR
                  && code != CATCH_EXPR
-                 && code != COND_EXPR
+                 && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
                  && code != EH_FILTER_EXPR
                  && code != GOTO_EXPR
                  && code != LABEL_EXPR
@@ -7117,6 +7116,18 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
       /* These types may not have declarations, so handle them here.  */
       gimplify_type_sizes (TREE_TYPE (type), list_p);
       gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
+      /* When not optimizing, ensure VLA bounds aren't removed.  */
+      if (!optimize
+         && TYPE_DOMAIN (type)
+         && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
+       {
+         t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
+         if (t && TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t))
+           DECL_IGNORED_P (t) = 0;
+         t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
+         if (t && TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t))
+           DECL_IGNORED_P (t) = 0;
+       }
       break;
 
     case RECORD_TYPE:
@@ -7126,6 +7137,8 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
        if (TREE_CODE (field) == FIELD_DECL)
          {
            gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
+           gimplify_one_sizepos (&DECL_SIZE (field), list_p);
+           gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
            gimplify_type_sizes (TREE_TYPE (field), list_p);
          }
       break;
@@ -7354,10 +7367,10 @@ gimplify_function_tree (tree fndecl)
       x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
       gimplify_seq_add_stmt (&body, gimple_build_call (x, 0));
       gimplify_seq_add_stmt (&body, tf);
-      new_bind = gimple_build_bind (NULL, body, gimple_block (bind));
+      new_bind = gimple_build_bind (NULL, body, gimple_bind_block (bind));
       /* Clear the block for BIND, since it is no longer directly inside
          the function, but within a try block.  */
-      gimple_set_block (bind, NULL);
+      gimple_bind_set_block (bind, NULL);
 
       /* Replace the current function body with the body
          wrapped in the try/finally TF.  */
@@ -7398,6 +7411,10 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
       gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL,
                     is_gimple_val, fb_rvalue);
       break;
+    case GIMPLE_SWITCH:
+      gimplify_expr (gimple_switch_index_ptr (stmt), &pre, NULL,
+                    is_gimple_val, fb_rvalue);
+      break;
     case GIMPLE_OMP_ATOMIC_LOAD:
       gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL,
                     is_gimple_val, fb_rvalue);
@@ -7472,9 +7489,9 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
        }
 
       lhs = gimple_get_lhs (stmt);
-      /* If regimplification of the LHS changed it in a way that requires
-        a simple RHS, create temporary.  */
-      if (orig_lhs != lhs && !is_gimple_formal_tmp_var (lhs))
+      /* If the LHS changed it in a way that requires a simple RHS,
+        create temporary.  */
+      if (lhs && !is_gimple_formal_tmp_var (lhs))
        {
          bool need_temp = false;
 
@@ -7548,6 +7565,10 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
       break;
     }
 
+  if (gimple_referenced_vars (cfun))
+    for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
+      add_referenced_var (t);
+
   if (!gimple_seq_empty_p (pre))
     {
       if (gimple_in_ssa_p (cfun))
@@ -7562,10 +7583,6 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
   if (post_stmt)
     gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
 
-  if (gimple_referenced_vars (cfun))
-    for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
-      add_referenced_var (t);
-
   pop_gimplify_context (NULL);
 }