OSDN Git Service

2010-09-09 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index 7f1dc4a..5953160 100644 (file)
@@ -1,6 +1,6 @@
 /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
    tree representation into the GIMPLE form.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Major work done by Sebastian Pop <s.pop@laposte.net>,
    Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
@@ -26,34 +26,31 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
-#include "varray.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 "diagnostic-core.h"
 #include "toplev.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
 {
@@ -75,9 +72,10 @@ enum gimplify_omp_var_data
 enum omp_region_type
 {
   ORT_WORKSHARE = 0,
-  ORT_TASK = 1,
   ORT_PARALLEL = 2,
-  ORT_COMBINED_PARALLEL = 3
+  ORT_COMBINED_PARALLEL = 3,
+  ORT_TASK = 4,
+  ORT_UNTIED_TASK = 5
 };
 
 struct gimplify_omp_ctx
@@ -113,10 +111,13 @@ 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;
 }
 
@@ -158,7 +159,7 @@ gimple_tree_eq (const void *p1, const void *p2)
    During gimplification, we need to manipulate statement sequences
    before the def/use vectors have been constructed.  */
 
-static void
+void
 gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
 {
   gimple_stmt_iterator si;
@@ -319,7 +320,7 @@ new_omp_context (enum omp_region_type region_type)
   c->privatized_types = pointer_set_create ();
   c->location = input_location;
   c->region_type = region_type;
-  if (region_type != ORT_TASK)
+  if ((region_type & ORT_TASK) == 0)
     c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
   else
     c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
@@ -340,47 +341,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.  */
@@ -508,6 +468,23 @@ create_tmp_var (tree type, const char *prefix)
   return tmp_var;
 }
 
+/* Create a new temporary variable declaration of type TYPE by calling
+   create_tmp_var and if TYPE is a vector or a complex number, mark the new
+   temporary as gimple register.  */
+
+tree
+create_tmp_reg (tree type, const char *prefix)
+{
+  tree tmp;
+
+  tmp = create_tmp_var (type, prefix);
+  if (TREE_CODE (type) == COMPLEX_TYPE
+      || TREE_CODE (type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (tmp) = 1;
+
+  return tmp;
+}
+
 /* Create a temporary with a name derived from VAL.  Subroutine of
    lookup_tmp_var; nobody else should call this function.  */
 
@@ -561,7 +538,7 @@ lookup_tmp_var (tree val, bool is_formal)
 
 
 /* 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.  */
 
@@ -676,7 +653,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
@@ -724,7 +701,7 @@ force_constant_size (tree var)
 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
@@ -737,7 +714,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.  */
@@ -777,23 +754,6 @@ should_carry_location_p (gimple gs)
   return true;
 }
 
-/* Same, but for a tree.  */
-
-static bool
-tree_should_carry_location_p (const_tree stmt)
-{
-  /* Don't emit a line note for a label.  We particularly don't want to
-     emit one for the break label, since it doesn't actually correspond
-     to the beginning of the loop/switch.  */
-  if (TREE_CODE (stmt) == LABEL_EXPR)
-    return false;
-
-  /* Do not annotate empty statements, since it confuses gcov.  */
-  if (!TREE_SIDE_EFFECTS (stmt))
-    return false;
-
-  return true;
-}
 
 /* Return true if a location should not be emitted for this statement
    by annotate_one_with_location.  */
@@ -820,22 +780,12 @@ gimple_set_do_not_emit_location (gimple g)
 static void
 annotate_one_with_location (gimple gs, location_t location)
 {
-  if (!gimple_has_location (gs) 
+  if (!gimple_has_location (gs)
       && !gimple_do_not_emit_location_p (gs)
       && should_carry_location_p (gs))
     gimple_set_location (gs, location);
 }
 
-/* Same, but for tree T.  */
-
-static void
-tree_annotate_one_with_location (tree t, location_t location)
-{
-  if (CAN_HAVE_LOCATION_P (t)
-      && ! EXPR_HAS_LOCATION (t) && tree_should_carry_location_p (t))
-    SET_EXPR_LOCATION (t, location);
-}
-
 
 /* Set LOCATION for all the statements after iterator GSI in sequence
    SEQ.  If GSI is pointing to the end of the sequence, start with the
@@ -871,32 +821,44 @@ annotate_all_with_location (gimple_seq stmt_p, location_t location)
       annotate_one_with_location (gs, location);
     }
 }
-
-/* Same, but for statement or statement list in *STMT_P.  */
-
-void
-tree_annotate_all_with_location (tree *stmt_p, location_t location)
-{
-  tree_stmt_iterator i;
-
-  if (!*stmt_p)
-    return;
-
-  for (i = tsi_start (*stmt_p); !tsi_end_p (i); tsi_next (&i))
-    {
-      tree t = tsi_stmt (i);
-
-      /* Assuming we've already been gimplified, we shouldn't
-         see nested chaining constructs anymore.  */
-      gcc_assert (TREE_CODE (t) != STATEMENT_LIST
-                 && TREE_CODE (t) != COMPOUND_EXPR);
-
-      tree_annotate_one_with_location (t, location);
-    }
-}
-
-
-/* Similar to copy_tree_r() but do not copy SAVE_EXPR or TARGET_EXPR nodes.
+\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 should only be done once.  If we
    were to unshare something like SAVE_EXPR(i++), the gimplification
    process would create wrong code.  */
@@ -904,38 +866,47 @@ tree_annotate_all_with_location (tree *stmt_p, location_t location)
 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.  */
+   then *TP is deep copied by calling mostly_copy_tree_r.  */
 
 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);
@@ -958,27 +929,29 @@ 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;
 }
 
-static tree
-unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
-                 void *data ATTRIBUTE_UNUSED)
-{
-  if (TREE_VISITED (*tp))
-    TREE_VISITED (*tp) = 0;
-  else
-    *walk_subtrees = 0;
+/* Unshare most of the shared trees rooted at *TP. */
 
-  return NULL_TREE;
+static inline void
+copy_if_shared (tree *tp)
+{
+  /* 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;
+  walk_tree (tp, copy_if_shared_r, visited, NULL);
+  if (visited)
+    pointer_set_destroy (visited);
 }
 
 /* Unshare all the trees in BODY_P, a pointer into the body of FNDECL, and the
@@ -990,12 +963,40 @@ unshare_body (tree *body_p, tree fndecl)
 {
   struct cgraph_node *cgn = cgraph_node (fndecl);
 
-  walk_tree (body_p, copy_if_shared_r, NULL, NULL);
+  copy_if_shared (body_p);
+
   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);
 }
 
+/* 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, void *data ATTRIBUTE_UNUSED)
+{
+  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;
+}
+
+/* Unmark the visited trees rooted at *TP.  */
+
+static inline void
+unmark_visited (tree *tp)
+{
+  walk_tree (tp, unmark_visited_r, NULL, NULL);
+}
+
 /* Likewise, but mark all trees as not visited.  */
 
 static void
@@ -1003,7 +1004,8 @@ unvisit_body (tree *body_p, tree fndecl)
 {
   struct cgraph_node *cgn = cgraph_node (fndecl);
 
-  walk_tree (body_p, unmark_visited_r, NULL, NULL);
+  unmark_visited (body_p);
+
   if (body_p == &DECL_SAVED_TREE (fndecl))
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
       unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
@@ -1131,7 +1133,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
   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)
        {
@@ -1152,14 +1154,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))
@@ -1262,17 +1259,27 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
      hard_function_value generates a PARALLEL, we'll die during normal
      expansion of structure assignments; there's special code in expand_return
      to handle this case that does not exist in expand_expr.  */
-  if (!result_decl
-      || aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
-    result = result_decl;
+  if (!result_decl)
+    result = NULL_TREE;
+  else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
+    {
+      if (TREE_CODE (DECL_SIZE (result_decl)) != INTEGER_CST)
+       {
+         if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
+           gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
+         /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
+            should be effectively allocated by the caller, i.e. all calls to
+            this function must be subject to the Return Slot Optimization.  */
+         gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
+         gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
+       }
+      result = result_decl;
+    }
   else if (gimplify_ctxp->return_temp)
     result = gimplify_ctxp->return_temp;
   else
     {
-      result = create_tmp_var (TREE_TYPE (result_decl), NULL);
-      if (TREE_CODE (TREE_TYPE (result)) == COMPLEX_TYPE
-          || TREE_CODE (TREE_TYPE (result)) == VECTOR_TYPE)
-        DECL_GIMPLE_REG_P (result) = 1;
+      result = create_tmp_reg (TREE_TYPE (result_decl), NULL);
 
       /* ??? With complex control flow (usually involving abnormal edges),
         we can wind up warning about an uninitialized value for this.  Due
@@ -1322,6 +1329,8 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
 
   t = built_in_decls[BUILT_IN_ALLOCA];
   t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
+  /* The call has been built for a variable-sized object.  */
+  ALLOCA_FOR_VAR_P (t) = 1;
   t = fold_convert (ptr_type, t);
   t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
 
@@ -1495,12 +1504,12 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
       tree default_case = NULL_TREE;
       size_t i, len;
       gimple gimple_switch;
-      
+
       /* If someone can be bothered to fill in the labels, they can
         be bothered to null out the body too.  */
       gcc_assert (!SWITCH_LABELS (switch_expr));
 
-      /* save old labels, get new ones from body, then restore the old 
+      /* save old labels, get new ones from body, then restore the old
          labels.  Save all the things from the switch body to append after.  */
       saved_labels = gimplify_ctxp->case_labels;
       gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8);
@@ -1508,7 +1517,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
       gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
       labels = gimplify_ctxp->case_labels;
       gimplify_ctxp->case_labels = saved_labels;
+
       i = 0;
       while (i < VEC_length (tree, labels))
        {
@@ -1597,7 +1606,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
            }
        }
 
-      gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr), 
+      gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr),
                                                default_case, labels);
       gimplify_seq_add_stmt (pre_p, gimple_switch);
       gimplify_seq_add_seq (pre_p, switch_body_seq);
@@ -1843,7 +1852,7 @@ gimplify_conversion (tree *expr_p)
 /* Nonlocal VLAs seen in the current function.  */
 static struct pointer_set_t *nonlocal_vlas;
 
-/* Gimplify a VAR_DECL or PARM_DECL.  Returns GS_OK if we expanded a 
+/* Gimplify a VAR_DECL or PARM_DECL.  Returns GS_OK if we expanded a
    DECL_VALUE_EXPR, and it's worth re-examining things.  */
 
 static enum gimplify_status
@@ -1862,7 +1871,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;
     }
 
@@ -1892,10 +1901,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;
@@ -1938,9 +1947,10 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 {
   tree *p;
   VEC(tree,heap) *stack;
-  enum gimplify_status ret = GS_OK, tret;
+  enum gimplify_status ret = GS_ALL_DONE, tret;
   int i;
   location_t loc = EXPR_LOCATION (*expr_p);
+  tree expr = *expr_p;
 
   /* Create a stack of the subexpressions so later we can walk them in
      order from inner to outer.  */
@@ -1963,7 +1973,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        goto restart;
       else
        break;
-              
+
       VEC_safe_push (tree, heap, stack, *p);
     }
 
@@ -2094,11 +2104,12 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF)
     {
       canonicalize_component_ref (expr_p);
-      ret = MIN (ret, GS_OK);
     }
 
   VEC_free (tree, heap, stack);
 
+  gcc_assert (*expr_p == expr || ret != GS_ALL_DONE);
+
   return ret;
 }
 
@@ -2322,7 +2333,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
              *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
              return GS_OK;
            }
-         
+
          if (fold_builtin_next_arg (*expr_p, true))
            {
              *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
@@ -2770,6 +2781,36 @@ gimple_boolify (tree expr)
   tree type = TREE_TYPE (expr);
   location_t loc = EXPR_LOCATION (expr);
 
+  if (TREE_CODE (expr) == NE_EXPR
+      && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
+      && integer_zerop (TREE_OPERAND (expr, 1)))
+    {
+      tree call = TREE_OPERAND (expr, 0);
+      tree fn = get_callee_fndecl (call);
+
+      /* For __builtin_expect ((long) (x), y) recurse into x as well
+        if x is truth_value_p.  */
+      if (fn
+         && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
+         && DECL_FUNCTION_CODE (fn) == BUILT_IN_EXPECT
+         && call_expr_nargs (call) == 2)
+       {
+         tree arg = CALL_EXPR_ARG (call, 0);
+         if (arg)
+           {
+             if (TREE_CODE (arg) == NOP_EXPR
+                 && TREE_TYPE (arg) == TREE_TYPE (call))
+               arg = TREE_OPERAND (arg, 0);
+             if (truth_value_p (TREE_CODE (arg)))
+               {
+                 arg = gimple_boolify (arg);
+                 CALL_EXPR_ARG (call, 0)
+                   = fold_convert_loc (loc, TREE_TYPE (call), arg);
+               }
+           }
+       }
+    }
+
   if (TREE_CODE (type) == BOOLEAN_TYPE)
     return expr;
 
@@ -2873,71 +2914,67 @@ static enum gimplify_status
 gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
 {
   tree expr = *expr_p;
-  tree tmp, type, arm1, arm2;
+  tree type = TREE_TYPE (expr);
+  location_t loc = EXPR_LOCATION (expr);
+  tree tmp, arm1, arm2;
   enum gimplify_status ret;
   tree label_true, label_false, label_cont;
   bool have_then_clause_p, have_else_clause_p;
   gimple gimple_cond;
   enum tree_code pred_code;
   gimple_seq seq = NULL;
-  location_t loc = EXPR_LOCATION (*expr_p);
-
-  type = TREE_TYPE (expr);
 
   /* If this COND_EXPR has a value, copy the values into a temporary within
      the arms.  */
-  if (! VOID_TYPE_P (type))
+  if (!VOID_TYPE_P (type))
     {
+      tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
       tree result;
 
-      /* If an rvalue is ok or we do not require an lvalue, avoid creating
-        an addressable temporary.  */
-      if (((fallback & fb_rvalue)
-          || !(fallback & fb_lvalue))
+      /* If either an rvalue is ok or we do not require an lvalue, create the
+        temporary.  But we cannot do that if the type is addressable.  */
+      if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
          && !TREE_ADDRESSABLE (type))
        {
          if (gimplify_ctxp->allow_rhs_cond_expr
              /* If either branch has side effects or could trap, it can't be
                 evaluated unconditionally.  */
-             && !TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1))
-             && !generic_expr_could_trap_p (TREE_OPERAND (*expr_p, 1))
-             && !TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 2))
-             && !generic_expr_could_trap_p (TREE_OPERAND (*expr_p, 2)))
+             && !TREE_SIDE_EFFECTS (then_)
+             && !generic_expr_could_trap_p (then_)
+             && !TREE_SIDE_EFFECTS (else_)
+             && !generic_expr_could_trap_p (else_))
            return gimplify_pure_cond_expr (expr_p, pre_p);
 
-         result = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
-         ret = GS_ALL_DONE;
+         tmp = create_tmp_var (type, "iftmp");
+         result = tmp;
        }
+
+      /* Otherwise, only create and copy references to the values.  */
       else
        {
-         tree type = build_pointer_type (TREE_TYPE (expr));
+         type = build_pointer_type (type);
 
-         if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node)
-           TREE_OPERAND (expr, 1) =
-             build_fold_addr_expr_loc (loc, TREE_OPERAND (expr, 1));
+         if (!VOID_TYPE_P (TREE_TYPE (then_)))
+           then_ = build_fold_addr_expr_loc (loc, then_);
 
-         if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
-           TREE_OPERAND (expr, 2) =
-             build_fold_addr_expr_loc (loc, TREE_OPERAND (expr, 2));
+         if (!VOID_TYPE_P (TREE_TYPE (else_)))
+           else_ = build_fold_addr_expr_loc (loc, else_);
+         expr
+           = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
 
          tmp = create_tmp_var (type, "iftmp");
-
-         expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (expr, 0),
-                        TREE_OPERAND (expr, 1), TREE_OPERAND (expr, 2));
-
-         result = build_fold_indirect_ref_loc (loc, tmp);
+         result = build_simple_mem_ref_loc (loc, tmp);
        }
 
-      /* Build the then clause, 't1 = a;'.  But don't build an assignment
-        if this branch is void; in C++ it can be, if it's a throw.  */
-      if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node)
-       TREE_OPERAND (expr, 1)
-         = build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, TREE_OPERAND (expr, 1));
+      /* Build the new then clause, `tmp = then_;'.  But don't build the
+        assignment if the value is void; in C++ it can be if it's a throw.  */
+      if (!VOID_TYPE_P (TREE_TYPE (then_)))
+       TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, then_);
 
-      /* Build the else clause, 't1 = b;'.  */
-      if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
-       TREE_OPERAND (expr, 2)
-         = build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, TREE_OPERAND (expr, 2));
+      /* Similarly, build the new else clause, `tmp = else_;'.  */
+      if (!VOID_TYPE_P (TREE_TYPE (else_)))
+       TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, else_);
 
       TREE_TYPE (expr) = void_type_node;
       recalculate_side_effects (expr);
@@ -3151,7 +3188,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;
     }
 
@@ -3175,7 +3212,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
   /* Assert our assumptions, to abort instead of producing wrong code
      silently if they are not met.  Beware that the RHS CONSTRUCTOR might
      not be immediately exposed.  */
-  from = TREE_OPERAND (*expr_p, 1);  
+  from = TREE_OPERAND (*expr_p, 1);
   if (TREE_CODE (from) == WITH_SIZE_EXPR)
     from = TREE_OPERAND (from, 0);
 
@@ -3235,13 +3272,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)));
@@ -3290,7 +3330,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;
@@ -3408,18 +3448,18 @@ gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
 }
 
 /* Return true if FDECL is accessing a field that is zero sized.  */
-   
+
 static bool
 zero_sized_field_decl (const_tree fdecl)
 {
-  if (TREE_CODE (fdecl) == FIELD_DECL && DECL_SIZE (fdecl) 
+  if (TREE_CODE (fdecl) == FIELD_DECL && DECL_SIZE (fdecl)
       && integer_zerop (DECL_SIZE (fdecl)))
     return true;
   return false;
 }
 
 /* Return true if TYPE is zero sized.  */
-   
+
 static bool
 zero_sized_type (const_tree type)
 {
@@ -3666,7 +3706,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              return GS_OK;
            break;
          }
+
        /* Fetch information about the constructor to direct later processing.
           We might want to make static versions of it in various cases, and
           can only do so if it known to be a valid constant initializer.  */
@@ -3768,25 +3808,14 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                && num_nonzero_elements > 1
                && !can_move_by_pieces (size, align))
              {
-               tree new_tree;
-
                if (notify_temp_creation)
                  return GS_ERROR;
 
-               new_tree = create_tmp_var_raw (type, "C");
-
-               gimple_add_tmp_var (new_tree);
-               TREE_STATIC (new_tree) = 1;
-               TREE_READONLY (new_tree) = 1;
-               DECL_INITIAL (new_tree) = ctor;
-               if (align > DECL_ALIGN (new_tree))
-                 {
-                   DECL_ALIGN (new_tree) = align;
-                   DECL_USER_ALIGN (new_tree) = 1;
-                 }
-               walk_tree (&DECL_INITIAL (new_tree), force_labels_r, NULL, NULL);
-
-               TREE_OPERAND (*expr_p, 1) = new_tree;
+               walk_tree (&ctor, force_labels_r, NULL, NULL);
+               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
@@ -3795,13 +3824,29 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              }
          }
 
+       /* 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
+           && VEC_length (constructor_elt, elts) > 1)
+         {
+           tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type), NULL);
+           TREE_OPERAND (*expr_p, 0) = temp;
+           *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
+                             *expr_p,
+                             build2 (MODIFY_EXPR, void_type_node,
+                                     object, temp));
+           return GS_OK;
+         }
+
        if (notify_temp_creation)
          return GS_OK;
 
-       /* If there are nonzero elements, pre-evaluate to capture elements
-          overlapping with the lhs into temporaries.  We must do this before
-          clearing to fetch the values before they are zeroed-out.  */
-       if (num_nonzero_elements > 0)
+       /* If there are nonzero elements and if needed, pre-evaluate to capture
+          elements overlapping with the lhs into temporaries.  We must do this
+          before clearing to fetch the values before they are zeroed-out.  */
+       if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
          {
            preeval_data.lhs_base_decl = get_base_address (object);
            if (!DECL_P (preeval_data.lhs_base_decl))
@@ -3915,7 +3960,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,
@@ -3966,11 +4011,11 @@ 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;
 
-  STRIP_USELESS_TYPE_CONVERSION (sub);
+  STRIP_NOPS (sub);
   subtype = TREE_TYPE (sub);
   if (!POINTER_TYPE_P (subtype))
     return NULL_TREE;
@@ -3985,18 +4030,81 @@ gimple_fold_indirect_ref (tree t)
 
       /* *(foo *)&fooarray => fooarray[0] */
       if (TREE_CODE (optype) == ARRAY_TYPE
+         && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST
          && useless_type_conversion_p (type, TREE_TYPE (optype)))
        {
          tree type_domain = TYPE_DOMAIN (optype);
          tree min_val = size_zero_node;
          if (type_domain && TYPE_MIN_VALUE (type_domain))
            min_val = TYPE_MIN_VALUE (type_domain);
-         return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+        if (TREE_CODE (min_val) == INTEGER_CST)
+          return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
        }
+      /* *(foo *)&complexfoo => __real__ complexfoo */
+      else if (TREE_CODE (optype) == COMPLEX_TYPE
+               && useless_type_conversion_p (type, TREE_TYPE (optype)))
+        return fold_build1 (REALPART_EXPR, type, op);
+      /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
+      else if (TREE_CODE (optype) == VECTOR_TYPE
+               && useless_type_conversion_p (type, TREE_TYPE (optype)))
+        {
+          tree part_width = TYPE_SIZE (type);
+          tree index = bitsize_int (0);
+          return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
+        }
+    }
+
+  /* *(p + CST) -> ...  */
+  if (TREE_CODE (sub) == POINTER_PLUS_EXPR
+      && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+    {
+      tree addr = TREE_OPERAND (sub, 0);
+      tree off = TREE_OPERAND (sub, 1);
+      tree addrtype;
+
+      STRIP_NOPS (addr);
+      addrtype = TREE_TYPE (addr);
+
+      /* ((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_WIDE_INT offset = tree_low_cst (off, 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 (addrtype)))
+            return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
+                                part_width, index);
+       }
+
+      /* ((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));
+        }
+
+      /* *(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] */
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
+      && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST
       && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     {
       tree type_domain;
@@ -4008,7 +4116,8 @@ gimple_fold_indirect_ref (tree t)
       type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
       if (type_domain && TYPE_MIN_VALUE (type_domain))
         min_val = TYPE_MIN_VALUE (type_domain);
-      return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
+      if (TREE_CODE (min_val) == INTEGER_CST)
+       return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
     }
 
   return NULL_TREE;
@@ -4036,241 +4145,259 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
                          gimple_seq *pre_p, gimple_seq *post_p,
                          bool want_value)
 {
-  enum gimplify_status ret = GS_OK;
+  enum gimplify_status ret = GS_UNHANDLED;
+  bool changed;
 
-  while (ret != GS_UNHANDLED)
-    switch (TREE_CODE (*from_p))
-      {
-      case VAR_DECL:
-       /* If we're assigning from a read-only variable initialized with
-          a constructor, do the direct assignment from the constructor,
-          but only if neither source nor target are volatile since this
-          latter assignment might end up being done on a per-field basis.  */
-       if (DECL_INITIAL (*from_p)
-           && TREE_READONLY (*from_p)
-           && !TREE_THIS_VOLATILE (*from_p)
-           && !TREE_THIS_VOLATILE (*to_p)
-           && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR)
+  do
+    {
+      changed = false;
+      switch (TREE_CODE (*from_p))
+       {
+       case VAR_DECL:
+         /* If we're assigning from a read-only variable initialized with
+            a constructor, do the direct assignment from the constructor,
+            but only if neither source nor target are volatile since this
+            latter assignment might end up being done on a per-field basis.  */
+         if (DECL_INITIAL (*from_p)
+             && TREE_READONLY (*from_p)
+             && !TREE_THIS_VOLATILE (*from_p)
+             && !TREE_THIS_VOLATILE (*to_p)
+             && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR)
+           {
+             tree old_from = *from_p;
+             enum gimplify_status subret;
+
+             /* Move the constructor into the RHS.  */
+             *from_p = unshare_expr (DECL_INITIAL (*from_p));
+
+             /* Let's see if gimplify_init_constructor will need to put
+                it in memory.  */
+             subret = gimplify_init_constructor (expr_p, NULL, NULL,
+                                                 false, true);
+             if (subret == GS_ERROR)
+               {
+                 /* If so, revert the change.  */
+                 *from_p = old_from;
+               }
+             else
+               {
+                 ret = GS_OK;
+                 changed = true;
+               }
+           }
+         break;
+       case INDIRECT_REF:
          {
-           tree old_from = *from_p;
+           /* If we have code like
 
-           /* Move the constructor into the RHS.  */
-           *from_p = unshare_expr (DECL_INITIAL (*from_p));
+            *(const A*)(A*)&x
 
-           /* Let's see if gimplify_init_constructor will need to put
-              it in memory.  If so, revert the change.  */
-           ret = gimplify_init_constructor (expr_p, NULL, NULL, false, true);
-           if (ret == GS_ERROR)
+            where the type of "x" is a (possibly cv-qualified variant
+            of "A"), treat the entire expression as identical to "x".
+            This kind of code arises in C++ when an object is bound
+            to a const reference, and if "x" is a TARGET_EXPR we want
+            to take advantage of the optimization below.  */
+           tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
+           if (t)
              {
-               *from_p = old_from;
-               /* Fall through.  */
+               *from_p = t;
+               ret = GS_OK;
+               changed = true;
              }
-           else
+           break;
+         }
+
+       case TARGET_EXPR:
+         {
+           /* If we are initializing something from a TARGET_EXPR, strip the
+              TARGET_EXPR and initialize it directly, if possible.  This can't
+              be done if the initializer is void, since that implies that the
+              temporary is set in some non-trivial way.
+
+              ??? What about code that pulls out the temp and uses it
+              elsewhere? I think that such code never uses the TARGET_EXPR as
+              an initializer.  If I'm wrong, we'll die because the temp won't
+              have any RTL.  In that case, I guess we'll need to replace
+              references somehow.  */
+           tree init = TARGET_EXPR_INITIAL (*from_p);
+
+           if (init
+               && !VOID_TYPE_P (TREE_TYPE (init)))
              {
+               *from_p = init;
                ret = GS_OK;
-               break;
+               changed = true;
              }
          }
-       ret = GS_UNHANDLED;
-       break;
-      case INDIRECT_REF:
-       {
-         /* If we have code like 
+         break;
 
-               *(const A*)(A*)&x
+       case COMPOUND_EXPR:
+         /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
+            caught.  */
+         gimplify_compound_expr (from_p, pre_p, true);
+         ret = GS_OK;
+         changed = true;
+         break;
 
-            where the type of "x" is a (possibly cv-qualified variant
-            of "A"), treat the entire expression as identical to "x".
-            This kind of code arises in C++ when an object is bound
-            to a const reference, and if "x" is a TARGET_EXPR we want
-            to take advantage of the optimization below.  */
-         tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
-         if (t)
+       case CONSTRUCTOR:
+         /* If we 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,
+                                           false);
+
+       case COND_EXPR:
+         /* If we're assigning to a non-register type, push the assignment
+            down into the branches.  This is mandatory for ADDRESSABLE types,
+            since we cannot generate temporaries for such, but it saves a
+            copy in other cases as well.  */
+         if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
            {
-             *from_p = t;
-             ret = GS_OK;
+             /* This code should mirror the code in gimplify_cond_expr. */
+             enum tree_code code = TREE_CODE (*expr_p);
+             tree cond = *from_p;
+             tree result = *to_p;
+
+             ret = gimplify_expr (&result, pre_p, post_p,
+                                  is_gimple_lvalue, fb_lvalue);
+             if (ret != GS_ERROR)
+               ret = GS_OK;
+
+             if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
+               TREE_OPERAND (cond, 1)
+                 = build2 (code, void_type_node, result,
+                           TREE_OPERAND (cond, 1));
+             if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
+               TREE_OPERAND (cond, 2)
+                 = build2 (code, void_type_node, unshare_expr (result),
+                           TREE_OPERAND (cond, 2));
+
+             TREE_TYPE (cond) = void_type_node;
+             recalculate_side_effects (cond);
+
+             if (want_value)
+               {
+                 gimplify_and_add (cond, pre_p);
+                 *expr_p = unshare_expr (result);
+               }
+             else
+               *expr_p = cond;
+             return ret;
            }
-         else
-           ret = GS_UNHANDLED;
          break;
-       }
 
-      case TARGET_EXPR:
-       {
-         /* If we are initializing something from a TARGET_EXPR, strip the
-            TARGET_EXPR and initialize it directly, if possible.  This can't
-            be done if the initializer is void, since that implies that the
-            temporary is set in some non-trivial way.
-
-            ??? What about code that pulls out the temp and uses it
-            elsewhere? I think that such code never uses the TARGET_EXPR as
-            an initializer.  If I'm wrong, we'll die because the temp won't
-            have any RTL.  In that case, I guess we'll need to replace
-            references somehow.  */
-         tree init = TARGET_EXPR_INITIAL (*from_p);
-
-         if (init
-             && !VOID_TYPE_P (TREE_TYPE (init)))
+       case CALL_EXPR:
+         /* For calls that return in memory, give *to_p as the CALL_EXPR's
+            return slot so that we don't generate a temporary.  */
+         if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
+             && aggregate_value_p (*from_p, *from_p))
            {
-             *from_p = init;
-             ret = GS_OK;
+             bool use_target;
+
+             if (!(rhs_predicate_for (*to_p))(*from_p))
+               /* If we need a temporary, *to_p isn't accurate.  */
+               use_target = false;
+             else if (TREE_CODE (*to_p) == RESULT_DECL
+                      && DECL_NAME (*to_p) == NULL_TREE
+                      && needs_to_live_in_memory (*to_p))
+               /* It's OK to use the return slot directly unless it's an NRV. */
+               use_target = true;
+             else if (is_gimple_reg_type (TREE_TYPE (*to_p))
+                      || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
+               /* Don't force regs into memory.  */
+               use_target = false;
+             else if (TREE_CODE (*expr_p) == INIT_EXPR)
+               /* It's OK to use the target directly if it's being
+                  initialized. */
+               use_target = true;
+             else if (!is_gimple_non_addressable (*to_p))
+               /* Don't use the original target if it's already addressable;
+                  if its address escapes, and the called function uses the
+                  NRV optimization, a conforming program could see *to_p
+                  change before the called function returns; see c++/19317.
+                  When optimizing, the return_slot pass marks more functions
+                  as safe after we have escape info.  */
+               use_target = false;
+             else
+               use_target = true;
+
+             if (use_target)
+               {
+                 CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
+                 mark_addressable (*to_p);
+               }
            }
-         else
-           ret = GS_UNHANDLED;
-       }
-       break;
+         break;
 
-      case COMPOUND_EXPR:
-       /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
-          caught.  */
-       gimplify_compound_expr (from_p, pre_p, true);
-       ret = GS_OK;
-       break;
+       case WITH_SIZE_EXPR:
+         /* Likewise for calls that return an aggregate of non-constant size,
+            since we would not be able to generate a temporary at all.  */
+         if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
+           {
+             *from_p = TREE_OPERAND (*from_p, 0);
+             /* We don't change ret in this case because the
+                WITH_SIZE_EXPR might have been added in
+                gimplify_modify_expr, so returning GS_OK would lead to an
+                infinite loop.  */
+             changed = true;
+           }
+         break;
 
-      case CONSTRUCTOR:
-       /* If we're initializing from a CONSTRUCTOR, break this into
-          individual MODIFY_EXPRs.  */
-       return gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
-                                         false);
-
-      case COND_EXPR:
-       /* If we're assigning to a non-register type, push the assignment
-          down into the branches.  This is mandatory for ADDRESSABLE types,
-          since we cannot generate temporaries for such, but it saves a
-          copy in other cases as well.  */
-       if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
+         /* If we're initializing from a container, push the initialization
+            inside it.  */
+       case CLEANUP_POINT_EXPR:
+       case BIND_EXPR:
+       case STATEMENT_LIST:
          {
-           /* This code should mirror the code in gimplify_cond_expr. */
-           enum tree_code code = TREE_CODE (*expr_p);
-           tree cond = *from_p;
-           tree result = *to_p;
+           tree wrap = *from_p;
+           tree t;
 
-           ret = gimplify_expr (&result, pre_p, post_p,
-                                is_gimple_lvalue, fb_lvalue);
+           ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
+                                fb_lvalue);
            if (ret != GS_ERROR)
              ret = GS_OK;
 
-           if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
-             TREE_OPERAND (cond, 1)
-               = build2 (code, void_type_node, result,
-                         TREE_OPERAND (cond, 1));
-           if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
-             TREE_OPERAND (cond, 2)
-               = build2 (code, void_type_node, unshare_expr (result),
-                         TREE_OPERAND (cond, 2));
-
-           TREE_TYPE (cond) = void_type_node;
-           recalculate_side_effects (cond);
+           t = voidify_wrapper_expr (wrap, *expr_p);
+           gcc_assert (t == *expr_p);
 
            if (want_value)
              {
-               gimplify_and_add (cond, pre_p);
-               *expr_p = unshare_expr (result);
+               gimplify_and_add (wrap, pre_p);
+               *expr_p = unshare_expr (*to_p);
              }
            else
-             *expr_p = cond;
-           return ret;
+             *expr_p = wrap;
+           return GS_OK;
          }
-       else
-         ret = GS_UNHANDLED;
-       break;
 
-      case CALL_EXPR:
-       /* For calls that return in memory, give *to_p as the CALL_EXPR's
-          return slot so that we don't generate a temporary.  */
-       if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
-           && aggregate_value_p (*from_p, *from_p))
+       case COMPOUND_LITERAL_EXPR:
          {
-           bool use_target;
-
-           if (!(rhs_predicate_for (*to_p))(*from_p))
-             /* If we need a temporary, *to_p isn't accurate.  */
-             use_target = false;
-           else if (TREE_CODE (*to_p) == RESULT_DECL
-                    && DECL_NAME (*to_p) == NULL_TREE
-                    && needs_to_live_in_memory (*to_p))
-             /* It's OK to use the return slot directly unless it's an NRV. */
-             use_target = true;
-           else if (is_gimple_reg_type (TREE_TYPE (*to_p))
-                    || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
-             /* Don't force regs into memory.  */
-             use_target = false;
-           else if (TREE_CODE (*expr_p) == INIT_EXPR)
-             /* It's OK to use the target directly if it's being
-                initialized. */
-             use_target = true;
-           else if (!is_gimple_non_addressable (*to_p))
-             /* Don't use the original target if it's already addressable;
-                if its address escapes, and the called function uses the
-                NRV optimization, a conforming program could see *to_p
-                change before the called function returns; see c++/19317.
-                When optimizing, the return_slot pass marks more functions
-                as safe after we have escape info.  */
-             use_target = false;
-           else
-             use_target = true;
-
-           if (use_target)
+           tree complit = TREE_OPERAND (*expr_p, 1);
+           tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
+           tree decl = DECL_EXPR_DECL (decl_s);
+           tree init = DECL_INITIAL (decl);
+
+           /* struct T x = (struct T) { 0, 1, 2 } can be optimized
+              into struct T x = { 0, 1, 2 } if the address of the
+              compound literal has never been taken.  */
+           if (!TREE_ADDRESSABLE (complit)
+               && !TREE_ADDRESSABLE (decl)
+               && init)
              {
-               CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
-               mark_addressable (*to_p);
+               *expr_p = copy_node (*expr_p);
+               TREE_OPERAND (*expr_p, 1) = init;
+               return GS_OK;
              }
          }
 
-       ret = GS_UNHANDLED;
-       break;
-
-       /* If we're initializing from a container, push the initialization
-          inside it.  */
-      case CLEANUP_POINT_EXPR:
-      case BIND_EXPR:
-      case STATEMENT_LIST:
-       {
-         tree wrap = *from_p;
-         tree t;
-
-         ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
-                              fb_lvalue);
-         if (ret != GS_ERROR)
-           ret = GS_OK;
-
-         t = voidify_wrapper_expr (wrap, *expr_p);
-         gcc_assert (t == *expr_p);
-
-         if (want_value)
-           {
-             gimplify_and_add (wrap, pre_p);
-             *expr_p = unshare_expr (*to_p);
-           }
-         else
-           *expr_p = wrap;
-         return GS_OK;
-       }
-       
-      case COMPOUND_LITERAL_EXPR:
-       {
-         tree complit = TREE_OPERAND (*expr_p, 1);
-         tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
-         tree decl = DECL_EXPR_DECL (decl_s);
-         tree init = DECL_INITIAL (decl);
-
-         /* struct T x = (struct T) { 0, 1, 2 } can be optimized
-            into struct T x = { 0, 1, 2 } if the address of the
-            compound literal has never been taken.  */
-         if (!TREE_ADDRESSABLE (complit)
-             && !TREE_ADDRESSABLE (decl)
-             && init)
-           {
-             *expr_p = copy_node (*expr_p);
-             TREE_OPERAND (*expr_p, 1) = init;
-             return GS_OK;
-           }
+       default:
+         break;
        }
-
-      default:
-       ret = GS_UNHANDLED;
-       break;
-      }
+    }
+  while (changed);
 
   return ret;
 }
@@ -4440,7 +4567,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))
@@ -4452,12 +4579,16 @@ 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.  */
       assign = gimple_build_call_from_tree (*from_p);
-      gimple_call_set_lhs (assign, *to_p);
+      if (!gimple_call_noreturn_p (assign))
+       gimple_call_set_lhs (assign, *to_p);
     }
   else
     {
@@ -4478,7 +4609,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
@@ -4660,7 +4791,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
@@ -4765,13 +4895,14 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
   VEC(tree, gc) *inputs;
   VEC(tree, gc) *outputs;
   VEC(tree, gc) *clobbers;
+  VEC(tree, gc) *labels;
   tree link_next;
-  
+
   expr = *expr_p;
   noutputs = list_length (ASM_OUTPUTS (expr));
   oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
 
-  inputs = outputs = clobbers = NULL;
+  inputs = outputs = clobbers = labels = NULL;
 
   ret = GS_ALL_DONE;
   link_next = NULL_TREE;
@@ -4951,15 +5082,18 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
       TREE_CHAIN (link) = NULL_TREE;
       VEC_safe_push (tree, gc, inputs, link);
     }
-  
+
   for (link = ASM_CLOBBERS (expr); link; ++i, link = TREE_CHAIN (link))
-      VEC_safe_push (tree, gc, clobbers, link);
+    VEC_safe_push (tree, gc, clobbers, link);
+
+  for (link = ASM_LABELS (expr); link; ++i, link = TREE_CHAIN (link))
+    VEC_safe_push (tree, gc, labels, link);
 
   /* Do not add ASMs with errors to the gimple IL stream.  */
   if (ret != GS_ERROR)
     {
       stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
-                                  inputs, outputs, clobbers);
+                                  inputs, outputs, clobbers, labels);
 
       gimple_asm_set_volatile (stmt, ASM_VOLATILE_P (expr));
       gimple_asm_set_input (stmt, ASM_INPUT_P (expr));
@@ -5015,9 +5149,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;
            }
@@ -5069,7 +5204,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 ())
@@ -5266,7 +5401,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));
@@ -5323,7 +5458,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
     }
 
   /* When adding a variable-sized variable, we have to handle all sorts
-     of additional bits of data: the pointer replacement variable, and 
+     of additional bits of data: the pointer replacement variable, and
      the parameters of the type.  */
   if (DECL_SIZE (decl) && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
     {
@@ -5355,7 +5490,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
        flags = GOVD_PRIVATE | GOVD_DEBUG_PRIVATE
                | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
 
-      /* We're going to make use of the TYPE_SIZE_UNIT at least in the 
+      /* We're going to make use of the TYPE_SIZE_UNIT at least in the
         alloca statement we generate for the variable, so make sure it
         is available.  This isn't automatically needed for the SHARED
         case, since we won't be allocating local storage then.
@@ -5383,6 +5518,31 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
   splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags);
 }
 
+/* Notice a threadprivate variable DECL used in OpenMP context CTX.
+   This just prints out diagnostics about threadprivate variable uses
+   in untied tasks.  If DECL2 is non-NULL, prevent this warning
+   on that variable.  */
+
+static bool
+omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
+                                  tree decl2)
+{
+  splay_tree_node n;
+
+  if (ctx->region_type != ORT_UNTIED_TASK)
+    return false;
+  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_at (ctx->location, "enclosing task");
+      splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
+    }
+  if (decl2)
+    splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0);
+  return false;
+}
+
 /* Record the fact that DECL was used within the OpenMP context CTX.
    IN_CODE is true when real code uses DECL, and false when we should
    merely emit default(none) errors.  Return true if DECL is going to
@@ -5403,14 +5563,14 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
   if (is_global_var (decl))
     {
       if (DECL_THREAD_LOCAL_P (decl))
-       return false;
+       return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
 
       if (DECL_HAS_VALUE_EXPR_P (decl))
        {
          tree value = get_base_address (DECL_VALUE_EXPR (decl));
 
          if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
-           return false;
+           return omp_notice_threadprivate_variable (ctx, decl, value);
        }
     }
 
@@ -5435,8 +5595,11 @@ 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));
-         error_at (ctx->location, "enclosing parallel");
+                DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
+         if ((ctx->region_type & ORT_TASK) != 0)
+           error_at (ctx->location, "enclosing task");
+         else
+           error_at (ctx->location, "enclosing parallel");
          /* FALLTHRU */
        case OMP_CLAUSE_DEFAULT_SHARED:
          flags |= GOVD_SHARED;
@@ -5449,7 +5612,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
          break;
        case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
          /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED.  */
-         gcc_assert (ctx->region_type == ORT_TASK);
+         gcc_assert ((ctx->region_type & ORT_TASK) != 0);
          if (ctx->outer_context)
            omp_notice_variable (ctx->outer_context, decl, in_code);
          for (octx = ctx->outer_context; octx; octx = octx->outer_context)
@@ -5674,7 +5837,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
              push_gimplify_context (&gctx);
              gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
                                &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
-             pop_gimplify_context 
+             pop_gimplify_context
                (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
              OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
              OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
@@ -5871,7 +6034,7 @@ gimplify_adjust_omp_clauses (tree *list_p)
          OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
            = (n->value & GOVD_FIRSTPRIVATE) != 0;
          break;
-         
+
        case OMP_CLAUSE_REDUCTION:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COPYPRIVATE:
@@ -5897,7 +6060,7 @@ gimplify_adjust_omp_clauses (tree *list_p)
 
   /* Add in any implicit data sharing.  */
   splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, list_p);
-  
+
   gimplify_omp_ctxp = ctx->outer_context;
   delete_omp_context (ctx);
 }
@@ -5952,7 +6115,10 @@ gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
   gimple_seq body = NULL;
   struct gimplify_ctx gctx;
 
-  gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p, ORT_TASK);
+  gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
+                            find_omp_clause (OMP_TASK_CLAUSES (expr),
+                                             OMP_CLAUSE_UNTIED)
+                            ? ORT_UNTIED_TASK : ORT_TASK);
 
   push_gimplify_context (&gctx);
 
@@ -6021,7 +6187,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
        {
          var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
          TREE_OPERAND (t, 0) = var;
-                              
+
          gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
 
          omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
@@ -6171,14 +6337,14 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
 }
 
 /* A subroutine of gimplify_omp_atomic.  The front end is supposed to have
-   stabilized the lhs of the atomic operation as *ADDR.  Return true if 
+   stabilized the lhs of the atomic operation as *ADDR.  Return true if
    EXPR is this stabilized form.  */
 
 static bool
 goa_lhs_expr_p (tree expr, tree addr)
 {
   /* Also include casts to other type variants.  The C front end is fond
-     of adding these for e.g. volatile variables.  This is like 
+     of adding these for e.g. volatile variables.  This is like
      STRIP_TYPE_NOPS but includes the main variant lookup.  */
   STRIP_USELESS_TYPE_CONVERSION (expr);
 
@@ -6224,7 +6390,7 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
     }
   if (is_gimple_val (expr))
     return 0;
+
   saw_lhs = 0;
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
@@ -6241,8 +6407,12 @@ 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;
@@ -6276,7 +6446,7 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
   tree tmp_load;
 
-   tmp_load = create_tmp_var (type, NULL);
+   tmp_load = create_tmp_reg (type, NULL);
    if (goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
      return GS_ERROR;
 
@@ -6357,7 +6527,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
@@ -6406,7 +6576,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)
@@ -6482,7 +6653,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       else if (ret != GS_UNHANDLED)
        break;
 
-      ret = GS_OK;
+      /* Make sure that all the cases set 'ret' appropriately.  */
+      ret = GS_UNHANDLED;
       switch (TREE_CODE (*expr_p))
        {
          /* First deal with the special cases.  */
@@ -6516,6 +6688,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            {
              *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
              mark_addressable (*expr_p);
+             ret = GS_OK;
            }
          break;
 
@@ -6530,6 +6703,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            {
              *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
              mark_addressable (*expr_p);
+             ret = GS_OK;
            }
          break;
 
@@ -6591,6 +6765,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              /* Just strip a conversion to void (or in void context) and
                 try again.  */
              *expr_p = TREE_OPERAND (*expr_p, 0);
+             ret = GS_OK;
              break;
            }
 
@@ -6609,15 +6784,47 @@ 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);
+           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);
+           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;
+           ret = GS_OK;
            break;
-         /* else fall through.  */
-       case ALIGN_INDIRECT_REF:
-       case MISALIGNED_INDIRECT_REF:
+         }
+
+       /* 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;
+           }
          ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-                              is_gimple_reg, fb_rvalue);
+                              is_gimple_mem_ref_addr, fb_rvalue);
          recalculate_side_effects (*expr_p);
+         ret = GS_ALL_DONE;
          break;
 
          /* Constants need not be gimplified.  */
@@ -6638,18 +6845,16 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          if (fallback & fb_lvalue)
            ret = GS_ALL_DONE;
          else
-           *expr_p = DECL_INITIAL (*expr_p);
+           {
+             *expr_p = DECL_INITIAL (*expr_p);
+             ret = GS_OK;
+           }
          break;
 
        case DECL_EXPR:
          ret = gimplify_decl_expr (expr_p, pre_p);
          break;
 
-       case EXC_PTR_EXPR:
-         /* FIXME make this a decl.  */
-         ret = GS_ALL_DONE;
-         break;
-
        case BIND_EXPR:
          ret = gimplify_bind_expr (expr_p, pre_p);
          break;
@@ -6678,6 +6883,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            }
          gimplify_seq_add_stmt (pre_p,
                          gimple_build_goto (GOTO_DESTINATION (*expr_p)));
+         ret = GS_ALL_DONE;
          break;
 
        case PREDICT_EXPR:
@@ -6710,17 +6916,14 @@ 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 = GS_OK;
+             ret = temp ? GS_OK : GS_ALL_DONE;
            }
          /* C99 code may assign to an array in a constructed
             structure or union, and this has undefined behavior only
@@ -6730,6 +6933,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            {
              *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
              mark_addressable (*expr_p);
+             ret = GS_OK;
            }
          else
            ret = GS_ALL_DONE;
@@ -6764,15 +6968,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);
          }
@@ -6841,8 +7045,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
            ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
            gimple_set_no_warning (ehf, TREE_NO_WARNING (*expr_p));
-           gimple_eh_filter_set_must_not_throw
-             (ehf, EH_FILTER_MUST_NOT_THROW (*expr_p));
            gimplify_seq_add_stmt (pre_p, ehf);
            ret = GS_ALL_DONE;
            break;
@@ -6879,6 +7081,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                           gimple_test_f, fallback);
            gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
                           is_gimple_val, fb_rvalue);
+           ret = GS_ALL_DONE;
          }
          break;
 
@@ -6966,6 +7169,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                   TREE_TYPE (*expr_p))))
            {
              *expr_p = tmp;
+             ret = GS_OK;
              break;
            }
          /* Convert (void *)&a + 4 into (void *)&a[1].  */
@@ -6981,6 +7185,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                                            0)))))
             {
                *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp);
+              ret = GS_OK;
               break;
             }
           /* FALLTHRU */
@@ -7050,9 +7255,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          break;
        }
 
-      /* If we replaced *expr_p, gimplify again.  */
-      if (ret == GS_OK && (*expr_p == NULL || *expr_p == save_expr))
-       ret = GS_ALL_DONE;
+      gcc_assert (*expr_p || ret != GS_OK);
     }
   while (ret == GS_OK);
 
@@ -7178,7 +7381,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  && code != GOTO_EXPR
                  && code != LABEL_EXPR
                  && code != LOOP_EXPR
-                 && code != RESX_EXPR
                  && code != SWITCH_EXPR
                  && code != TRY_FINALLY_EXPR
                  && code != OMP_CRITICAL
@@ -7216,7 +7418,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))
     {
@@ -7314,9 +7516,10 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
       /* These types may not have declarations, so handle them here.  */
       gimplify_type_sizes (TREE_TYPE (type), list_p);
       gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
-      /* When not optimizing, ensure VLA bounds aren't removed.  */
-      if (!optimize
-         && TYPE_DOMAIN (type)
+      /* Ensure VLA bounds aren't removed, for -O0 they should be variables
+        with assigned stack slots, for -O1+ -g they should be tracked
+        by VTA.  */
+      if (TYPE_DOMAIN (type)
          && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
        {
          t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
@@ -7331,7 +7534,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);
@@ -7481,11 +7684,21 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
   *body_p = NULL_TREE;
 
   /* If we had callee-copies statements, insert them at the beginning
-     of the function.  */
+     of the function and clear DECL_VALUE_EXPR_P on the parameters.  */
   if (!gimple_seq_empty_p (parm_stmts))
     {
+      tree parm;
+
       gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
       gimple_bind_set_body (outer_bind, parm_stmts);
+
+      for (parm = DECL_ARGUMENTS (current_function_decl);
+          parm; parm = DECL_CHAIN (parm))
+       if (DECL_HAS_VALUE_EXPR_P (parm))
+         {
+           DECL_HAS_VALUE_EXPR_P (parm) = 0;
+           DECL_IGNORED_P (parm) = 0;
+         }
     }
 
   if (nonlocal_vlas)
@@ -7498,7 +7711,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
   gcc_assert (gimplify_ctxp == NULL);
 
 #ifdef ENABLE_TYPES_CHECKING
-  if (!errorcount && !sorrycount)
+  if (!seen_error ())
     verify_types_in_gimple_seq (gimple_bind_body (outer_bind));
 #endif
 
@@ -7510,7 +7723,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
 
 /* Entry point to the gimplification pass.  FNDECL is the FUNCTION_DECL
    node for the function we want to gimplify.
-   
+
    Returns the sequence of GIMPLE statements corresponding to the body
    of FNDECL.  */
 
@@ -7530,7 +7743,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
@@ -7748,11 +7961,8 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
            }
          if (need_temp)
            {
-             tree temp = create_tmp_var (TREE_TYPE (lhs), NULL);
+             tree temp = create_tmp_reg (TREE_TYPE (lhs), NULL);
 
-             if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
-                 || TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
-               DECL_GIMPLE_REG_P (temp) = 1;
              if (TREE_CODE (orig_lhs) == SSA_NAME)
                orig_lhs = SSA_NAME_VAR (orig_lhs);
 
@@ -7789,17 +7999,16 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
 }
 
 
-/* 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
+/* Expands 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;
@@ -7807,8 +8016,6 @@ force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
   if (is_gimple_val (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;
@@ -7829,7 +8036,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);
@@ -7837,20 +8044,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).  */
+/* 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
+   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);
+}
+
+/* Invokes 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))
     {
@@ -7871,4 +8092,24 @@ force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
   return expr;
 }
 
+/* Invokes 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"