OSDN Git Service

PR c++/28710
[pf3gnuchains/gcc-fork.git] / gcc / tree-inline.c
index 9a93427..b05bf26 100644 (file)
@@ -266,7 +266,6 @@ remap_type_1 (tree type, copy_body_data *id)
     case REAL_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
-    case CHAR_TYPE:
       t = TYPE_MIN_VALUE (new);
       if (t && TREE_CODE (t) != INTEGER_CST)
         walk_tree (&TYPE_MIN_VALUE (new), copy_body_r, id, NULL);
@@ -591,6 +590,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
          if (n)
            {
              tree new;
+             tree old;
              /* If we happen to get an ADDR_EXPR in n->value, strip
                 it manually here as we'll eventually get ADDR_EXPRs
                 which lie about their types pointed to.  In this case
@@ -599,13 +599,17 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
                 does other useful transformations, try that first, though.  */
              tree type = TREE_TYPE (TREE_TYPE ((tree)n->value));
              new = unshare_expr ((tree)n->value);
+             old = *tp;
              *tp = fold_indirect_ref_1 (type, new);
              if (! *tp)
                {
                  if (TREE_CODE (new) == ADDR_EXPR)
                    *tp = TREE_OPERAND (new, 0);
                  else
-                   *tp = build1 (INDIRECT_REF, type, new);
+                   {
+                     *tp = build1 (INDIRECT_REF, type, new);
+                     TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
+                   }
                }
              *walk_subtrees = 0;
              return NULL;
@@ -655,7 +659,12 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
       else if (TREE_CODE (*tp) == ADDR_EXPR)
        {
          walk_tree (&TREE_OPERAND (*tp, 0), copy_body_r, id, NULL);
-         recompute_tree_invariant_for_addr_expr (*tp);
+         /* Handle the case where we substituted an INDIRECT_REF
+            into the operand of the ADDR_EXPR.  */
+         if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF)
+           *tp = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0);
+         else
+           recompute_tree_invariant_for_addr_expr (*tp);
          *walk_subtrees = 0;
        }
     }
@@ -695,6 +704,14 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal
       if (stmt)
        {
          tree call, decl;
+
+         /* With return slot optimization we can end up with
+            non-gimple (foo *)&this->m, fix that here.  */
+         if (TREE_CODE (stmt) == MODIFY_EXPR
+             && TREE_CODE (TREE_OPERAND (stmt, 1)) == NOP_EXPR
+             && !is_gimple_val (TREE_OPERAND (TREE_OPERAND (stmt, 1), 0)))
+           gimplify_stmt (&stmt);
+
           bsi_insert_after (&copy_bsi, stmt, BSI_NEW_STMT);
          call = get_call_expr_in (stmt);
          /* We're duplicating a CALL_EXPR.  Find any corresponding
@@ -894,7 +911,7 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency,
       *new_cfun = *DECL_STRUCT_FUNCTION (callee_fndecl);
       new_cfun->cfg = NULL;
       new_cfun->decl = new_fndecl = copy_node (callee_fndecl);
-      new_cfun->ib_boundaries_block = (varray_type) 0;
+      new_cfun->ib_boundaries_block = NULL;
       DECL_STRUCT_FUNCTION (new_fndecl) = new_cfun;
       push_cfun (new_cfun);
       init_empty_tree_cfg ();
@@ -925,7 +942,8 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency,
       if (id->transform_new_cfg)
         init_eh_for_function ();
       id->eh_region_offset
-       = duplicate_eh_regions (cfun_to_copy, remap_decl_1, id, id->eh_region);
+       = duplicate_eh_regions (cfun_to_copy, remap_decl_1, id,
+                               0, id->eh_region);
     }
   /* Use aux pointers to map the original blocks to copy.  */
   FOR_EACH_BB_FN (bb, cfun_to_copy)
@@ -1071,6 +1089,8 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
 
       if (rhs == error_mark_node)
        return;
+       
+      STRIP_USELESS_TYPE_CONVERSION (rhs);
 
       /* We want to use MODIFY_EXPR, not INIT_EXPR here so that we
         keep our trees in gimple form.  */
@@ -1223,6 +1243,10 @@ declare_return_variable (copy_body_data *id, tree return_slot_addr,
            use_it = false;
          else if (is_global_var (base_m))
            use_it = false;
+         else if (TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
+                  && !DECL_COMPLEX_GIMPLE_REG_P (result)
+                  && DECL_COMPLEX_GIMPLE_REG_P (base_m))
+           use_it = false;
          else if (!TREE_ADDRESSABLE (base_m))
            use_it = true;
        }
@@ -1253,6 +1277,8 @@ declare_return_variable (copy_body_data *id, tree return_slot_addr,
   use = var;
   if (!lang_hooks.types_compatible_p (TREE_TYPE (var), caller_type))
     use = fold_convert (caller_type, var);
+    
+  STRIP_USELESS_TYPE_CONVERSION (use);
 
  done:
   /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that
@@ -1598,6 +1624,9 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case LOOP_EXPR:
     case PHI_NODE:
     case WITH_SIZE_EXPR:
+    case OMP_CLAUSE:
+    case OMP_RETURN:
+    case OMP_CONTINUE:
       break;
 
     /* We don't account constants for now.  Assume that the cost is amortized
@@ -1784,6 +1813,20 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
        *count += PARAM_VALUE (PARAM_INLINE_CALL_COST);
        break;
       }
+
+    case OMP_PARALLEL:
+    case OMP_FOR:
+    case OMP_SECTIONS:
+    case OMP_SINGLE:
+    case OMP_SECTION:
+    case OMP_MASTER:
+    case OMP_ORDERED:
+    case OMP_CRITICAL:
+    case OMP_ATOMIC:
+      /* OpenMP directives are generally very expensive.  */
+      *count += 40;
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -2052,6 +2095,7 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
       if (CALL_EXPR_RETURN_SLOT_OPT (t))
        {
          return_slot_addr = build_fold_addr_expr (modify_dest);
+         STRIP_USELESS_TYPE_CONVERSION (return_slot_addr);
          modify_dest = NULL;
        }
     }
@@ -2119,8 +2163,6 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
   /* Update callgraph if needed.  */
   cgraph_remove_node (cg_edge->callee);
 
-  /* Declare the 'auto' variables added with this inlined body.  */
-  record_vars (BLOCK_VARS (id->block));
   id->block = NULL_TREE;
   successfully_inlined = TRUE;
 
@@ -2267,7 +2309,8 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
   if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
       || code == TREE_LIST
       || code == TREE_VEC
-      || code == TYPE_DECL)
+      || code == TYPE_DECL
+      || code == OMP_CLAUSE)
     {
       /* Because the chain gets clobbered when we make a copy, we save it
         here.  */
@@ -2285,7 +2328,9 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 
       /* Now, restore the chain, if appropriate.  That will cause
         walk_tree to walk into the chain as well.  */
-      if (code == PARM_DECL || code == TREE_LIST)
+      if (code == PARM_DECL
+         || code == TREE_LIST
+         || code == OMP_CLAUSE)
        TREE_CHAIN (*tp) = chain;
 
       /* For now, we don't update BLOCKs when we make copies.  So, we
@@ -2509,7 +2554,13 @@ declare_inline_vars (tree block, tree vars)
 {
   tree t;
   for (t = vars; t; t = TREE_CHAIN (t))
-    DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
+    {
+      DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
+      gcc_assert (!TREE_STATIC (t) && !TREE_ASM_WRITTEN (t));
+      cfun->unexpanded_var_list =
+       tree_cons (NULL_TREE, t,
+                  cfun->unexpanded_var_list);
+    }
 
   if (block)
     BLOCK_VARS (block) = chainon (BLOCK_VARS (block), vars);