OSDN Git Service

PR c++/43787
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index 7f1dc4a..8f7ff89 100644 (file)
@@ -1,6 +1,6 @@
 /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
    tree representation into the GIMPLE form.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Major work done by Sebastian Pop <s.pop@laposte.net>,
    Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
@@ -27,7 +27,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "tree.h"
 #include "rtl.h"
-#include "varray.h"
 #include "gimple.h"
 #include "tree-iterator.h"
 #include "tree-inline.h"
@@ -508,6 +507,23 @@ create_tmp_var (tree type, const char *prefix)
   return tmp_var;
 }
 
+/* Create a new temporary variable declaration of type TYPE by calling
+   create_tmp_var and if TYPE is a vector or a complex number, mark the new
+   temporary as gimple register.  */
+
+tree
+create_tmp_reg (tree type, const char *prefix)
+{
+  tree tmp;
+
+  tmp = create_tmp_var (type, prefix);
+  if (TREE_CODE (type) == COMPLEX_TYPE
+      || TREE_CODE (type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (tmp) = 1;
+
+  return tmp;
+}
+
 /* Create a temporary with a name derived from VAL.  Subroutine of
    lookup_tmp_var; nobody else should call this function.  */
 
@@ -777,23 +793,6 @@ should_carry_location_p (gimple gs)
   return true;
 }
 
-/* Same, but for a tree.  */
-
-static bool
-tree_should_carry_location_p (const_tree stmt)
-{
-  /* Don't emit a line note for a label.  We particularly don't want to
-     emit one for the break label, since it doesn't actually correspond
-     to the beginning of the loop/switch.  */
-  if (TREE_CODE (stmt) == LABEL_EXPR)
-    return false;
-
-  /* Do not annotate empty statements, since it confuses gcov.  */
-  if (!TREE_SIDE_EFFECTS (stmt))
-    return false;
-
-  return true;
-}
 
 /* Return true if a location should not be emitted for this statement
    by annotate_one_with_location.  */
@@ -820,22 +819,12 @@ gimple_set_do_not_emit_location (gimple g)
 static void
 annotate_one_with_location (gimple gs, location_t location)
 {
-  if (!gimple_has_location (gs) 
+  if (!gimple_has_location (gs)
       && !gimple_do_not_emit_location_p (gs)
       && should_carry_location_p (gs))
     gimple_set_location (gs, location);
 }
 
-/* Same, but for tree T.  */
-
-static void
-tree_annotate_one_with_location (tree t, location_t location)
-{
-  if (CAN_HAVE_LOCATION_P (t)
-      && ! EXPR_HAS_LOCATION (t) && tree_should_carry_location_p (t))
-    SET_EXPR_LOCATION (t, location);
-}
-
 
 /* Set LOCATION for all the statements after iterator GSI in sequence
    SEQ.  If GSI is pointing to the end of the sequence, start with the
@@ -872,29 +861,6 @@ annotate_all_with_location (gimple_seq stmt_p, location_t location)
     }
 }
 
-/* Same, but for statement or statement list in *STMT_P.  */
-
-void
-tree_annotate_all_with_location (tree *stmt_p, location_t location)
-{
-  tree_stmt_iterator i;
-
-  if (!*stmt_p)
-    return;
-
-  for (i = tsi_start (*stmt_p); !tsi_end_p (i); tsi_next (&i))
-    {
-      tree t = tsi_stmt (i);
-
-      /* Assuming we've already been gimplified, we shouldn't
-         see nested chaining constructs anymore.  */
-      gcc_assert (TREE_CODE (t) != STATEMENT_LIST
-                 && TREE_CODE (t) != COMPOUND_EXPR);
-
-      tree_annotate_one_with_location (t, location);
-    }
-}
-
 
 /* Similar to copy_tree_r() but do not copy SAVE_EXPR or TARGET_EXPR nodes.
    These nodes model computations that should only be done once.  If we
@@ -1269,10 +1235,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
     result = gimplify_ctxp->return_temp;
   else
     {
-      result = create_tmp_var (TREE_TYPE (result_decl), NULL);
-      if (TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
-          || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
-        DECL_GIMPLE_REG_P (result) = 1;
+      result = create_tmp_reg (TREE_TYPE (result_decl), NULL);
 
       /* ??? With complex control flow (usually involving abnormal edges),
         we can wind up warning about an uninitialized value for this.  Due
@@ -1495,12 +1458,12 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
       tree default_case = NULL_TREE;
       size_t i, len;
       gimple gimple_switch;
-      
+
       /* If someone can be bothered to fill in the labels, they can
         be bothered to null out the body too.  */
       gcc_assert (!SWITCH_LABELS (switch_expr));
 
-      /* save old labels, get new ones from body, then restore the old 
+      /* save old labels, get new ones from body, then restore the old
          labels.  Save all the things from the switch body to append after.  */
       saved_labels = gimplify_ctxp->case_labels;
       gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8);
@@ -1508,7 +1471,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
       gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
       labels = gimplify_ctxp->case_labels;
       gimplify_ctxp->case_labels = saved_labels;
+
       i = 0;
       while (i < VEC_length (tree, labels))
        {
@@ -1597,7 +1560,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
            }
        }
 
-      gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr), 
+      gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr),
                                                default_case, labels);
       gimplify_seq_add_stmt (pre_p, gimple_switch);
       gimplify_seq_add_seq (pre_p, switch_body_seq);
@@ -1843,7 +1806,7 @@ gimplify_conversion (tree *expr_p)
 /* Nonlocal VLAs seen in the current function.  */
 static struct pointer_set_t *nonlocal_vlas;
 
-/* Gimplify a VAR_DECL or PARM_DECL.  Returns GS_OK if we expanded a 
+/* Gimplify a VAR_DECL or PARM_DECL.  Returns GS_OK if we expanded a
    DECL_VALUE_EXPR, and it's worth re-examining things.  */
 
 static enum gimplify_status
@@ -1963,7 +1926,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        goto restart;
       else
        break;
-              
+
       VEC_safe_push (tree, heap, stack, *p);
     }
 
@@ -2322,7 +2285,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
              *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
              return GS_OK;
            }
-         
+
          if (fold_builtin_next_arg (*expr_p, true))
            {
              *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
@@ -2770,6 +2733,36 @@ gimple_boolify (tree expr)
   tree type = TREE_TYPE (expr);
   location_t loc = EXPR_LOCATION (expr);
 
+  if (TREE_CODE (expr) == NE_EXPR
+      && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
+      && integer_zerop (TREE_OPERAND (expr, 1)))
+    {
+      tree call = TREE_OPERAND (expr, 0);
+      tree fn = get_callee_fndecl (call);
+
+      /* For __builtin_expect ((long) (x), y) recurse into x as well
+        if x is truth_value_p.  */
+      if (fn
+         && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
+         && DECL_FUNCTION_CODE (fn) == BUILT_IN_EXPECT
+         && call_expr_nargs (call) == 2)
+       {
+         tree arg = CALL_EXPR_ARG (call, 0);
+         if (arg)
+           {
+             if (TREE_CODE (arg) == NOP_EXPR
+                 && TREE_TYPE (arg) == TREE_TYPE (call))
+               arg = TREE_OPERAND (arg, 0);
+             if (truth_value_p (TREE_CODE (arg)))
+               {
+                 arg = gimple_boolify (arg);
+                 CALL_EXPR_ARG (call, 0)
+                   = fold_convert_loc (loc, TREE_TYPE (call), arg);
+               }
+           }
+       }
+    }
+
   if (TREE_CODE (type) == BOOLEAN_TYPE)
     return expr;
 
@@ -2873,71 +2866,67 @@ static enum gimplify_status
 gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
 {
   tree expr = *expr_p;
-  tree tmp, type, arm1, arm2;
+  tree type = TREE_TYPE (expr);
+  location_t loc = EXPR_LOCATION (expr);
+  tree tmp, arm1, arm2;
   enum gimplify_status ret;
   tree label_true, label_false, label_cont;
   bool have_then_clause_p, have_else_clause_p;
   gimple gimple_cond;
   enum tree_code pred_code;
   gimple_seq seq = NULL;
-  location_t loc = EXPR_LOCATION (*expr_p);
-
-  type = TREE_TYPE (expr);
 
   /* If this COND_EXPR has a value, copy the values into a temporary within
      the arms.  */
-  if (! VOID_TYPE_P (type))
+  if (!VOID_TYPE_P (type))
     {
+      tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
       tree result;
 
-      /* If an rvalue is ok or we do not require an lvalue, avoid creating
-        an addressable temporary.  */
-      if (((fallback & fb_rvalue)
-          || !(fallback & fb_lvalue))
+      /* If either an rvalue is ok or we do not require an lvalue, create the
+        temporary.  But we cannot do that if the type is addressable.  */
+      if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
          && !TREE_ADDRESSABLE (type))
        {
          if (gimplify_ctxp->allow_rhs_cond_expr
              /* If either branch has side effects or could trap, it can't be
                 evaluated unconditionally.  */
-             && !TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1))
-             && !generic_expr_could_trap_p (TREE_OPERAND (*expr_p, 1))
-             && !TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 2))
-             && !generic_expr_could_trap_p (TREE_OPERAND (*expr_p, 2)))
+             && !TREE_SIDE_EFFECTS (then_)
+             && !generic_expr_could_trap_p (then_)
+             && !TREE_SIDE_EFFECTS (else_)
+             && !generic_expr_could_trap_p (else_))
            return gimplify_pure_cond_expr (expr_p, pre_p);
 
-         result = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
-         ret = GS_ALL_DONE;
+         tmp = create_tmp_var (type, "iftmp");
+         result = tmp;
        }
+
+      /* Otherwise, only create and copy references to the values.  */
       else
        {
-         tree type = build_pointer_type (TREE_TYPE (expr));
+         type = build_pointer_type (type);
 
-         if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node)
-           TREE_OPERAND (expr, 1) =
-             build_fold_addr_expr_loc (loc, TREE_OPERAND (expr, 1));
+         if (!VOID_TYPE_P (TREE_TYPE (then_)))
+           then_ = build_fold_addr_expr_loc (loc, then_);
 
-         if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
-           TREE_OPERAND (expr, 2) =
-             build_fold_addr_expr_loc (loc, TREE_OPERAND (expr, 2));
+         if (!VOID_TYPE_P (TREE_TYPE (else_)))
+           else_ = build_fold_addr_expr_loc (loc, else_);
+         expr
+           = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
 
          tmp = create_tmp_var (type, "iftmp");
-
-         expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (expr, 0),
-                        TREE_OPERAND (expr, 1), TREE_OPERAND (expr, 2));
-
          result = build_fold_indirect_ref_loc (loc, tmp);
        }
 
-      /* Build the then clause, 't1 = a;'.  But don't build an assignment
-        if this branch is void; in C++ it can be, if it's a throw.  */
-      if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node)
-       TREE_OPERAND (expr, 1)
-         = build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, TREE_OPERAND (expr, 1));
+      /* Build the new then clause, `tmp = then_;'.  But don't build the
+        assignment if the value is void; in C++ it can be if it's a throw.  */
+      if (!VOID_TYPE_P (TREE_TYPE (then_)))
+       TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, then_);
 
-      /* Build the else clause, 't1 = b;'.  */
-      if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
-       TREE_OPERAND (expr, 2)
-         = build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, TREE_OPERAND (expr, 2));
+      /* Similarly, build the new else clause, `tmp = else_;'.  */
+      if (!VOID_TYPE_P (TREE_TYPE (else_)))
+       TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, else_);
 
       TREE_TYPE (expr) = void_type_node;
       recalculate_side_effects (expr);
@@ -3175,7 +3164,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
   /* Assert our assumptions, to abort instead of producing wrong code
      silently if they are not met.  Beware that the RHS CONSTRUCTOR might
      not be immediately exposed.  */
-  from = TREE_OPERAND (*expr_p, 1);  
+  from = TREE_OPERAND (*expr_p, 1);
   if (TREE_CODE (from) == WITH_SIZE_EXPR)
     from = TREE_OPERAND (from, 0);
 
@@ -3408,18 +3397,18 @@ gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
 }
 
 /* Return true if FDECL is accessing a field that is zero sized.  */
-   
+
 static bool
 zero_sized_field_decl (const_tree fdecl)
 {
-  if (TREE_CODE (fdecl) == FIELD_DECL && DECL_SIZE (fdecl) 
+  if (TREE_CODE (fdecl) == FIELD_DECL && DECL_SIZE (fdecl)
       && integer_zerop (DECL_SIZE (fdecl)))
     return true;
   return false;
 }
 
 /* Return true if TYPE is zero sized.  */
-   
+
 static bool
 zero_sized_type (const_tree type)
 {
@@ -3666,7 +3655,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              return GS_OK;
            break;
          }
+
        /* Fetch information about the constructor to direct later processing.
           We might want to make static versions of it in various cases, and
           can only do so if it known to be a valid constant initializer.  */
@@ -3768,25 +3757,11 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                && num_nonzero_elements > 1
                && !can_move_by_pieces (size, align))
              {
-               tree new_tree;
-
                if (notify_temp_creation)
                  return GS_ERROR;
 
-               new_tree = create_tmp_var_raw (type, "C");
-
-               gimple_add_tmp_var (new_tree);
-               TREE_STATIC (new_tree) = 1;
-               TREE_READONLY (new_tree) = 1;
-               DECL_INITIAL (new_tree) = ctor;
-               if (align > DECL_ALIGN (new_tree))
-                 {
-                   DECL_ALIGN (new_tree) = align;
-                   DECL_USER_ALIGN (new_tree) = 1;
-                 }
-               walk_tree (&DECL_INITIAL (new_tree), force_labels_r, NULL, NULL);
-
-               TREE_OPERAND (*expr_p, 1) = new_tree;
+               walk_tree (&ctor, force_labels_r, NULL, NULL);
+               TREE_OPERAND (*expr_p, 1) = tree_output_constant_def (ctor);
 
                /* This is no longer an assignment of a CONSTRUCTOR, but
                   we still may have processing to do on the LHS.  So
@@ -3795,13 +3770,28 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              }
          }
 
+       /* If the target is volatile and we have non-zero elements
+          initialize the target from a temporary.  */
+       if (TREE_THIS_VOLATILE (object)
+           && !TREE_ADDRESSABLE (type)
+           && num_nonzero_elements > 0)
+         {
+           tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type), NULL);
+           TREE_OPERAND (*expr_p, 0) = temp;
+           *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
+                             *expr_p,
+                             build2 (MODIFY_EXPR, void_type_node,
+                                     object, temp));
+           return GS_OK;
+         }
+
        if (notify_temp_creation)
          return GS_OK;
 
-       /* If there are nonzero elements, pre-evaluate to capture elements
-          overlapping with the lhs into temporaries.  We must do this before
-          clearing to fetch the values before they are zeroed-out.  */
-       if (num_nonzero_elements > 0)
+       /* If there are nonzero elements and if needed, pre-evaluate to capture
+          elements overlapping with the lhs into temporaries.  We must do this
+          before clearing to fetch the values before they are zeroed-out.  */
+       if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
          {
            preeval_data.lhs_base_decl = get_base_address (object);
            if (!DECL_P (preeval_data.lhs_base_decl))
@@ -3970,7 +3960,7 @@ gimple_fold_indirect_ref (tree t)
   tree sub = t;
   tree subtype;
 
-  STRIP_USELESS_TYPE_CONVERSION (sub);
+  STRIP_NOPS (sub);
   subtype = TREE_TYPE (sub);
   if (!POINTER_TYPE_P (subtype))
     return NULL_TREE;
@@ -3985,18 +3975,80 @@ gimple_fold_indirect_ref (tree t)
 
       /* *(foo *)&fooarray => fooarray[0] */
       if (TREE_CODE (optype) == ARRAY_TYPE
+         && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST
          && useless_type_conversion_p (type, TREE_TYPE (optype)))
        {
          tree type_domain = TYPE_DOMAIN (optype);
          tree min_val = size_zero_node;
          if (type_domain && TYPE_MIN_VALUE (type_domain))
            min_val = TYPE_MIN_VALUE (type_domain);
-         return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+        if (TREE_CODE (min_val) == INTEGER_CST)
+          return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
        }
+      /* *(foo *)&complexfoo => __real__ complexfoo */
+      else if (TREE_CODE (optype) == COMPLEX_TYPE
+               && useless_type_conversion_p (type, TREE_TYPE (optype)))
+        return fold_build1 (REALPART_EXPR, type, op);
+      /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
+      else if (TREE_CODE (optype) == VECTOR_TYPE
+               && useless_type_conversion_p (type, TREE_TYPE (optype)))
+        {
+          tree part_width = TYPE_SIZE (type);
+          tree index = bitsize_int (0);
+          return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
+        }
+    }
+
+  /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+  if (TREE_CODE (sub) == POINTER_PLUS_EXPR
+      && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+    {
+      tree op00 = TREE_OPERAND (sub, 0);
+      tree op01 = TREE_OPERAND (sub, 1);
+      tree op00type;
+
+      STRIP_NOPS (op00);
+      op00type = TREE_TYPE (op00);
+      if (TREE_CODE (op00) == ADDR_EXPR
+         && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
+         && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
+       {
+         HOST_WIDE_INT offset = tree_low_cst (op01, 0);
+         tree part_width = TYPE_SIZE (type);
+         unsigned HOST_WIDE_INT part_widthi
+           = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
+         unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+         tree index = bitsize_int (indexi);
+         if (offset / part_widthi
+             <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
+           return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
+                               part_width, index);
+       }
+    }
+
+  /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+  if (TREE_CODE (sub) == POINTER_PLUS_EXPR
+      && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+    {
+      tree op00 = TREE_OPERAND (sub, 0);
+      tree op01 = TREE_OPERAND (sub, 1);
+      tree op00type;
+
+      STRIP_NOPS (op00);
+      op00type = TREE_TYPE (op00);
+      if (TREE_CODE (op00) == ADDR_EXPR
+         && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
+         && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
+       {
+         tree size = TYPE_SIZE_UNIT (type);
+         if (tree_int_cst_equal (size, op01))
+           return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
+       }
     }
 
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
+      && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST
       && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     {
       tree type_domain;
@@ -4008,7 +4060,8 @@ gimple_fold_indirect_ref (tree t)
       type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
       if (type_domain && TYPE_MIN_VALUE (type_domain))
         min_val = TYPE_MIN_VALUE (type_domain);
-      return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
+      if (TREE_CODE (min_val) == INTEGER_CST)
+       return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
     }
 
   return NULL_TREE;
@@ -4036,241 +4089,252 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
                          gimple_seq *pre_p, gimple_seq *post_p,
                          bool want_value)
 {
-  enum gimplify_status ret = GS_OK;
+  enum gimplify_status ret = GS_UNHANDLED;
+  bool changed;
 
-  while (ret != GS_UNHANDLED)
-    switch (TREE_CODE (*from_p))
-      {
-      case VAR_DECL:
-       /* If we're assigning from a read-only variable initialized with
-          a constructor, do the direct assignment from the constructor,
-          but only if neither source nor target are volatile since this
-          latter assignment might end up being done on a per-field basis.  */
-       if (DECL_INITIAL (*from_p)
-           && TREE_READONLY (*from_p)
-           && !TREE_THIS_VOLATILE (*from_p)
-           && !TREE_THIS_VOLATILE (*to_p)
-           && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR)
+  do
+    {
+      changed = false;
+      switch (TREE_CODE (*from_p))
+       {
+       case VAR_DECL:
+         /* If we're assigning from a read-only variable initialized with
+            a constructor, do the direct assignment from the constructor,
+            but only if neither source nor target are volatile since this
+            latter assignment might end up being done on a per-field basis.  */
+         if (DECL_INITIAL (*from_p)
+             && TREE_READONLY (*from_p)
+             && !TREE_THIS_VOLATILE (*from_p)
+             && !TREE_THIS_VOLATILE (*to_p)
+             && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR)
+           {
+             tree old_from = *from_p;
+             enum gimplify_status subret;
+
+             /* Move the constructor into the RHS.  */
+             *from_p = unshare_expr (DECL_INITIAL (*from_p));
+
+             /* Let's see if gimplify_init_constructor will need to put
+                it in memory.  */
+             subret = gimplify_init_constructor (expr_p, NULL, NULL,
+                                                 false, true);
+             if (subret == GS_ERROR)
+               {
+                 /* If so, revert the change.  */
+                 *from_p = old_from;
+               }
+             else
+               {
+                 ret = GS_OK;
+                 changed = true;
+               }
+           }
+         break;
+       case INDIRECT_REF:
          {
-           tree old_from = *from_p;
+           /* If we have code like
 
-           /* Move the constructor into the RHS.  */
-           *from_p = unshare_expr (DECL_INITIAL (*from_p));
+            *(const A*)(A*)&x
 
-           /* Let's see if gimplify_init_constructor will need to put
-              it in memory.  If so, revert the change.  */
-           ret = gimplify_init_constructor (expr_p, NULL, NULL, false, true);
-           if (ret == GS_ERROR)
+            where the type of "x" is a (possibly cv-qualified variant
+            of "A"), treat the entire expression as identical to "x".
+            This kind of code arises in C++ when an object is bound
+            to a const reference, and if "x" is a TARGET_EXPR we want
+            to take advantage of the optimization below.  */
+           tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
+           if (t)
              {
-               *from_p = old_from;
-               /* Fall through.  */
+               *from_p = t;
+               ret = GS_OK;
+               changed = true;
              }
-           else
+           break;
+         }
+
+       case TARGET_EXPR:
+         {
+           /* If we are initializing something from a TARGET_EXPR, strip the
+              TARGET_EXPR and initialize it directly, if possible.  This can't
+              be done if the initializer is void, since that implies that the
+              temporary is set in some non-trivial way.
+
+              ??? What about code that pulls out the temp and uses it
+              elsewhere? I think that such code never uses the TARGET_EXPR as
+              an initializer.  If I'm wrong, we'll die because the temp won't
+              have any RTL.  In that case, I guess we'll need to replace
+              references somehow.  */
+           tree init = TARGET_EXPR_INITIAL (*from_p);
+
+           if (init
+               && !VOID_TYPE_P (TREE_TYPE (init)))
              {
+               *from_p = init;
                ret = GS_OK;
-               break;
+               changed = true;
              }
          }
-       ret = GS_UNHANDLED;
-       break;
-      case INDIRECT_REF:
-       {
-         /* If we have code like 
+         break;
 
-               *(const A*)(A*)&x
+       case COMPOUND_EXPR:
+         /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
+            caught.  */
+         gimplify_compound_expr (from_p, pre_p, true);
+         ret = GS_OK;
+         changed = true;
+         break;
 
-            where the type of "x" is a (possibly cv-qualified variant
-            of "A"), treat the entire expression as identical to "x".
-            This kind of code arises in C++ when an object is bound
-            to a const reference, and if "x" is a TARGET_EXPR we want
-            to take advantage of the optimization below.  */
-         tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
-         if (t)
+       case CONSTRUCTOR:
+         /* If we're initializing from a CONSTRUCTOR, break this into
+            individual MODIFY_EXPRs.  */
+         return gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
+                                           false);
+
+       case COND_EXPR:
+         /* If we're assigning to a non-register type, push the assignment
+            down into the branches.  This is mandatory for ADDRESSABLE types,
+            since we cannot generate temporaries for such, but it saves a
+            copy in other cases as well.  */
+         if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
            {
-             *from_p = t;
-             ret = GS_OK;
+             /* This code should mirror the code in gimplify_cond_expr. */
+             enum tree_code code = TREE_CODE (*expr_p);
+             tree cond = *from_p;
+             tree result = *to_p;
+
+             ret = gimplify_expr (&result, pre_p, post_p,
+                                  is_gimple_lvalue, fb_lvalue);
+             if (ret != GS_ERROR)
+               ret = GS_OK;
+
+             if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
+               TREE_OPERAND (cond, 1)
+                 = build2 (code, void_type_node, result,
+                           TREE_OPERAND (cond, 1));
+             if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
+               TREE_OPERAND (cond, 2)
+                 = build2 (code, void_type_node, unshare_expr (result),
+                           TREE_OPERAND (cond, 2));
+
+             TREE_TYPE (cond) = void_type_node;
+             recalculate_side_effects (cond);
+
+             if (want_value)
+               {
+                 gimplify_and_add (cond, pre_p);
+                 *expr_p = unshare_expr (result);
+               }
+             else
+               *expr_p = cond;
+             return ret;
            }
-         else
-           ret = GS_UNHANDLED;
          break;
-       }
 
-      case TARGET_EXPR:
-       {
-         /* If we are initializing something from a TARGET_EXPR, strip the
-            TARGET_EXPR and initialize it directly, if possible.  This can't
-            be done if the initializer is void, since that implies that the
-            temporary is set in some non-trivial way.
-
-            ??? What about code that pulls out the temp and uses it
-            elsewhere? I think that such code never uses the TARGET_EXPR as
-            an initializer.  If I'm wrong, we'll die because the temp won't
-            have any RTL.  In that case, I guess we'll need to replace
-            references somehow.  */
-         tree init = TARGET_EXPR_INITIAL (*from_p);
-
-         if (init
-             && !VOID_TYPE_P (TREE_TYPE (init)))
+       case CALL_EXPR:
+         /* For calls that return in memory, give *to_p as the CALL_EXPR's
+            return slot so that we don't generate a temporary.  */
+         if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
+             && aggregate_value_p (*from_p, *from_p))
            {
-             *from_p = init;
-             ret = GS_OK;
+             bool use_target;
+
+             if (!(rhs_predicate_for (*to_p))(*from_p))
+               /* If we need a temporary, *to_p isn't accurate.  */
+               use_target = false;
+             else if (TREE_CODE (*to_p) == RESULT_DECL
+                      && DECL_NAME (*to_p) == NULL_TREE
+                      && needs_to_live_in_memory (*to_p))
+               /* It's OK to use the return slot directly unless it's an NRV. */
+               use_target = true;
+             else if (is_gimple_reg_type (TREE_TYPE (*to_p))
+                      || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
+               /* Don't force regs into memory.  */
+               use_target = false;
+             else if (TREE_CODE (*expr_p) == INIT_EXPR)
+               /* It's OK to use the target directly if it's being
+                  initialized. */
+               use_target = true;
+             else if (!is_gimple_non_addressable (*to_p))
+               /* Don't use the original target if it's already addressable;
+                  if its address escapes, and the called function uses the
+                  NRV optimization, a conforming program could see *to_p
+                  change before the called function returns; see c++/19317.
+                  When optimizing, the return_slot pass marks more functions
+                  as safe after we have escape info.  */
+               use_target = false;
+             else
+               use_target = true;
+
+             if (use_target)
+               {
+                 CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
+                 mark_addressable (*to_p);
+               }
            }
-         else
-           ret = GS_UNHANDLED;
-       }
-       break;
+         break;
 
-      case COMPOUND_EXPR:
-       /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
-          caught.  */
-       gimplify_compound_expr (from_p, pre_p, true);
-       ret = GS_OK;
-       break;
+       case WITH_SIZE_EXPR:
+         /* Likewise for calls that return an aggregate of non-constant size,
+            since we would not be able to generate a temporary at all.  */
+         if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
+           {
+             *from_p = TREE_OPERAND (*from_p, 0);
+             ret = GS_OK;
+             changed = true;
+           }
+         break;
 
-      case CONSTRUCTOR:
-       /* If we're initializing from a CONSTRUCTOR, break this into
-          individual MODIFY_EXPRs.  */
-       return gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
-                                         false);
-
-      case COND_EXPR:
-       /* If we're assigning to a non-register type, push the assignment
-          down into the branches.  This is mandatory for ADDRESSABLE types,
-          since we cannot generate temporaries for such, but it saves a
-          copy in other cases as well.  */
-       if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
+         /* If we're initializing from a container, push the initialization
+            inside it.  */
+       case CLEANUP_POINT_EXPR:
+       case BIND_EXPR:
+       case STATEMENT_LIST:
          {
-           /* This code should mirror the code in gimplify_cond_expr. */
-           enum tree_code code = TREE_CODE (*expr_p);
-           tree cond = *from_p;
-           tree result = *to_p;
+           tree wrap = *from_p;
+           tree t;
 
-           ret = gimplify_expr (&result, pre_p, post_p,
-                                is_gimple_lvalue, fb_lvalue);
+           ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
+                                fb_lvalue);
            if (ret != GS_ERROR)
              ret = GS_OK;
 
-           if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
-             TREE_OPERAND (cond, 1)
-               = build2 (code, void_type_node, result,
-                         TREE_OPERAND (cond, 1));
-           if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
-             TREE_OPERAND (cond, 2)
-               = build2 (code, void_type_node, unshare_expr (result),
-                         TREE_OPERAND (cond, 2));
-
-           TREE_TYPE (cond) = void_type_node;
-           recalculate_side_effects (cond);
+           t = voidify_wrapper_expr (wrap, *expr_p);
+           gcc_assert (t == *expr_p);
 
            if (want_value)
              {
-               gimplify_and_add (cond, pre_p);
-               *expr_p = unshare_expr (result);
+               gimplify_and_add (wrap, pre_p);
+               *expr_p = unshare_expr (*to_p);
              }
            else
-             *expr_p = cond;
-           return ret;
+             *expr_p = wrap;
+           return GS_OK;
          }
-       else
-         ret = GS_UNHANDLED;
-       break;
 
-      case CALL_EXPR:
-       /* For calls that return in memory, give *to_p as the CALL_EXPR's
-          return slot so that we don't generate a temporary.  */
-       if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
-           && aggregate_value_p (*from_p, *from_p))
+       case COMPOUND_LITERAL_EXPR:
          {
-           bool use_target;
-
-           if (!(rhs_predicate_for (*to_p))(*from_p))
-             /* If we need a temporary, *to_p isn't accurate.  */
-             use_target = false;
-           else if (TREE_CODE (*to_p) == RESULT_DECL
-                    && DECL_NAME (*to_p) == NULL_TREE
-                    && needs_to_live_in_memory (*to_p))
-             /* It's OK to use the return slot directly unless it's an NRV. */
-             use_target = true;
-           else if (is_gimple_reg_type (TREE_TYPE (*to_p))
-                    || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
-             /* Don't force regs into memory.  */
-             use_target = false;
-           else if (TREE_CODE (*expr_p) == INIT_EXPR)
-             /* It's OK to use the target directly if it's being
-                initialized. */
-             use_target = true;
-           else if (!is_gimple_non_addressable (*to_p))
-             /* Don't use the original target if it's already addressable;
-                if its address escapes, and the called function uses the
-                NRV optimization, a conforming program could see *to_p
-                change before the called function returns; see c++/19317.
-                When optimizing, the return_slot pass marks more functions
-                as safe after we have escape info.  */
-             use_target = false;
-           else
-             use_target = true;
-
-           if (use_target)
+           tree complit = TREE_OPERAND (*expr_p, 1);
+           tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
+           tree decl = DECL_EXPR_DECL (decl_s);
+           tree init = DECL_INITIAL (decl);
+
+           /* struct T x = (struct T) { 0, 1, 2 } can be optimized
+              into struct T x = { 0, 1, 2 } if the address of the
+              compound literal has never been taken.  */
+           if (!TREE_ADDRESSABLE (complit)
+               && !TREE_ADDRESSABLE (decl)
+               && init)
              {
-               CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
-               mark_addressable (*to_p);
+               *expr_p = copy_node (*expr_p);
+               TREE_OPERAND (*expr_p, 1) = init;
+               return GS_OK;
              }
          }
 
-       ret = GS_UNHANDLED;
-       break;
-
-       /* If we're initializing from a container, push the initialization
-          inside it.  */
-      case CLEANUP_POINT_EXPR:
-      case BIND_EXPR:
-      case STATEMENT_LIST:
-       {
-         tree wrap = *from_p;
-         tree t;
-
-         ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
-                              fb_lvalue);
-         if (ret != GS_ERROR)
-           ret = GS_OK;
-
-         t = voidify_wrapper_expr (wrap, *expr_p);
-         gcc_assert (t == *expr_p);
-
-         if (want_value)
-           {
-             gimplify_and_add (wrap, pre_p);
-             *expr_p = unshare_expr (*to_p);
-           }
-         else
-           *expr_p = wrap;
-         return GS_OK;
-       }
-       
-      case COMPOUND_LITERAL_EXPR:
-       {
-         tree complit = TREE_OPERAND (*expr_p, 1);
-         tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
-         tree decl = DECL_EXPR_DECL (decl_s);
-         tree init = DECL_INITIAL (decl);
-
-         /* struct T x = (struct T) { 0, 1, 2 } can be optimized
-            into struct T x = { 0, 1, 2 } if the address of the
-            compound literal has never been taken.  */
-         if (!TREE_ADDRESSABLE (complit)
-             && !TREE_ADDRESSABLE (decl)
-             && init)
-           {
-             *expr_p = copy_node (*expr_p);
-             TREE_OPERAND (*expr_p, 1) = init;
-             return GS_OK;
-           }
+       default:
+         break;
        }
-
-      default:
-       ret = GS_UNHANDLED;
-       break;
-      }
+    }
+  while (changed);
 
   return ret;
 }
@@ -4457,7 +4521,8 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
         instead of a GIMPLE_ASSIGN.  */
       assign = gimple_build_call_from_tree (*from_p);
-      gimple_call_set_lhs (assign, *to_p);
+      if (!gimple_call_noreturn_p (assign))
+       gimple_call_set_lhs (assign, *to_p);
     }
   else
     {
@@ -4765,13 +4830,14 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
   VEC(tree, gc) *inputs;
   VEC(tree, gc) *outputs;
   VEC(tree, gc) *clobbers;
+  VEC(tree, gc) *labels;
   tree link_next;
-  
+
   expr = *expr_p;
   noutputs = list_length (ASM_OUTPUTS (expr));
   oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
 
-  inputs = outputs = clobbers = NULL;
+  inputs = outputs = clobbers = labels = NULL;
 
   ret = GS_ALL_DONE;
   link_next = NULL_TREE;
@@ -4951,15 +5017,18 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
       TREE_CHAIN (link) = NULL_TREE;
       VEC_safe_push (tree, gc, inputs, link);
     }
-  
+
   for (link = ASM_CLOBBERS (expr); link; ++i, link = TREE_CHAIN (link))
-      VEC_safe_push (tree, gc, clobbers, link);
+    VEC_safe_push (tree, gc, clobbers, link);
+
+  for (link = ASM_LABELS (expr); link; ++i, link = TREE_CHAIN (link))
+    VEC_safe_push (tree, gc, labels, link);
 
   /* Do not add ASMs with errors to the gimple IL stream.  */
   if (ret != GS_ERROR)
     {
       stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
-                                  inputs, outputs, clobbers);
+                                  inputs, outputs, clobbers, labels);
 
       gimple_asm_set_volatile (stmt, ASM_VOLATILE_P (expr));
       gimple_asm_set_input (stmt, ASM_INPUT_P (expr));
@@ -5323,7 +5392,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
     }
 
   /* When adding a variable-sized variable, we have to handle all sorts
-     of additional bits of data: the pointer replacement variable, and 
+     of additional bits of data: the pointer replacement variable, and
      the parameters of the type.  */
   if (DECL_SIZE (decl) && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
     {
@@ -5355,7 +5424,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
        flags = GOVD_PRIVATE | GOVD_DEBUG_PRIVATE
                | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
 
-      /* We're going to make use of the TYPE_SIZE_UNIT at least in the 
+      /* We're going to make use of the TYPE_SIZE_UNIT at least in the
         alloca statement we generate for the variable, so make sure it
         is available.  This isn't automatically needed for the SHARED
         case, since we won't be allocating local storage then.
@@ -5674,7 +5743,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
              push_gimplify_context (&gctx);
              gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
                                &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
-             pop_gimplify_context 
+             pop_gimplify_context
                (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
              OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
              OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
@@ -5871,7 +5940,7 @@ gimplify_adjust_omp_clauses (tree *list_p)
          OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
            = (n->value & GOVD_FIRSTPRIVATE) != 0;
          break;
-         
+
        case OMP_CLAUSE_REDUCTION:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COPYPRIVATE:
@@ -5897,7 +5966,7 @@ gimplify_adjust_omp_clauses (tree *list_p)
 
   /* Add in any implicit data sharing.  */
   splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, list_p);
-  
+
   gimplify_omp_ctxp = ctx->outer_context;
   delete_omp_context (ctx);
 }
@@ -6021,7 +6090,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
        {
          var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
          TREE_OPERAND (t, 0) = var;
-                              
+
          gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
 
          omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
@@ -6171,14 +6240,14 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
 }
 
 /* A subroutine of gimplify_omp_atomic.  The front end is supposed to have
-   stabilized the lhs of the atomic operation as *ADDR.  Return true if 
+   stabilized the lhs of the atomic operation as *ADDR.  Return true if
    EXPR is this stabilized form.  */
 
 static bool
 goa_lhs_expr_p (tree expr, tree addr)
 {
   /* Also include casts to other type variants.  The C front end is fond
-     of adding these for e.g. volatile variables.  This is like 
+     of adding these for e.g. volatile variables.  This is like
      STRIP_TYPE_NOPS but includes the main variant lookup.  */
   STRIP_USELESS_TYPE_CONVERSION (expr);
 
@@ -6224,7 +6293,7 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
     }
   if (is_gimple_val (expr))
     return 0;
+
   saw_lhs = 0;
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
@@ -6276,7 +6345,7 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
   tree tmp_load;
 
-   tmp_load = create_tmp_var (type, NULL);
+   tmp_load = create_tmp_reg (type, NULL);
    if (goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
      return GS_ERROR;
 
@@ -6546,8 +6615,16 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
        case MODIFY_EXPR:
        case INIT_EXPR:
-         ret = gimplify_modify_expr (expr_p, pre_p, post_p,
-                                     fallback != fb_none);
+         {
+           tree from = TREE_OPERAND (*expr_p, 1);
+           ret = gimplify_modify_expr (expr_p, pre_p, post_p,
+                                       fallback != fb_none);
+           /* Don't let the end of loop logic change GS_OK into GS_ALL_DONE
+              if the RHS has changed.  */
+           if (ret == GS_OK && *expr_p == save_expr
+               && TREE_OPERAND (*expr_p, 1) != from)
+             continue;
+         }
          break;
 
        case TRUTH_ANDIF_EXPR:
@@ -6645,11 +6722,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          ret = gimplify_decl_expr (expr_p, pre_p);
          break;
 
-       case EXC_PTR_EXPR:
-         /* FIXME make this a decl.  */
-         ret = GS_ALL_DONE;
-         break;
-
        case BIND_EXPR:
          ret = gimplify_bind_expr (expr_p, pre_p);
          break;
@@ -6841,8 +6913,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
            ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
            gimple_set_no_warning (ehf, TREE_NO_WARNING (*expr_p));
-           gimple_eh_filter_set_must_not_throw
-             (ehf, EH_FILTER_MUST_NOT_THROW (*expr_p));
            gimplify_seq_add_stmt (pre_p, ehf);
            ret = GS_ALL_DONE;
            break;
@@ -7178,7 +7248,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  && code != GOTO_EXPR
                  && code != LABEL_EXPR
                  && code != LOOP_EXPR
-                 && code != RESX_EXPR
                  && code != SWITCH_EXPR
                  && code != TRY_FINALLY_EXPR
                  && code != OMP_CRITICAL
@@ -7314,9 +7383,10 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
       /* These types may not have declarations, so handle them here.  */
       gimplify_type_sizes (TREE_TYPE (type), list_p);
       gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
-      /* When not optimizing, ensure VLA bounds aren't removed.  */
-      if (!optimize
-         && TYPE_DOMAIN (type)
+      /* Ensure VLA bounds aren't removed, for -O0 they should be variables
+        with assigned stack slots, for -O1+ -g they should be tracked
+        by VTA.  */
+      if (TYPE_DOMAIN (type)
          && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
        {
          t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
@@ -7481,11 +7551,21 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
   *body_p = NULL_TREE;
 
   /* If we had callee-copies statements, insert them at the beginning
-     of the function.  */
+     of the function and clear DECL_VALUE_EXPR_P on the parameters.  */
   if (!gimple_seq_empty_p (parm_stmts))
     {
+      tree parm;
+
       gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
       gimple_bind_set_body (outer_bind, parm_stmts);
+
+      for (parm = DECL_ARGUMENTS (current_function_decl);
+          parm; parm = TREE_CHAIN (parm))
+       if (DECL_HAS_VALUE_EXPR_P (parm))
+         {
+           DECL_HAS_VALUE_EXPR_P (parm) = 0;
+           DECL_IGNORED_P (parm) = 0;
+         }
     }
 
   if (nonlocal_vlas)
@@ -7510,7 +7590,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
 
 /* Entry point to the gimplification pass.  FNDECL is the FUNCTION_DECL
    node for the function we want to gimplify.
-   
+
    Returns the sequence of GIMPLE statements corresponding to the body
    of FNDECL.  */
 
@@ -7748,11 +7828,8 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
            }
          if (need_temp)
            {
-             tree temp = create_tmp_var (TREE_TYPE (lhs), NULL);
+             tree temp = create_tmp_reg (TREE_TYPE (lhs), NULL);
 
-             if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
-                 || TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
-               DECL_GIMPLE_REG_P (temp) = 1;
              if (TREE_CODE (orig_lhs) == SSA_NAME)
                orig_lhs = SSA_NAME_VAR (orig_lhs);