OSDN Git Service

2011-11-09 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index 9e74f58..d81cc67 100644 (file)
@@ -117,6 +117,7 @@ static int gimple_verify_flow_info (void);
 static void gimple_make_forwarder_block (edge);
 static void gimple_cfg2vcg (FILE *);
 static gimple first_non_label_stmt (basic_block);
+static bool verify_gimple_transaction (gimple);
 
 /* Flowgraph optimization and cleanup.  */
 static void gimple_merge_blocks (basic_block, basic_block);
@@ -261,8 +262,7 @@ struct gimple_opt_pass pass_build_cfg =
   PROP_cfg,                            /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_verify_stmts | TODO_cleanup_cfg
-  | TODO_dump_func                     /* todo_flags_finish */
+  TODO_verify_stmts | TODO_cleanup_cfg  /* todo_flags_finish */
  }
 };
 
@@ -667,6 +667,15 @@ make_edges (void)
                }
              break;
 
+           case GIMPLE_TRANSACTION:
+             {
+               tree abort_label = gimple_transaction_label (last);
+               if (abort_label)
+                 make_edge (bb, label_to_block (abort_label), 0);
+               fallthru = true;
+             }
+             break;
+
            default:
              gcc_assert (!stmt_ends_bb_p (last));
              fallthru = true;
@@ -1197,22 +1206,30 @@ cleanup_dead_labels (void)
   FOR_EACH_BB (bb)
     {
       gimple stmt = last_stmt (bb);
+      tree label, new_label;
+
       if (!stmt)
        continue;
 
       switch (gimple_code (stmt))
        {
        case GIMPLE_COND:
-         {
-           tree true_label = gimple_cond_true_label (stmt);
-           tree false_label = gimple_cond_false_label (stmt);
+         label = gimple_cond_true_label (stmt);
+         if (label)
+           {
+             new_label = main_block_label (label);
+             if (new_label != label)
+               gimple_cond_set_true_label (stmt, new_label);
+           }
 
-           if (true_label)
-             gimple_cond_set_true_label (stmt, main_block_label (true_label));
-           if (false_label)
-             gimple_cond_set_false_label (stmt, main_block_label (false_label));
-           break;
-         }
+         label = gimple_cond_false_label (stmt);
+         if (label)
+           {
+             new_label = main_block_label (label);
+             if (new_label != label)
+               gimple_cond_set_false_label (stmt, new_label);
+           }
+         break;
 
        case GIMPLE_SWITCH:
          {
@@ -1222,8 +1239,10 @@ cleanup_dead_labels (void)
            for (i = 0; i < n; ++i)
              {
                tree case_label = gimple_switch_label (stmt, i);
-               tree label = main_block_label (CASE_LABEL (case_label));
-               CASE_LABEL (case_label) = label;
+               label = CASE_LABEL (case_label);
+               new_label = main_block_label (label);
+               if (new_label != label)
+                 CASE_LABEL (case_label) = new_label;
              }
            break;
          }
@@ -1244,13 +1263,27 @@ cleanup_dead_labels (void)
        /* We have to handle gotos until they're removed, and we don't
           remove them until after we've created the CFG edges.  */
        case GIMPLE_GOTO:
-          if (!computed_goto_p (stmt))
+         if (!computed_goto_p (stmt))
            {
-             tree new_dest = main_block_label (gimple_goto_dest (stmt));
-             gimple_goto_set_dest (stmt, new_dest);
+             label = gimple_goto_dest (stmt);
+             new_label = main_block_label (label);
+             if (new_label != label)
+               gimple_goto_set_dest (stmt, new_label);
            }
          break;
 
+       case GIMPLE_TRANSACTION:
+         {
+           tree label = gimple_transaction_label (stmt);
+           if (label)
+             {
+               tree new_label = main_block_label (label);
+               if (new_label != label)
+                 gimple_transaction_set_label (stmt, new_label);
+             }
+         }
+         break;
+
        default:
          break;
       }
@@ -1422,7 +1455,7 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
   if (!single_succ_p (a))
     return false;
 
-  if (single_succ_edge (a)->flags & (EDGE_ABNORMAL | EDGE_EH))
+  if (single_succ_edge (a)->flags & (EDGE_ABNORMAL | EDGE_EH | EDGE_PRESERVE))
     return false;
 
   if (single_succ (a) != b)
@@ -1455,8 +1488,8 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
        break;
       lab = gimple_label_label (stmt);
 
-      /* Do not remove user labels.  */
-      if (!DECL_ARTIFICIAL (lab))
+      /* Do not remove user forced labels or for -O0 any user labels.  */
+      if (!DECL_ARTIFICIAL (lab) && (!optimize || FORCED_LABEL (lab)))
        return false;
     }
 
@@ -1567,9 +1600,11 @@ replace_uses_by (tree name, tree val)
 
       if (gimple_code (stmt) != GIMPLE_PHI)
        {
+         gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
          size_t i;
 
-         fold_stmt_inplace (stmt);
+         fold_stmt (&gsi);
+         stmt = gsi_stmt (gsi);
          if (cfgcleanup_altered_bbs && !is_gimple_debug (stmt))
            bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
 
@@ -1700,6 +1735,15 @@ gimple_merge_blocks (basic_block a, basic_block b)
              gimple_stmt_iterator dest_gsi = gsi_start_bb (a);
              gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT);
            }
+         /* 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_debug_bind_reset_value (dbg);
+             gsi_insert_before (&gsi, dbg, GSI_SAME_STMT);
+           }
 
          lp_nr = EH_LANDING_PAD_NR (label);
          if (lp_nr)
@@ -2052,11 +2096,7 @@ gimple_dump_cfg (FILE *file, int flags)
 {
   if (flags & TDF_DETAILS)
     {
-      const char *funcname
-       = lang_hooks.decl_printable_name (current_function_decl, 2);
-
-      fputc ('\n', file);
-      fprintf (file, ";; Function %s\n\n", funcname);
+      dump_function_header (file, current_function_decl, flags);
       fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
               n_basic_blocks, n_edges, last_basic_block);
 
@@ -2266,6 +2306,13 @@ is_ctrl_altering_stmt (gimple t)
        if (flags & ECF_NORETURN)
          return true;
 
+       /* TM ending statements have backedges out of the transaction.
+          Return true so we split the basic block containing them.
+          Note that the TM_BUILTIN test is merely an optimization.  */
+       if ((flags & ECF_TM_BUILTIN)
+           && is_tm_ending_fndecl (gimple_call_fndecl (t)))
+         return true;
+
        /* BUILT_IN_RETURN call is same as return statement.  */
        if (gimple_call_builtin_p (t, BUILT_IN_RETURN))
          return true;
@@ -2287,6 +2334,10 @@ is_ctrl_altering_stmt (gimple t)
       /* OpenMP directives alter control flow.  */
       return true;
 
+    case GIMPLE_TRANSACTION:
+      /* A transaction start alters control flow.  */
+      return true;
+
     default:
       break;
     }
@@ -2685,7 +2736,8 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       break;
 
     case NON_LVALUE_EXPR:
-       gcc_unreachable ();
+    case TRUTH_NOT_EXPR:
+      gcc_unreachable ();
 
     CASE_CONVERT:
     case FIX_TRUNC_EXPR:
@@ -2693,7 +2745,6 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
     case NEGATE_EXPR:
     case ABS_EXPR:
     case BIT_NOT_EXPR:
-    case TRUTH_NOT_EXPR:
       CHECK_OP (0, "invalid operand to unary operator");
       break;
 
@@ -2777,13 +2828,11 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
          error ("invalid operand to pointer plus, first operand is not a pointer");
          return t;
        }
-      /* Check to make sure the second operand is an integer with type of
-        sizetype.  */
-      if (!useless_type_conversion_p (sizetype,
-                                    TREE_TYPE (TREE_OPERAND (t, 1))))
+      /* Check to make sure the second operand is a ptrofftype.  */
+      if (!ptrofftype_p (TREE_TYPE (TREE_OPERAND (t, 1))))
        {
          error ("invalid operand to pointer plus, second operand is not an "
-                "integer with type of sizetype");
+                "integer type of appropriate width");
          return t;
        }
       /* FALLTHROUGH */
@@ -3200,23 +3249,55 @@ verify_gimple_comparison (tree type, tree op0, tree op1)
      effective type the comparison is carried out in.  Instead
      we require that either the first operand is trivially
      convertible into the second, or the other way around.
-     The resulting type of a comparison may be any integral type.
      Because we special-case pointers to void we allow
      comparisons of pointers with the same mode as well.  */
-  if ((!useless_type_conversion_p (op0_type, op1_type)
-       && !useless_type_conversion_p (op1_type, op0_type)
-       && (!POINTER_TYPE_P (op0_type)
-          || !POINTER_TYPE_P (op1_type)
-          || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
-      || !INTEGRAL_TYPE_P (type))
-    {
-      error ("type mismatch in comparison expression");
-      debug_generic_expr (type);
+  if (!useless_type_conversion_p (op0_type, op1_type)
+      && !useless_type_conversion_p (op1_type, op0_type)
+      && (!POINTER_TYPE_P (op0_type)
+         || !POINTER_TYPE_P (op1_type)
+         || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
+    {
+      error ("mismatching comparison operand types");
       debug_generic_expr (op0_type);
       debug_generic_expr (op1_type);
       return true;
     }
 
+  /* The resulting type of a comparison may be an effective boolean type.  */
+  if (INTEGRAL_TYPE_P (type)
+      && (TREE_CODE (type) == BOOLEAN_TYPE
+         || TYPE_PRECISION (type) == 1))
+    ;
+  /* Or an integer vector type with the same size and element count
+     as the comparison operand types.  */
+  else if (TREE_CODE (type) == VECTOR_TYPE
+          && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+    {
+      if (TREE_CODE (op0_type) != VECTOR_TYPE
+         || TREE_CODE (op1_type) != VECTOR_TYPE)
+        {
+          error ("non-vector operands in vector comparison");
+          debug_generic_expr (op0_type);
+          debug_generic_expr (op1_type);
+          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)))))
+        {
+          error ("invalid vector comparison resulting type");
+          debug_generic_expr (type);
+          return true;
+        }
+    }
+  else
+    {
+      error ("bogus comparison result type");
+      debug_generic_expr (type);
+      return true;
+    }
+
   return false;
 }
 
@@ -3251,17 +3332,17 @@ verify_gimple_assign_unary (gimple stmt)
       {
        /* Allow conversions between integral types and pointers only if
           there is no sign or zero extension involved.
-          For targets were the precision of sizetype doesn't match that
+          For targets were the precision of ptrofftype doesn't match that
           of pointers we need to allow arbitrary conversions from and
-          to sizetype.  */
+          to ptrofftype.  */
        if ((POINTER_TYPE_P (lhs_type)
             && INTEGRAL_TYPE_P (rhs1_type)
             && (TYPE_PRECISION (lhs_type) >= TYPE_PRECISION (rhs1_type)
-                || rhs1_type == sizetype))
+                || ptrofftype_p (rhs1_type)))
            || (POINTER_TYPE_P (rhs1_type)
                && INTEGRAL_TYPE_P (lhs_type)
                && (TYPE_PRECISION (rhs1_type) >= TYPE_PRECISION (lhs_type)
-                   || lhs_type == sizetype)))
+                   || ptrofftype_p (sizetype))))
          return false;
 
        /* Allow conversion from integer to offset type and vice versa.  */
@@ -3315,7 +3396,9 @@ verify_gimple_assign_unary (gimple stmt)
 
     case FLOAT_EXPR:
       {
-       if (!INTEGRAL_TYPE_P (rhs1_type) || !SCALAR_FLOAT_TYPE_P (lhs_type))
+       if ((!INTEGRAL_TYPE_P (rhs1_type) || !SCALAR_FLOAT_TYPE_P (lhs_type))
+           && (!VECTOR_INTEGER_TYPE_P (rhs1_type)
+               || !VECTOR_FLOAT_TYPE_P(lhs_type)))
          {
            error ("invalid types in conversion to floating point");
            debug_generic_expr (lhs_type);
@@ -3328,7 +3411,9 @@ verify_gimple_assign_unary (gimple stmt)
 
     case FIX_TRUNC_EXPR:
       {
-       if (!INTEGRAL_TYPE_P (lhs_type) || !SCALAR_FLOAT_TYPE_P (rhs1_type))
+        if ((!INTEGRAL_TYPE_P (lhs_type) || !SCALAR_FLOAT_TYPE_P (rhs1_type))
+            && (!VECTOR_INTEGER_TYPE_P (lhs_type)
+                || !VECTOR_FLOAT_TYPE_P(rhs1_type)))
          {
            error ("invalid types in conversion to integer");
            debug_generic_expr (lhs_type);
@@ -3349,16 +3434,6 @@ verify_gimple_assign_unary (gimple stmt)
       /* FIXME.  */
       return false;
 
-    case TRUTH_NOT_EXPR:
-      if (!useless_type_conversion_p (boolean_type_node,  rhs1_type))
-        {
-           error ("invalid types in truth not");
-           debug_generic_expr (lhs_type);
-           debug_generic_expr (rhs1_type);
-           return true;
-        }
-      break;
-
     case NEGATE_EXPR:
     case ABS_EXPR:
     case BIT_NOT_EXPR:
@@ -3493,6 +3568,44 @@ verify_gimple_assign_binary (gimple stmt)
        return false;
       }
 
+    case WIDEN_LSHIFT_EXPR:
+      {
+        if (!INTEGRAL_TYPE_P (lhs_type)
+            || !INTEGRAL_TYPE_P (rhs1_type)
+            || TREE_CODE (rhs2) != INTEGER_CST
+            || (2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)))
+          {
+            error ("type mismatch in widening vector shift expression");
+            debug_generic_expr (lhs_type);
+            debug_generic_expr (rhs1_type);
+            debug_generic_expr (rhs2_type);
+            return true;
+          }
+
+        return false;
+      }
+
+    case VEC_WIDEN_LSHIFT_HI_EXPR:
+    case VEC_WIDEN_LSHIFT_LO_EXPR:
+      {
+        if (TREE_CODE (rhs1_type) != VECTOR_TYPE
+            || TREE_CODE (lhs_type) != VECTOR_TYPE
+            || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
+            || !INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))
+            || TREE_CODE (rhs2) != INTEGER_CST
+            || (2 * TYPE_PRECISION (TREE_TYPE (rhs1_type))
+                > TYPE_PRECISION (TREE_TYPE (lhs_type))))
+          {
+            error ("type mismatch in widening vector shift expression");
+            debug_generic_expr (lhs_type);
+            debug_generic_expr (rhs1_type);
+            debug_generic_expr (rhs2_type);
+            return true;
+          }
+
+        return false;
+      }
+
     case PLUS_EXPR:
     case MINUS_EXPR:
       {
@@ -3538,7 +3651,7 @@ verify_gimple_assign_binary (gimple stmt)
 do_pointer_plus_expr_check:
        if (!POINTER_TYPE_P (rhs1_type)
            || !useless_type_conversion_p (lhs_type, rhs1_type)
-           || !useless_type_conversion_p (sizetype, rhs2_type))
+           || !ptrofftype_p (rhs2_type))
          {
            error ("type mismatch in pointer plus expression");
            debug_generic_stmt (lhs_type);
@@ -3552,26 +3665,11 @@ do_pointer_plus_expr_check:
 
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
-      gcc_unreachable ();
-
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
-      {
-       /* We allow only boolean typed or compatible argument and result.  */
-       if (!useless_type_conversion_p (boolean_type_node,  rhs1_type)
-           || !useless_type_conversion_p (boolean_type_node,  rhs2_type)
-           || !useless_type_conversion_p (boolean_type_node,  lhs_type))
-         {
-           error ("type mismatch in binary truth expression");
-           debug_generic_expr (lhs_type);
-           debug_generic_expr (rhs1_type);
-           debug_generic_expr (rhs2_type);
-           return true;
-         }
 
-       return false;
-      }
+      gcc_unreachable ();
 
     case LT_EXPR:
     case LE_EXPR:
@@ -3594,7 +3692,7 @@ do_pointer_plus_expr_check:
     case WIDEN_MULT_EXPR:
       if (TREE_CODE (lhs_type) != INTEGER_TYPE)
        return true;
-      return ((2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type))
+      return ((2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type))
              || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)));
 
     case WIDEN_SUM_EXPR:
@@ -3668,7 +3766,8 @@ verify_gimple_assign_ternary (gimple stmt)
       return true;
     }
 
-  if (!is_gimple_val (rhs1)
+  if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
+       ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
       || !is_gimple_val (rhs2)
       || !is_gimple_val (rhs3))
     {
@@ -3685,7 +3784,7 @@ verify_gimple_assign_ternary (gimple stmt)
           && !FIXED_POINT_TYPE_P (rhs1_type))
          || !useless_type_conversion_p (rhs1_type, rhs2_type)
          || !useless_type_conversion_p (lhs_type, rhs3_type)
-         || 2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type)
+         || 2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)
          || TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type))
        {
          error ("type mismatch in widening multiply-accumulate expression");
@@ -3711,6 +3810,72 @@ verify_gimple_assign_ternary (gimple stmt)
        }
       break;
 
+    case COND_EXPR:
+    case VEC_COND_EXPR:
+      if (!useless_type_conversion_p (lhs_type, rhs2_type)
+         || !useless_type_conversion_p (lhs_type, rhs3_type))
+       {
+         error ("type mismatch in conditional expression");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs2_type);
+         debug_generic_expr (rhs3_type);
+         return true;
+       }
+      break;
+
+    case VEC_PERM_EXPR:
+      if (!useless_type_conversion_p (lhs_type, rhs1_type)
+         || !useless_type_conversion_p (lhs_type, rhs2_type))
+       {
+         error ("type mismatch in vector permute expression");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs1_type);
+         debug_generic_expr (rhs2_type);
+         debug_generic_expr (rhs3_type);
+         return true;
+       }
+
+      if (TREE_CODE (rhs1_type) != VECTOR_TYPE
+         || TREE_CODE (rhs2_type) != VECTOR_TYPE
+         || TREE_CODE (rhs3_type) != VECTOR_TYPE)
+       {
+         error ("vector types expected in vector permute expression");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs1_type);
+         debug_generic_expr (rhs2_type);
+         debug_generic_expr (rhs3_type);
+         return true;
+       }
+
+      if (TYPE_VECTOR_SUBPARTS (rhs1_type) != TYPE_VECTOR_SUBPARTS (rhs2_type)
+         || TYPE_VECTOR_SUBPARTS (rhs2_type)
+            != TYPE_VECTOR_SUBPARTS (rhs3_type)
+         || TYPE_VECTOR_SUBPARTS (rhs3_type)
+            != TYPE_VECTOR_SUBPARTS (lhs_type))
+       {
+         error ("vectors with different element number found "
+                "in vector permute expression");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs1_type);
+         debug_generic_expr (rhs2_type);
+         debug_generic_expr (rhs3_type);
+         return true;
+       }
+
+      if (TREE_CODE (TREE_TYPE (rhs3_type)) != INTEGER_TYPE
+         || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs3_type)))
+            != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1_type))))
+       {
+         error ("invalid mask type in vector permute expression");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs1_type);
+         debug_generic_expr (rhs2_type);
+         debug_generic_expr (rhs3_type);
+         return true;
+       }
+
+      return false;
+
     case DOT_PROD_EXPR:
     case REALIGN_LOAD_EXPR:
       /* FIXME.  */
@@ -3827,26 +3992,10 @@ verify_gimple_assign_single (gimple stmt)
        }
       return res;
 
-    case COND_EXPR:
-      if (!is_gimple_reg (lhs)
-         || (!is_gimple_reg (TREE_OPERAND (rhs1, 0))
-             && !COMPARISON_CLASS_P (TREE_OPERAND (rhs1, 0)))
-         || (!is_gimple_reg (TREE_OPERAND (rhs1, 1))
-             && !is_gimple_min_invariant (TREE_OPERAND (rhs1, 1)))
-         || (!is_gimple_reg (TREE_OPERAND (rhs1, 2))
-             && !is_gimple_min_invariant (TREE_OPERAND (rhs1, 2))))
-       {
-         error ("invalid COND_EXPR in gimple assignment");
-         debug_generic_stmt (rhs1);
-         return true;
-       }
-      return res;
-
     case CONSTRUCTOR:
     case OBJ_TYPE_REF:
     case ASSERT_EXPR:
     case WITH_SIZE_EXPR:
-    case VEC_COND_EXPR:
       /* FIXME.  */
       return res;
 
@@ -3959,7 +4108,6 @@ verify_gimple_switch (gimple stmt)
   return false;
 }
 
-
 /* Verify a gimple debug statement STMT.
    Returns true if anything is wrong.  */
 
@@ -4060,6 +4208,9 @@ verify_gimple_stmt (gimple stmt)
     case GIMPLE_ASM:
       return false;
 
+    case GIMPLE_TRANSACTION:
+      return verify_gimple_transaction (stmt);
+
     /* Tuples that do not have tree operands.  */
     case GIMPLE_NOP:
     case GIMPLE_PREDICT:
@@ -4176,10 +4327,19 @@ verify_gimple_in_seq_2 (gimple_seq stmts)
          err |= verify_gimple_in_seq_2 (gimple_eh_filter_failure (stmt));
          break;
 
+       case GIMPLE_EH_ELSE:
+         err |= verify_gimple_in_seq_2 (gimple_eh_else_n_body (stmt));
+         err |= verify_gimple_in_seq_2 (gimple_eh_else_e_body (stmt));
+         break;
+
        case GIMPLE_CATCH:
          err |= verify_gimple_in_seq_2 (gimple_catch_handler (stmt));
          break;
 
+       case GIMPLE_TRANSACTION:
+         err |= verify_gimple_transaction (stmt);
+         break;
+
        default:
          {
            bool err2 = verify_gimple_stmt (stmt);
@@ -4193,6 +4353,18 @@ verify_gimple_in_seq_2 (gimple_seq stmts)
   return err;
 }
 
+/* Verify the contents of a GIMPLE_TRANSACTION.  Returns true if there
+   is a problem, otherwise false.  */
+
+static bool
+verify_gimple_transaction (gimple stmt)
+{
+  tree lab = gimple_transaction_label (stmt);
+  if (lab != NULL && TREE_CODE (lab) != LABEL_DECL)
+    return true;
+  return verify_gimple_in_seq_2 (gimple_transaction_body (stmt));
+}
+
 
 /* Verify the GIMPLE statements inside the statement list STMTS.  */
 
@@ -4957,6 +5129,13 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
        redirect_eh_dispatch_edge (stmt, e, 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 (stmt, gimple_block_label (dest));
+      break;
+
     default:
       /* Otherwise it must be a fallthru edge, and we don't need to
         do anything besides redirecting it.  */
@@ -5106,11 +5285,18 @@ gimple_duplicate_bb (basic_block bb)
     {
       def_operand_p def_p;
       ssa_op_iter op_iter;
+      tree lhs;
 
       stmt = gsi_stmt (gsi);
       if (gimple_code (stmt) == GIMPLE_LABEL)
        continue;
 
+      /* Don't duplicate label debug stmts.  */
+      if (gimple_debug_bind_p (stmt)
+         && TREE_CODE (gimple_debug_bind_get_var (stmt))
+            == LABEL_DECL)
+       continue;
+
       /* Create a new copy of STMT and duplicate STMT's virtual
         operands.  */
       copy = gimple_copy (stmt);
@@ -5119,6 +5305,24 @@ gimple_duplicate_bb (basic_block bb)
       maybe_duplicate_eh_stmt (copy, stmt);
       gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt);
 
+      /* When copying around a stmt writing into a local non-user
+        aggregate, make sure it won't share stack slot with other
+        vars.  */
+      lhs = gimple_get_lhs (stmt);
+      if (lhs && TREE_CODE (lhs) != SSA_NAME)
+       {
+         tree base = get_base_address (lhs);
+         if (base
+             && (TREE_CODE (base) == VAR_DECL
+                 || TREE_CODE (base) == RESULT_DECL)
+             && DECL_IGNORED_P (base)
+             && !TREE_STATIC (base)
+             && !DECL_EXTERNAL (base)
+             && (TREE_CODE (base) != VAR_DECL
+                 || !DECL_HAS_VALUE_EXPR_P (base)))
+           DECL_NONSHAREABLE (base) = 1;
+       }
+
       /* Create new names for all the definitions created by COPY and
         add replacement mappings for each new name.  */
       FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_ALL_DEFS)
@@ -5409,12 +5613,10 @@ gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNU
   int total_freq = 0, exit_freq = 0;
   gcov_type total_count = 0, exit_count = 0;
   edge exits[2], nexits[2], e;
-  gimple_stmt_iterator gsi,gsi1;
+  gimple_stmt_iterator gsi;
   gimple cond_stmt;
   edge sorig, snew;
   basic_block exit_bb;
-  basic_block iters_bb;
-  tree new_rhs;
   gimple_stmt_iterator psi;
   gimple phi;
   tree def;
@@ -5495,35 +5697,6 @@ gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNU
   gcc_assert (gimple_code (cond_stmt) == GIMPLE_COND);
   cond_stmt = gimple_copy (cond_stmt);
 
- /* If the block consisting of the exit condition has the latch as
-    successor, then the body of the loop is executed before
-    the exit condition is tested.  In such case, moving the
-    condition to the entry, causes that the loop will iterate
-    one less iteration (which is the wanted outcome, since we
-    peel out the last iteration).  If the body is executed after
-    the condition, moving the condition to the entry requires
-    decrementing one iteration.  */
-  if (exits[1]->dest == orig_loop->latch)
-    new_rhs = gimple_cond_rhs (cond_stmt);
-  else
-  {
-    new_rhs = fold_build2 (MINUS_EXPR, TREE_TYPE (gimple_cond_rhs (cond_stmt)),
-                          gimple_cond_rhs (cond_stmt),
-                          build_int_cst (TREE_TYPE (gimple_cond_rhs (cond_stmt)), 1));
-
-    if (TREE_CODE (gimple_cond_rhs (cond_stmt)) == SSA_NAME)
-      {
-       iters_bb = gimple_bb (SSA_NAME_DEF_STMT (gimple_cond_rhs (cond_stmt)));
-       for (gsi1 = gsi_start_bb (iters_bb); !gsi_end_p (gsi1); gsi_next (&gsi1))
-         if (gsi_stmt (gsi1) == SSA_NAME_DEF_STMT (gimple_cond_rhs (cond_stmt)))
-           break;
-
-       new_rhs = force_gimple_operand_gsi (&gsi1, new_rhs, true,
-                                           NULL_TREE,false,GSI_CONTINUE_LINKING);
-      }
-  }
-  gimple_cond_set_rhs (cond_stmt, unshare_expr (new_rhs));
-  gimple_cond_set_lhs (cond_stmt, unshare_expr (gimple_cond_lhs (cond_stmt)));
   gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
 
   sorig = single_succ_edge (switch_bb);
@@ -6345,8 +6518,10 @@ dump_function_to_file (tree fn, FILE *file, int flags)
   bool ignore_topmost_bind = false, any_var = false;
   basic_block bb;
   tree chain;
+  bool tmclone = TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn);
 
-  fprintf (file, "%s (", lang_hooks.decl_printable_name (fn, 2));
+  fprintf (file, "%s %s(", lang_hooks.decl_printable_name (fn, 2),
+          tmclone ? "[tm-clone] " : "");
 
   arg = DECL_ARGUMENTS (fn);
   while (arg)
@@ -7250,7 +7425,7 @@ struct gimple_opt_pass pass_split_crit_edges =
   PROP_no_crit_edges,            /* properties_provided */
   0,                             /* properties_destroyed */
   0,                             /* todo_flags_start */
-  TODO_dump_func | TODO_verify_flow  /* todo_flags_finish */
+  TODO_verify_flow               /* todo_flags_finish */
  }
 };
 
@@ -7537,4 +7712,3 @@ struct gimple_opt_pass pass_warn_unused_result =
     0,                                 /* todo_flags_finish */
   }
 };
-