OSDN Git Service

2012-02-21 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index 6d00fef..a214134 100644 (file)
@@ -1,7 +1,7 @@
 /* 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, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+   2012 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>.
 
@@ -26,33 +26,30 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "gimple.h"
 #include "tree-iterator.h"
 #include "tree-inline.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
 #include "langhooks.h"
-#include "langhooks-def.h"
 #include "tree-flow.h"
 #include "cgraph.h"
 #include "timevar.h"
-#include "except.h"
 #include "hashtab.h"
 #include "flags.h"
-#include "real.h"
 #include "function.h"
 #include "output.h"
-#include "expr.h"
 #include "ggc.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "target.h"
-#include "optabs.h"
 #include "pointer-set.h"
 #include "splay-tree.h"
 #include "vec.h"
 #include "gimple.h"
 #include "tree-pass.h"
 
+#include "langhooks-def.h"     /* FIXME: for lhd_set_decl_assembler_name.  */
+#include "expr.h"              /* FIXME: for can_move_by_pieces
+                                  and STACK_CHECK_MAX_VAR_SIZE.  */
 
 enum gimplify_omp_var_data
 {
@@ -94,7 +91,7 @@ static struct gimplify_ctx *gimplify_ctxp;
 static struct gimplify_omp_ctx *gimplify_omp_ctxp;
 
 
-/* Formal (expression) temporary table handling: Multiple occurrences of
+/* Formal (expression) temporary table handling: multiple occurrences of
    the same scalar expression are evaluated into the same temporary.  */
 
 typedef struct gimple_temp_hash_elt
@@ -103,20 +100,24 @@ typedef struct gimple_temp_hash_elt
   tree temp;  /* Value */
 } elt_t;
 
-/* Forward declarations.  */
+/* Forward declaration.  */
 static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
 
 /* Mark X addressable.  Unlike the langhook we expect X to be in gimple
    form and we don't do any syntax checking.  */
+
 void
 mark_addressable (tree x)
 {
   while (handled_component_p (x))
     x = TREE_OPERAND (x, 0);
+  if (TREE_CODE (x) == MEM_REF
+      && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
+    x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
   if (TREE_CODE (x) != VAR_DECL
       && TREE_CODE (x) != PARM_DECL
       && TREE_CODE (x) != RESULT_DECL)
-    return ;
+    return;
   TREE_ADDRESSABLE (x) = 1;
 }
 
@@ -145,9 +146,11 @@ gimple_tree_eq (const void *p1, const void *p2)
   if (!operand_equal_p (t1, t2, 0))
     return 0;
 
+#ifdef ENABLE_CHECKING
   /* Only allow them to compare equal if they also hash equal; otherwise
      results are nondeterminate, and we fail bootstrap comparison.  */
   gcc_assert (gimple_tree_hash (p1) == gimple_tree_hash (p2));
+#endif
 
   return 1;
 }
@@ -159,7 +162,7 @@ gimple_tree_eq (const void *p1, const void *p2)
    before the def/use vectors have been constructed.  */
 
 void
-gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
+gimple_seq_add_stmt_without_update (gimple_seq *seq_p, gimple gs)
 {
   gimple_stmt_iterator si;
 
@@ -174,6 +177,15 @@ gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
   gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
 }
 
+/* Shorter alias name for the above function for use in gimplify.c
+   only.  */
+
+static inline void
+gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
+{
+  gimple_seq_add_stmt_without_update (seq_p, gs);
+}
+
 /* Append sequence SRC to the end of sequence *DST_P.  If *DST_P is
    NULL, a new sequence is allocated.   This function is
    similar to gimple_seq_add_seq, but does not scan the operands.
@@ -230,6 +242,8 @@ pop_gimplify_context (gimple body)
     htab_delete (c->temp_htab);
 }
 
+/* Push a GIMPLE_BIND tuple onto the stack of bindings.  */
+
 static void
 gimple_push_bind_expr (gimple gimple_bind)
 {
@@ -238,19 +252,23 @@ gimple_push_bind_expr (gimple gimple_bind)
   VEC_safe_push (gimple, heap, gimplify_ctxp->bind_expr_stack, gimple_bind);
 }
 
+/* Pop the first element off the stack of bindings.  */
+
 static void
 gimple_pop_bind_expr (void)
 {
   VEC_pop (gimple, gimplify_ctxp->bind_expr_stack);
 }
 
+/* Return the first element of the stack of bindings.  */
+
 gimple
 gimple_current_bind_expr (void)
 {
   return VEC_last (gimple, gimplify_ctxp->bind_expr_stack);
 }
 
-/* Return the stack GIMPLE_BINDs created during gimplification.  */
+/* Return the stack of bindings created during gimplification.  */
 
 VEC(gimple, heap) *
 gimple_bind_expr_stack (void)
@@ -258,7 +276,7 @@ gimple_bind_expr_stack (void)
   return gimplify_ctxp->bind_expr_stack;
 }
 
-/* Returns true iff there is a COND_EXPR between us and the innermost
+/* Return true iff there is a COND_EXPR between us and the innermost
    CLEANUP_POINT_EXPR.  This info is used by gimple_push_cleanup.  */
 
 static bool
@@ -340,47 +358,6 @@ delete_omp_context (struct gimplify_omp_ctx *c)
 static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
 static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
 
-/* A subroutine of append_to_statement_list{,_force}.  T is not NULL.  */
-
-static void
-append_to_statement_list_1 (tree t, tree *list_p)
-{
-  tree list = *list_p;
-  tree_stmt_iterator i;
-
-  if (!list)
-    {
-      if (t && TREE_CODE (t) == STATEMENT_LIST)
-       {
-         *list_p = t;
-         return;
-       }
-      *list_p = list = alloc_stmt_list ();
-    }
-
-  i = tsi_last (list);
-  tsi_link_after (&i, t, TSI_CONTINUE_LINKING);
-}
-
-/* Add T to the end of the list container pointed to by LIST_P.
-   If T is an expression with no effects, it is ignored.  */
-
-void
-append_to_statement_list (tree t, tree *list_p)
-{
-  if (t && TREE_SIDE_EFFECTS (t))
-    append_to_statement_list_1 (t, list_p);
-}
-
-/* Similar, but the statement is always added, regardless of side effects.  */
-
-void
-append_to_statement_list_force (tree t, tree *list_p)
-{
-  if (t != NULL_TREE)
-    append_to_statement_list_1 (t, list_p);
-}
-
 /* Both gimplify the statement T and append it to *SEQ_P.  This function
    behaves exactly as gimplify_stmt, but you don't have to pass T as a
    reference.  */
@@ -431,7 +408,7 @@ remove_suffix (char *name, int len)
     }
 }
 
-/* Create a new temporary name with PREFIX.  Returns an identifier.  */
+/* Create a new temporary name with PREFIX.  Return an identifier.  */
 
 static GTY(()) unsigned int tmp_var_id_num;
 
@@ -445,6 +422,8 @@ create_tmp_var_name (const char *prefix)
       char *preftmp = ASTRDUP (prefix);
 
       remove_suffix (preftmp, strlen (preftmp));
+      clean_symbol_name (preftmp);
+
       prefix = preftmp;
     }
 
@@ -452,19 +431,13 @@ create_tmp_var_name (const char *prefix)
   return get_identifier (tmp_name);
 }
 
-
 /* Create a new temporary variable declaration of type TYPE.
-   Does NOT push it into the current binding.  */
+   Do NOT push it into the current binding.  */
 
 tree
 create_tmp_var_raw (tree type, const char *prefix)
 {
   tree tmp_var;
-  tree new_type;
-
-  /* Make the type of the variable writable.  */
-  new_type = build_type_variant (type, 0, 0);
-  TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type);
 
   tmp_var = build_decl (input_location,
                        VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL,
@@ -485,7 +458,7 @@ create_tmp_var_raw (tree type, const char *prefix)
   return tmp_var;
 }
 
-/* Create a new temporary variable declaration of type TYPE.  DOES push the
+/* Create a new temporary variable declaration of type TYPE.  DO push the
    variable into the current binding.  Further, assume that this is called
    only from gimplification or optimization, at which point the creation of
    certain types are bugs.  */
@@ -576,9 +549,8 @@ lookup_tmp_var (tree val, bool is_formal)
   return ret;
 }
 
-
 /* Return true if T is a CALL_EXPR or an expression that can be
-   assignmed to a temporary.  Note that this predicate should only be
+   assigned to a temporary.  Note that this predicate should only be
    used during gimplification.  See the rationale for this in
    gimplify_modify_expr.  */
 
@@ -627,10 +599,7 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
 
   mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
 
-  if (EXPR_HAS_LOCATION (val))
-    SET_EXPR_LOCATION (mod, EXPR_LOCATION (val));
-  else
-    SET_EXPR_LOCATION (mod, input_location);
+  SET_EXPR_LOCATION (mod, EXPR_LOC_OR_HERE (val));
 
   /* gimplify_modify_expr might want to reduce this further.  */
   gimplify_and_add (mod, pre_p);
@@ -647,7 +616,7 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
   return t;
 }
 
-/* Returns a formal temporary variable initialized with VAL.  PRE_P is as
+/* Return a formal temporary variable initialized with VAL.  PRE_P is as
    in gimplify_expr.  Only use this function if:
 
    1) The value of the unfactored expression represented by VAL will not
@@ -665,7 +634,7 @@ get_formal_tmp_var (tree val, gimple_seq *pre_p)
   return internal_get_tmp_var (val, pre_p, NULL, true);
 }
 
-/* Returns a temporary variable initialized with VAL.  PRE_P and POST_P
+/* Return a temporary variable initialized with VAL.  PRE_P and POST_P
    are as in gimplify_expr.  */
 
 tree
@@ -674,8 +643,8 @@ get_initialized_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p)
   return internal_get_tmp_var (val, pre_p, post_p, false);
 }
 
-/* Declares all the variables in VARS in SCOPE.  If DEBUG_INFO is
-   true, generate debug info for them; otherwise don't.  */
+/* Declare all the variables in VARS in SCOPE.  If DEBUG_INFO is true,
+   generate debug info for them; otherwise don't.  */
 
 void
 declare_vars (tree vars, gimple scope, bool debug_info)
@@ -693,7 +662,7 @@ declare_vars (tree vars, gimple scope, bool debug_info)
       gcc_assert (!block || TREE_CODE (block) == BLOCK);
       if (!block || !debug_info)
        {
-         TREE_CHAIN (last) = gimple_bind_vars (scope);
+         DECL_CHAIN (last) = gimple_bind_vars (scope);
          gimple_bind_set_vars (scope, temps);
        }
       else
@@ -738,10 +707,12 @@ force_constant_size (tree var)
     = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
 }
 
+/* Push the temporary variable TMP into the current binding.  */
+
 void
 gimple_add_tmp_var (tree tmp)
 {
-  gcc_assert (!TREE_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
+  gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
 
   /* Later processing assumes that the object size is constant, which might
      not be true at this point.  Force the use of a constant upper bound in
@@ -754,7 +725,7 @@ gimple_add_tmp_var (tree tmp)
 
   if (gimplify_ctxp)
     {
-      TREE_CHAIN (tmp) = gimplify_ctxp->temps;
+      DECL_CHAIN (tmp) = gimplify_ctxp->temps;
       gimplify_ctxp->temps = tmp;
 
       /* Mark temporaries local within the nearest enclosing parallel.  */
@@ -780,7 +751,7 @@ gimple_add_tmp_var (tree tmp)
     }
 }
 
-/* Determines whether to assign a location to the statement GS.  */
+/* Determine whether to assign a location to the statement GS.  */
 
 static bool
 should_carry_location_p (gimple gs)
@@ -794,7 +765,6 @@ should_carry_location_p (gimple gs)
   return true;
 }
 
-
 /* Return true if a location should not be emitted for this statement
    by annotate_one_with_location.  */
 
@@ -826,7 +796,6 @@ annotate_one_with_location (gimple gs, location_t location)
     gimple_set_location (gs, 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
    first statement in SEQ.  */
@@ -844,7 +813,6 @@ annotate_all_with_location_after (gimple_seq seq, gimple_stmt_iterator gsi,
     annotate_one_with_location (gsi_stmt (gsi), location);
 }
 
-
 /* Set the location for all the statements in a sequence STMT_P to LOCATION.  */
 
 void
@@ -861,48 +829,93 @@ annotate_all_with_location (gimple_seq stmt_p, location_t location)
       annotate_one_with_location (gs, 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
-   were to unshare something like SAVE_EXPR(i++), the gimplification
-   process would create wrong code.  */
+\f
+/* This page contains routines to unshare tree nodes, i.e. to duplicate tree
+   nodes that are referenced more than once in GENERIC functions.  This is
+   necessary because gimplification (translation into GIMPLE) is performed
+   by modifying tree nodes in-place, so gimplication of a shared node in a
+   first context could generate an invalid GIMPLE form in a second context.
+
+   This is achieved with a simple mark/copy/unmark algorithm that walks the
+   GENERIC representation top-down, marks nodes with TREE_VISITED the first
+   time it encounters them, duplicates them if they already have TREE_VISITED
+   set, and finally removes the TREE_VISITED marks it has set.
+
+   The algorithm works only at the function level, i.e. it generates a GENERIC
+   representation of a function with no nodes shared within the function when
+   passed a GENERIC function (except for nodes that are allowed to be shared).
+
+   At the global level, it is also necessary to unshare tree nodes that are
+   referenced in more than one function, for the same aforementioned reason.
+   This requires some cooperation from the front-end.  There are 2 strategies:
+
+     1. Manual unsharing.  The front-end needs to call unshare_expr on every
+        expression that might end up being shared across functions.
+
+     2. Deep unsharing.  This is an extension of regular unsharing.  Instead
+        of calling unshare_expr on expressions that might be shared across
+        functions, the front-end pre-marks them with TREE_VISITED.  This will
+        ensure that they are unshared on the first reference within functions
+        when the regular unsharing algorithm runs.  The counterpart is that
+        this algorithm must look deeper than for manual unsharing, which is
+        specified by LANG_HOOKS_DEEP_UNSHARING.
+
+  If there are only few specific cases of node sharing across functions, it is
+  probably easier for a front-end to unshare the expressions manually.  On the
+  contrary, if the expressions generated at the global level are as widespread
+  as expressions generated within functions, deep unsharing is very likely the
+  way to go.  */
+
+/* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
+   These nodes model computations that must be done once.  If we were to
+   unshare something like SAVE_EXPR(i++), the gimplification process would
+   create wrong code.  However, if DATA is non-null, it must hold a pointer
+   set that is used to unshare the subtrees of these nodes.  */
 
 static tree
 mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
 {
-  enum tree_code code = TREE_CODE (*tp);
-  /* Don't unshare types, decls, constants and SAVE_EXPR nodes.  */
-  if (TREE_CODE_CLASS (code) == tcc_type
-      || TREE_CODE_CLASS (code) == tcc_declaration
-      || TREE_CODE_CLASS (code) == tcc_constant
-      || code == SAVE_EXPR || code == TARGET_EXPR
-      /* We can't do anything sensible with a BLOCK used as an expression,
-        but we also can't just die when we see it because of non-expression
-        uses.  So just avert our eyes and cross our fingers.  Silly Java.  */
-      || code == BLOCK)
-    *walk_subtrees = 0;
-  else
+  tree t = *tp;
+  enum tree_code code = TREE_CODE (t);
+
+  /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
+     copy their subtrees if we can make sure to do it only once.  */
+  if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
     {
-      gcc_assert (code != BIND_EXPR);
-      copy_tree_r (tp, walk_subtrees, data);
+      if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
+       ;
+      else
+       *walk_subtrees = 0;
     }
 
+  /* Stop at types, decls, constants like copy_tree_r.  */
+  else if (TREE_CODE_CLASS (code) == tcc_type
+          || TREE_CODE_CLASS (code) == tcc_declaration
+          || TREE_CODE_CLASS (code) == tcc_constant
+          /* We can't do anything sensible with a BLOCK used as an
+             expression, but we also can't just die when we see it
+             because of non-expression uses.  So we avert our eyes
+             and cross our fingers.  Silly Java.  */
+          || code == BLOCK)
+    *walk_subtrees = 0;
+
+  /* Cope with the statement expression extension.  */
+  else if (code == STATEMENT_LIST)
+    ;
+
+  /* Leave the bulk of the work to copy_tree_r itself.  */
+  else
+    copy_tree_r (tp, walk_subtrees, NULL);
+
   return NULL_TREE;
 }
 
-/* Callback for walk_tree to unshare most of the shared trees rooted at
-   *TP.  If *TP has been visited already (i.e., TREE_VISITED (*TP) == 1),
-   then *TP is deep copied by calling copy_tree_r.
-
-   This unshares the same trees as copy_tree_r with the exception of
-   SAVE_EXPR nodes.  These nodes model computations that should only be
-   done once.  If we were to unshare something like SAVE_EXPR(i++), the
-   gimplification process would create wrong code.  */
+/* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
+   If *TP has been visited already, then *TP is deeply copied by calling
+   mostly_copy_tree_r.  DATA is passed to mostly_copy_tree_r unmodified.  */
 
 static tree
-copy_if_shared_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
-                 void *data ATTRIBUTE_UNUSED)
+copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
 {
   tree t = *tp;
   enum tree_code code = TREE_CODE (t);
@@ -925,55 +938,91 @@ copy_if_shared_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
      any deeper.  */
   else if (TREE_VISITED (t))
     {
-      walk_tree (tp, mostly_copy_tree_r, NULL, NULL);
+      walk_tree (tp, mostly_copy_tree_r, data, NULL);
       *walk_subtrees = 0;
     }
 
-  /* Otherwise, mark the tree as visited and keep looking.  */
+  /* Otherwise, mark the node as visited and keep looking.  */
   else
     TREE_VISITED (t) = 1;
 
   return NULL_TREE;
 }
 
+/* Unshare most of the shared trees rooted at *TP.  DATA is passed to the
+   copy_if_shared_r callback unmodified.  */
+
+static inline void
+copy_if_shared (tree *tp, void *data)
+{
+  walk_tree (tp, copy_if_shared_r, data, NULL);
+}
+
+/* Unshare all the trees in the body of FNDECL, as well as in the bodies of
+   any nested functions.  */
+
+static void
+unshare_body (tree fndecl)
+{
+  struct cgraph_node *cgn = cgraph_get_node (fndecl);
+  /* If the language requires deep unsharing, we need a pointer set to make
+     sure we don't repeatedly unshare subtrees of unshareable nodes.  */
+  struct pointer_set_t *visited
+    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
+
+  copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
+  copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
+  copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
+
+  if (visited)
+    pointer_set_destroy (visited);
+
+  if (cgn)
+    for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
+      unshare_body (cgn->decl);
+}
+
+/* Callback for walk_tree to unmark the visited trees rooted at *TP.
+   Subtrees are walked until the first unvisited node is encountered.  */
+
 static tree
-unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
-                 void *data ATTRIBUTE_UNUSED)
+unmark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 {
-  if (TREE_VISITED (*tp))
-    TREE_VISITED (*tp) = 0;
+  tree t = *tp;
+
+  /* If this node has been visited, unmark it and keep looking.  */
+  if (TREE_VISITED (t))
+    TREE_VISITED (t) = 0;
+
+  /* Otherwise, don't look any deeper.  */
   else
     *walk_subtrees = 0;
 
   return NULL_TREE;
 }
 
-/* Unshare all the trees in BODY_P, a pointer into the body of FNDECL, and the
-   bodies of any nested functions if we are unsharing the entire body of
-   FNDECL.  */
+/* Unmark the visited trees rooted at *TP.  */
 
-static void
-unshare_body (tree *body_p, tree fndecl)
+static inline void
+unmark_visited (tree *tp)
 {
-  struct cgraph_node *cgn = cgraph_node (fndecl);
-
-  walk_tree (body_p, copy_if_shared_r, NULL, NULL);
-  if (body_p == &DECL_SAVED_TREE (fndecl))
-    for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
-      unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
+  walk_tree (tp, unmark_visited_r, NULL, NULL);
 }
 
 /* Likewise, but mark all trees as not visited.  */
 
 static void
-unvisit_body (tree *body_p, tree fndecl)
+unvisit_body (tree fndecl)
 {
-  struct cgraph_node *cgn = cgraph_node (fndecl);
+  struct cgraph_node *cgn = cgraph_get_node (fndecl);
 
-  walk_tree (body_p, unmark_visited_r, NULL, NULL);
-  if (body_p == &DECL_SAVED_TREE (fndecl))
+  unmark_visited (&DECL_SAVED_TREE (fndecl));
+  unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
+  unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
+
+  if (cgn)
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
-      unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
+      unvisit_body (cgn->decl);
 }
 
 /* Unconditionally make an unshared copy of EXPR.  This is used when using
@@ -989,7 +1038,7 @@ unshare_expr (tree expr)
 \f
 /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
    contain statements and have a value.  Assign its value to a temporary
-   and give it void_type_node.  Returns the temporary, or NULL_TREE if
+   and give it void_type_node.  Return the temporary, or NULL_TREE if
    WRAPPER was already void.  */
 
 tree
@@ -1031,7 +1080,8 @@ voidify_wrapper_expr (tree wrapper, tree temp)
              break;
 
            case COMPOUND_EXPR:
-             /* Advance to the last statement.  Set all container types to void.  */
+             /* Advance to the last statement.  Set all container types to
+                void.  */
              for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
                {
                  TREE_SIDE_EFFECTS (*p) = 1;
@@ -1039,7 +1089,22 @@ voidify_wrapper_expr (tree wrapper, tree temp)
                }
              break;
 
+           case TRANSACTION_EXPR:
+             TREE_SIDE_EFFECTS (*p) = 1;
+             TREE_TYPE (*p) = void_type_node;
+             p = &TRANSACTION_EXPR_BODY (*p);
+             break;
+
            default:
+             /* Assume that any tree upon which voidify_wrapper_expr is
+                directly called is a wrapper, and that its body is op0.  */
+             if (p == &wrapper)
+               {
+                 TREE_SIDE_EFFECTS (*p) = 1;
+                 TREE_TYPE (*p) = void_type_node;
+                 p = &TREE_OPERAND (*p, 0);
+                 break;
+               }
              goto out;
            }
        }
@@ -1076,12 +1141,13 @@ build_stack_save_restore (gimple *save, gimple *restore)
 {
   tree tmp_var;
 
-  *save = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_SAVE], 0);
+  *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
   tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
   gimple_call_set_lhs (*save, tmp_var);
 
-  *restore = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_RESTORE],
-                           1, tmp_var);
+  *restore
+    = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
+                        1, tmp_var);
 }
 
 /* Gimplify a BIND_EXPR.  Just voidify and recurse.  */
@@ -1093,19 +1159,20 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
   bool old_save_stack = gimplify_ctxp->save_stack;
   tree t;
   gimple gimple_bind;
-  gimple_seq body;
+  gimple_seq body, cleanup;
+  gimple stack_save;
 
   tree temp = voidify_wrapper_expr (bind_expr, NULL);
 
   /* Mark variables seen in this bind expr.  */
-  for (t = BIND_EXPR_VARS (bind_expr); t ; t = TREE_CHAIN (t))
+  for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
     {
       if (TREE_CODE (t) == VAR_DECL)
        {
          struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
 
          /* Mark variable as local.  */
-         if (ctx && !is_global_var (t)
+         if (ctx && !DECL_EXTERNAL (t)
              && (! DECL_SEEN_IN_BIND_EXPR_P (t)
                  || splay_tree_lookup (ctx->variables,
                                        (splay_tree_key) t) == NULL))
@@ -1119,14 +1186,9 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
 
       /* Preliminarily mark non-addressed complex variables as eligible
         for promotion to gimple registers.  We'll transform their uses
-        as we find them.
-        We exclude complex types if not optimizing because they can be
-        subject to partial stores in GNU C by means of the __real__ and
-        __imag__ operators and we cannot promote them to total stores
-        (see gimplify_modify_expr_complex_part).  */
-      if (optimize
-         && (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-             || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+        as we find them.  */
+      if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+          || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
          && !TREE_THIS_VOLATILE (t)
          && (TREE_CODE (t) == VAR_DECL && !DECL_HARD_REGISTER (t))
          && !needs_to_live_in_memory (t))
@@ -1144,22 +1206,50 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
   gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
   gimple_bind_set_body (gimple_bind, body);
 
+  cleanup = NULL;
+  stack_save = NULL;
   if (gimplify_ctxp->save_stack)
     {
-      gimple stack_save, stack_restore, gs;
-      gimple_seq cleanup, new_body;
+      gimple stack_restore;
 
       /* Save stack on entry and restore it on exit.  Add a try_finally
         block to achieve this.  Note that mudflap depends on the
         format of the emitted code: see mx_register_decls().  */
       build_stack_save_restore (&stack_save, &stack_restore);
 
-      cleanup = new_body = NULL;
       gimplify_seq_add_stmt (&cleanup, stack_restore);
+    }
+
+  /* Add clobbers for all variables that go out of scope.  */
+  for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
+    {
+      if (TREE_CODE (t) == VAR_DECL
+         && !is_global_var (t)
+         && DECL_CONTEXT (t) == current_function_decl
+         && !DECL_HARD_REGISTER (t)
+         && !TREE_THIS_VOLATILE (t)
+         && !DECL_HAS_VALUE_EXPR_P (t)
+         /* Only care for variables that have to be in memory.  Others
+            will be rewritten into SSA names, hence moved to the top-level.  */
+         && !is_gimple_reg (t))
+       {
+         tree clobber = build_constructor (TREE_TYPE (t), NULL);
+         TREE_THIS_VOLATILE (clobber) = 1;
+         gimplify_seq_add_stmt (&cleanup, gimple_build_assign (t, clobber));
+       }
+    }
+
+  if (cleanup)
+    {
+      gimple gs;
+      gimple_seq new_body;
+
+      new_body = NULL;
       gs = gimple_build_try (gimple_bind_body (gimple_bind), cleanup,
                             GIMPLE_TRY_FINALLY);
 
-      gimplify_seq_add_stmt (&new_body, stack_save);
+      if (stack_save)
+       gimplify_seq_add_stmt (&new_body, stack_save);
       gimplify_seq_add_stmt (&new_body, gs);
       gimple_bind_set_body (gimple_bind, new_body);
     }
@@ -1274,6 +1364,8 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
   return GS_ALL_DONE;
 }
 
+/* Gimplify a variable-length array DECL.  */
+
 static void
 gimplify_vla_decl (tree decl, gimple_seq *seq_p)
 {
@@ -1294,11 +1386,15 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
   addr = create_tmp_var (ptr_type, get_name (decl));
   DECL_IGNORED_P (addr) = 0;
   t = build_fold_indirect_ref (addr);
+  TREE_THIS_NOTRAP (t) = 1;
   SET_DECL_VALUE_EXPR (decl, t);
   DECL_HAS_VALUE_EXPR_P (decl) = 1;
 
-  t = built_in_decls[BUILT_IN_ALLOCA];
-  t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
+  t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+  t = build_call_expr (t, 2, DECL_SIZE_UNIT (decl),
+                      size_int (DECL_ALIGN (decl)));
+  /* The call has been built for a variable-sized object.  */
+  CALL_ALLOCA_FOR_VAR_P (t) = 1;
   t = fold_convert (ptr_type, t);
   t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
 
@@ -1309,8 +1405,7 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
   gimplify_ctxp->save_stack = true;
 }
 
-
-/* Gimplifies a DECL_EXPR node *STMT_P by making any necessary allocation
+/* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
    and initialization explicit.  */
 
 static enum gimplify_status
@@ -1340,6 +1435,14 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
                                   STACK_CHECK_MAX_VAR_SIZE) > 0))
        gimplify_vla_decl (decl, seq_p);
 
+      /* Some front ends do not explicitly declare all anonymous
+        artificial variables.  We compensate here by declaring the
+        variables, though it would be better if the front ends would
+        explicitly declare them.  */
+      if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
+         && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
+       gimple_add_tmp_var (decl);
+
       if (init && init != error_mark_node)
        {
          if (!TREE_STATIC (decl))
@@ -1354,14 +1457,6 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
               as they may contain a label address.  */
            walk_tree (&init, force_labels_r, NULL, NULL);
        }
-
-      /* Some front ends do not explicitly declare all anonymous
-        artificial variables.  We compensate here by declaring the
-        variables, though it would be better if the front ends would
-        explicitly declare them.  */
-      if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
-         && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
-       gimple_add_tmp_var (decl);
     }
 
   return GS_ALL_DONE;
@@ -1386,7 +1481,8 @@ gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
   gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
 
   if (gimplify_ctxp->exit_label)
-    gimplify_seq_add_stmt (pre_p, gimple_build_label (gimplify_ctxp->exit_label));
+    gimplify_seq_add_stmt (pre_p,
+                          gimple_build_label (gimplify_ctxp->exit_label));
 
   gimplify_ctxp->exit_label = saved_label;
 
@@ -1394,7 +1490,7 @@ gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
   return GS_ALL_DONE;
 }
 
-/* Gimplifies a statement list onto a sequence.  These may be created either
+/* Gimplify a statement list onto a sequence.  These may be created either
    by an enlightened front-end, or by shortcut_cond_expr.  */
 
 static enum gimplify_status
@@ -1438,18 +1534,14 @@ compare_case_labels (const void *p1, const void *p2)
     return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
 }
 
-
 /* Sort the case labels in LABEL_VEC in place in ascending order.  */
 
 void
 sort_case_labels (VEC(tree,heap)* label_vec)
 {
-  size_t len = VEC_length (tree, label_vec);
-  qsort (VEC_address (tree, label_vec), len, sizeof (tree),
-         compare_case_labels);
+  VEC_qsort (tree, label_vec, compare_case_labels);
 }
 
-
 /* Gimplify a SWITCH_EXPR, and collect a TREE_VEC of the labels it can
    branch to.  */
 
@@ -1554,10 +1646,11 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
                        break;
                    }
                  if (i == len)
-                   default_case = build3 (CASE_LABEL_EXPR, void_type_node,
-                                          NULL_TREE, NULL_TREE,
-                                          CASE_LABEL (VEC_index (tree,
-                                                                 labels, 0)));
+                   {
+                     tree label = CASE_LABEL (VEC_index (tree, labels, 0));
+                     default_case = build_case_label (NULL_TREE, NULL_TREE,
+                                                      label);
+                   }
                }
            }
 
@@ -1566,9 +1659,8 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
              gimple new_default;
 
              default_case
-               = build3 (CASE_LABEL_EXPR, void_type_node,
-                         NULL_TREE, NULL_TREE,
-                         create_artificial_label (UNKNOWN_LOCATION));
+               = build_case_label (NULL_TREE, NULL_TREE,
+                                   create_artificial_label (UNKNOWN_LOCATION));
              new_default = gimple_build_label (CASE_LABEL (default_case));
              gimplify_seq_add_stmt (&switch_body_seq, new_default);
            }
@@ -1586,6 +1678,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
   return GS_ALL_DONE;
 }
 
+/* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P.  */
 
 static enum gimplify_status
 gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
@@ -1768,7 +1861,6 @@ canonicalize_addr_expr (tree *expr_p)
 static enum gimplify_status
 gimplify_conversion (tree *expr_p)
 {
-  tree tem;
   location_t loc = EXPR_LOCATION (*expr_p);
   gcc_assert (CONVERT_EXPR_P (*expr_p));
 
@@ -1779,17 +1871,6 @@ gimplify_conversion (tree *expr_p)
   if (tree_ssa_useless_type_conversion (*expr_p))
     *expr_p = TREE_OPERAND (*expr_p, 0);
 
-  /* Attempt to avoid NOP_EXPR by producing reference to a subtype.
-     For example this fold (subclass *)&A into &A->subclass avoiding
-     a need for statement.  */
-  if (CONVERT_EXPR_P (*expr_p)
-      && POINTER_TYPE_P (TREE_TYPE (*expr_p))
-      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
-      && (tem = maybe_fold_offset_to_address
-         (EXPR_LOCATION (*expr_p), TREE_OPERAND (*expr_p, 0),
-          integer_zero_node, TREE_TYPE (*expr_p))) != NULL_TREE)
-    *expr_p = tem;
-
   /* If we still have a conversion at the toplevel,
      then canonicalize some constructs.  */
   if (CONVERT_EXPR_P (*expr_p))
@@ -1820,7 +1901,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.  Return GS_OK if we expanded a
    DECL_VALUE_EXPR, and it's worth re-examining things.  */
 
 static enum gimplify_status
@@ -1839,7 +1920,7 @@ gimplify_var_or_parm_decl (tree *expr_p)
       && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
       && decl_function_context (decl) == current_function_decl)
     {
-      gcc_assert (errorcount || sorrycount);
+      gcc_assert (seen_error ());
       return GS_ERROR;
     }
 
@@ -1869,10 +1950,10 @@ gimplify_var_or_parm_decl (tree *expr_p)
              tree copy = copy_node (decl), block;
 
              lang_hooks.dup_lang_specific_decl (copy);
-             SET_DECL_RTL (copy, NULL_RTX);
+             SET_DECL_RTL (copy, 0);
              TREE_USED (copy) = 1;
              block = DECL_INITIAL (current_function_decl);
-             TREE_CHAIN (copy) = BLOCK_VARS (block);
+             DECL_CHAIN (copy) = BLOCK_VARS (block);
              BLOCK_VARS (block) = copy;
              SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr));
              DECL_HAS_VALUE_EXPR_P (copy) = 1;
@@ -1886,7 +1967,6 @@ gimplify_var_or_parm_decl (tree *expr_p)
   return GS_ALL_DONE;
 }
 
-
 /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
    node *EXPR_P.
 
@@ -1980,8 +2060,14 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  ret = MIN (ret, tret);
                }
            }
+         else
+           {
+             tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+                                   is_gimple_reg, fb_rvalue);
+             ret = MIN (ret, tret);
+           }
 
-         if (!TREE_OPERAND (t, 3))
+         if (TREE_OPERAND (t, 3) == NULL_TREE)
            {
              tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
              tree elmt_size = unshare_expr (array_ref_element_size (t));
@@ -1989,7 +2075,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
              /* Divide the element size by the alignment of the element
                 type (above).  */
-             elmt_size = size_binop_loc (loc, EXACT_DIV_EXPR, elmt_size, factor);
+             elmt_size
+               = size_binop_loc (loc, EXACT_DIV_EXPR, elmt_size, factor);
 
              if (!is_gimple_min_invariant (elmt_size))
                {
@@ -2000,11 +2087,17 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  ret = MIN (ret, tret);
                }
            }
+         else
+           {
+             tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
+                                   is_gimple_reg, fb_rvalue);
+             ret = MIN (ret, tret);
+           }
        }
       else if (TREE_CODE (t) == COMPONENT_REF)
        {
          /* Set the field offset into T and gimplify it.  */
-         if (!TREE_OPERAND (t, 2))
+         if (TREE_OPERAND (t, 2) == NULL_TREE)
            {
              tree offset = unshare_expr (component_ref_field_offset (t));
              tree field = TREE_OPERAND (t, 1);
@@ -2023,6 +2116,12 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  ret = MIN (ret, tret);
                }
            }
+         else
+           {
+             tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+                                   is_gimple_reg, fb_rvalue);
+             ret = MIN (ret, tret);
+           }
        }
     }
 
@@ -2159,7 +2258,7 @@ gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   /* For POINTERs increment, use POINTER_PLUS_EXPR.  */
   if (POINTER_TYPE_P (TREE_TYPE (lhs)))
     {
-      rhs = fold_convert_loc (loc, sizetype, rhs);
+      rhs = convert_to_ptrofftype_loc (loc, rhs);
       if (arith_code == MINUS_EXPR)
        rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
       arith_code = POINTER_PLUS_EXPR;
@@ -2181,7 +2280,6 @@ gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
     }
 }
 
-
 /* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR.  */
 
 static void
@@ -2208,7 +2306,6 @@ maybe_with_size_expr (tree *expr_p)
   *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
 }
 
-
 /* Helper for gimplify_call_expr.  Gimplify a single argument *ARG_P
    Store any side-effects in PRE_P.  CALL_LOCATION is the location of
    the CALL_EXPR.  */
@@ -2227,7 +2324,17 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
   if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
     test = is_gimple_val, fb = fb_rvalue;
   else
-    test = is_gimple_lvalue, fb = fb_either;
+    {
+      test = is_gimple_lvalue, fb = fb_either;
+      /* Also strip a TARGET_EXPR that would force an extra copy.  */
+      if (TREE_CODE (*arg_p) == TARGET_EXPR)
+       {
+         tree init = TARGET_EXPR_INITIAL (*arg_p);
+         if (init
+             && !VOID_TYPE_P (TREE_TYPE (init)))
+           *arg_p = init;
+       }
+    }
 
   /* If this is a variable sized type, we must remember the size.  */
   maybe_with_size_expr (arg_p);
@@ -2244,14 +2351,13 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
   return gimplify_expr (arg_p, pre_p, NULL, test, fb);
 }
 
-
 /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
    WANT_VALUE is true if the result of the call is desired.  */
 
 static enum gimplify_status
 gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
 {
-  tree fndecl, parms, p;
+  tree fndecl, parms, p, fnptrtype;
   enum gimplify_status ret;
   int i, nargs;
   gimple call;
@@ -2310,6 +2416,9 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
        }
     }
 
+  /* Remember the original function pointer type.  */
+  fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
+
   /* There is a sequence point before the call, so any side effects in
      the calling expression must occur before the actual call.  Force
      gimplify_expr to use an internal post queue.  */
@@ -2364,7 +2473,6 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
          CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
            = CALL_EXPR_RETURN_SLOT_OPT (call);
          CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
-         CALL_CANNOT_INLINE_P (*expr_p) = CALL_CANNOT_INLINE_P (call);
          SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
          TREE_BLOCK (*expr_p) = TREE_BLOCK (call);
 
@@ -2397,7 +2505,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
 
   /* Verify the function result.  */
   if (want_value && fndecl
-      && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
+      && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
     {
       error_at (loc, "using result of function returning %<void%>");
       ret = GS_ERROR;
@@ -2447,10 +2555,18 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
     {
       /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
         have to do is replicate it as a GIMPLE_CALL tuple.  */
+      gimple_stmt_iterator gsi;
       call = gimple_build_call_from_tree (*expr_p);
+      gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
       gimplify_seq_add_stmt (pre_p, call);
+      gsi = gsi_last (*pre_p);
+      fold_stmt (&gsi);
       *expr_p = NULL_TREE;
     }
+  else
+    /* Remember the original function type.  */
+    CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
+                                    CALL_EXPR_FN (*expr_p));
 
   return ret;
 }
@@ -2524,7 +2640,9 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
                           new_locus);
       append_to_statement_list (t, &expr);
     }
-  else if (TREE_CODE (pred) == COND_EXPR)
+  else if (TREE_CODE (pred) == COND_EXPR
+          && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
+          && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
     {
       location_t new_locus;
 
@@ -2532,7 +2650,10 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
         if (a)
           if (b) goto yes; else goto no;
         else
-          if (c) goto yes; else goto no;  */
+          if (c) goto yes; else goto no;
+
+        Don't do this if one of the arms has void type, which can happen
+        in C++ when the arm is throw.  */
 
       /* Keep the original source location on the first 'if'.  Set the source
         location of the ? on the second 'if'.  */
@@ -2587,8 +2708,7 @@ shortcut_cond_expr (tree expr)
       while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
        {
          /* Keep the original source location on the first 'if'.  */
-         location_t locus = EXPR_HAS_LOCATION (expr)
-                            ? EXPR_LOCATION (expr) : input_location;
+         location_t locus = EXPR_LOC_OR_HERE (expr);
          TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
          /* Set the source location of the && on the second 'if'.  */
          if (EXPR_HAS_LOCATION (pred))
@@ -2610,8 +2730,7 @@ shortcut_cond_expr (tree expr)
       while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
        {
          /* Keep the original source location on the first 'if'.  */
-         location_t locus = EXPR_HAS_LOCATION (expr)
-                            ? EXPR_LOCATION (expr) : input_location;
+         location_t locus = EXPR_LOC_OR_HERE (expr);
          TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
          /* Set the source location of the || on the second 'if'.  */
          if (EXPR_HAS_LOCATION (pred))
@@ -2675,8 +2794,7 @@ shortcut_cond_expr (tree expr)
   /* If there was nothing else in our arms, just forward the label(s).  */
   if (!then_se && !else_se)
     return shortcut_cond_r (pred, true_label_p, false_label_p,
-                           EXPR_HAS_LOCATION (expr)
-                           ? EXPR_LOCATION (expr) : input_location);
+                           EXPR_LOC_OR_HERE (expr));
 
   /* If our last subexpression already has a terminal label, reuse it.  */
   if (else_se)
@@ -2708,8 +2826,7 @@ shortcut_cond_expr (tree expr)
   jump_over_else = block_may_fallthru (then_);
 
   pred = shortcut_cond_r (pred, true_label_p, false_label_p,
-                         EXPR_HAS_LOCATION (expr)
-                         ? EXPR_LOCATION (expr) : input_location);
+                         EXPR_LOC_OR_HERE (expr));
 
   expr = NULL;
   append_to_statement_list (pred, &expr);
@@ -2779,9 +2896,6 @@ gimple_boolify (tree expr)
        }
     }
 
-  if (TREE_CODE (type) == BOOLEAN_TYPE)
-    return expr;
-
   switch (TREE_CODE (expr))
     {
     case TRUTH_AND_EXPR:
@@ -2795,17 +2909,24 @@ gimple_boolify (tree expr)
 
     case TRUTH_NOT_EXPR:
       TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
-      /* FALLTHRU */
 
-    case EQ_EXPR: case NE_EXPR:
-    case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
       /* These expressions always produce boolean results.  */
-      TREE_TYPE (expr) = boolean_type_node;
+      if (TREE_CODE (type) != BOOLEAN_TYPE)
+       TREE_TYPE (expr) = boolean_type_node;
       return expr;
 
     default:
+      if (COMPARISON_CLASS_P (expr))
+       {
+         /* There expressions always prduce boolean results.  */
+         if (TREE_CODE (type) != BOOLEAN_TYPE)
+           TREE_TYPE (expr) = boolean_type_node;
+         return expr;
+       }
       /* Other expressions that get here must have boolean values, but
         might need to be converted to the appropriate mode.  */
+      if (TREE_CODE (type) == BOOLEAN_TYPE)
+       return expr;
       return fold_convert_loc (loc, boolean_type_node, expr);
     }
 }
@@ -2841,7 +2962,7 @@ gimplify_pure_cond_expr (tree *expr_p, gimple_seq *pre_p)
   return MIN (ret, tret);
 }
 
-/* Returns true if evaluating EXPR could trap.
+/* Return true if evaluating EXPR could trap.
    EXPR is GENERIC, while tree_could_trap_p can be called
    only on GIMPLE.  */
 
@@ -2932,7 +3053,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
            = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
 
          tmp = create_tmp_var (type, "iftmp");
-         result = build_fold_indirect_ref_loc (loc, tmp);
+         result = build_simple_mem_ref_loc (loc, tmp);
        }
 
       /* Build the new then clause, `tmp = then_;'.  But don't build the
@@ -2954,6 +3075,11 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
       return GS_ALL_DONE;
     }
 
+  /* Remove any COMPOUND_EXPR so the following cases will be caught.  */
+  STRIP_TYPE_NOPS (TREE_OPERAND (expr, 0));
+  if (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPOUND_EXPR)
+    gimplify_compound_expr (&TREE_OPERAND (expr, 0), pre_p, true);
+
   /* Make sure the condition has BOOLEAN_TYPE.  */
   TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
 
@@ -3145,7 +3271,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
 
-  t = implicit_built_in_decls[BUILT_IN_MEMCPY];
+  t = builtin_decl_implicit (BUILT_IN_MEMCPY);
 
   gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
 
@@ -3156,7 +3282,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
       gimple_call_set_lhs (gs, t);
       gimplify_seq_add_stmt (seq_p, gs);
 
-      *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
+      *expr_p = build_simple_mem_ref (t);
       return GS_ALL_DONE;
     }
 
@@ -3192,7 +3318,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
 
   to_ptr = build_fold_addr_expr_loc (loc, to);
   gimplify_arg (&to_ptr, seq_p, loc);
-  t = implicit_built_in_decls[BUILT_IN_MEMSET];
+  t = builtin_decl_implicit (BUILT_IN_MEMSET);
 
   gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
 
@@ -3214,7 +3340,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
 
 /* A subroutine of gimplify_init_ctor_preeval.  Called via walk_tree,
    determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
-   assignment.  Returns non-null if we detect a potential overlap.  */
+   assignment.  Return non-null if we detect a potential overlap.  */
 
 struct gimplify_init_ctor_preeval_data
 {
@@ -3240,13 +3366,16 @@ gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
   /* If the constructor component is indirect, determine if we have a
      potential overlap with the lhs.  The only bits of information we
      have to go on at this point are addressability and alias sets.  */
-  if (TREE_CODE (t) == INDIRECT_REF
+  if ((INDIRECT_REF_P (t)
+       || TREE_CODE (t) == MEM_REF)
       && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
       && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
     return t;
 
   /* If the constructor component is a call, determine if it can hide a
-     potential overlap with the lhs through an INDIRECT_REF like above.  */
+     potential overlap with the lhs through an INDIRECT_REF like above.
+     ??? Ugh - this is completely broken.  In fact this whole analysis
+     doesn't look conservative.  */
   if (TREE_CODE (t) == CALL_EXPR)
     {
       tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
@@ -3295,7 +3424,7 @@ gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       constructor_elt *ce;
       VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (*expr_p);
 
-      for (ix = 0; VEC_iterate (constructor_elt, v, ix, ce); ix++)
+      FOR_EACH_VEC_ELT (constructor_elt, v, ix, ce)
        gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
 
       return;
@@ -3497,8 +3626,9 @@ gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
        {
          /* Do not use bitsizetype for ARRAY_REF indices.  */
          if (TYPE_DOMAIN (TREE_TYPE (object)))
-           purpose = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
-                                   purpose);
+           purpose
+             = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
+                             purpose);
          cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
                         purpose, NULL_TREE, NULL_TREE);
        }
@@ -3522,8 +3652,7 @@ gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
     }
 }
 
-
-/* Returns the appropriate RHS predicate for this LHS.  */
+/* Return the appropriate RHS predicate for this LHS.  */
 
 gimple_predicate
 rhs_predicate_for (tree lhs)
@@ -3610,8 +3739,6 @@ optimize_compound_literals_in_ctor (tree orig_ctor)
   return ctor;
 }
 
-
-
 /* A subroutine of gimplify_modify_expr.  Break out elements of a
    CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
 
@@ -3658,9 +3785,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
     case ARRAY_TYPE:
       {
        struct gimplify_init_ctor_preeval_data preeval_data;
-       HOST_WIDE_INT num_type_elements, num_ctor_elements;
-       HOST_WIDE_INT num_nonzero_elements;
-       bool cleared, valid_const_initializer;
+       HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
+       bool cleared, complete_p, valid_const_initializer;
 
        /* Aggregate types must lower constructors to initialization of
           individual elements.  The exception is that a CONSTRUCTOR node
@@ -3677,7 +3803,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
           can only do so if it known to be a valid constant initializer.  */
        valid_const_initializer
          = categorize_ctor_elements (ctor, &num_nonzero_elements,
-                                     &num_ctor_elements, &cleared);
+                                     &num_ctor_elements, &complete_p);
 
        /* If a const aggregate variable is being initialized, then it
           should never be a lose to promote the variable to be static.  */
@@ -3715,26 +3841,29 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
           parts in, then generate code for the non-constant parts.  */
        /* TODO.  There's code in cp/typeck.c to do this.  */
 
-       num_type_elements = count_type_elements (type, true);
-
-       /* If count_type_elements could not determine number of type elements
-          for a constant-sized object, assume clearing is needed.
-          Don't do this for variable-sized objects, as store_constructor
-          will ignore the clearing of variable-sized objects.  */
-       if (num_type_elements < 0 && int_size_in_bytes (type) >= 0)
+       if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
+         /* store_constructor will ignore the clearing of variable-sized
+            objects.  Initializers for such objects must explicitly set
+            every field that needs to be set.  */
+         cleared = false;
+       else if (!complete_p)
+         /* If the constructor isn't complete, clear the whole object
+            beforehand.
+
+            ??? This ought not to be needed.  For any element not present
+            in the initializer, we should simply set them to zero.  Except
+            we'd need to *find* the elements that are not present, and that
+            requires trickery to avoid quadratic compile-time behavior in
+            large cases or excessive memory use in small cases.  */
          cleared = true;
-       /* If there are "lots" of zeros, then block clear the object first.  */
-       else if (num_type_elements - num_nonzero_elements
+       else if (num_ctor_elements - num_nonzero_elements
                 > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
-                && num_nonzero_elements < num_type_elements/4)
-         cleared = true;
-       /* ??? This bit ought not be needed.  For any element not present
-          in the initializer, we should simply set them to zero.  Except
-          we'd need to *find* the elements that are not present, and that
-          requires trickery to avoid quadratic compile-time behavior in
-          large cases or excessive memory use in small cases.  */
-       else if (num_ctor_elements < num_type_elements)
+                && num_nonzero_elements < num_ctor_elements / 4)
+         /* If there are "lots" of zeros, it's more efficient to clear
+            the memory and then set the nonzero elements.  */
          cleared = true;
+       else
+         cleared = false;
 
        /* If there are "lots" of initialized elements, and all of them
           are valid address constants, then the entire initializer can
@@ -3776,8 +3905,11 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                if (notify_temp_creation)
                  return GS_ERROR;
 
-               walk_tree (&ctor, force_labels_r, NULL, NULL);
-               TREE_OPERAND (*expr_p, 1) = tree_output_constant_def (ctor);
+               walk_tree (&ctor, force_labels_r, NULL, NULL);
+               ctor = tree_output_constant_def (ctor);
+               if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
+                 ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
+               TREE_OPERAND (*expr_p, 1) = ctor;
 
                /* This is no longer an assignment of a CONSTRUCTOR, but
                   we still may have processing to do on the LHS.  So
@@ -3786,11 +3918,12 @@ 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 the target is volatile, we have non-zero elements and more than
+          one field to assign, initialize the target from a temporary.  */
        if (TREE_THIS_VOLATILE (object)
            && !TREE_ADDRESSABLE (type)
-           && num_nonzero_elements > 0)
+           && num_nonzero_elements > 0
+           && VEC_length (constructor_elt, elts) > 1)
          {
            tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type), NULL);
            TREE_OPERAND (*expr_p, 0) = temp;
@@ -3852,7 +3985,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        i = VEC_index (constructor_elt, elts, 1)->value;
        if (r == NULL || i == NULL)
          {
-           tree zero = fold_convert (TREE_TYPE (type), integer_zero_node);
+           tree zero = build_zero_cst (TREE_TYPE (type));
            if (r == NULL)
              r = zero;
            if (i == NULL)
@@ -3921,7 +4054,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
        /* Vector types use CONSTRUCTOR all the way through gimple
          compilation as a general initializer.  */
-       for (ix = 0; VEC_iterate (constructor_elt, elts, ix, ce); ix++)
+       FOR_EACH_VEC_ELT (constructor_elt, elts, ix, ce)
          {
            enum gimplify_status tret;
            tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
@@ -3972,7 +4105,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 tree
 gimple_fold_indirect_ref (tree t)
 {
-  tree type = TREE_TYPE (TREE_TYPE (t));
+  tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
   tree sub = t;
   tree subtype;
 
@@ -4015,51 +4148,53 @@ gimple_fold_indirect_ref (tree t)
         }
     }
 
-  /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+  /* *(p + CST) -> ...  */
   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;
+      tree addr = TREE_OPERAND (sub, 0);
+      tree off = TREE_OPERAND (sub, 1);
+      tree addrtype;
+
+      STRIP_NOPS (addr);
+      addrtype = TREE_TYPE (addr);
 
-      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))))
+      /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */
+      if (TREE_CODE (addr) == ADDR_EXPR
+         && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
+         && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype)))
+         && host_integerp (off, 1))
        {
-         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);
+          unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1);
+          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 (addrtype)))
+            return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 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;
+      /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */
+      if (TREE_CODE (addr) == ADDR_EXPR
+         && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE
+         && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
+        {
+          tree size = TYPE_SIZE_UNIT (type);
+          if (tree_int_cst_equal (size, off))
+            return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0));
+        }
 
-      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));
-       }
+      /* *(p + CST) -> MEM_REF <p, CST>.  */
+      if (TREE_CODE (addr) != ADDR_EXPR
+         || DECL_P (TREE_OPERAND (addr, 0)))
+       return fold_build2 (MEM_REF, type,
+                           addr,
+                           build_int_cst_wide (ptype,
+                                               TREE_INT_CST_LOW (off),
+                                               TREE_INT_CST_HIGH (off)));
     }
 
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
@@ -4157,9 +4292,18 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
             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.  */
+           bool volatile_p = TREE_THIS_VOLATILE (*from_p);
            tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
            if (t)
              {
+               if (TREE_THIS_VOLATILE (t) != volatile_p)
+                 {
+                   if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
+                     t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
+                                                   build_fold_addr_expr (t));
+                   if (REFERENCE_CLASS_P (t))
+                     TREE_THIS_VOLATILE (t) = volatile_p;
+                 }
                *from_p = t;
                ret = GS_OK;
                changed = true;
@@ -4200,6 +4344,10 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
          break;
 
        case CONSTRUCTOR:
+         /* If we already made some changes, let the front end have a
+            crack at this before we break it down.  */
+         if (ret != GS_UNHANDLED)
+           break;
          /* 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,
@@ -4256,10 +4404,10 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
              if (!(rhs_predicate_for (*to_p))(*from_p))
                /* If we need a temporary, *to_p isn't accurate.  */
                use_target = false;
+             /* It's OK to use the return slot directly unless it's an NRV. */
              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)))
@@ -4269,7 +4417,14 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
                /* It's OK to use the target directly if it's being
                   initialized. */
                use_target = true;
-             else if (!is_gimple_non_addressable (*to_p))
+             else if (variably_modified_type_p (TREE_TYPE (*to_p), NULL_TREE))
+               /* Always use the target and thus RSO for variable-sized types.
+                  GIMPLE cannot deal with a variable-sized assignment
+                  embedded in a call statement.  */
+               use_target = true;
+             else if (TREE_CODE (*to_p) != SSA_NAME
+                     && (!is_gimple_variable (*to_p)
+                         || needs_to_live_in_memory (*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
@@ -4358,7 +4513,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
   return ret;
 }
 
-
 /* Promote partial stores to COMPLEX variables to total stores.  *EXPR_P is
    a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a variable with
    DECL_GIMPLE_REG_P set.
@@ -4385,6 +4539,7 @@ gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
 
   ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
   other = build1 (ocode, TREE_TYPE (rhs), lhs);
+  TREE_NO_WARNING (other) = 1;
   other = get_formal_tmp_var (other, pre_p);
 
   realpart = code == REALPART_EXPR ? rhs : other;
@@ -4401,7 +4556,6 @@ gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
   return GS_ALL_DONE;
 }
 
-
 /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
 
       modify_expr
@@ -4430,6 +4584,16 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
              || TREE_CODE (*expr_p) == INIT_EXPR);
 
+  /* Trying to simplify a clobber using normal logic doesn't work,
+     so handle it here.  */
+  if (TREE_CLOBBER_P (*from_p))
+    {
+      gcc_assert (!want_value && TREE_CODE (*to_p) == VAR_DECL);
+      gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
+      *expr_p = NULL;
+      return GS_ALL_DONE;
+    }
+
   /* Insert pointer conversions required by the middle-end that are not
      required by the frontend.  This fixes middle-end type checking for
      for example gcc.dg/redecl-6.c.  */
@@ -4523,7 +4687,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   /* Try to alleviate the effects of the gimplification creating artificial
      temporaries (see for example is_gimple_reg_rhs) on the debug info.  */
   if (!gimplify_ctxp->into_ssa
-      && DECL_P (*from_p)
+      && TREE_CODE (*from_p) == VAR_DECL
       && DECL_IGNORED_P (*from_p)
       && DECL_P (*to_p)
       && !DECL_IGNORED_P (*to_p))
@@ -4535,11 +4699,18 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       SET_DECL_DEBUG_EXPR (*from_p, *to_p);
    }
 
+  if (want_value && TREE_THIS_VOLATILE (*to_p))
+    *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
+
   if (TREE_CODE (*from_p) == CALL_EXPR)
     {
       /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
         instead of a GIMPLE_ASSIGN.  */
+      tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
+      CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
+      STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
       assign = gimple_build_call_from_tree (*from_p);
+      gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
       if (!gimple_call_noreturn_p (assign))
        gimple_call_set_lhs (assign, *to_p);
     }
@@ -4562,7 +4733,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
   if (want_value)
     {
-      *expr_p = unshare_expr (*to_p);
+      *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
       return GS_OK;
     }
   else
@@ -4571,32 +4742,35 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   return GS_ALL_DONE;
 }
 
-/*  Gimplify a comparison between two variable-sized objects.  Do this
-    with a call to BUILT_IN_MEMCMP.  */
+/* Gimplify a comparison between two variable-sized objects.  Do this
+   with a call to BUILT_IN_MEMCMP.  */
 
 static enum gimplify_status
 gimplify_variable_sized_compare (tree *expr_p)
 {
+  location_t loc = EXPR_LOCATION (*expr_p);
   tree op0 = TREE_OPERAND (*expr_p, 0);
   tree op1 = TREE_OPERAND (*expr_p, 1);
-  tree t, arg, dest, src;
-  location_t loc = EXPR_LOCATION (*expr_p);
+  tree t, arg, dest, src, expr;
 
   arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
   arg = unshare_expr (arg);
   arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
   src = build_fold_addr_expr_loc (loc, op1);
   dest = build_fold_addr_expr_loc (loc, op0);
-  t = implicit_built_in_decls[BUILT_IN_MEMCMP];
+  t = builtin_decl_implicit (BUILT_IN_MEMCMP);
   t = build_call_expr_loc (loc, t, 3, dest, src, arg);
-  *expr_p
+
+  expr
     = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
+  SET_EXPR_LOCATION (expr, loc);
+  *expr_p = expr;
 
   return GS_OK;
 }
 
-/*  Gimplify a comparison between two aggregate objects of integral scalar
-    mode as a comparison between the bitwise equivalent scalar values.  */
+/* Gimplify a comparison between two aggregate objects of integral scalar
+   mode as a comparison between the bitwise equivalent scalar values.  */
 
 static enum gimplify_status
 gimplify_scalar_mode_aggregate_compare (tree *expr_p)
@@ -4617,33 +4791,8 @@ gimplify_scalar_mode_aggregate_compare (tree *expr_p)
   return GS_OK;
 }
 
-/*  Gimplify TRUTH_ANDIF_EXPR and TRUTH_ORIF_EXPR expressions.  EXPR_P
-    points to the expression to gimplify.
-
-    Expressions of the form 'a && b' are gimplified to:
-
-       a && b ? true : false
-
-    LOCUS is the source location to be put on the generated COND_EXPR.
-    gimplify_cond_expr will do the rest.  */
-
-static enum gimplify_status
-gimplify_boolean_expr (tree *expr_p, location_t locus)
-{
-  /* Preserve the original type of the expression.  */
-  tree type = TREE_TYPE (*expr_p);
-
-  *expr_p = build3 (COND_EXPR, type, *expr_p,
-                   fold_convert_loc (locus, type, boolean_true_node),
-                   fold_convert_loc (locus, type, boolean_false_node));
-
-  SET_EXPR_LOCATION (*expr_p, locus);
-
-  return GS_OK;
-}
-
-/* Gimplifies an expression sequence.  This function gimplifies each
-   expression and re-writes the original expression with the last
+/* Gimplify an expression sequence.  This function gimplifies each
+   expression and rewrites the original expression with the last
    expression of the sequence in GIMPLE form.
 
    PRE_P points to the list where the side effects for all the
@@ -4679,13 +4828,12 @@ gimplify_compound_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
     }
 }
 
-
 /* Gimplify a SAVE_EXPR node.  EXPR_P points to the expression to
    gimplify.  After gimplification, EXPR_P will point to a new temporary
    that holds the original value of the SAVE_EXPR node.
 
    PRE_P points to the list where side effects that must happen before
-      *EXPR_P should be stored.  */
+   *EXPR_P should be stored.  */
 
 static enum gimplify_status
 gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
@@ -4720,7 +4868,7 @@ gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
   return ret;
 }
 
-/*  Re-write the ADDR_EXPR node pointed to by EXPR_P
+/* Rewrite the ADDR_EXPR node pointed to by EXPR_P
 
       unary_expr
              : ...
@@ -4744,7 +4892,6 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
   switch (TREE_CODE (op0))
     {
     case INDIRECT_REF:
-    case MISALIGNED_INDIRECT_REF:
     do_indirect_ref:
       /* Check if we are dealing with an expression of the form '&*ptr'.
         While the front end folds away '&*ptr' into 'ptr', these
@@ -5014,6 +5161,13 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
       /* If the operand is a memory input, it should be an lvalue.  */
       if (!allows_reg && allows_mem)
        {
+         tree inputv = TREE_VALUE (link);
+         STRIP_NOPS (inputv);
+         if (TREE_CODE (inputv) == PREDECREMENT_EXPR
+             || TREE_CODE (inputv) == PREINCREMENT_EXPR
+             || TREE_CODE (inputv) == POSTDECREMENT_EXPR
+             || TREE_CODE (inputv) == POSTINCREMENT_EXPR)
+           TREE_VALUE (link) = error_mark_node;
          tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
                                is_gimple_lvalue, fb_lvalue | fb_mayfail);
          mark_addressable (TREE_VALUE (link));
@@ -5085,13 +5239,16 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
      any cleanups collected outside the CLEANUP_POINT_EXPR.  */
   int old_conds = gimplify_ctxp->conditions;
   gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
+  bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
   gimplify_ctxp->conditions = 0;
   gimplify_ctxp->conditional_cleanups = NULL;
+  gimplify_ctxp->in_cleanup_point_expr = true;
 
   gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
 
   gimplify_ctxp->conditions = old_conds;
   gimplify_ctxp->conditional_cleanups = old_cleanups;
+  gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
 
   for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
     {
@@ -5103,9 +5260,10 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
            {
               /* Note that gsi_insert_seq_before and gsi_remove do not
                  scan operands, unlike some other sequence mutators.  */
-             gsi_insert_seq_before_without_update (&iter,
-                                                    gimple_wce_cleanup (wce),
-                                                    GSI_SAME_STMT);
+             if (!gimple_wce_cleanup_eh_only (wce))
+               gsi_insert_seq_before_without_update (&iter,
+                                                     gimple_wce_cleanup (wce),
+                                                     GSI_SAME_STMT);
              gsi_remove (&iter, true);
              break;
            }
@@ -5157,7 +5315,7 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p)
 
   /* Errors can result in improperly nested cleanups.  Which results in
      confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR.  */
-  if (errorcount || sorrycount)
+  if (seen_error ())
     return;
 
   if (gimple_conditional_context ())
@@ -5220,6 +5378,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
   if (init)
     {
+      tree cleanup = NULL_TREE;
+
       /* TARGET_EXPR temps aren't part of the enclosing block, so add it
         to the temps list.  Handle also variable length TARGET_EXPRs.  */
       if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST)
@@ -5254,8 +5414,31 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
       /* If needed, push the cleanup for the temp.  */
       if (TARGET_EXPR_CLEANUP (targ))
-       gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
-                            CLEANUP_EH_ONLY (targ), pre_p);
+       {
+         if (CLEANUP_EH_ONLY (targ))
+           gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
+                                CLEANUP_EH_ONLY (targ), pre_p);
+         else
+           cleanup = TARGET_EXPR_CLEANUP (targ);
+       }
+
+      /* Add a clobber for the temporary going out of scope, like
+        gimplify_bind_expr.  */
+      if (gimplify_ctxp->in_cleanup_point_expr
+         && needs_to_live_in_memory (temp))
+       {
+         tree clobber = build_constructor (TREE_TYPE (temp), NULL);
+         TREE_THIS_VOLATILE (clobber) = true;
+         clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
+         if (cleanup)
+           cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
+                             clobber);
+         else
+           cleanup = clobber;
+       }
+
+      if (cleanup)
+       gimple_push_cleanup (temp, cleanup, false, pre_p);
 
       /* Only expand this once.  */
       TREE_OPERAND (targ, 3) = init;
@@ -5290,7 +5473,6 @@ gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
   return last != gimple_seq_last (*seq_p);
 }
 
-
 /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
    to CTX.  If entries already exist, force them to be some flavor of private.
    If there is no enclosing parallel, do nothing.  */
@@ -5354,7 +5536,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
     case QUAL_UNION_TYPE:
       {
        tree field;
-       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+       for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
          if (TREE_CODE (field) == FIELD_DECL)
            {
              omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
@@ -5386,7 +5568,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
   unsigned int nflags;
   tree t;
 
-  if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+  if (error_operand_p (decl))
     return;
 
   /* Never elide decls whose type has TREE_ADDRESSABLE set.  This means
@@ -5450,7 +5632,8 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
         For local variables TYPE_SIZE_UNIT might not be gimplified yet,
         in this case omp_notice_variable will be called later
         on when it is gimplified.  */
-      else if (! (flags & GOVD_LOCAL))
+      else if (! (flags & GOVD_LOCAL)
+              && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
        omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
     }
   else if (lang_hooks.decls.omp_privatize_by_reference (decl))
@@ -5487,7 +5670,8 @@ omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
   n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
   if (n == NULL)
     {
-      error ("threadprivate variable %qE used in untied task", DECL_NAME (decl));
+      error ("threadprivate variable %qE used in untied task",
+            DECL_NAME (decl));
       error_at (ctx->location, "enclosing task");
       splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
     }
@@ -5509,7 +5693,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
   unsigned flags = in_code ? GOVD_SEEN : 0;
   bool ret = false, shared;
 
-  if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+  if (error_operand_p (decl))
     return false;
 
   /* Threadprivate variables are predetermined.  */
@@ -5548,7 +5732,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
        {
        case OMP_CLAUSE_DEFAULT_NONE:
          error ("%qE not specified in enclosing parallel",
-                DECL_NAME (decl));
+                DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
          if ((ctx->region_type & ORT_TASK) != 0)
            error_at (ctx->location, "enclosing task");
          else
@@ -5766,7 +5950,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 
        do_add:
          decl = OMP_CLAUSE_DECL (c);
-         if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+         if (error_operand_p (decl))
            {
              remove = true;
              break;
@@ -5825,7 +6009,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COPYPRIVATE:
          decl = OMP_CLAUSE_DECL (c);
-         if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+         if (error_operand_p (decl))
            {
              remove = true;
              break;
@@ -5843,6 +6027,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
            }
          break;
 
+       case OMP_CLAUSE_FINAL:
        case OMP_CLAUSE_IF:
          OMP_CLAUSE_OPERAND (c, 0)
            = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
@@ -5859,6 +6044,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        case OMP_CLAUSE_DEFAULT:
@@ -5999,6 +6185,8 @@ gimplify_adjust_omp_clauses (tree *list_p)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          break;
 
        default:
@@ -6324,10 +6512,10 @@ goa_lhs_expr_p (tree expr, tree addr)
   return false;
 }
 
-/* Walk *EXPR_P and replace
-   appearances of *LHS_ADDR with LHS_VAR.  If an expression does not involve
-   the lhs, evaluate it into a temporary.  Return 1 if the lhs appeared as
-   a subexpression, 0 if it did not, or -1 if an error was encountered.  */
+/* Walk *EXPR_P and replace appearances of *LHS_ADDR with LHS_VAR.  If an
+   expression does not involve the lhs, evaluate it into a temporary.
+   Return 1 if the lhs appeared as a subexpression, 0 if it did not,
+   or -1 if an error was encountered.  */
 
 static int
 goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
@@ -6360,11 +6548,22 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
        {
        case TRUTH_ANDIF_EXPR:
        case TRUTH_ORIF_EXPR:
+       case TRUTH_AND_EXPR:
+       case TRUTH_OR_EXPR:
+       case TRUTH_XOR_EXPR:
          saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
                                         lhs_addr, lhs_var);
+       case TRUTH_NOT_EXPR:
          saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
                                         lhs_addr, lhs_var);
          break;
+       case COMPOUND_EXPR:
+         /* Break out any preevaluations from cp_build_modify_expr.  */
+         for (; TREE_CODE (expr) == COMPOUND_EXPR;
+              expr = TREE_OPERAND (expr, 1))
+           gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
+         *expr_p = expr;
+         return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var);
        default:
          break;
        }
@@ -6384,37 +6583,103 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
   return saw_lhs;
 }
 
-
 /* Gimplify an OMP_ATOMIC statement.  */
 
 static enum gimplify_status
 gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
 {
   tree addr = TREE_OPERAND (*expr_p, 0);
-  tree rhs = TREE_OPERAND (*expr_p, 1);
+  tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
+            ? NULL : TREE_OPERAND (*expr_p, 1);
   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
   tree tmp_load;
+  gimple loadstmt, storestmt;
 
-   tmp_load = create_tmp_reg (type, NULL);
-   if (goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
-     return GS_ERROR;
+  tmp_load = create_tmp_reg (type, NULL);
+  if (rhs && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
+    return GS_ERROR;
+
+  if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
+      != GS_ALL_DONE)
+    return GS_ERROR;
 
-   if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
-       != GS_ALL_DONE)
-     return GS_ERROR;
+  loadstmt = gimple_build_omp_atomic_load (tmp_load, addr);
+  gimplify_seq_add_stmt (pre_p, loadstmt);
+  if (rhs && gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
+      != GS_ALL_DONE)
+    return GS_ERROR;
 
-   gimplify_seq_add_stmt (pre_p, gimple_build_omp_atomic_load (tmp_load, addr));
-   if (gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
-       != GS_ALL_DONE)
-     return GS_ERROR;
-   gimplify_seq_add_stmt (pre_p, gimple_build_omp_atomic_store (rhs));
-   *expr_p = NULL;
+  if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
+    rhs = tmp_load;
+  storestmt = gimple_build_omp_atomic_store (rhs);
+  gimplify_seq_add_stmt (pre_p, storestmt);
+  switch (TREE_CODE (*expr_p))
+    {
+    case OMP_ATOMIC_READ:
+    case OMP_ATOMIC_CAPTURE_OLD:
+      *expr_p = tmp_load;
+      gimple_omp_atomic_set_need_value (loadstmt);
+      break;
+    case OMP_ATOMIC_CAPTURE_NEW:
+      *expr_p = rhs;
+      gimple_omp_atomic_set_need_value (storestmt);
+      break;
+    default:
+      *expr_p = NULL;
+      break;
+    }
 
    return GS_ALL_DONE;
 }
 
+/* Gimplify a TRANSACTION_EXPR.  This involves gimplification of the
+   body, and adding some EH bits.  */
 
-/* Converts the GENERIC expression tree *EXPR_P to GIMPLE.  If the
+static enum gimplify_status
+gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
+{
+  tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
+  gimple g;
+  gimple_seq body = NULL;
+  struct gimplify_ctx gctx;
+  int subcode = 0;
+
+  /* Wrap the transaction body in a BIND_EXPR so we have a context
+     where to put decls for OpenMP.  */
+  if (TREE_CODE (tbody) != BIND_EXPR)
+    {
+      tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
+      TREE_SIDE_EFFECTS (bind) = 1;
+      SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
+      TRANSACTION_EXPR_BODY (expr) = bind;
+    }
+
+  push_gimplify_context (&gctx);
+  temp = voidify_wrapper_expr (*expr_p, NULL);
+
+  g = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
+  pop_gimplify_context (g);
+
+  g = gimple_build_transaction (body, NULL);
+  if (TRANSACTION_EXPR_OUTER (expr))
+    subcode = GTMA_IS_OUTER;
+  else if (TRANSACTION_EXPR_RELAXED (expr))
+    subcode = GTMA_IS_RELAXED;
+  gimple_transaction_set_subcode (g, subcode);
+
+  gimplify_seq_add_stmt (pre_p, g);
+
+  if (temp)
+    {
+      *expr_p = temp;
+      return GS_OK;
+    }
+
+  *expr_p = NULL_TREE;
+  return GS_ALL_DONE;
+}
+
+/* Convert the GENERIC expression tree *EXPR_P to GIMPLE.  If the
    expression produces a value to be used as an operand inside a GIMPLE
    statement, the value will be stored back in *EXPR_P.  This value will
    be a tree of class tcc_declaration, tcc_constant, tcc_reference or
@@ -6476,7 +6741,7 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
 
    GIMPLE_TEST_F points to a function that takes a tree T and
        returns nonzero if T is in the GIMPLE form requested by the
-       caller.  The GIMPLE predicates are in tree-gimple.c.
+       caller.  The GIMPLE predicates are in gimple.c.
 
    FALLBACK tells the function what sort of a temporary we want if
        gimplification cannot produce an expression that complies with
@@ -6525,7 +6790,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            || gimple_test_f == is_gimple_mem_rhs_or_call
            || gimple_test_f == is_gimple_reg_rhs
            || gimple_test_f == is_gimple_reg_rhs_or_call
-           || gimple_test_f == is_gimple_asm_val)
+           || gimple_test_f == is_gimple_asm_val
+          || gimple_test_f == is_gimple_mem_ref_addr)
     gcc_assert (fallback & fb_rvalue);
   else if (gimple_test_f == is_gimple_min_lval
           || gimple_test_f == is_gimple_lvalue)
@@ -6674,23 +6940,45 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
        case TRUTH_ANDIF_EXPR:
        case TRUTH_ORIF_EXPR:
-         /* Pass the source location of the outer expression.  */
-         ret = gimplify_boolean_expr (expr_p, saved_location);
-         break;
+         {
+           /* Preserve the original type of the expression and the
+              source location of the outer expression.  */
+           tree org_type = TREE_TYPE (*expr_p);
+           *expr_p = gimple_boolify (*expr_p);
+           *expr_p = build3_loc (input_location, COND_EXPR,
+                                 org_type, *expr_p,
+                                 fold_convert_loc
+                                   (input_location,
+                                    org_type, boolean_true_node),
+                                 fold_convert_loc
+                                   (input_location,
+                                    org_type, boolean_false_node));
+           ret = GS_OK;
+           break;
+         }
 
        case TRUTH_NOT_EXPR:
-         if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
-           {
-             tree type = TREE_TYPE (*expr_p);
-             *expr_p = fold_convert (type, gimple_boolify (*expr_p));
-             ret = GS_OK;
-             break;
-           }
-
-         ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-                              is_gimple_val, fb_rvalue);
-         recalculate_side_effects (*expr_p);
-         break;
+         {
+           tree type = TREE_TYPE (*expr_p);
+           /* The parsers are careful to generate TRUTH_NOT_EXPR
+              only with operands that are always zero or one.
+              We do not fold here but handle the only interesting case
+              manually, as fold may re-introduce the TRUTH_NOT_EXPR.  */
+           *expr_p = gimple_boolify (*expr_p);
+           if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
+             *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
+                                   TREE_TYPE (*expr_p),
+                                   TREE_OPERAND (*expr_p, 0));
+           else
+             *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
+                                   TREE_TYPE (*expr_p),
+                                   TREE_OPERAND (*expr_p, 0),
+                                   build_int_cst (TREE_TYPE (*expr_p), 1));
+           if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
+             *expr_p = fold_convert_loc (input_location, type, *expr_p);
+           ret = GS_OK;
+           break;
+         }
 
        case ADDR_EXPR:
          ret = gimplify_addr_expr (expr_p, pre_p, post_p);
@@ -6732,21 +7020,64 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          break;
 
        case INDIRECT_REF:
-         *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
-         if (*expr_p != save_expr)
+         {
+           bool volatilep = TREE_THIS_VOLATILE (*expr_p);
+           bool notrap = TREE_THIS_NOTRAP (*expr_p);
+           tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
+
+           *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
+           if (*expr_p != save_expr)
+             {
+               ret = GS_OK;
+               break;
+             }
+
+           ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+                                is_gimple_reg, fb_rvalue);
+           if (ret == GS_ERROR)
+             break;
+
+           recalculate_side_effects (*expr_p);
+           *expr_p = fold_build2_loc (input_location, MEM_REF,
+                                      TREE_TYPE (*expr_p),
+                                      TREE_OPERAND (*expr_p, 0),
+                                      build_int_cst (saved_ptr_type, 0));
+           TREE_THIS_VOLATILE (*expr_p) = volatilep;
+           TREE_THIS_NOTRAP (*expr_p) = notrap;
+           ret = GS_OK;
+           break;
+         }
+
+       /* We arrive here through the various re-gimplifcation paths.  */
+       case MEM_REF:
+         /* First try re-folding the whole thing.  */
+         tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
+                            TREE_OPERAND (*expr_p, 0),
+                            TREE_OPERAND (*expr_p, 1));
+         if (tmp)
            {
+             *expr_p = tmp;
+             recalculate_side_effects (*expr_p);
              ret = GS_OK;
              break;
            }
-         /* else fall through.  */
-       case ALIGN_INDIRECT_REF:
-       case MISALIGNED_INDIRECT_REF:
-         ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-                              is_gimple_reg, fb_rvalue);
+         /* Avoid re-gimplifying the address operand if it is already
+            in suitable form.  Re-gimplifying would mark the address
+            operand addressable.  Always gimplify when not in SSA form
+            as we still may have to gimplify decls with value-exprs.  */
+         if (!gimplify_ctxp || !gimplify_ctxp->into_ssa
+             || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
+           {
+             ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+                                  is_gimple_mem_ref_addr, fb_rvalue);
+             if (ret == GS_ERROR)
+               break;
+           }
          recalculate_side_effects (*expr_p);
+         ret = GS_ALL_DONE;
          break;
 
-         /* Constants need not be gimplified.  */
+       /* Constants need not be gimplified.  */
        case INTEGER_CST:
        case REAL_CST:
        case FIXED_CST:
@@ -6835,14 +7166,11 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          if (fallback == fb_none)
            {
              unsigned HOST_WIDE_INT ix;
-             constructor_elt *ce;
+             tree val;
              tree temp = NULL_TREE;
-             for (ix = 0;
-                  VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (*expr_p),
-                               ix, ce);
-                  ix++)
-               if (TREE_SIDE_EFFECTS (ce->value))
-                 append_to_statement_list (ce->value, &temp);
+             FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
+               if (TREE_SIDE_EFFECTS (val))
+                 append_to_statement_list (val, &temp);
 
              *expr_p = temp;
              ret = temp ? GS_OK : GS_ALL_DONE;
@@ -6890,15 +7218,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          {
            enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
 
-           if (TMR_SYMBOL (*expr_p))
-             r0 = gimplify_expr (&TMR_SYMBOL (*expr_p), pre_p,
-                                 post_p, is_gimple_lvalue, fb_either);
-           else if (TMR_BASE (*expr_p))
+           if (TMR_BASE (*expr_p))
              r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
-                                 post_p, is_gimple_val, fb_either);
+                                 post_p, is_gimple_mem_ref_addr, fb_either);
            if (TMR_INDEX (*expr_p))
              r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
                                  post_p, is_gimple_val, fb_rvalue);
+           if (TMR_INDEX2 (*expr_p))
+             r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
+                                 post_p, is_gimple_val, fb_rvalue);
            /* TMR_STEP and TMR_OFFSET are always integer constants.  */
            ret = MIN (r0, r1);
          }
@@ -7077,40 +7405,97 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          }
 
        case OMP_ATOMIC:
+       case OMP_ATOMIC_READ:
+       case OMP_ATOMIC_CAPTURE_OLD:
+       case OMP_ATOMIC_CAPTURE_NEW:
          ret = gimplify_omp_atomic (expr_p, pre_p);
          break;
 
+       case TRANSACTION_EXPR:
+         ret = gimplify_transaction (expr_p, pre_p);
+         break;
+
+       case TRUTH_AND_EXPR:
+       case TRUTH_OR_EXPR:
+       case TRUTH_XOR_EXPR:
+         {
+           tree orig_type = TREE_TYPE (*expr_p);
+           tree new_type, xop0, xop1;
+           *expr_p = gimple_boolify (*expr_p);
+           new_type = TREE_TYPE (*expr_p);
+           if (!useless_type_conversion_p (orig_type, new_type))
+             {
+               *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
+               ret = GS_OK;
+               break;
+             }
+
+         /* Boolified binary truth expressions are semantically equivalent
+            to bitwise binary expressions.  Canonicalize them to the
+            bitwise variant.  */
+           switch (TREE_CODE (*expr_p))
+             {
+             case TRUTH_AND_EXPR:
+               TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
+               break;
+             case TRUTH_OR_EXPR:
+               TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
+               break;
+             case TRUTH_XOR_EXPR:
+               TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
+               break;
+             default:
+               break;
+             }
+           /* Now make sure that operands have compatible type to
+              expression's new_type.  */
+           xop0 = TREE_OPERAND (*expr_p, 0);
+           xop1 = TREE_OPERAND (*expr_p, 1);
+           if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
+             TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
+                                                           new_type,
+                                                           xop0);
+           if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
+             TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
+                                                           new_type,
+                                                           xop1);
+           /* Continue classified as tcc_binary.  */
+           goto expr_2;
+         }
+
+       case FMA_EXPR:
+       case VEC_PERM_EXPR:
+         /* Classified as tcc_expression.  */
+         goto expr_3;
+
        case POINTER_PLUS_EXPR:
-          /* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
-            The second is gimple immediate saving a need for extra statement.
-          */
-         if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
-             && (tmp = maybe_fold_offset_to_address
-                 (EXPR_LOCATION (*expr_p),
-                  TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
-                  TREE_TYPE (*expr_p))))
-           {
-             *expr_p = tmp;
-             ret = GS_OK;
-             break;
-           }
-         /* Convert (void *)&a + 4 into (void *)&a[1].  */
-         if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR
-             && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
-             && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
-                                                                       0),0)))
-             && (tmp = maybe_fold_offset_to_address
-                 (EXPR_LOCATION (*expr_p),
-                  TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0),
-                  TREE_OPERAND (*expr_p, 1),
-                  TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0),
-                                           0)))))
-            {
-               *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp);
-              ret = GS_OK;
-              break;
-            }
-          /* FALLTHRU */
+         {
+           enum gimplify_status r0, r1;
+           r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+                               post_p, is_gimple_val, fb_rvalue);
+           r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+                               post_p, is_gimple_val, fb_rvalue);
+           recalculate_side_effects (*expr_p);
+           ret = MIN (r0, r1);
+           /* Convert &X + CST to invariant &MEM[&X, CST].  Do this
+              after gimplifying operands - this is similar to how
+              it would be folding all gimplified stmts on creation
+              to have them canonicalized, which is what we eventually
+              should do anyway.  */
+           if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
+               && is_gimple_min_invariant (TREE_OPERAND (*expr_p, 0)))
+             {
+               *expr_p = build_fold_addr_expr_with_type_loc
+                  (input_location,
+                   fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (*expr_p)),
+                                TREE_OPERAND (*expr_p, 0),
+                                fold_convert (ptr_type_node,
+                                              TREE_OPERAND (*expr_p, 1))),
+                   TREE_TYPE (*expr_p));
+               ret = MIN (ret, GS_OK);
+             }
+           break;
+         }
 
        default:
          switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
@@ -7128,8 +7513,23 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                {
                  tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
 
-                 if (!AGGREGATE_TYPE_P (type))
+                 /* Vector comparisons need no boolification.  */
+                 if (TREE_CODE (type) == VECTOR_TYPE)
                    goto expr_2;
+                 else if (!AGGREGATE_TYPE_P (type))
+                   {
+                     tree org_type = TREE_TYPE (*expr_p);
+                     *expr_p = gimple_boolify (*expr_p);
+                     if (!useless_type_conversion_p (org_type,
+                                                     TREE_TYPE (*expr_p)))
+                       {
+                         *expr_p = fold_convert_loc (input_location,
+                                                     org_type, *expr_p);
+                         ret = GS_OK;
+                       }
+                     else
+                       goto expr_2;
+                   }
                  else if (TYPE_MODE (type) != BLKmode)
                    ret = gimplify_scalar_mode_aggregate_compare (expr_p);
                  else
@@ -7159,16 +7559,28 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                break;
              }
 
+           expr_3:
+             {
+               enum gimplify_status r0, r1, r2;
+
+               r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+                                   post_p, is_gimple_val, fb_rvalue);
+               r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+                                   post_p, is_gimple_val, fb_rvalue);
+               r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
+                                   post_p, is_gimple_val, fb_rvalue);
+
+               ret = MIN (MIN (r0, r1), r2);
+               break;
+             }
+
            case tcc_declaration:
            case tcc_constant:
              ret = GS_ALL_DONE;
              goto dont_recalculate;
 
            default:
-             gcc_assert (TREE_CODE (*expr_p) == TRUTH_AND_EXPR
-                         || TREE_CODE (*expr_p) == TRUTH_OR_EXPR
-                         || TREE_CODE (*expr_p) == TRUTH_XOR_EXPR);
-             goto expr_2;
+             gcc_unreachable ();
            }
 
          recalculate_side_effects (*expr_p);
@@ -7340,7 +7752,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
         that temporary.  */
       tmp = build_fold_addr_expr_loc (input_location, *expr_p);
       gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
-      *expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp);
+      *expr_p = build_simple_mem_ref (tmp);
     }
   else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
     {
@@ -7441,7 +7853,10 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
       /* 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)
+      if (!(TYPE_NAME (type)
+           && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+           && DECL_IGNORED_P (TYPE_NAME (type)))
+         && TYPE_DOMAIN (type)
          && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
        {
          t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
@@ -7456,7 +7871,7 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        if (TREE_CODE (field) == FIELD_DECL)
          {
            gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
@@ -7538,26 +7953,22 @@ gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
       *expr_p = create_tmp_var (type, NULL);
       tmp = build1 (NOP_EXPR, type, expr);
       stmt = gimplify_assign (*expr_p, tmp, stmt_p);
-      if (EXPR_HAS_LOCATION (expr))
-       gimple_set_location (stmt, EXPR_LOCATION (expr));
-      else
-       gimple_set_location (stmt, input_location);
+      gimple_set_location (stmt, EXPR_LOC_OR_HERE (expr));
     }
 }
 
-
-/* Gimplify the body of statements pointed to by BODY_P and return a
-   GIMPLE_BIND containing the sequence of GIMPLE statements
-   corresponding to BODY_P.  FNDECL is the function decl containing
-   *BODY_P.  */
+/* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
+   containing the sequence of corresponding GIMPLE statements.  If DO_PARMS
+   is true, also gimplify the parameters.  */
 
 gimple
-gimplify_body (tree *body_p, tree fndecl, bool do_parms)
+gimplify_body (tree fndecl, bool do_parms)
 {
   location_t saved_location = input_location;
   gimple_seq parm_stmts, seq;
   gimple outer_bind;
   struct gimplify_ctx gctx;
+  struct cgraph_node *cgn;
 
   timevar_push (TV_TREE_GIMPLIFY);
 
@@ -7572,10 +7983,11 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
      It would seem we don't have to do this for nested functions because
      they are supposed to be output and then the outer function gimplified
      first, but the g++ front end doesn't always do it that way.  */
-  unshare_body (body_p, fndecl);
-  unvisit_body (body_p, fndecl);
+  unshare_body (fndecl);
+  unvisit_body (fndecl);
 
-  if (cgraph_node (fndecl)->origin)
+  cgn = cgraph_get_node (fndecl);
+  if (cgn && cgn->origin)
     nonlocal_vlas = pointer_set_create ();
 
   /* Make sure input_location isn't set to something weird.  */
@@ -7583,11 +7995,11 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
 
   /* Resolve callee-copies.  This has to be done before processing
      the body so that DECL_VALUE_EXPR gets processed correctly.  */
-  parm_stmts = (do_parms) ? gimplify_parameters () : NULL;
+  parm_stmts = do_parms ? gimplify_parameters () : NULL;
 
   /* Gimplify the function's body.  */
   seq = NULL;
-  gimplify_stmt (body_p, &seq);
+  gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
   outer_bind = gimple_seq_first_stmt (seq);
   if (!outer_bind)
     {
@@ -7603,7 +8015,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
   else
     outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
 
-  *body_p = NULL_TREE;
+  DECL_SAVED_TREE (fndecl) = NULL_TREE;
 
   /* If we had callee-copies statements, insert them at the beginning
      of the function and clear DECL_VALUE_EXPR_P on the parameters.  */
@@ -7615,7 +8027,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
       gimple_bind_set_body (outer_bind, parm_stmts);
 
       for (parm = DECL_ARGUMENTS (current_function_decl);
-          parm; parm = TREE_CHAIN (parm))
+          parm; parm = DECL_CHAIN (parm))
        if (DECL_HAS_VALUE_EXPR_P (parm))
          {
            DECL_HAS_VALUE_EXPR_P (parm) = 0;
@@ -7632,10 +8044,8 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
   pop_gimplify_context (outer_bind);
   gcc_assert (gimplify_ctxp == NULL);
 
-#ifdef ENABLE_TYPES_CHECKING
-  if (!errorcount && !sorrycount)
-    verify_types_in_gimple_seq (gimple_bind_body (outer_bind));
-#endif
+  if (!seen_error ())
+    verify_gimple_in_seq (gimple_bind_body (outer_bind));
 
   timevar_pop (TV_TREE_GIMPLIFY);
   input_location = saved_location;
@@ -7643,10 +8053,50 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
   return outer_bind;
 }
 
+typedef char *char_p; /* For DEF_VEC_P.  */
+DEF_VEC_P(char_p);
+DEF_VEC_ALLOC_P(char_p,heap);
+
+/* Return whether we should exclude FNDECL from instrumentation.  */
+
+static bool
+flag_instrument_functions_exclude_p (tree fndecl)
+{
+  VEC(char_p,heap) *vec;
+
+  vec = (VEC(char_p,heap) *) flag_instrument_functions_exclude_functions;
+  if (VEC_length (char_p, vec) > 0)
+    {
+      const char *name;
+      int i;
+      char *s;
+
+      name = lang_hooks.decl_printable_name (fndecl, 0);
+      FOR_EACH_VEC_ELT (char_p, vec, i, s)
+       if (strstr (name, s) != NULL)
+         return true;
+    }
+
+  vec = (VEC(char_p,heap) *) flag_instrument_functions_exclude_files;
+  if (VEC_length (char_p, vec) > 0)
+    {
+      const char *name;
+      int i;
+      char *s;
+
+      name = DECL_SOURCE_FILE (fndecl);
+      FOR_EACH_VEC_ELT (char_p, vec, i, s)
+       if (strstr (name, s) != NULL)
+         return true;
+    }
+
+  return false;
+}
+
 /* 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
+   Return the sequence of GIMPLE statements corresponding to the body
    of FNDECL.  */
 
 void
@@ -7665,7 +8115,7 @@ gimplify_function_tree (tree fndecl)
   else
     push_struct_function (fndecl);
 
-  for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = TREE_CHAIN (parm))
+  for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm))
     {
       /* Preliminarily mark non-addressed complex variables as eligible
          for promotion to gimple registers.  We'll transform their uses
@@ -7683,7 +8133,7 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
-  bind = gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl, true);
+  bind = gimplify_body (fndecl, true);
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */
@@ -7703,13 +8153,31 @@ gimplify_function_tree (tree fndecl)
       gimple new_bind;
       gimple tf;
       gimple_seq cleanup = NULL, body = NULL;
-
-      x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
-      gimplify_seq_add_stmt (&cleanup, gimple_build_call (x, 0));
+      tree tmp_var;
+      gimple call;
+
+      x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
+      call = gimple_build_call (x, 1, integer_zero_node);
+      tmp_var = create_tmp_var (ptr_type_node, "return_addr");
+      gimple_call_set_lhs (call, tmp_var);
+      gimplify_seq_add_stmt (&cleanup, call);
+      x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_EXIT);
+      call = gimple_build_call (x, 2,
+                               build_fold_addr_expr (current_function_decl),
+                               tmp_var);
+      gimplify_seq_add_stmt (&cleanup, call);
       tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
 
-      x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
-      gimplify_seq_add_stmt (&body, gimple_build_call (x, 0));
+      x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
+      call = gimple_build_call (x, 1, integer_zero_node);
+      tmp_var = create_tmp_var (ptr_type_node, "return_addr");
+      gimple_call_set_lhs (call, tmp_var);
+      gimplify_seq_add_stmt (&body, call);
+      x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_ENTER);
+      call = gimple_build_call (x, 2,
+                               build_fold_addr_expr (current_function_decl),
+                               tmp_var);
+      gimplify_seq_add_stmt (&body, call);
       gimplify_seq_add_stmt (&body, tf);
       new_bind = gimple_build_bind (NULL, body, gimple_bind_block (bind));
       /* Clear the block for BIND, since it is no longer directly inside
@@ -7730,7 +8198,6 @@ gimplify_function_tree (tree fndecl)
   pop_cfun ();
 }
 
-
 /* Some transformations like inlining may invalidate the GIMPLE form
    for operands.  This function traverses all the operands in STMT and
    gimplifies anything that is not a valid gimple operand.  Any new
@@ -7920,27 +8387,27 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
   pop_gimplify_context (NULL);
 }
 
-
-/* Expands EXPR to list of gimple statements STMTS.  If SIMPLE is true,
-   force the result to be either ssa_name or an invariant, otherwise
-   just force it to be a rhs expression.  If VAR is not NULL, make the
+/* Expand EXPR to list of gimple statements STMTS.  GIMPLE_TEST_F specifies
+   the predicate that will hold for the result.  If VAR is not NULL, make the
    base variable of the final destination be VAR if suitable.  */
 
 tree
-force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
+force_gimple_operand_1 (tree expr, gimple_seq *stmts,
+                       gimple_predicate gimple_test_f, tree var)
 {
   tree t;
   enum gimplify_status ret;
-  gimple_predicate gimple_test_f;
   struct gimplify_ctx gctx;
 
   *stmts = NULL;
 
-  if (is_gimple_val (expr))
+  /* gimple_test_f might be more strict than is_gimple_val, make
+     sure we pass both.  Just checking gimple_test_f doesn't work
+     because most gimple predicates do not work recursively.  */
+  if (is_gimple_val (expr)
+      && (*gimple_test_f) (expr))
     return expr;
 
-  gimple_test_f = simple ? is_gimple_val : is_gimple_reg_rhs;
-
   push_gimplify_context (&gctx);
   gimplify_ctxp->into_ssa = gimple_in_ssa_p (cfun);
   gimplify_ctxp->allow_rhs_cond_expr = true;
@@ -7961,7 +8428,7 @@ force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
     }
 
   if (gimple_referenced_vars (cfun))
-    for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
+    for (t = gimplify_ctxp->temps; t ; t = DECL_CHAIN (t))
       add_referenced_var (t);
 
   pop_gimplify_context (NULL);
@@ -7969,20 +8436,34 @@ force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
   return expr;
 }
 
-/* Invokes force_gimple_operand for EXPR with parameters SIMPLE_P and VAR.  If
-   some statements are produced, emits them at GSI.  If BEFORE is true.
-   the statements are appended before GSI, otherwise they are appended after
-   it.  M specifies the way GSI moves after insertion (GSI_SAME_STMT or
-   GSI_CONTINUE_LINKING are the usual values).  */
+/* Expand EXPR to list of gimple statements STMTS.  If SIMPLE is true,
+   force the result to be either ssa_name or an invariant, otherwise
+   just force it to be a rhs expression.  If VAR is not NULL, make the
+   base variable of the final destination be VAR if suitable.  */
 
 tree
-force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
-                         bool simple_p, tree var, bool before,
-                         enum gsi_iterator_update m)
+force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
+{
+  return force_gimple_operand_1 (expr, stmts,
+                                simple ? is_gimple_val : is_gimple_reg_rhs,
+                                var);
+}
+
+/* Invoke force_gimple_operand_1 for EXPR with parameters GIMPLE_TEST_F
+   and VAR.  If some statements are produced, emits them at GSI.
+   If BEFORE is true.  the statements are appended before GSI, otherwise
+   they are appended after it.  M specifies the way GSI moves after
+   insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING are the usual values).  */
+
+tree
+force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr,
+                           gimple_predicate gimple_test_f,
+                           tree var, bool before,
+                           enum gsi_iterator_update m)
 {
   gimple_seq stmts;
 
-  expr = force_gimple_operand (expr, &stmts, simple_p, var);
+  expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var);
 
   if (!gimple_seq_empty_p (stmts))
     {
@@ -8003,4 +8484,24 @@ force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
   return expr;
 }
 
+/* Invoke force_gimple_operand_1 for EXPR with parameter VAR.
+   If SIMPLE is true, force the result to be either ssa_name or an invariant,
+   otherwise just force it to be a rhs expression.  If some statements are
+   produced, emits them at GSI.  If BEFORE is true, the statements are
+   appended before GSI, otherwise they are appended after it.  M specifies
+   the way GSI moves after insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING
+   are the usual values).  */
+
+tree
+force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
+                         bool simple_p, tree var, bool before,
+                         enum gsi_iterator_update m)
+{
+  return force_gimple_operand_gsi_1 (gsi, expr,
+                                    simple_p
+                                    ? is_gimple_val : is_gimple_reg_rhs,
+                                    var, before, m);
+}
+
+
 #include "gt-gimplify.h"