PR c++/68795: fix uninitialized close_paren_loc in cp_parser_postfix_expression
[gcc.git] / gcc / tree-cfg.c
index 9430151fdf6c23c6ccb5f9e14e78bdaac1d688ba..dbfa506c5d8b53d20aa90a3dcfa724a0d44daa3e 100644 (file)
@@ -1,5 +1,5 @@
 /* Control flow functions for trees.
-   Copyright (C) 2001-2015 Free Software Foundation, Inc.
+   Copyright (C) 2001-2016 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
@@ -21,72 +21,43 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "input.h"
-#include "alias.h"
-#include "symtab.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
 #include "tree.h"
+#include "gimple.h"
+#include "cfghooks.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "cgraph.h"
+#include "gimple-pretty-print.h"
+#include "diagnostic-core.h"
 #include "fold-const.h"
 #include "trans-mem.h"
 #include "stor-layout.h"
 #include "print-tree.h"
-#include "tm_p.h"
-#include "predict.h"
-#include "hard-reg-set.h"
-#include "function.h"
-#include "dominance.h"
-#include "cfg.h"
 #include "cfganal.h"
-#include "basic-block.h"
-#include "flags.h"
-#include "gimple-pretty-print.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
 #include "gimple-fold.h"
 #include "tree-eh.h"
-#include "gimple-expr.h"
-#include "is-a.h"
-#include "gimple.h"
 #include "gimple-iterator.h"
 #include "gimplify-me.h"
 #include "gimple-walk.h"
-#include "gimple-ssa.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
-#include "cgraph.h"
 #include "tree-cfg.h"
-#include "tree-phinodes.h"
-#include "ssa-iterators.h"
-#include "stringpool.h"
-#include "tree-ssanames.h"
 #include "tree-ssa-loop-manip.h"
 #include "tree-ssa-loop-niter.h"
 #include "tree-into-ssa.h"
-#include "rtl.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "tree-dfa.h"
 #include "tree-ssa.h"
-#include "tree-dump.h"
-#include "tree-pass.h"
-#include "diagnostic-core.h"
 #include "except.h"
 #include "cfgloop.h"
 #include "tree-ssa-propagate.h"
 #include "value-prof.h"
 #include "tree-inline.h"
-#include "target.h"
 #include "tree-ssa-live.h"
 #include "omp-low.h"
 #include "tree-cfgcleanup.h"
-#include "wide-int-print.h"
+#include "gimplify.h"
+#include "attribs.h"
 
 /* This file contains functions for building the Control Flow Graph (CFG)
    for a function tree.  */
@@ -125,6 +96,13 @@ struct cfg_stats_d
 
 static struct cfg_stats_d cfg_stats;
 
+/* Data to pass to replace_block_vars_by_duplicates_1.  */
+struct replace_decls_d
+{
+  hash_map<tree, tree> *vars_map;
+  tree to_context;
+};
+
 /* Hash table to store last discriminator assigned for each locus.  */
 struct locus_discrim_map
 {
@@ -134,10 +112,8 @@ struct locus_discrim_map
 
 /* Hashtable helpers.  */
 
-struct locus_discrim_hasher : typed_free_remove <locus_discrim_map>
+struct locus_discrim_hasher : free_ptr_hash <locus_discrim_map>
 {
-  typedef locus_discrim_map *value_type;
-  typedef locus_discrim_map *compare_type;
   static inline hashval_t hash (const locus_discrim_map *);
   static inline bool equal (const locus_discrim_map *,
                            const locus_discrim_map *);
@@ -178,12 +154,12 @@ static edge gimple_redirect_edge_and_branch (edge, basic_block);
 static edge gimple_try_redirect_by_replacing_jump (edge, basic_block);
 
 /* Various helpers.  */
-static inline bool stmt_starts_bb_p (gimple, gimple);
+static inline bool stmt_starts_bb_p (gimple *, gimple *);
 static int gimple_verify_flow_info (void);
 static void gimple_make_forwarder_block (edge);
-static gimple first_non_label_stmt (basic_block);
+static gimple *first_non_label_stmt (basic_block);
 static bool verify_gimple_transaction (gtransaction *);
-static bool call_can_make_abnormal_goto (gimple);
+static bool call_can_make_abnormal_goto (gimple *);
 
 /* Flowgraph optimization and cleanup.  */
 static void gimple_merge_blocks (basic_block, basic_block);
@@ -280,7 +256,7 @@ static void
 replace_loop_annotate_in_block (basic_block bb, struct loop *loop)
 {
   gimple_stmt_iterator gsi = gsi_last_bb (bb);
-  gimple stmt = gsi_stmt (gsi);
+  gimple *stmt = gsi_stmt (gsi);
 
   if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
     return;
@@ -326,7 +302,7 @@ replace_loop_annotate (void)
   struct loop *loop;
   basic_block bb;
   gimple_stmt_iterator gsi;
-  gimple stmt;
+  gimple *stmt;
 
   FOR_EACH_LOOP (loop, 0)
     {
@@ -426,7 +402,7 @@ make_pass_build_cfg (gcc::context *ctxt)
 /* Return true if T is a computed goto.  */
 
 bool
-computed_goto_p (gimple t)
+computed_goto_p (gimple *t)
 {
   return (gimple_code (t) == GIMPLE_GOTO
          && TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL);
@@ -449,7 +425,7 @@ bool
 assert_unreachable_fallthru_edge_p (edge e)
 {
   basic_block pred_bb = e->src;
-  gimple last = last_stmt (pred_bb);
+  gimple *last = last_stmt (pred_bb);
   if (last && gimple_code (last) == GIMPLE_COND)
     {
       basic_block other_bb = EDGE_SUCC (pred_bb, 0)->dest;
@@ -458,7 +434,7 @@ assert_unreachable_fallthru_edge_p (edge e)
       if (EDGE_COUNT (other_bb->succs) == 0)
        {
          gimple_stmt_iterator gsi = gsi_after_labels (other_bb);
-         gimple stmt;
+         gimple *stmt;
 
          if (gsi_end_p (gsi))
            return false;
@@ -482,7 +458,7 @@ assert_unreachable_fallthru_edge_p (edge e)
    CFG build time and only ever clear it later.  */
 
 static void
-gimple_call_initialize_ctrl_altering (gimple stmt)
+gimple_call_initialize_ctrl_altering (gimple *stmt)
 {
   int flags = gimple_call_flags (stmt);
 
@@ -496,7 +472,11 @@ gimple_call_initialize_ctrl_altering (gimple stmt)
       || ((flags & ECF_TM_BUILTIN)
          && is_tm_ending_fndecl (gimple_call_fndecl (stmt)))
       /* BUILT_IN_RETURN call is same as return statement.  */
-      || gimple_call_builtin_p (stmt, BUILT_IN_RETURN))
+      || gimple_call_builtin_p (stmt, BUILT_IN_RETURN)
+      /* IFN_UNIQUE should be the last insn, to make checking for it
+        as cheap as possible.  */
+      || (gimple_call_internal_p (stmt)
+         && gimple_call_internal_unique_p (stmt)))
     gimple_call_set_ctrl_altering (stmt, true);
   else
     gimple_call_set_ctrl_altering (stmt, false);
@@ -509,13 +489,13 @@ static basic_block
 make_blocks_1 (gimple_seq seq, basic_block bb)
 {
   gimple_stmt_iterator i = gsi_start (seq);
-  gimple stmt = NULL;
+  gimple *stmt = NULL;
   bool start_new_block = true;
   bool first_stmt_of_seq = true;
 
   while (!gsi_end_p (i))
     {
-      gimple prev_stmt;
+      gimple *prev_stmt;
 
       prev_stmt = stmt;
       stmt = gsi_stmt (i);
@@ -553,7 +533,7 @@ make_blocks_1 (gimple_seq seq, basic_block bb)
            {
              tree lhs = gimple_get_lhs (stmt);
              tree tmp = create_tmp_var (TREE_TYPE (lhs));
-             gimple s = gimple_build_assign (lhs, tmp);
+             gimple *s = gimple_build_assign (lhs, tmp);
              gimple_set_location (s, gimple_location (stmt));
              gimple_set_block (s, gimple_block (stmt));
              gimple_set_lhs (stmt, tmp);
@@ -624,48 +604,6 @@ create_bb (void *h, void *e, basic_block after)
                                 Edge creation
 ---------------------------------------------------------------------------*/
 
-/* Fold COND_EXPR_COND of each COND_EXPR.  */
-
-void
-fold_cond_expr_cond (void)
-{
-  basic_block bb;
-
-  FOR_EACH_BB_FN (bb, cfun)
-    {
-      gimple stmt = last_stmt (bb);
-
-      if (stmt && gimple_code (stmt) == GIMPLE_COND)
-       {
-         gcond *cond_stmt = as_a <gcond *> (stmt);
-         location_t loc = gimple_location (stmt);
-         tree cond;
-         bool zerop, onep;
-
-         fold_defer_overflow_warnings ();
-         cond = fold_binary_loc (loc, gimple_cond_code (cond_stmt),
-                                 boolean_type_node,
-                                 gimple_cond_lhs (cond_stmt),
-                                 gimple_cond_rhs (cond_stmt));
-         if (cond)
-           {
-             zerop = integer_zerop (cond);
-             onep = integer_onep (cond);
-           }
-         else
-           zerop = onep = false;
-
-         fold_undefer_overflow_warnings (zerop || onep,
-                                         stmt,
-                                         WARN_STRICT_OVERFLOW_CONDITIONAL);
-         if (zerop)
-           gimple_cond_make_false (cond_stmt);
-         else if (onep)
-           gimple_cond_make_true (cond_stmt);
-       }
-    }
-}
-
 /* If basic block BB has an abnormal edge to a basic block
    containing IFN_ABNORMAL_DISPATCHER internal call, return
    that the dispatcher's basic block, otherwise return NULL.  */
@@ -681,7 +619,7 @@ get_abnormal_succ_dispatcher (basic_block bb)
       {
        gimple_stmt_iterator gsi
          = gsi_start_nondebug_after_labels_bb (e->dest);
-       gimple g = gsi_stmt (gsi);
+       gimple *g = gsi_stmt (gsi);
        if (g
            && is_gimple_call (g)
            && gimple_call_internal_p (g)
@@ -753,12 +691,12 @@ handle_abnormal_edges (basic_block *dispatcher_bbs,
             factored computed goto.  */
          tree factored_label_decl
            = create_artificial_label (UNKNOWN_LOCATION);
-         gimple factored_computed_goto_label
+         gimple *factored_computed_goto_label
            = gimple_build_label (factored_label_decl);
          gsi_insert_after (&gsi, factored_computed_goto_label, GSI_NEW_STMT);
 
          /* Build our new computed goto.  */
-         gimple factored_computed_goto = gimple_build_goto (var);
+         gimple *factored_computed_goto = gimple_build_goto (var);
          gsi_insert_after (&gsi, factored_computed_goto, GSI_NEW_STMT);
 
          FOR_EACH_VEC_ELT (*bbs, idx, bb)
@@ -768,12 +706,12 @@ handle_abnormal_edges (basic_block *dispatcher_bbs,
                continue;
 
              gsi = gsi_last_bb (bb);
-             gimple last = gsi_stmt (gsi);
+             gimple *last = gsi_stmt (gsi);
 
              gcc_assert (computed_goto_p (last));
 
              /* Copy the original computed goto's destination into VAR.  */
-             gimple assignment
+             gimple *assignment
                = gimple_build_assign (var, gimple_goto_dest (last));
              gsi_insert_before (&gsi, assignment, GSI_SAME_STMT);
 
@@ -785,7 +723,7 @@ handle_abnormal_edges (basic_block *dispatcher_bbs,
       else
        {
          tree arg = inner ? boolean_true_node : boolean_false_node;
-         gimple g = gimple_build_call_internal (IFN_ABNORMAL_DISPATCHER,
+         gimple *g = gimple_build_call_internal (IFN_ABNORMAL_DISPATCHER,
                                                 1, arg);
          gimple_stmt_iterator gsi = gsi_after_labels (*dispatcher);
          gsi_insert_after (&gsi, g, GSI_NEW_STMT);
@@ -812,7 +750,7 @@ handle_abnormal_edges (basic_block *dispatcher_bbs,
 static int
 make_edges_bb (basic_block bb, struct omp_region **pcur_region, int *pomp_index)
 {
-  gimple last = last_stmt (bb);
+  gimple *last = last_stmt (bb);
   bool fallthru = false;
   int ret = 0;
 
@@ -890,11 +828,22 @@ make_edges_bb (basic_block bb, struct omp_region **pcur_region, int *pomp_index)
 
     case GIMPLE_TRANSACTION:
       {
-       tree abort_label
-         = gimple_transaction_label (as_a <gtransaction *> (last));
-       if (abort_label)
-         make_edge (bb, label_to_block (abort_label), EDGE_TM_ABORT);
-       fallthru = true;
+        gtransaction *txn = as_a <gtransaction *> (last);
+       tree label1 = gimple_transaction_label_norm (txn);
+       tree label2 = gimple_transaction_label_uninst (txn);
+
+       if (label1)
+         make_edge (bb, label_to_block (label1), EDGE_FALLTHRU);
+       if (label2)
+         make_edge (bb, label_to_block (label2),
+                    EDGE_TM_UNINSTRUMENTED | (label1 ? 0 : EDGE_FALLTHRU));
+
+       tree label3 = gimple_transaction_label_over (txn);
+       if (gimple_transaction_subcode (txn)
+           & (GTMA_HAVE_ABORT | GTMA_IS_OUTER))
+         make_edge (bb, label_to_block (label3), EDGE_TM_ABORT);
+
+       fallthru = false;
       }
       break;
 
@@ -1001,7 +950,7 @@ make_edges (void)
          if (!gsi_end_p (gsi))
            {
              /* Make an edge to every setjmp-like call.  */
-             gimple call_stmt = gsi_stmt (gsi);
+             gimple *call_stmt = gsi_stmt (gsi);
              if (is_gimple_call (call_stmt)
                  && ((gimple_call_flags (call_stmt) & ECF_RETURNS_TWICE)
                      || gimple_call_builtin_p (call_stmt,
@@ -1018,9 +967,6 @@ make_edges (void)
   XDELETE (bb_to_omp_idx);
 
   free_omp_regions ();
-
-  /* Fold COND_EXPR_COND of each COND_EXPR.  */
-  fold_cond_expr_cond ();
 }
 
 /* Add SEQ after GSI.  Start new bb after GSI, and created further bbs as
@@ -1033,7 +979,7 @@ make_edges (void)
 bool
 gimple_find_sub_bbs (gimple_seq seq, gimple_stmt_iterator *gsi)
 {
-  gimple stmt = gsi_stmt (*gsi);
+  gimple *stmt = gsi_stmt (*gsi);
   basic_block bb = gimple_bb (stmt);
   basic_block lastbb, afterbb;
   int old_num_bbs = n_basic_blocks_for_fn (cfun);
@@ -1120,7 +1066,7 @@ assign_discriminators (void)
     {
       edge e;
       edge_iterator ei;
-      gimple last = last_stmt (bb);
+      gimple *last = last_stmt (bb);
       location_t locus = last ? gimple_location (last) : UNKNOWN_LOCATION;
 
       if (locus == UNKNOWN_LOCATION)
@@ -1128,8 +1074,8 @@ assign_discriminators (void)
 
       FOR_EACH_EDGE (e, ei, bb->succs)
        {
-         gimple first = first_non_label_stmt (e->dest);
-         gimple last = last_stmt (e->dest);
+         gimple *first = first_non_label_stmt (e->dest);
+         gimple *last = last_stmt (e->dest);
          if ((first && same_line_p (locus, gimple_location (first)))
              || (last && same_line_p (locus, gimple_location (last))))
            {
@@ -1148,7 +1094,7 @@ static void
 make_cond_expr_edges (basic_block bb)
 {
   gcond *entry = as_a <gcond *> (last_stmt (bb));
-  gimple then_stmt, else_stmt;
+  gimple *then_stmt, *else_stmt;
   basic_block then_bb, else_bb;
   tree then_label, else_label;
   edge e;
@@ -1230,7 +1176,7 @@ end_recording_case_labels (void)
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
       if (bb)
        {
-         gimple stmt = last_stmt (bb);
+         gimple *stmt = last_stmt (bb);
          if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
            group_case_labels_stmt (as_a <gswitch *> (stmt));
        }
@@ -1312,7 +1258,7 @@ label_to_block_fn (struct function *ifun, tree dest)
     {
       gimple_stmt_iterator gsi =
        gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, NUM_FIXED_BLOCKS));
-      gimple stmt;
+      gimple *stmt;
 
       stmt = gimple_build_label (dest);
       gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
@@ -1330,7 +1276,7 @@ static bool
 make_goto_expr_edges (basic_block bb)
 {
   gimple_stmt_iterator last = gsi_last_bb (bb);
-  gimple goto_t = gsi_stmt (last);
+  gimple *goto_t = gsi_stmt (last);
 
   /* A simple GOTO creates normal edges.  */
   if (simple_goto_p (goto_t))
@@ -1507,7 +1453,7 @@ cleanup_dead_labels (void)
      First do so for each block ending in a control statement.  */
   FOR_EACH_BB_FN (bb, cfun)
     {
-      gimple stmt = last_stmt (bb);
+      gimple *stmt = last_stmt (bb);
       tree label, new_label;
 
       if (!stmt)
@@ -1582,13 +1528,30 @@ cleanup_dead_labels (void)
 
        case GIMPLE_TRANSACTION:
          {
-           gtransaction *trans_stmt = as_a <gtransaction *> (stmt);
-           tree label = gimple_transaction_label (trans_stmt);
+           gtransaction *txn = as_a <gtransaction *> (stmt);
+
+           label = gimple_transaction_label_norm (txn);
+           if (label)
+             {
+               new_label = main_block_label (label);
+               if (new_label != label)
+                 gimple_transaction_set_label_norm (txn, new_label);
+             }
+
+           label = gimple_transaction_label_uninst (txn);
+           if (label)
+             {
+               new_label = main_block_label (label);
+               if (new_label != label)
+                 gimple_transaction_set_label_uninst (txn, new_label);
+             }
+
+           label = gimple_transaction_label_over (txn);
            if (label)
              {
-               tree new_label = main_block_label (label);
+               new_label = main_block_label (label);
                if (new_label != label)
-                 gimple_transaction_set_label (trans_stmt, new_label);
+                 gimple_transaction_set_label_over (txn, new_label);
              }
          }
          break;
@@ -1730,7 +1693,7 @@ group_case_labels (void)
 
   FOR_EACH_BB_FN (bb, cfun)
     {
-      gimple stmt = last_stmt (bb);
+      gimple *stmt = last_stmt (bb);
       if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
        group_case_labels_stmt (as_a <gswitch *> (stmt));
     }
@@ -1741,7 +1704,7 @@ group_case_labels (void)
 static bool
 gimple_can_merge_blocks_p (basic_block a, basic_block b)
 {
-  gimple stmt;
+  gimple *stmt;
 
   if (!single_succ_p (a))
     return false;
@@ -1835,7 +1798,7 @@ replace_uses_by (tree name, tree val)
 {
   imm_use_iterator imm_iter;
   use_operand_p use;
-  gimple stmt;
+  gimple *stmt;
   edge e;
 
   FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
@@ -1868,7 +1831,7 @@ replace_uses_by (tree name, tree val)
       if (gimple_code (stmt) != GIMPLE_PHI)
        {
          gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
-         gimple orig_stmt = stmt;
+         gimple *orig_stmt = stmt;
          size_t i;
 
          /* FIXME.  It shouldn't be required to keep TREE_CONSTANT
@@ -1926,9 +1889,9 @@ gimple_merge_blocks (basic_block a, basic_block b)
   gsi = gsi_last_bb (a);
   for (psi = gsi_start_phis (b); !gsi_end_p (psi); )
     {
-      gimple phi = gsi_stmt (psi);
+      gimple *phi = gsi_stmt (psi);
       tree def = gimple_phi_result (phi), use = gimple_phi_arg_def (phi, 0);
-      gimple copy;
+      gimple *copy;
       bool may_replace_uses = (virtual_operand_p (def)
                               || may_propagate_copy (def, use));
 
@@ -1962,7 +1925,7 @@ gimple_merge_blocks (basic_block a, basic_block b)
            {
              imm_use_iterator iter;
              use_operand_p use_p;
-             gimple stmt;
+             gimple *stmt;
 
              FOR_EACH_IMM_USE_STMT (stmt, iter, def)
                FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
@@ -1987,7 +1950,7 @@ gimple_merge_blocks (basic_block a, basic_block b)
   /* Remove labels from B and set gimple_bb to A for other statements.  */
   for (gsi = gsi_start_bb (b); !gsi_end_p (gsi);)
     {
-      gimple stmt = gsi_stmt (gsi);
+      gimple *stmt = gsi_stmt (gsi);
       if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
        {
          tree label = gimple_label_label (label_stmt);
@@ -2009,9 +1972,9 @@ gimple_merge_blocks (basic_block a, basic_block b)
          /* Other user labels keep around in a form of a debug stmt.  */
          else if (!DECL_ARTIFICIAL (label) && MAY_HAVE_DEBUG_STMTS)
            {
-             gimple dbg = gimple_build_debug_bind (label,
-                                                   integer_zero_node,
-                                                   stmt);
+             gimple *dbg = gimple_build_debug_bind (label,
+                                                    integer_zero_node,
+                                                    stmt);
              gimple_debug_bind_reset_value (dbg);
              gsi_insert_before (&gsi, dbg, GSI_SAME_STMT);
            }
@@ -2147,7 +2110,7 @@ remove_bb (basic_block bb)
         details.  */
       for (i = gsi_last_bb (bb); !gsi_end_p (i);)
        {
-         gimple stmt = gsi_stmt (i);
+         gimple *stmt = gsi_stmt (i);
          glabel *label_stmt = dyn_cast <glabel *> (stmt);
          if (label_stmt
              && (FORCED_LABEL (gimple_label_label (label_stmt))
@@ -2202,7 +2165,7 @@ remove_bb (basic_block bb)
 edge
 find_taken_edge (basic_block bb, tree val)
 {
-  gimple stmt;
+  gimple *stmt;
 
   stmt = last_stmt (bb);
 
@@ -2460,7 +2423,7 @@ debug_cfg_stats (void)
    flow.  Transfers of control flow associated with EH are excluded.  */
 
 static bool
-call_can_make_abnormal_goto (gimple t)
+call_can_make_abnormal_goto (gimple *t)
 {
   /* If the function has no non-local labels, then a call cannot make an
      abnormal transfer of control.  */
@@ -2484,7 +2447,7 @@ call_can_make_abnormal_goto (gimple t)
    Transfers of control flow associated with EH are excluded.  */
 
 bool
-stmt_can_make_abnormal_goto (gimple t)
+stmt_can_make_abnormal_goto (gimple *t)
 {
   if (computed_goto_p (t))
     return true;
@@ -2497,7 +2460,7 @@ stmt_can_make_abnormal_goto (gimple t)
 /* Return true if T represents a stmt that always transfers control.  */
 
 bool
-is_ctrl_stmt (gimple t)
+is_ctrl_stmt (gimple *t)
 {
   switch (gimple_code (t))
     {
@@ -2517,7 +2480,7 @@ is_ctrl_stmt (gimple t)
    (e.g., a call to a non-returning function).  */
 
 bool
-is_ctrl_altering_stmt (gimple t)
+is_ctrl_altering_stmt (gimple *t)
 {
   gcc_assert (t);
 
@@ -2561,7 +2524,7 @@ is_ctrl_altering_stmt (gimple t)
 /* Return true if T is a simple local goto.  */
 
 bool
-simple_goto_p (gimple t)
+simple_goto_p (gimple *t)
 {
   return (gimple_code (t) == GIMPLE_GOTO
          && TREE_CODE (gimple_goto_dest (t)) == LABEL_DECL);
@@ -2576,7 +2539,7 @@ simple_goto_p (gimple t)
    label.  */
 
 static inline bool
-stmt_starts_bb_p (gimple stmt, gimple prev_stmt)
+stmt_starts_bb_p (gimple *stmt, gimple *prev_stmt)
 {
   if (stmt == NULL)
     return false;
@@ -2616,7 +2579,7 @@ stmt_starts_bb_p (gimple stmt, gimple prev_stmt)
 /* Return true if T should end a basic block.  */
 
 bool
-stmt_ends_bb_p (gimple t)
+stmt_ends_bb_p (gimple *t)
 {
   return is_ctrl_stmt (t) || is_ctrl_altering_stmt (t);
 }
@@ -2624,19 +2587,36 @@ stmt_ends_bb_p (gimple t)
 /* Remove block annotations and other data structures.  */
 
 void
-delete_tree_cfg_annotations (void)
+delete_tree_cfg_annotations (struct function *fn)
 {
-  vec_free (label_to_block_map_for_fn (cfun));
+  vec_free (label_to_block_map_for_fn (fn));
 }
 
+/* Return the virtual phi in BB.  */
+
+gphi *
+get_virtual_phi (basic_block bb)
+{
+  for (gphi_iterator gsi = gsi_start_phis (bb);
+       !gsi_end_p (gsi);
+       gsi_next (&gsi))
+    {
+      gphi *phi = gsi.phi ();
+
+      if (virtual_operand_p (PHI_RESULT (phi)))
+       return phi;
+    }
+
+  return NULL;
+}
 
 /* Return the first statement in basic block BB.  */
 
-gimple
+gimple *
 first_stmt (basic_block bb)
 {
   gimple_stmt_iterator i = gsi_start_bb (bb);
-  gimple stmt = NULL;
+  gimple *stmt = NULL;
 
   while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
     {
@@ -2648,7 +2628,7 @@ first_stmt (basic_block bb)
 
 /* Return the first non-label statement in basic block BB.  */
 
-static gimple
+static gimple *
 first_non_label_stmt (basic_block bb)
 {
   gimple_stmt_iterator i = gsi_start_bb (bb);
@@ -2659,11 +2639,11 @@ first_non_label_stmt (basic_block bb)
 
 /* Return the last statement in basic block BB.  */
 
-gimple
+gimple *
 last_stmt (basic_block bb)
 {
   gimple_stmt_iterator i = gsi_last_bb (bb);
-  gimple stmt = NULL;
+  gimple *stmt = NULL;
 
   while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
     {
@@ -2677,11 +2657,11 @@ last_stmt (basic_block bb)
    if the block is totally empty, or if it contains more than one
    statement.  */
 
-gimple
+gimple *
 last_and_only_stmt (basic_block bb)
 {
   gimple_stmt_iterator i = gsi_last_nondebug_bb (bb);
-  gimple last, prev;
+  gimple *last, *prev;
 
   if (gsi_end_p (i))
     return NULL;
@@ -3391,7 +3371,8 @@ verify_gimple_call (gcall *stmt)
   if (lhs
       && gimple_call_ctrl_altering_p (stmt)
       && gimple_call_noreturn_p (stmt)
-      && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST)
+      && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST
+      && !TREE_ADDRESSABLE (TREE_TYPE (lhs)))
     {
       error ("LHS in noreturn call");
       return true;
@@ -3502,10 +3483,10 @@ verify_gimple_comparison (tree type, tree op0, tree op1)
           return true;
         }
     }
-  /* Or an integer vector type with the same size and element count
+  /* Or a boolean vector type with the same element count
      as the comparison operand types.  */
   else if (TREE_CODE (type) == VECTOR_TYPE
-          && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+          && TREE_CODE (TREE_TYPE (type)) == BOOLEAN_TYPE)
     {
       if (TREE_CODE (op0_type) != VECTOR_TYPE
          || TREE_CODE (op1_type) != VECTOR_TYPE)
@@ -3516,12 +3497,7 @@ verify_gimple_comparison (tree type, tree op0, tree op1)
           return true;
         }
 
-      if (TYPE_VECTOR_SUBPARTS (type) != TYPE_VECTOR_SUBPARTS (op0_type)
-         || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type)))
-             != GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0_type))))
-         /* The result of a vector comparison is of signed
-            integral type.  */
-         || TYPE_UNSIGNED (TREE_TYPE (type)))
+      if (TYPE_VECTOR_SUBPARTS (type) != TYPE_VECTOR_SUBPARTS (op0_type))
         {
           error ("invalid vector comparison resulting type");
           debug_generic_expr (type);
@@ -4007,8 +3983,20 @@ verify_gimple_assign_ternary (gassign *stmt)
        }
       break;
 
-    case COND_EXPR:
     case VEC_COND_EXPR:
+      if (!VECTOR_BOOLEAN_TYPE_P (rhs1_type)
+         || TYPE_VECTOR_SUBPARTS (rhs1_type)
+            != TYPE_VECTOR_SUBPARTS (lhs_type))
+       {
+         error ("the first argument of a VEC_COND_EXPR must be of a "
+                "boolean vector type of the same number of elements "
+                "as the result");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs1_type);
+         return true;
+       }
+      /* Fallthrough.  */
+    case COND_EXPR:
       if (!useless_type_conversion_p (lhs_type, rhs2_type)
          || !useless_type_conversion_p (lhs_type, rhs3_type))
        {
@@ -4076,10 +4064,8 @@ verify_gimple_assign_ternary (gassign *stmt)
     case SAD_EXPR:
       if (!useless_type_conversion_p (rhs1_type, rhs2_type)
          || !useless_type_conversion_p (lhs_type, rhs3_type)
-         || 2 * GET_MODE_BITSIZE (GET_MODE_INNER
-                                    (TYPE_MODE (TREE_TYPE (rhs1_type))))
-              > GET_MODE_BITSIZE (GET_MODE_INNER
-                                    (TYPE_MODE (TREE_TYPE (lhs_type)))))
+         || 2 * GET_MODE_UNIT_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1_type)))
+              > GET_MODE_UNIT_BITSIZE (TYPE_MODE (TREE_TYPE (lhs_type))))
        {
          error ("type mismatch in sad expression");
          debug_generic_expr (lhs_type);
@@ -4509,7 +4495,7 @@ verify_gimple_switch (gswitch *stmt)
    Returns true if anything is wrong.  */
 
 static bool
-verify_gimple_debug (gimple stmt ATTRIBUTE_UNUSED)
+verify_gimple_debug (gimple *stmt ATTRIBUTE_UNUSED)
 {
   /* There isn't much that could be wrong in a gimple debug stmt.  A
      gimple debug bind stmt, for example, maps a tree, that's usually
@@ -4591,7 +4577,7 @@ verify_gimple_cond (gcond *stmt)
    error, otherwise false.  */
 
 static bool
-verify_gimple_stmt (gimple stmt)
+verify_gimple_stmt (gimple *stmt)
 {
   switch (gimple_code (stmt))
     {
@@ -4651,7 +4637,7 @@ verify_gimple_stmt (gimple stmt)
    and false otherwise.  */
 
 static bool
-verify_gimple_phi (gimple phi)
+verify_gimple_phi (gimple *phi)
 {
   bool err = false;
   unsigned i;
@@ -4721,7 +4707,7 @@ verify_gimple_in_seq_2 (gimple_seq stmts)
 
   for (ittr = gsi_start (stmts); !gsi_end_p (ittr); gsi_next (&ittr))
     {
-      gimple stmt = gsi_stmt (ittr);
+      gimple *stmt = gsi_stmt (ittr);
 
       switch (gimple_code (stmt))
         {
@@ -4775,9 +4761,18 @@ verify_gimple_in_seq_2 (gimple_seq stmts)
 static bool
 verify_gimple_transaction (gtransaction *stmt)
 {
-  tree lab = gimple_transaction_label (stmt);
+  tree lab;
+
+  lab = gimple_transaction_label_norm (stmt);
   if (lab != NULL && TREE_CODE (lab) != LABEL_DECL)
     return true;
+  lab = gimple_transaction_label_uninst (stmt);
+  if (lab != NULL && TREE_CODE (lab) != LABEL_DECL)
+    return true;
+  lab = gimple_transaction_label_over (stmt);
+  if (lab != NULL && TREE_CODE (lab) != LABEL_DECL)
+    return true;
+
   return verify_gimple_in_seq_2 (gimple_transaction_body (stmt));
 }
 
@@ -4844,8 +4839,8 @@ verify_node_sharing (tree *tp, int *walk_subtrees, void *data)
 
 static bool eh_error_found;
 bool
-verify_eh_throw_stmt_node (const gimple &stmt, const int &,
-                          hash_set<gimple> *visited)
+verify_eh_throw_stmt_node (gimple *const &stmt, const int &,
+                          hash_set<gimple *> *visited)
 {
   if (!visited->contains (stmt))
     {
@@ -4962,7 +4957,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 
   timevar_push (TV_TREE_STMT_VERIFY);
   hash_set<void *> visited;
-  hash_set<gimple> visited_stmts;
+  hash_set<gimple *> visited_stmts;
 
   /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
   hash_set<tree> blocks;
@@ -5035,7 +5030,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
-         gimple stmt = gsi_stmt (gsi);
+         gimple *stmt = gsi_stmt (gsi);
          bool err2 = false;
          struct walk_stmt_info wi;
          tree addr;
@@ -5116,9 +5111,9 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
     }
 
   eh_error_found = false;
-  hash_map<gimple, int> *eh_table = get_eh_throw_stmt_table (cfun);
+  hash_map<gimple *, int> *eh_table = get_eh_throw_stmt_table (cfun);
   if (eh_table)
-    eh_table->traverse<hash_set<gimple> *, verify_eh_throw_stmt_node>
+    eh_table->traverse<hash_set<gimple *> *, verify_eh_throw_stmt_node>
       (&visited_stmts);
 
   if (err || eh_error_found)
@@ -5137,7 +5132,7 @@ gimple_verify_flow_info (void)
   int err = 0;
   basic_block bb;
   gimple_stmt_iterator gsi;
-  gimple stmt;
+  gimple *stmt;
   edge e;
   edge_iterator ei;
 
@@ -5172,7 +5167,7 @@ gimple_verify_flow_info (void)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
          tree label;
-         gimple prev_stmt = stmt;
+         gimple *prev_stmt = stmt;
 
          stmt = gsi_stmt (gsi);
 
@@ -5220,7 +5215,7 @@ gimple_verify_flow_info (void)
       /* Verify that body of basic block BB is free of control flow.  */
       for (; !gsi_end_p (gsi); gsi_next (&gsi))
        {
-         gimple stmt = gsi_stmt (gsi);
+         gimple *stmt = gsi_stmt (gsi);
 
          if (found_ctrl_stmt)
            {
@@ -5528,7 +5523,7 @@ gimple_try_redirect_by_replacing_jump (edge e, basic_block target)
 {
   basic_block src = e->src;
   gimple_stmt_iterator i;
-  gimple stmt;
+  gimple *stmt;
 
   /* We can replace or remove a complex jump only when we have exactly
      two edges.  */
@@ -5565,7 +5560,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
   basic_block bb = e->src;
   gimple_stmt_iterator gsi;
   edge ret;
-  gimple stmt;
+  gimple *stmt;
 
   if (e->flags & EDGE_ABNORMAL)
     return NULL;
@@ -5685,11 +5680,15 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
       break;
 
     case GIMPLE_TRANSACTION:
-      /* The ABORT edge has a stored label associated with it, otherwise
-        the edges are simply redirectable.  */
-      if (e->flags == 0)
-       gimple_transaction_set_label (as_a <gtransaction *> (stmt),
-                                     gimple_block_label (dest));
+      if (e->flags & EDGE_TM_ABORT)
+       gimple_transaction_set_label_over (as_a <gtransaction *> (stmt),
+                                          gimple_block_label (dest));
+      else if (e->flags & EDGE_TM_UNINSTRUMENTED)
+       gimple_transaction_set_label_uninst (as_a <gtransaction *> (stmt),
+                                            gimple_block_label (dest));
+      else
+       gimple_transaction_set_label_norm (as_a <gtransaction *> (stmt),
+                                          gimple_block_label (dest));
       break;
 
     default:
@@ -5753,11 +5752,11 @@ gimple_split_block (basic_block bb, void *stmt)
     e->src = new_bb;
 
   /* Get a stmt iterator pointing to the first stmt to move.  */
-  if (!stmt || gimple_code ((gimple) stmt) == GIMPLE_LABEL)
+  if (!stmt || gimple_code ((gimple *) stmt) == GIMPLE_LABEL)
     gsi = gsi_after_labels (bb);
   else
     {
-      gsi = gsi_for_stmt ((gimple) stmt);
+      gsi = gsi_for_stmt ((gimple *) stmt);
       gsi_next (&gsi);
     }
  
@@ -5818,7 +5817,7 @@ gimple_empty_block_p (basic_block bb)
 static basic_block
 gimple_split_block_before_cond_jump (basic_block bb)
 {
-  gimple last, split_point;
+  gimple *last, *split_point;
   gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
   if (gsi_end_p (gsi))
     return NULL;
@@ -5826,7 +5825,7 @@ gimple_split_block_before_cond_jump (basic_block bb)
   if (gimple_code (last) != GIMPLE_COND
       && gimple_code (last) != GIMPLE_SWITCH)
     return NULL;
-  gsi_prev_nondebug (&gsi);
+  gsi_prev (&gsi);
   split_point = gsi_stmt (gsi);
   return split_block (bb, split_point)->dest;
 }
@@ -5873,7 +5872,7 @@ gimple_duplicate_bb (basic_block bb)
       def_operand_p def_p;
       ssa_op_iter op_iter;
       tree lhs;
-      gimple stmt, copy;
+      gimple *stmt, *copy;
 
       stmt = gsi_stmt (gsi);
       if (gimple_code (stmt) == GIMPLE_LABEL)
@@ -6223,7 +6222,7 @@ gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNU
   gcov_type total_count = 0, exit_count = 0;
   edge exits[2], nexits[2], e;
   gimple_stmt_iterator gsi;
-  gimple cond_stmt;
+  gimple *cond_stmt;
   edge sorig, snew;
   basic_block exit_bb;
   gphi_iterator psi;
@@ -6446,17 +6445,19 @@ replace_ssa_name (tree name, hash_map<tree, tree> *vars_map,
       tree decl = SSA_NAME_VAR (name);
       if (decl)
        {
+         gcc_assert (!SSA_NAME_IS_DEFAULT_DEF (name));
          replace_by_duplicate_decl (&decl, vars_map, to_context);
          new_name = make_ssa_name_fn (DECL_STRUCT_FUNCTION (to_context),
                                       decl, SSA_NAME_DEF_STMT (name));
-         if (SSA_NAME_IS_DEFAULT_DEF (name))
-           set_ssa_default_def (DECL_STRUCT_FUNCTION (to_context),
-                                decl, new_name);
        }
       else
        new_name = copy_ssa_name_fn (DECL_STRUCT_FUNCTION (to_context),
                                     name, SSA_NAME_DEF_STMT (name));
 
+      /* Now that we've used the def stmt to define new_name, make sure it
+        doesn't define name anymore.  */
+      SSA_NAME_DEF_STMT (name) = NULL;
+
       vars_map->put (name, new_name);
     }
   else
@@ -6495,19 +6496,20 @@ move_stmt_op (tree *tp, int *walk_subtrees, void *data)
          || (p->orig_block == NULL_TREE
              && block != NULL_TREE))
        TREE_SET_BLOCK (t, p->new_block);
-#ifdef ENABLE_CHECKING
-      else if (block != NULL_TREE)
+      else if (flag_checking && block != NULL_TREE)
        {
          while (block && TREE_CODE (block) == BLOCK && block != p->orig_block)
            block = BLOCK_SUPERCONTEXT (block);
          gcc_assert (block == p->orig_block);
        }
-#endif
     }
   else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
     {
       if (TREE_CODE (t) == SSA_NAME)
        *tp = replace_ssa_name (t, p->vars_map, p->to_context);
+      else if (TREE_CODE (t) == PARM_DECL
+              && gimple_in_ssa_p (cfun))
+       *tp = *(p->vars_map->get (t));
       else if (TREE_CODE (t) == LABEL_DECL)
        {
          if (p->new_label_map)
@@ -6582,7 +6584,7 @@ move_stmt_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
             struct walk_stmt_info *wi)
 {
   struct move_stmt_d *p = (struct move_stmt_d *) wi->info;
-  gimple stmt = gsi_stmt (*gsi_p);
+  gimple *stmt = gsi_stmt (*gsi_p);
   tree block = gimple_block (stmt);
 
   if (block == p->orig_block
@@ -6759,10 +6761,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
            continue;
          if (d->orig_block == NULL_TREE || block == d->orig_block)
            {
-             if (d->new_block == NULL_TREE)
-               locus = LOCATION_LOCUS (locus);
-             else
-               locus = COMBINE_LOCATION_DATA (line_table, locus, d->new_block);
+             locus = set_block (locus, d->new_block);
              gimple_phi_arg_set_location (phi, i, locus);
            }
        }
@@ -6772,7 +6771,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
 
   for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
     {
-      gimple stmt = gsi_stmt (si);
+      gimple *stmt = gsi_stmt (si);
       struct walk_stmt_info wi;
 
       memset (&wi, 0, sizeof (wi));
@@ -6822,9 +6821,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
        tree block = LOCATION_BLOCK (e->goto_locus);
        if (d->orig_block == NULL_TREE
            || block == d->orig_block)
-         e->goto_locus = d->new_block ?
-             COMBINE_LOCATION_DATA (line_table, e->goto_locus, d->new_block) :
-             LOCATION_LOCUS (e->goto_locus);
+         e->goto_locus = set_block (e->goto_locus, d->new_block);
       }
 }
 
@@ -6839,7 +6836,7 @@ find_outermost_region_in_block (struct function *src_cfun,
 
   for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
     {
-      gimple stmt = gsi_stmt (si);
+      gimple *stmt = gsi_stmt (si);
       eh_region stmt_region;
       int lp_nr;
 
@@ -6885,6 +6882,31 @@ new_label_mapper (tree decl, void *data)
   return m->to;
 }
 
+/* Tree walker to replace the decls used inside value expressions by
+   duplicates.  */
+
+static tree
+replace_block_vars_by_duplicates_1 (tree *tp, int *walk_subtrees, void *data)
+{
+  struct replace_decls_d *rd = (struct replace_decls_d *)data;
+
+  switch (TREE_CODE (*tp))
+    {
+    case VAR_DECL:
+    case PARM_DECL:
+    case RESULT_DECL:
+      replace_by_duplicate_decl (tp, rd->vars_map, rd->to_context);
+      break;
+    default:
+      break;
+    }
+
+  if (IS_TYPE_OR_DECL_P (*tp))
+    *walk_subtrees = false;
+
+  return NULL;
+}
+
 /* Change DECL_CONTEXT of all BLOCK_VARS in block, including
    subblocks.  */
 
@@ -6904,7 +6926,11 @@ replace_block_vars_by_duplicates (tree block, hash_map<tree, tree> *vars_map,
        {
          if (TREE_CODE (*tp) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*tp))
            {
-             SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (*tp));
+             tree x = DECL_VALUE_EXPR (*tp);
+             struct replace_decls_d rd = { vars_map, to_context };
+             unshare_expr (x);
+             walk_tree (&x, replace_block_vars_by_duplicates_1, &rd, NULL);
+             SET_DECL_VALUE_EXPR (t, x);
              DECL_HAS_VALUE_EXPR_P (t) = 1;
            }
          DECL_CHAIN (t) = DECL_CHAIN (*tp);
@@ -6989,6 +7015,19 @@ verify_sese (basic_block entry, basic_block exit, vec<basic_block> *bbs_p)
   BITMAP_FREE (bbs);
 }
 
+/* If FROM is an SSA_NAME, mark the version in bitmap DATA.  */
+
+bool
+gather_ssa_name_hash_map_from (tree const &from, tree const &, void *data)
+{
+  bitmap release_names = (bitmap)data;
+
+  if (TREE_CODE (from) != SSA_NAME)
+    return true;
+
+  bitmap_set_bit (release_names, SSA_NAME_VERSION (from));
+  return true;
+}
 
 /* Move a single-entry, single-exit region delimited by ENTRY_BB and
    EXIT_BB to function DEST_CFUN.  The whole region is replaced by a
@@ -7006,7 +7045,11 @@ verify_sese (basic_block entry, basic_block exit, vec<basic_block> *bbs_p)
 
    All local variables referenced in the region are assumed to be in
    the corresponding BLOCK_VARS and unexpanded variable lists
-   associated with DEST_CFUN.  */
+   associated with DEST_CFUN.
+
+   TODO: investigate whether we can reuse gimple_duplicate_sese_region to
+   reimplement move_sese_region_to_fn by duplicating the region rather than
+   moving it.  */
 
 basic_block
 move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
@@ -7038,9 +7081,9 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
   bbs.create (0);
   bbs.safe_push (entry_bb);
   gather_blocks_in_sese_region (entry_bb, exit_bb, &bbs);
-#ifdef ENABLE_CHECKING
-  verify_sese (entry_bb, exit_bb, &bbs);
-#endif
+
+  if (flag_checking)
+    verify_sese (entry_bb, exit_bb, &bbs);
 
   /* The blocks that used to be dominated by something in BBS will now be
      dominated by the new block.  */
@@ -7182,6 +7225,14 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
   d.eh_map = eh_map;
   d.remap_decls_p = true;
 
+  if (gimple_in_ssa_p (cfun))
+    for (tree arg = DECL_ARGUMENTS (d.to_context); arg; arg = DECL_CHAIN (arg))
+      {
+       tree narg = make_ssa_name_fn (dest_cfun, arg, gimple_build_nop ());
+       set_ssa_default_def (dest_cfun, arg, narg);
+       vars_map.put (arg, narg);
+      }
+
   FOR_EACH_VEC_ELT (bbs, i, bb)
     {
       /* No need to update edge counts on the last block.  It has
@@ -7239,6 +7290,19 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
   if (eh_map)
     delete eh_map;
 
+  if (gimple_in_ssa_p (cfun))
+    {
+      /* We need to release ssa-names in a defined order, so first find them,
+        and then iterate in ascending version order.  */
+      bitmap release_names = BITMAP_ALLOC (NULL);
+      vars_map.traverse<void *, gather_ssa_name_hash_map_from> (release_names);
+      bitmap_iterator bi;
+      unsigned i;
+      EXECUTE_IF_SET_IN_BITMAP (release_names, 0, i, bi)
+       release_ssa_name (ssa_name (i));
+      BITMAP_FREE (release_names);
+    }
+
   /* Rewire the entry and exit blocks.  The successor to the entry
      block turns into the successor of DEST_FN's ENTRY_BLOCK_PTR in
      the child function.  Similarly, the predecessor of DEST_FN's
@@ -7290,6 +7354,23 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
   return bb;
 }
 
+/* Dump default def DEF to file FILE using FLAGS and indentation
+   SPC.  */
+
+static void
+dump_default_def (FILE *file, tree def, int spc, int flags)
+{
+  for (int i = 0; i < spc; ++i)
+    fprintf (file, " ");
+  dump_ssaname_info_to_file (file, def, spc);
+
+  print_generic_expr (file, TREE_TYPE (def), flags);
+  fprintf (file, " ");
+  print_generic_expr (file, def, flags);
+  fprintf (file, " = ");
+  print_generic_expr (file, SSA_NAME_VAR (def), flags);
+  fprintf (file, ";\n");
+}
 
 /* Dump FUNCTION_DECL FN to file FILE using FLAGS (see TDF_* in dumpfile.h)
    */
@@ -7306,6 +7387,30 @@ dump_function_to_file (tree fndecl, FILE *file, int flags)
                  && decl_is_tm_clone (fndecl));
   struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
 
+  if (DECL_ATTRIBUTES (fndecl) != NULL_TREE)
+    {
+      fprintf (file, "__attribute__((");
+
+      bool first = true;
+      tree chain;
+      for (chain = DECL_ATTRIBUTES (fndecl); chain;
+          first = false, chain = TREE_CHAIN (chain))
+       {
+         if (!first)
+           fprintf (file, ", ");
+
+         print_generic_expr (file, get_attribute_name (chain), dump_flags);
+         if (TREE_VALUE (chain) != NULL_TREE)
+           {
+             fprintf (file, " (");
+             print_generic_expr (file, TREE_VALUE (chain), dump_flags);
+             fprintf (file, ")");
+           }
+       }
+
+      fprintf (file, "))\n");
+    }
+
   current_function_decl = fndecl;
   fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
 
@@ -7345,6 +7450,35 @@ dump_function_to_file (tree fndecl, FILE *file, int flags)
       ignore_topmost_bind = true;
 
       fprintf (file, "{\n");
+      if (gimple_in_ssa_p (fun)
+         && (flags & TDF_ALIAS))
+       {
+         for (arg = DECL_ARGUMENTS (fndecl); arg != NULL;
+              arg = DECL_CHAIN (arg))
+           {
+             tree def = ssa_default_def (fun, arg);
+             if (def)
+               dump_default_def (file, def, 2, flags);
+           }
+
+         tree res = DECL_RESULT (fun->decl);
+         if (res != NULL_TREE
+             && DECL_BY_REFERENCE (res))
+           {
+             tree def = ssa_default_def (fun, res);
+             if (def)
+               dump_default_def (file, def, 2, flags);
+           }
+
+         tree static_chain = fun->static_chain_decl;
+         if (static_chain != NULL_TREE)
+           {
+             tree def = ssa_default_def (fun, static_chain);
+             if (def)
+               dump_default_def (file, def, 2, flags);
+           }
+       }
+
       if (!vec_safe_is_empty (fun->local_decls))
        FOR_EACH_LOCAL_DECL (fun, ix, var)
          {
@@ -7600,6 +7734,7 @@ print_loops (FILE *file, int verbosity)
   basic_block bb;
 
   bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+  fprintf (file, "\nLoops in function: %s\n", current_function_name ());
   if (bb && bb->loop_father)
     print_loop_and_siblings (file, bb->loop_father, 0, verbosity);
 }
@@ -7682,7 +7817,7 @@ gimple_block_ends_with_call_p (basic_block bb)
 static bool
 gimple_block_ends_with_condjump_p (const_basic_block bb)
 {
-  gimple stmt = last_stmt (CONST_CAST_BB (bb));
+  gimple *stmt = last_stmt (CONST_CAST_BB (bb));
   return (stmt && gimple_code (stmt) == GIMPLE_COND);
 }
 
@@ -7691,7 +7826,7 @@ gimple_block_ends_with_condjump_p (const_basic_block bb)
    Helper function for gimple_flow_call_edges_add.  */
 
 static bool
-need_fake_edge_p (gimple t)
+need_fake_edge_p (gimple *t)
 {
   tree fndecl = NULL_TREE;
   int call_flags = 0;
@@ -7787,7 +7922,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
     {
       basic_block bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
       gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
-      gimple t = NULL;
+      gimple *t = NULL;
 
       if (!gsi_end_p (gsi))
        t = gsi_stmt (gsi);
@@ -7812,7 +7947,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
     {
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
       gimple_stmt_iterator gsi;
-      gimple stmt, last_stmt;
+      gimple *stmt, *last_stmt;
 
       if (!bb)
        continue;
@@ -7836,13 +7971,11 @@ gimple_flow_call_edges_add (sbitmap blocks)
                     no edge to the exit block in CFG already.
                     Calling make_edge in such case would cause us to
                     mark that edge as fake and remove it later.  */
-#ifdef ENABLE_CHECKING
-                 if (stmt == last_stmt)
+                 if (flag_checking && stmt == last_stmt)
                    {
                      e = find_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun));
                      gcc_assert (e == NULL);
                    }
-#endif
 
                  /* Note that the following may create a new basic block
                     and renumber the existing basic blocks.  */
@@ -8007,7 +8140,7 @@ gimple_purge_dead_eh_edges (basic_block bb)
   bool changed = false;
   edge e;
   edge_iterator ei;
-  gimple stmt = last_stmt (bb);
+  gimple *stmt = last_stmt (bb);
 
   if (stmt && stmt_can_throw_internal (stmt))
     return false;
@@ -8057,7 +8190,7 @@ gimple_purge_dead_abnormal_call_edges (basic_block bb)
   bool changed = false;
   edge e;
   edge_iterator ei;
-  gimple stmt = last_stmt (bb);
+  gimple *stmt = last_stmt (bb);
 
   if (!cfun->has_nonlocal_label
       && !cfun->calls_setjmp)
@@ -8179,7 +8312,7 @@ gimple_lv_add_condition_to_bb (basic_block first_head ATTRIBUTE_UNUSED,
                               basic_block cond_bb, void *cond_e)
 {
   gimple_stmt_iterator gsi;
-  gimple new_cond_expr;
+  gimple *new_cond_expr;
   tree cond_expr = (tree) cond_e;
   edge e0;
 
@@ -8350,7 +8483,7 @@ make_pass_split_crit_edges (gcc::context *ctxt)
    and creation of a new conditionally executed basic block.
    Return created basic block.  */
 basic_block
-insert_cond_bb (basic_block bb, gimple stmt, gimple cond)
+insert_cond_bb (basic_block bb, gimple *stmt, gimple *cond)
 {
   edge fall = split_block (bb, stmt);
   gimple_stmt_iterator iter = gsi_last_bb (bb);
@@ -8460,6 +8593,75 @@ extract_true_false_edges_from_block (basic_block b,
     }
 }
 
+
+/* From a controlling predicate in the immediate dominator DOM of
+   PHIBLOCK determine the edges into PHIBLOCK that are chosen if the
+   predicate evaluates to true and false and store them to
+   *TRUE_CONTROLLED_EDGE and *FALSE_CONTROLLED_EDGE if
+   they are non-NULL.  Returns true if the edges can be determined,
+   else return false.  */
+
+bool
+extract_true_false_controlled_edges (basic_block dom, basic_block phiblock,
+                                    edge *true_controlled_edge,
+                                    edge *false_controlled_edge)
+{
+  basic_block bb = phiblock;
+  edge true_edge, false_edge, tem;
+  edge e0 = NULL, e1 = NULL;
+
+  /* We have to verify that one edge into the PHI node is dominated
+     by the true edge of the predicate block and the other edge
+     dominated by the false edge.  This ensures that the PHI argument
+     we are going to take is completely determined by the path we
+     take from the predicate block.
+     We can only use BB dominance checks below if the destination of
+     the true/false edges are dominated by their edge, thus only
+     have a single predecessor.  */
+  extract_true_false_edges_from_block (dom, &true_edge, &false_edge);
+  tem = EDGE_PRED (bb, 0);
+  if (tem == true_edge
+      || (single_pred_p (true_edge->dest)
+         && (tem->src == true_edge->dest
+             || dominated_by_p (CDI_DOMINATORS,
+                                tem->src, true_edge->dest))))
+    e0 = tem;
+  else if (tem == false_edge
+          || (single_pred_p (false_edge->dest)
+              && (tem->src == false_edge->dest
+                  || dominated_by_p (CDI_DOMINATORS,
+                                     tem->src, false_edge->dest))))
+    e1 = tem;
+  else
+    return false;
+  tem = EDGE_PRED (bb, 1);
+  if (tem == true_edge
+      || (single_pred_p (true_edge->dest)
+         && (tem->src == true_edge->dest
+             || dominated_by_p (CDI_DOMINATORS,
+                                tem->src, true_edge->dest))))
+    e0 = tem;
+  else if (tem == false_edge
+          || (single_pred_p (false_edge->dest)
+              && (tem->src == false_edge->dest
+                  || dominated_by_p (CDI_DOMINATORS,
+                                     tem->src, false_edge->dest))))
+    e1 = tem;
+  else
+    return false;
+  if (!e0 || !e1)
+    return false;
+
+  if (true_controlled_edge)
+    *true_controlled_edge = e0;
+  if (false_controlled_edge)
+    *false_controlled_edge = e1;
+
+  return true;
+}
+
+
+
 /* Emit return warnings.  */
 
 namespace {
@@ -8493,7 +8695,7 @@ unsigned int
 pass_warn_function_return::execute (function *fun)
 {
   source_location location;
-  gimple last;
+  gimple *last;
   edge e;
   edge_iterator ei;
 
@@ -8527,7 +8729,7 @@ pass_warn_function_return::execute (function *fun)
     {
       FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
        {
-         gimple last = last_stmt (e->src);
+         gimple *last = last_stmt (e->src);
          greturn *return_stmt = dyn_cast <greturn *> (last);
          if (return_stmt
              && gimple_return_retval (return_stmt) == NULL
@@ -8565,7 +8767,7 @@ do_warn_unused_result (gimple_seq seq)
 
   for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
     {
-      gimple g = gsi_stmt (i);
+      gimple *g = gsi_stmt (i);
 
       switch (gimple_code (g))
        {
@@ -8695,7 +8897,7 @@ execute_fixup_cfg (void)
       bb->count = apply_scale (bb->count, count_scale);
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
        {
-         gimple stmt = gsi_stmt (gsi);
+         gimple *stmt = gsi_stmt (gsi);
          tree decl = is_gimple_call (stmt)
                      ? gimple_call_fndecl (stmt)
                      : NULL;
@@ -8770,7 +8972,7 @@ execute_fixup_cfg (void)
         when inlining a noreturn call that does in fact return.  */
       if (EDGE_COUNT (bb->succs) == 0)
        {
-         gimple stmt = last_stmt (bb);
+         gimple *stmt = last_stmt (bb);
          if (!stmt
              || (!is_ctrl_stmt (stmt)
                  && (!is_gimple_call (stmt)
@@ -8834,7 +9036,7 @@ make_pass_fixup_cfg (gcc::context *ctxt)
 /* Garbage collection support for edge_def.  */
 
 extern void gt_ggc_mx (tree&);
-extern void gt_ggc_mx (gimple&);
+extern void gt_ggc_mx (gimple *&);
 extern void gt_ggc_mx (rtx&);
 extern void gt_ggc_mx (basic_block&);
 
@@ -8861,7 +9063,7 @@ gt_ggc_mx (edge_def *e)
 /* PCH support for edge_def.  */
 
 extern void gt_pch_nx (tree&);
-extern void gt_pch_nx (gimple&);
+extern void gt_pch_nx (gimple *&);
 extern void gt_pch_nx (rtx&);
 extern void gt_pch_nx (basic_block&);