OSDN Git Service

* patch_tester.sh (usage): Watermark is not lexicographic.
[pf3gnuchains/gcc-fork.git] / gcc / tree-inline.c
index d50b2c7..74895a8 100644 (file)
@@ -1,5 +1,5 @@
 /* Tree inlining.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
    Contributed by Alexandre Oliva <aoliva@redhat.com>
 
@@ -186,15 +186,42 @@ remap_ssa_name (tree name, copy_body_data *id)
     {
       new = make_ssa_name (new, NULL);
       insert_decl_map (id, name, new);
-      if (IS_EMPTY_STMT (SSA_NAME_DEF_STMT (name)))
-       {
-         SSA_NAME_DEF_STMT (new) = build_empty_stmt ();
-         if (gimple_default_def (id->src_cfun, SSA_NAME_VAR (name)) == name)
-           set_default_def (SSA_NAME_VAR (new), new);
-       }
       SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new)
        = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name);
       TREE_TYPE (new) = TREE_TYPE (SSA_NAME_VAR (new));
+      if (IS_EMPTY_STMT (SSA_NAME_DEF_STMT (name)))
+       {
+         /* By inlining function having uninitialized variable, we might
+            extend the lifetime (variable might get reused).  This cause
+            ICE in the case we end up extending lifetime of SSA name across
+            abnormal edge, but also increase register presure.
+
+            We simply initialize all uninitialized vars by 0 except for case
+            we are inlining to very first BB.  We can avoid this for all
+            BBs that are not withing strongly connected regions of the CFG,
+            but this is bit expensive to test.
+          */
+         if (id->entry_bb && is_gimple_reg (SSA_NAME_VAR (name))
+             && TREE_CODE (SSA_NAME_VAR (name)) != PARM_DECL
+             && (id->entry_bb != EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->dest
+                 || EDGE_COUNT (id->entry_bb->preds) != 1))
+           {
+             block_stmt_iterator bsi = bsi_last (id->entry_bb);
+             tree init_stmt
+                 = build_gimple_modify_stmt (new,
+                                             fold_convert (TREE_TYPE (new),
+                                                           integer_zero_node));
+             bsi_insert_after (&bsi, init_stmt, BSI_NEW_STMT);
+             SSA_NAME_DEF_STMT (new) = init_stmt;
+             SSA_NAME_IS_DEFAULT_DEF (new) = 0;
+           }
+         else
+           {
+             SSA_NAME_DEF_STMT (new) = build_empty_stmt ();
+             if (gimple_default_def (id->src_cfun, SSA_NAME_VAR (name)) == name)
+               set_default_def (SSA_NAME_VAR (new), new);
+           }
+       }
     }
   else
     insert_decl_map (id, name, new);
@@ -259,7 +286,8 @@ remap_decl (tree decl, copy_body_data *id)
              tree map = remap_ssa_name (def, id);
              /* Watch out RESULT_DECLs whose SSA names map directly
                 to them.  */
-             if (TREE_CODE (map) == SSA_NAME)
+             if (TREE_CODE (map) == SSA_NAME
+                 && IS_EMPTY_STMT (SSA_NAME_DEF_STMT (map)))
                set_default_def (t, map);
            }
          add_referenced_var (t);
@@ -273,24 +301,8 @@ remap_decl (tree decl, copy_body_data *id)
 static tree
 remap_type_1 (tree type, copy_body_data *id)
 {
-  tree *node;
   tree new, t;
 
-  if (type == NULL)
-    return type;
-
-  /* See if we have remapped this type.  */
-  node = (tree *) pointer_map_contains (id->decl_map, type);
-  if (node)
-    return *node;
-
-  /* The type only needs remapping if it's variably modified.  */
-  if (! variably_modified_type_p (type, id->src_fn))
-    {
-      insert_decl_map (id, type, type);
-      return type;
-    }
-
   /* We do need a copy.  build and register it now.  If this is a pointer or
      reference type, remap the designated type and make a new pointer or
      reference type.  */
@@ -322,7 +334,7 @@ remap_type_1 (tree type, copy_body_data *id)
     {
       t = remap_type (t, id);
       TYPE_MAIN_VARIANT (new) = t;
-      TYPE_NEXT_VARIANT (new) = TYPE_MAIN_VARIANT (t);
+      TYPE_NEXT_VARIANT (new) = TYPE_NEXT_VARIANT (t);
       TYPE_NEXT_VARIANT (t) = new;
     }
   else
@@ -397,6 +409,7 @@ tree
 remap_type (tree type, copy_body_data *id)
 {
   tree *node;
+  tree tmp;
 
   if (type == NULL)
     return type;
@@ -413,7 +426,11 @@ remap_type (tree type, copy_body_data *id)
       return type;
     }
 
-  return remap_type_1 (type, id);
+  id->remapping_type_depth++;
+  tmp = remap_type_1 (type, id);
+  id->remapping_type_depth--;
+
+  return tmp;
 }
 
 static tree
@@ -684,11 +701,18 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
              tree type = TREE_TYPE (TREE_TYPE (*n));
              new = unshare_expr (*n);
              old = *tp;
-             *tp = fold_indirect_ref_1 (type, new);
+             *tp = gimple_fold_indirect_ref (new);
              if (! *tp)
                {
                  if (TREE_CODE (new) == ADDR_EXPR)
-                   *tp = TREE_OPERAND (new, 0);
+                   {
+                     *tp = fold_indirect_ref_1 (type, new);
+                     /* ???  We should either assert here or build
+                        a VIEW_CONVERT_EXPR instead of blindly leaking
+                        incompatible types to our IL.  */
+                     if (! *tp)
+                       *tp = TREE_OPERAND (new, 0);
+                   }
                  else
                    {
                      *tp = build1 (INDIRECT_REF, type, new);
@@ -704,9 +728,10 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
         tweak some special cases.  */
       copy_tree_r (tp, walk_subtrees, NULL);
 
-      /* Global variables we didn't seen yet needs to go into referenced
-        vars.  */
-      if (gimple_in_ssa_p (cfun) && TREE_CODE (*tp) == VAR_DECL)
+      /* Global variables we haven't seen yet needs to go into referenced
+        vars.  If not referenced from types only.  */
+      if (gimple_in_ssa_p (cfun) && TREE_CODE (*tp) == VAR_DECL
+         && id->remapping_type_depth == 0)
        add_referenced_var (*tp);
        
       /* If EXPR has block defined, map it to newly constructed block.
@@ -748,6 +773,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
         and friends are up-to-date.  */
       else if (TREE_CODE (*tp) == ADDR_EXPR)
        {
+         int invariant = TREE_INVARIANT (*tp);
          walk_tree (&TREE_OPERAND (*tp, 0), copy_body_r, id, NULL);
          /* Handle the case where we substituted an INDIRECT_REF
             into the operand of the ADDR_EXPR.  */
@@ -755,6 +781,10 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
            *tp = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0);
          else
            recompute_tree_invariant_for_addr_expr (*tp);
+         /* If this used to be invariant, but is not any longer,
+            then regimplification is probably needed.  */
+         if (invariant && !TREE_INVARIANT (*tp))
+           id->regimplify = true;
          *walk_subtrees = 0;
        }
     }
@@ -792,6 +822,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal
       tree stmt = bsi_stmt (bsi);
       tree orig_stmt = stmt;
 
+      id->regimplify = false;
       walk_tree (&stmt, copy_body_r, id, NULL);
 
       /* RETURN_EXPR might be removed,
@@ -804,9 +835,10 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal
 
          /* With return slot optimization we can end up with
             non-gimple (foo *)&this->m, fix that here.  */
-         if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
-             && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == NOP_EXPR
-             && !is_gimple_val (TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt, 1), 0)))
+         if ((TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+              && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == NOP_EXPR
+              && !is_gimple_val (TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt, 1), 0)))
+             || id->regimplify)
            gimplify_stmt (&stmt);
 
           bsi_insert_after (&copy_bsi, stmt, BSI_NEW_STMT);
@@ -863,9 +895,18 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal
                  if (TREE_CODE (*call_ptr) == WITH_SIZE_EXPR)
                    call_ptr = &TREE_OPERAND (*call_ptr, 0);
                  gcc_assert (*call_ptr == call);
-                 *call_ptr = new_call;
-                 stmt = *stmtp;
-                 update_stmt (stmt);
+                 if (call_ptr == stmtp)
+                   {
+                     bsi_replace (&copy_bsi, new_call, true);
+                     stmtp = bsi_stmt_ptr (copy_bsi);
+                     stmt = *stmtp;
+                   }
+                 else
+                   {
+                     *call_ptr = new_call;
+                     stmt = *stmtp;
+                     update_stmt (stmt);
+                   }
                }
              else if (call
                       && id->call_expr
@@ -1009,16 +1050,19 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal
    across EH edges from basic block within inlined functions destinating
    to landing pads in function we inline into.
 
-   The function mark PHI_RESULT of such PHI nodes for renaming; it is
-   safe the EH edges are abnormal and SSA_NAME_OCCURS_IN_ABNORMAL_PHI
-   must be set.  This means, that there will be no overlapping live ranges
+   The function fills in PHI_RESULTs of such PHI nodes if they refer
+   to gimple regs.  Otherwise, the function mark PHI_RESULT of such
+   PHI nodes for renaming.  For non-gimple regs, renaming is safe: the
+   EH edges are abnormal and SSA_NAME_OCCURS_IN_ABNORMAL_PHI must be
+   set, and this means that there will be no overlapping live ranges
    for the underlying symbol.
 
    This might change in future if we allow redirecting of EH edges and
    we might want to change way build CFG pre-inlining to include
    all the possible edges then.  */
 static void
-update_ssa_across_eh_edges (basic_block bb)
+update_ssa_across_abnormal_edges (basic_block bb, basic_block ret_bb,
+                                 bool can_throw, bool nonlocal_goto)
 {
   edge e;
   edge_iterator ei;
@@ -1029,13 +1073,35 @@ update_ssa_across_eh_edges (basic_block bb)
       {
        tree phi;
 
-       gcc_assert (e->flags & EDGE_EH);
+       gcc_assert (e->flags & EDGE_ABNORMAL);
+       if (!nonlocal_goto)
+         gcc_assert (e->flags & EDGE_EH);
+       if (!can_throw)
+         gcc_assert (!(e->flags & EDGE_EH));
        for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
          {
+           edge re;
+
+           /* There shouldn't be any PHI nodes in the ENTRY_BLOCK.  */
+           gcc_assert (!e->dest->aux);
+
            gcc_assert (SSA_NAME_OCCURS_IN_ABNORMAL_PHI
                        (PHI_RESULT (phi)));
-           mark_sym_for_renaming
-             (SSA_NAME_VAR (PHI_RESULT (phi)));
+
+           if (!is_gimple_reg (PHI_RESULT (phi)))
+             {
+               mark_sym_for_renaming
+                 (SSA_NAME_VAR (PHI_RESULT (phi)));
+               continue;
+             }
+
+           re = find_edge (ret_bb, e->dest);
+           gcc_assert (re);
+           gcc_assert ((re->flags & (EDGE_EH | EDGE_ABNORMAL))
+                       == (e->flags & (EDGE_EH | EDGE_ABNORMAL)));
+
+           SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e),
+                    USE_FROM_PTR (PHI_ARG_DEF_PTR_FROM_EDGE (phi, re)));
          }
       }
 }
@@ -1044,7 +1110,7 @@ update_ssa_across_eh_edges (basic_block bb)
    accordingly.  Edges will be taken care of later.  Assume aux
    pointers to point to the copies of each BB.  */
 static void
-copy_edges_for_bb (basic_block bb, int count_scale)
+copy_edges_for_bb (basic_block bb, int count_scale, basic_block ret_bb)
 {
   basic_block new_bb = (basic_block) bb->aux;
   edge_iterator ei;
@@ -1076,6 +1142,7 @@ copy_edges_for_bb (basic_block bb, int count_scale)
   for (bsi = bsi_start (new_bb); !bsi_end_p (bsi);)
     {
       tree copy_stmt;
+      bool can_throw, nonlocal_goto;
 
       copy_stmt = bsi_stmt (bsi);
       update_stmt (copy_stmt);
@@ -1096,7 +1163,10 @@ copy_edges_for_bb (basic_block bb, int count_scale)
          into a COMPONENT_REF which doesn't.  If the copy
          can throw, the original could also throw.  */
 
-      if (tree_can_throw_internal (copy_stmt))
+      can_throw = tree_can_throw_internal (copy_stmt);
+      nonlocal_goto = tree_can_make_abnormal_goto (copy_stmt);
+
+      if (can_throw || nonlocal_goto)
        {
          if (!bsi_end_p (bsi))
            /* Note that bb's predecessor edges aren't necessarily
@@ -1108,12 +1178,18 @@ copy_edges_for_bb (basic_block bb, int count_scale)
              new_bb->aux = e->src->aux;
              bsi = bsi_start (new_bb);
            }
+       }
 
-           make_eh_edges (copy_stmt);
+      if (can_throw)
+       make_eh_edges (copy_stmt);
 
-          if (gimple_in_ssa_p (cfun))
-            update_ssa_across_eh_edges (bb_for_stmt (copy_stmt));
-       }
+      if (nonlocal_goto)
+       make_abnormal_goto_edges (bb_for_stmt (copy_stmt), true);
+
+      if ((can_throw || nonlocal_goto)
+         && gimple_in_ssa_p (cfun))
+       update_ssa_across_abnormal_edges (bb_for_stmt (copy_stmt), ret_bb,
+                                         can_throw, nonlocal_goto);
     }
 }
 
@@ -1149,6 +1225,17 @@ copy_phis_for_bb (basic_block bb, copy_body_data *id)
 
              walk_tree (&new_arg, copy_body_r, id, NULL);
              gcc_assert (new_arg);
+             /* With return slot optimization we can end up with
+                non-gimple (foo *)&this->m, fix that here.  */
+             if (TREE_CODE (new_arg) != SSA_NAME
+                 && TREE_CODE (new_arg) != FUNCTION_DECL
+                 && !is_gimple_val (new_arg))
+               {
+                 tree stmts = NULL_TREE;
+                 new_arg = force_gimple_operand (new_arg, &stmts,
+                                                 true, NULL);
+                 bsi_insert_on_edge_immediate (new_edge, stmts);
+               }
              add_phi_arg (new_phi, new_arg, new_edge);
            }
        }
@@ -1285,7 +1372,7 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency,
   last = last_basic_block;
   /* Now that we've duplicated the blocks, duplicate their edges.  */
   FOR_ALL_BB_FN (bb, cfun_to_copy)
-    copy_edges_for_bb (bb, count_scale);
+    copy_edges_for_bb (bb, count_scale, exit_block_map);
   if (gimple_in_ssa_p (cfun))
     FOR_ALL_BB_FN (bb, cfun_to_copy)
       copy_phis_for_bb (bb, id);
@@ -1363,7 +1450,16 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
   if (value
       && value != error_mark_node
       && !useless_type_conversion_p (TREE_TYPE (p), TREE_TYPE (value)))
-    rhs = fold_build1 (NOP_EXPR, TREE_TYPE (p), value);
+    {
+      if (fold_convertible_p (TREE_TYPE (p), value))
+       rhs = fold_build1 (NOP_EXPR, TREE_TYPE (p), value);
+      else
+       /* ???  For valid (GIMPLE) programs we should not end up here.
+          Still if something has gone wrong and we end up with truly
+          mismatched types here, fall back to using a VIEW_CONVERT_EXPR
+          to not leak invalid GIMPLE to the following passes.  */
+       rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (p), value);
+    }
 
   /* If the parameter is never assigned to, has no SSA_NAMEs created,
      we may not need to create a new variable here at all.  Instead, we may
@@ -1462,6 +1558,14 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
       return;
     }
 
+  /* If the value of argument is never used, don't care about initializing
+     it.  */
+  if (gimple_in_ssa_p (cfun) && !def && is_gimple_reg (p))
+    {
+      gcc_assert (!value || !TREE_SIDE_EFFECTS (value));
+      return;
+    }
+
   /* Initialize this VAR_DECL from the equivalent argument.  Convert
      the argument to the proper type in case it was promoted.  */
   if (value)
@@ -1637,6 +1741,7 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
        {
          var = return_slot;
          gcc_assert (TREE_CODE (var) != SSA_NAME);
+         TREE_ADDRESSABLE (var) |= TREE_ADDRESSABLE (result);
        }
       if ((TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
            || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
@@ -1794,7 +1899,6 @@ inline_forbidden_p_1 (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED,
            /* We cannot inline functions that take a variable number of
               arguments.  */
          case BUILT_IN_VA_START:
-         case BUILT_IN_STDARG_START:
          case BUILT_IN_NEXT_ARG:
          case BUILT_IN_VA_END:
            inline_forbidden_reason
@@ -1897,6 +2001,27 @@ inline_forbidden_p_1 (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED,
   return NULL_TREE;
 }
 
+static tree
+inline_forbidden_p_2 (tree *nodep, int *walk_subtrees,
+                     void *fnp)
+{
+  tree node = *nodep;
+  tree fn = (tree) fnp;
+
+  if (TREE_CODE (node) == LABEL_DECL && DECL_CONTEXT (node) == fn)
+    {
+      inline_forbidden_reason
+       = G_("function %q+F can never be inlined "
+            "because it saves address of local label in a static variable");
+      return node;
+    }
+
+  if (TYPE_P (node))
+    *walk_subtrees = 0;
+
+  return NULL_TREE;
+}
+
 /* Return subexpression representing possible alloca call, if any.  */
 static tree
 inline_forbidden_p (tree fndecl)
@@ -1905,16 +2030,31 @@ inline_forbidden_p (tree fndecl)
   block_stmt_iterator bsi;
   basic_block bb;
   tree ret = NULL_TREE;
+  struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
+  tree step;
 
-  FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (fndecl))
+  FOR_EACH_BB_FN (bb, fun)
     for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
       {
        ret = walk_tree_without_duplicates (bsi_stmt_ptr (bsi),
-                                   inline_forbidden_p_1, fndecl);
+                                           inline_forbidden_p_1, fndecl);
        if (ret)
          goto egress;
       }
 
+  for (step = fun->unexpanded_var_list; step; step = TREE_CHAIN (step))
+    {
+      tree decl = TREE_VALUE (step);
+      if (TREE_CODE (decl) == VAR_DECL
+         && TREE_STATIC (decl)
+         && !DECL_EXTERNAL (decl)
+         && DECL_INITIAL (decl))
+       ret = walk_tree_without_duplicates (&DECL_INITIAL (decl),
+                                           inline_forbidden_p_2, fndecl);
+       if (ret)
+         goto egress;
+    }
+
 egress:
   input_location = saved_loc;
   return ret;
@@ -2081,6 +2221,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case COMPOUND_EXPR:
     case BIND_EXPR:
     case WITH_CLEANUP_EXPR:
+    case PAREN_EXPR:
     case NOP_EXPR:
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
@@ -2110,6 +2251,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case OMP_RETURN:
     case OMP_CONTINUE:
     case OMP_SECTIONS_SWITCH:
+    case OMP_ATOMIC_STORE:
       break;
 
     /* We don't account constants for now.  Assume that the cost is amortized
@@ -2267,9 +2409,12 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
       break;
 
     case SWITCH_EXPR:
-      /* TODO: Cost of a switch should be derived from the number of
-        branches.  */
-      d->count += d->weights->switch_cost;
+      /* Take into account cost of the switch + guess 2 conditional jumps for
+         each case label.  
+
+        TODO: once the switch expansion logic is sufficiently separated, we can
+        do better job on estimating cost of the switch.  */
+      d->count += TREE_VEC_LENGTH (SWITCH_LABELS (x)) * 2;
       break;
 
     /* Few special cases of expensive operations.  This is useful
@@ -2289,8 +2434,17 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case CALL_EXPR:
       {
        tree decl = get_callee_fndecl (x);
+       tree addr = CALL_EXPR_FN (x);
+       tree funtype = TREE_TYPE (addr);
 
-       cost = d->weights->call_cost;
+       gcc_assert (POINTER_TYPE_P (funtype));
+       funtype = TREE_TYPE (funtype);
+
+       if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD)
+         cost = d->weights->target_builtin_call_cost;
+       else
+         cost = d->weights->call_cost;
+       
        if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
          switch (DECL_FUNCTION_CODE (decl))
            {
@@ -2307,21 +2461,34 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
              break;
            }
 
+       if (decl)
+         funtype = TREE_TYPE (decl);
+
        /* Our cost must be kept in sync with cgraph_estimate_size_after_inlining
-          that does use function declaration to figure out the arguments.  */
-       if (!decl)
+          that does use function declaration to figure out the arguments. 
+
+          When we deal with function with no body nor prototype, base estimates on
+          actual parameters of the call expression.  Otherwise use either the actual
+          arguments types or function declaration for more precise answer.  */
+       if (decl && DECL_ARGUMENTS (decl))
+         {
+           tree arg;
+           for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
+             d->count += estimate_move_cost (TREE_TYPE (arg));
+         }
+       else if (funtype && prototype_p (funtype))
+         {
+           tree t;
+           for (t = TYPE_ARG_TYPES (funtype); t; t = TREE_CHAIN (t))
+             d->count += estimate_move_cost (TREE_VALUE (t));
+         }
+       else
          {
            tree a;
            call_expr_arg_iterator iter;
            FOR_EACH_CALL_EXPR_ARG (a, iter, x)
              d->count += estimate_move_cost (TREE_TYPE (a));
          }
-       else
-         {
-           tree arg;
-           for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
-             d->count += estimate_move_cost (TREE_TYPE (arg));
-         }
 
        d->count += cost;
        break;
@@ -2336,6 +2503,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case OMP_ORDERED:
     case OMP_CRITICAL:
     case OMP_ATOMIC:
+    case OMP_ATOMIC_LOAD:
       /* OpenMP directives are generally very expensive.  */
       d->count += d->weights->omp_cost;
       break;
@@ -2391,13 +2559,13 @@ void
 init_inline_once (void)
 {
   eni_inlining_weights.call_cost = PARAM_VALUE (PARAM_INLINE_CALL_COST);
+  eni_inlining_weights.target_builtin_call_cost = 1;
   eni_inlining_weights.div_mod_cost = 10;
-  eni_inlining_weights.switch_cost = 1;
   eni_inlining_weights.omp_cost = 40;
 
   eni_size_weights.call_cost = 1;
+  eni_size_weights.target_builtin_call_cost = 1;
   eni_size_weights.div_mod_cost = 1;
-  eni_size_weights.switch_cost = 10;
   eni_size_weights.omp_cost = 40;
 
   /* Estimating time for call is difficult, since we have no idea what the
@@ -2405,8 +2573,8 @@ init_inline_once (void)
      underestimating the cost does less harm than overestimating it, so
      we choose a rather small value here.  */
   eni_time_weights.call_cost = 10;
+  eni_time_weights.target_builtin_call_cost = 10;
   eni_time_weights.div_mod_cost = 10;
-  eni_time_weights.switch_cost = 4;
   eni_time_weights.omp_cost = 40;
 }
 
@@ -2419,7 +2587,7 @@ add_lexical_block (tree current_block, tree new_block)
   /* Walk to the last sub-block.  */
   for (blk_p = &BLOCK_SUBBLOCKS (current_block);
        *blk_p;
-       blk_p = &TREE_CHAIN (*blk_p))
+       blk_p = &BLOCK_CHAIN (*blk_p))
     ;
   *blk_p = new_block;
   BLOCK_SUPERCONTEXT (new_block) = current_block;
@@ -2432,7 +2600,7 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
 {
   copy_body_data *id;
   tree t;
-  tree use_retvar;
+  tree retvar, use_retvar;
   tree fn;
   struct pointer_map_t *st;
   tree return_slot;
@@ -2597,6 +2765,9 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
   id->src_cfun = DECL_STRUCT_FUNCTION (fn);
   id->call_expr = t;
 
+  gcc_assert (!id->src_cfun->after_inlining);
+
+  id->entry_bb = bb;
   initialize_inlined_parameters (id, t, fn, bb);
 
   if (DECL_INITIAL (fn))
@@ -2631,9 +2802,27 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
   else
     modify_dest = NULL;
 
+  /* If we are inlining a call to the C++ operator new, we don't want
+     to use type based alias analysis on the return value.  Otherwise
+     we may get confused if the compiler sees that the inlined new
+     function returns a pointer which was just deleted.  See bug
+     33407.  */
+  if (DECL_IS_OPERATOR_NEW (fn))
+    {
+      return_slot = NULL;
+      modify_dest = NULL;
+    }
+
   /* Declare the return variable for the function.  */
-  declare_return_variable (id, return_slot,
-                          modify_dest, &use_retvar);
+  retvar = declare_return_variable (id, return_slot,
+                                   modify_dest, &use_retvar);
+
+  if (DECL_IS_OPERATOR_NEW (fn))
+    {
+      gcc_assert (TREE_CODE (retvar) == VAR_DECL
+                 && POINTER_TYPE_P (TREE_TYPE (retvar)));
+      DECL_NO_TBAA_P (retvar) = 1;
+    }
 
   /* This is it.  Duplicate the callee body.  Assume callee is
      pre-gimplified.  Note that we must not alter the caller
@@ -2771,11 +2960,17 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
          if (pointer_set_contains (statements, bsi_stmt (bsi)))
            {
              tree old_stmt = bsi_stmt (bsi);
+             tree old_call = get_call_expr_in (old_stmt);
+
              if (fold_stmt (bsi_stmt_ptr (bsi)))
                {
                  update_stmt (bsi_stmt (bsi));
-                 if (maybe_clean_or_replace_eh_stmt (old_stmt, bsi_stmt (bsi)))
-                    tree_purge_dead_eh_edges (BASIC_BLOCK (first));
+                 if (old_call)
+                   cgraph_update_edges_for_call_stmt (old_stmt, old_call,
+                                                      bsi_stmt (bsi));
+                 if (maybe_clean_or_replace_eh_stmt (old_stmt,
+                                                     bsi_stmt (bsi)))
+                   tree_purge_dead_eh_edges (BASIC_BLOCK (first));
                }
            }
       }
@@ -2796,60 +2991,6 @@ has_abnormal_outgoing_edge_p (basic_block bb)
   return false;
 }
 
-/* When a block from the inlined function contains a call with side-effects
-   in the middle gets inlined in a function with non-locals labels, the call
-   becomes a potential non-local goto so we need to add appropriate edge.  */
-
-static void
-make_nonlocal_label_edges (void)
-{
-  block_stmt_iterator bsi;
-  basic_block bb;
-
-  FOR_EACH_BB (bb)
-    {
-      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-       {
-         tree stmt = bsi_stmt (bsi);
-         if (tree_can_make_abnormal_goto (stmt))
-           {
-             if (stmt == bsi_stmt (bsi_last (bb)))
-               {
-                 if (!has_abnormal_outgoing_edge_p (bb))
-                   make_abnormal_goto_edges (bb, true);
-               }
-             else
-               {
-                 edge e = split_block (bb, stmt);
-                 bb = e->src;
-                 make_abnormal_goto_edges (bb, true);
-               }
-             break;
-           }
-
-         /* Update PHIs on nonlocal goto receivers we (possibly)
-            just created new edges into.  */
-         if (TREE_CODE (stmt) == LABEL_EXPR
-             && gimple_in_ssa_p (cfun))
-           {
-             tree target = LABEL_EXPR_LABEL (stmt);
-             if (DECL_NONLOCAL (target))
-               {
-                 tree phi;
-
-                 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-                   {
-                     gcc_assert (SSA_NAME_OCCURS_IN_ABNORMAL_PHI
-                                 (PHI_RESULT (phi)));
-                     mark_sym_for_renaming
-                       (SSA_NAME_VAR (PHI_RESULT (phi)));
-                   }
-               }
-           }
-       }
-    }
-}
-
 /* Expand calls to inline functions in the body of FN.  */
 
 unsigned int
@@ -2928,8 +3069,6 @@ optimize_inline_calls (tree fn)
   cgraph_node_remove_callees (id.dst_node);
 
   fold_cond_expr_cond ();
-  if (current_function_has_nonlocal_label)
-    make_nonlocal_label_edges ();
   /* It would be nice to check SSA/CFG/statement consistency here, but it is
      not possible yet - the IPA passes might make various functions to not
      throw and they don't care to proactively update local EH info.  This is
@@ -3578,10 +3717,13 @@ build_duplicate_type (tree type)
   id.dst_fn = current_function_decl;
   id.src_cfun = cfun;
   id.decl_map = pointer_map_create ();
+  id.copy_decl = copy_decl_no_change;
 
   type = remap_type_1 (type, &id);
 
   pointer_map_destroy (id.decl_map);
 
+  TYPE_CANONICAL (type) = type;
+
   return type;
 }