OSDN Git Service

2009-06-17 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index bb38ba3..15005c3 100644 (file)
@@ -1,6 +1,6 @@
 /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
    tree representation into the GIMPLE form.
 /* 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
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    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>.
    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>.
@@ -107,12 +107,14 @@ 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.  */
 
 /* Mark X addressable.  Unlike the langhook we expect X to be in gimple
    form and we don't do any syntax checking.  */
-static void
+void
 mark_addressable (tree x)
 {
   while (handled_component_p (x))
     x = TREE_OPERAND (x, 0);
 mark_addressable (tree x)
 {
   while (handled_component_p (x))
     x = TREE_OPERAND (x, 0);
-  if (TREE_CODE (x) != VAR_DECL && TREE_CODE (x) != PARM_DECL)
+  if (TREE_CODE (x) != VAR_DECL
+      && TREE_CODE (x) != PARM_DECL
+      && TREE_CODE (x) != RESULT_DECL)
     return ;
   TREE_ADDRESSABLE (x) = 1;
 }
     return ;
   TREE_ADDRESSABLE (x) = 1;
 }
@@ -212,16 +214,12 @@ void
 pop_gimplify_context (gimple body)
 {
   struct gimplify_ctx *c = gimplify_ctxp;
 pop_gimplify_context (gimple body)
 {
   struct gimplify_ctx *c = gimplify_ctxp;
-  tree t;
 
   gcc_assert (c && (c->bind_expr_stack == NULL
                    || VEC_empty (gimple, c->bind_expr_stack)));
   VEC_free (gimple, heap, c->bind_expr_stack);
   gimplify_ctxp = c->prev_context;
 
 
   gcc_assert (c && (c->bind_expr_stack == NULL
                    || VEC_empty (gimple, c->bind_expr_stack)));
   VEC_free (gimple, heap, c->bind_expr_stack);
   gimplify_ctxp = c->prev_context;
 
-  for (t = c->temps; t ; t = TREE_CHAIN (t))
-    DECL_GIMPLE_FORMAL_TEMP_P (t) = 0;
-
   if (body)
     declare_vars (c->temps, body, false);
   else
   if (body)
     declare_vars (c->temps, body, false);
   else
@@ -518,7 +516,8 @@ create_tmp_var_raw (tree type, const char *prefix)
   new_type = build_type_variant (type, 0, 0);
   TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type);
 
   new_type = build_type_variant (type, 0, 0);
   TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type);
 
-  tmp_var = build_decl (VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL,
+  tmp_var = build_decl (input_location,
+                       VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL,
                        type);
 
   /* The variable was declared by the compiler.  */
                        type);
 
   /* The variable was declared by the compiler.  */
@@ -565,7 +564,7 @@ create_tmp_var (tree type, const char *prefix)
 static inline tree
 create_tmp_from_val (tree val)
 {
 static inline tree
 create_tmp_from_val (tree val)
 {
-  return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val));
+  return create_tmp_var (TREE_TYPE (val), get_name (val));
 }
 
 /* Create a temporary to hold the value of VAL.  If IS_FORMAL, try to reuse
 }
 
 /* Create a temporary to hold the value of VAL.  If IS_FORMAL, try to reuse
@@ -607,9 +606,6 @@ lookup_tmp_var (tree val, bool is_formal)
        }
     }
 
        }
     }
 
-  if (is_formal)
-    DECL_GIMPLE_FORMAL_TEMP_P (ret) = 1;
-
   return ret;
 }
 
   return ret;
 }
 
@@ -620,32 +616,10 @@ lookup_tmp_var (tree val, bool is_formal)
    gimplify_modify_expr.  */
 
 static bool
    gimplify_modify_expr.  */
 
 static bool
-is_gimple_formal_tmp_or_call_rhs (tree t)
+is_gimple_reg_rhs_or_call (tree t)
 {
 {
-  return TREE_CODE (t) == CALL_EXPR || is_gimple_formal_tmp_rhs (t);
-}
-
-/* Returns true iff T is a valid RHS for an assignment to a renamed
-   user -- or front-end generated artificial -- variable.  */
-
-static bool
-is_gimple_reg_or_call_rhs (tree t)
-{
-  /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto
-     and the LHS is a user variable, then we need to introduce a formal
-     temporary.  This way the optimizers can determine that the user
-     variable is only modified if evaluation of the RHS does not throw.
-
-     Don't force a temp of a non-renamable type; the copy could be
-     arbitrarily expensive.  Instead we will generate a VDEF for
-     the assignment.  */
-
-  if (is_gimple_reg_type (TREE_TYPE (t))
-      && ((TREE_CODE (t) == CALL_EXPR && TREE_SIDE_EFFECTS (t))
-         || tree_could_throw_p (t)))
-    return false;
-
-  return is_gimple_formal_tmp_or_call_rhs (t);
+  return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
+         || TREE_CODE (t) == CALL_EXPR);
 }
 
 /* Return true if T is a valid memory RHS or a CALL_EXPR.  Note that
 }
 
 /* Return true if T is a valid memory RHS or a CALL_EXPR.  Note that
@@ -653,33 +627,18 @@ is_gimple_reg_or_call_rhs (tree t)
    rationale for this in gimplify_modify_expr.  */
 
 static bool
    rationale for this in gimplify_modify_expr.  */
 
 static bool
-is_gimple_mem_or_call_rhs (tree t)
+is_gimple_mem_rhs_or_call (tree t)
 {
   /* If we're dealing with a renamable type, either source or dest must be
 {
   /* If we're dealing with a renamable type, either source or dest must be
-     a renamed variable.  Also force a temporary if the type doesn't need
-     to be stored in memory, since it's cheap and prevents erroneous
-     tailcalls (PR 17526).  */
-  if (is_gimple_reg_type (TREE_TYPE (t))
-      || (TYPE_MODE (TREE_TYPE (t)) != BLKmode
-         && (TREE_CODE (t) != CALL_EXPR
-              || ! aggregate_value_p (t, t))))
+     a renamed variable.  */
+  if (is_gimple_reg_type (TREE_TYPE (t)))
     return is_gimple_val (t);
   else
     return is_gimple_val (t);
   else
-    return is_gimple_formal_tmp_or_call_rhs (t);
+    return (is_gimple_val (t) || is_gimple_lvalue (t)
+           || TREE_CODE (t) == CALL_EXPR);
 }
 
 }
 
-
-/* Returns 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
-      change between the initialization and use of the temporary, and
-   2) The temporary will not be otherwise modified.
-
-   For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
-   and #2 means it is inappropriate for && temps.
-
-   For other cases, use get_initialized_tmp_var instead.  */
+/* Helper for get_formal_tmp_var and get_initialized_tmp_var.  */
 
 static tree
 internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
 
 static tree
 internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
@@ -689,7 +648,7 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
 
   /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
      can create an INIT_EXPR and convert it into a GIMPLE_CALL below.  */
 
   /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
      can create an INIT_EXPR and convert it into a GIMPLE_CALL below.  */
-  gimplify_expr (&val, pre_p, post_p, is_gimple_formal_tmp_or_call_rhs,
+  gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
                 fb_rvalue);
 
   t = lookup_tmp_var (val, is_formal);
                 fb_rvalue);
 
   t = lookup_tmp_var (val, is_formal);
@@ -710,11 +669,11 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
              SET_DECL_RESTRICT_BASE (t, u);
            }
        }
              SET_DECL_RESTRICT_BASE (t, u);
            }
        }
-    }
 
 
-  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-    DECL_GIMPLE_REG_P (t) = 1;
+      if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+         || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+       DECL_GIMPLE_REG_P (t) = 1;
+    }
 
   mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
 
 
   mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
 
@@ -738,9 +697,17 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
   return t;
 }
 
   return t;
 }
 
-/* Returns a formal temporary variable initialized with VAL.  PRE_P
-   points to a sequence where side-effects needed to compute VAL should be
-   stored.  */
+/* Returns 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
+      change between the initialization and use of the temporary, and
+   2) The temporary will not be otherwise modified.
+
+   For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
+   and #2 means it is inappropriate for && temps.
+
+   For other cases, use get_initialized_tmp_var instead.  */
 
 tree
 get_formal_tmp_var (tree val, gimple_seq *pre_p)
 
 tree
 get_formal_tmp_var (tree val, gimple_seq *pre_p)
@@ -772,7 +739,7 @@ declare_vars (tree vars, gimple scope, bool debug_info)
 
       temps = nreverse (last);
 
 
       temps = nreverse (last);
 
-      block = gimple_block (scope);
+      block = gimple_bind_block (scope);
       gcc_assert (!block || TREE_CODE (block) == BLOCK);
       if (!block || !debug_info)
        {
       gcc_assert (!block || TREE_CODE (block) == BLOCK);
       if (!block || !debug_info)
        {
@@ -1245,13 +1212,21 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
            omp_add_variable (gimplify_omp_ctxp, t, GOVD_LOCAL | GOVD_SEEN);
 
          DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
            omp_add_variable (gimplify_omp_ctxp, t, GOVD_LOCAL | GOVD_SEEN);
 
          DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
+
+         if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
+           cfun->has_local_explicit_reg_vars = true;
        }
 
       /* Preliminarily mark non-addressed complex variables as eligible
         for promotion to gimple registers.  We'll transform their uses
        }
 
       /* Preliminarily mark non-addressed complex variables as eligible
         for promotion to gimple registers.  We'll transform their uses
-        as we find them.  */
-      if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-          || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+        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)
          && !TREE_THIS_VOLATILE (t)
          && (TREE_CODE (t) == VAR_DECL && !DECL_HARD_REGISTER (t))
          && !needs_to_live_in_memory (t))
          && !TREE_THIS_VOLATILE (t)
          && (TREE_CODE (t) == VAR_DECL && !DECL_HARD_REGISTER (t))
          && !needs_to_live_in_memory (t))
@@ -1490,7 +1465,7 @@ static enum gimplify_status
 gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
 {
   tree saved_label = gimplify_ctxp->exit_label;
 gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
 {
   tree saved_label = gimplify_ctxp->exit_label;
-  tree start_label = create_artificial_label ();
+  tree start_label = create_artificial_label (UNKNOWN_LOCATION);
 
   gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
 
 
   gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
 
@@ -1630,20 +1605,64 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
        }
       len = i;
 
        }
       len = i;
 
+      if (!VEC_empty (tree, labels))
+       sort_case_labels (labels);
+
       if (!default_case)
        {
       if (!default_case)
        {
-         gimple new_default;
+         tree type = TREE_TYPE (switch_expr);
 
          /* If the switch has no default label, add one, so that we jump
 
          /* If the switch has no default label, add one, so that we jump
-            around the switch body.  */
-         default_case = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
-                                NULL_TREE, create_artificial_label ());
-         new_default = gimple_build_label (CASE_LABEL (default_case));
-         gimplify_seq_add_stmt (&switch_body_seq, new_default);
-       }
+            around the switch body.  If the labels already cover the whole
+            range of type, add the default label pointing to one of the
+            existing labels.  */
+         if (type == void_type_node)
+           type = TREE_TYPE (SWITCH_COND (switch_expr));
+         if (len
+             && INTEGRAL_TYPE_P (type)
+             && TYPE_MIN_VALUE (type)
+             && TYPE_MAX_VALUE (type)
+             && tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)),
+                                    TYPE_MIN_VALUE (type)))
+           {
+             tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1));
+             if (!high)
+               high = CASE_LOW (VEC_index (tree, labels, len - 1));
+             if (tree_int_cst_equal (high, TYPE_MAX_VALUE (type)))
+               {
+                 for (i = 1; i < len; i++)
+                   {
+                     high = CASE_LOW (VEC_index (tree, labels, i));
+                     low = CASE_HIGH (VEC_index (tree, labels, i - 1));
+                     if (!low)
+                       low = CASE_LOW (VEC_index (tree, labels, i - 1));
+                     if ((TREE_INT_CST_LOW (low) + 1
+                          != TREE_INT_CST_LOW (high))
+                         || (TREE_INT_CST_HIGH (low)
+                             + (TREE_INT_CST_LOW (high) == 0)
+                             != TREE_INT_CST_HIGH (high)))
+                       break;
+                   }
+                 if (i == len)
+                   default_case = build3 (CASE_LABEL_EXPR, void_type_node,
+                                          NULL_TREE, NULL_TREE,
+                                          CASE_LABEL (VEC_index (tree,
+                                                                 labels, 0)));
+               }
+           }
 
 
-      if (!VEC_empty (tree, labels))
-       sort_case_labels (labels);
+         if (!default_case)
+           {
+             gimple new_default;
+
+             default_case
+               = build3 (CASE_LABEL_EXPR, void_type_node,
+                         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);
+           }
+       }
 
       gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr), 
                                                default_case, labels);
 
       gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr), 
                                                default_case, labels);
@@ -1690,7 +1709,7 @@ build_and_jump (tree *label_p)
 
   if (*label_p == NULL_TREE)
     {
 
   if (*label_p == NULL_TREE)
     {
-      tree label = create_artificial_label ();
+      tree label = create_artificial_label (UNKNOWN_LOCATION);
       *label_p = label;
     }
 
       *label_p = label;
     }
 
@@ -1836,7 +1855,7 @@ gimplify_conversion (tree *expr_p)
 {
   tree tem;
   gcc_assert (CONVERT_EXPR_P (*expr_p));
 {
   tree tem;
   gcc_assert (CONVERT_EXPR_P (*expr_p));
-  
+
   /* Then strip away all but the outermost conversion.  */
   STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
 
   /* Then strip away all but the outermost conversion.  */
   STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
 
@@ -1851,8 +1870,8 @@ gimplify_conversion (tree *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
       && POINTER_TYPE_P (TREE_TYPE (*expr_p))
       && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
       && (tem = maybe_fold_offset_to_address
-                 (TREE_OPERAND (*expr_p, 0),
-                  integer_zero_node, TREE_TYPE (*expr_p))) != NULL_TREE)
+         (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,
     *expr_p = tem;
 
   /* If we still have a conversion at the toplevel,
@@ -1882,6 +1901,9 @@ gimplify_conversion (tree *expr_p)
   return GS_OK;
 }
 
   return GS_OK;
 }
 
+/* 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 
    DECL_VALUE_EXPR, and it's worth re-examining things.  */
 
 /* Gimplify a VAR_DECL or PARM_DECL.  Returns GS_OK if we expanded a 
    DECL_VALUE_EXPR, and it's worth re-examining things.  */
 
@@ -1912,7 +1934,36 @@ gimplify_var_or_parm_decl (tree *expr_p)
   /* If the decl is an alias for another expression, substitute it now.  */
   if (DECL_HAS_VALUE_EXPR_P (decl))
     {
   /* If the decl is an alias for another expression, substitute it now.  */
   if (DECL_HAS_VALUE_EXPR_P (decl))
     {
-      *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
+      tree value_expr = DECL_VALUE_EXPR (decl);
+
+      /* For referenced nonlocal VLAs add a decl for debugging purposes
+        to the current function.  */
+      if (TREE_CODE (decl) == VAR_DECL
+         && TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
+         && nonlocal_vlas != NULL
+         && TREE_CODE (value_expr) == INDIRECT_REF
+         && TREE_CODE (TREE_OPERAND (value_expr, 0)) == VAR_DECL
+         && decl_function_context (decl) != current_function_decl)
+       {
+         struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+         while (ctx && ctx->region_type == ORT_WORKSHARE)
+           ctx = ctx->outer_context;
+         if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
+           {
+             tree copy = copy_node (decl), block;
+
+             lang_hooks.dup_lang_specific_decl (copy);
+             SET_DECL_RTL (copy, NULL_RTX);
+             TREE_USED (copy) = 1;
+             block = DECL_INITIAL (current_function_decl);
+             TREE_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;
+           }
+       }
+
+      *expr_p = unshare_expr (value_expr);
       return GS_OK;
     }
 
       return GS_OK;
     }
 
@@ -2006,7 +2057,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                {
                  TREE_OPERAND (t, 2) = low;
                  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
                {
                  TREE_OPERAND (t, 2) = low;
                  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
-                                       post_p, is_gimple_formal_tmp_reg,
+                                       post_p, is_gimple_reg,
                                        fb_rvalue);
                  ret = MIN (ret, tret);
                }
                                        fb_rvalue);
                  ret = MIN (ret, tret);
                }
@@ -2026,7 +2077,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                {
                  TREE_OPERAND (t, 3) = elmt_size;
                  tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
                {
                  TREE_OPERAND (t, 3) = elmt_size;
                  tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
-                                       post_p, is_gimple_formal_tmp_reg,
+                                       post_p, is_gimple_reg,
                                        fb_rvalue);
                  ret = MIN (ret, tret);
                }
                                        fb_rvalue);
                  ret = MIN (ret, tret);
                }
@@ -2049,7 +2100,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                {
                  TREE_OPERAND (t, 2) = offset;
                  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
                {
                  TREE_OPERAND (t, 2) = offset;
                  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
-                                       post_p, is_gimple_formal_tmp_reg,
+                                       post_p, is_gimple_reg,
                                        fb_rvalue);
                  ret = MIN (ret, tret);
                }
                                        fb_rvalue);
                  ret = MIN (ret, tret);
                }
@@ -2072,19 +2123,11 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
       if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
        {
 
       if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
        {
-         /* Gimplify the dimension.
-            Temporary fix for gcc.c-torture/execute/20040313-1.c.
-            Gimplify non-constant array indices into a temporary
-            variable.
-            FIXME - The real fix is to gimplify post-modify
-            expressions into a minimal gimple lvalue.  However, that
-            exposes bugs in alias analysis.  The alias analyzer does
-            not handle &PTR->FIELD very well.  Will fix after the
-            branch is merged into mainline (dnovillo 2004-05-03).  */
+         /* Gimplify the dimension.  */
          if (!is_gimple_min_invariant (TREE_OPERAND (t, 1)))
            {
              tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
          if (!is_gimple_min_invariant (TREE_OPERAND (t, 1)))
            {
              tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
-                                   is_gimple_formal_tmp_reg, fb_rvalue);
+                                   is_gimple_val, fb_rvalue);
              ret = MIN (ret, tret);
            }
        }
              ret = MIN (ret, tret);
            }
        }
@@ -2176,9 +2219,18 @@ gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   rhs = TREE_OPERAND (*expr_p, 1);
 
   /* For postfix operator, we evaluate the LHS to an rvalue and then use
   rhs = TREE_OPERAND (*expr_p, 1);
 
   /* For postfix operator, we evaluate the LHS to an rvalue and then use
-     that as the result value and in the postqueue operation.  */
+     that as the result value and in the postqueue operation.  We also
+     make sure to make lvalue a minimal lval, see
+     gcc.c-torture/execute/20040313-1.c for an example where this matters.  */
   if (postfix)
     {
   if (postfix)
     {
+      if (!is_gimple_min_lval (lvalue))
+       {
+         mark_addressable (lvalue);
+         lvalue = build_fold_addr_expr (lvalue);
+         gimplify_expr (&lvalue, pre_p, post_p, is_gimple_val, fb_rvalue);
+         lvalue = build_fold_indirect_ref (lvalue);
+       }
       ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
       if (ret == GS_ERROR)
        return ret;
       ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
       if (ret == GS_ERROR)
        return ret;
@@ -2238,10 +2290,11 @@ maybe_with_size_expr (tree *expr_p)
 
 
 /* Helper for gimplify_call_expr.  Gimplify a single argument *ARG_P
 
 
 /* Helper for gimplify_call_expr.  Gimplify a single argument *ARG_P
-   Store any side-effects in PRE_P.  */
+   Store any side-effects in PRE_P.  CALL_LOCATION is the location of
+   the CALL_EXPR.  */
 
 static enum gimplify_status
 
 static enum gimplify_status
-gimplify_arg (tree *arg_p, gimple_seq *pre_p)
+gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
 {
   bool (*test) (tree);
   fallback_t fb;
 {
   bool (*test) (tree);
   fallback_t fb;
@@ -2259,6 +2312,11 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p)
   /* If this is a variable sized type, we must remember the size.  */
   maybe_with_size_expr (arg_p);
 
   /* If this is a variable sized type, we must remember the size.  */
   maybe_with_size_expr (arg_p);
 
+  /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c.  */
+  /* Make sure arguments have the same location as the function call
+     itself.  */
+  protected_set_expr_location (*arg_p, call_location);
+
   /* There is a sequence point before a function call.  Side effects in
      the argument list must occur before the actual call. So, when
      gimplifying arguments, force gimplify_expr to use an internal
   /* There is a sequence point before a function call.  Side effects in
      the argument list must occur before the actual call. So, when
      gimplifying arguments, force gimplify_expr to use an internal
@@ -2319,13 +2377,13 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
          if (call_expr_nargs (*expr_p) < 2)
            {
              error ("too few arguments to function %<va_start%>");
          if (call_expr_nargs (*expr_p) < 2)
            {
              error ("too few arguments to function %<va_start%>");
-             *expr_p = build_empty_stmt ();
+             *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
              return GS_OK;
            }
          
          if (fold_builtin_next_arg (*expr_p, true))
            {
              return GS_OK;
            }
          
          if (fold_builtin_next_arg (*expr_p, true))
            {
-             *expr_p = build_empty_stmt ();
+             *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
              return GS_OK;
            }
        }
              return GS_OK;
            }
        }
@@ -2347,56 +2405,14 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
   else if (POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_FN (*expr_p))))
     parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*expr_p))));
 
   else if (POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_FN (*expr_p))))
     parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*expr_p))));
 
-  /* Verify if the type of the argument matches that of the function
-     declaration.  If we cannot verify this or there is a mismatch,
-     mark the call expression so it doesn't get inlined later.  */
   if (fndecl && DECL_ARGUMENTS (fndecl))
   if (fndecl && DECL_ARGUMENTS (fndecl))
-    {
-      for (i = 0, p = DECL_ARGUMENTS (fndecl);
-          i < nargs;
-          i++, p = TREE_CHAIN (p))
-       {
-         /* We cannot distinguish a varargs function from the case
-            of excess parameters, still deferring the inlining decision
-            to the callee is possible.  */
-         if (!p)
-           break;
-         if (p == error_mark_node
-             || CALL_EXPR_ARG (*expr_p, i) == error_mark_node
-             || !fold_convertible_p (DECL_ARG_TYPE (p),
-                                     CALL_EXPR_ARG (*expr_p, i)))
-           {
-             CALL_CANNOT_INLINE_P (*expr_p) = 1;
-             break;
-           }
-       }
-    }
+    p = DECL_ARGUMENTS (fndecl);
   else if (parms)
   else if (parms)
-    {
-      for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p))
-       {
-         /* If this is a varargs function defer inlining decision
-            to callee.  */
-         if (!p)
-           break;
-         if (TREE_VALUE (p) == error_mark_node
-             || CALL_EXPR_ARG (*expr_p, i) == error_mark_node
-             || TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
-             || !fold_convertible_p (TREE_VALUE (p),
-                                     CALL_EXPR_ARG (*expr_p, i)))
-           {
-             CALL_CANNOT_INLINE_P (*expr_p) = 1;
-             break;
-           }
-       }
-    }
+    p = parms;
   else
   else
-    {
-      if (nargs != 0)
-       CALL_CANNOT_INLINE_P (*expr_p) = 1;
-      i = 0;
-      p = NULL_TREE;
-    }
+    p = NULL_TREE;
+  for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
+    ;
 
   /* If the last argument is __builtin_va_arg_pack () and it is not
      passed as a named argument, decrease the number of CALL_EXPR
 
   /* If the last argument is __builtin_va_arg_pack () and it is not
      passed as a named argument, decrease the number of CALL_EXPR
@@ -2448,7 +2464,8 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
              be the plain PARM_DECL.  */
           if ((i != 1) || !builtin_va_start_p)
             {
              be the plain PARM_DECL.  */
           if ((i != 1) || !builtin_va_start_p)
             {
-              t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p);
+              t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
+                               EXPR_LOCATION (*expr_p));
 
               if (t == GS_ERROR)
                 ret = GS_ERROR;
 
               if (t == GS_ERROR)
                 ret = GS_ERROR;
@@ -2515,12 +2532,15 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
    condition is true or false, respectively.  If null, we should generate
    our own to skip over the evaluation of this specific expression.
 
    condition is true or false, respectively.  If null, we should generate
    our own to skip over the evaluation of this specific expression.
 
+   LOCUS is the source location of the COND_EXPR.
+
    This function is the tree equivalent of do_jump.
 
    shortcut_cond_r should only be called by shortcut_cond_expr.  */
 
 static tree
    This function is the tree equivalent of do_jump.
 
    shortcut_cond_r should only be called by shortcut_cond_expr.  */
 
 static tree
-shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
+shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
+                location_t locus)
 {
   tree local_label = NULL_TREE;
   tree t, expr = NULL;
 {
   tree local_label = NULL_TREE;
   tree t, expr = NULL;
@@ -2530,6 +2550,8 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
      shortcut_cond_expr will append the real blocks later.  */
   if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
     {
      shortcut_cond_expr will append the real blocks later.  */
   if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
     {
+      location_t new_locus;
+
       /* Turn if (a && b) into
 
         if (a); else goto no;
       /* Turn if (a && b) into
 
         if (a); else goto no;
@@ -2539,15 +2561,20 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
       if (false_label_p == NULL)
        false_label_p = &local_label;
 
       if (false_label_p == NULL)
        false_label_p = &local_label;
 
-      t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p);
+      /* Keep the original source location on the first 'if'.  */
+      t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus);
       append_to_statement_list (t, &expr);
 
       append_to_statement_list (t, &expr);
 
-      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-                          false_label_p);
+      /* Set the source location of the && on the second 'if'.  */
+      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
+                          new_locus);
       append_to_statement_list (t, &expr);
     }
   else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
     {
       append_to_statement_list (t, &expr);
     }
   else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
     {
+      location_t new_locus;
+
       /* Turn if (a || b) into
 
         if (a) goto yes;
       /* Turn if (a || b) into
 
         if (a) goto yes;
@@ -2557,31 +2584,41 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
       if (true_label_p == NULL)
        true_label_p = &local_label;
 
       if (true_label_p == NULL)
        true_label_p = &local_label;
 
-      t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL);
+      /* Keep the original source location on the first 'if'.  */
+      t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus);
       append_to_statement_list (t, &expr);
 
       append_to_statement_list (t, &expr);
 
-      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-                          false_label_p);
+      /* Set the source location of the || on the second 'if'.  */
+      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
+                          new_locus);
       append_to_statement_list (t, &expr);
     }
   else if (TREE_CODE (pred) == COND_EXPR)
     {
       append_to_statement_list (t, &expr);
     }
   else if (TREE_CODE (pred) == COND_EXPR)
     {
+      location_t new_locus;
+
       /* As long as we're messing with gotos, turn if (a ? b : c) into
         if (a)
           if (b) goto yes; else goto no;
         else
           if (c) goto yes; else goto no;  */
       /* As long as we're messing with gotos, turn if (a ? b : c) into
         if (a)
           if (b) goto yes; else goto no;
         else
           if (c) goto yes; else goto no;  */
+
+      /* Keep the original source location on the first 'if'.  Set the source
+        location of the ? on the second 'if'.  */
+      new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
       expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
                     shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
       expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
                     shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-                                     false_label_p),
+                                     false_label_p, locus),
                     shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
                     shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
-                                     false_label_p));
+                                     false_label_p, new_locus));
     }
   else
     {
       expr = build3 (COND_EXPR, void_type_node, pred,
                     build_and_jump (true_label_p),
                     build_and_jump (false_label_p));
     }
   else
     {
       expr = build3 (COND_EXPR, void_type_node, pred,
                     build_and_jump (true_label_p),
                     build_and_jump (false_label_p));
+      SET_EXPR_LOCATION (expr, locus);
     }
 
   if (local_label)
     }
 
   if (local_label)
@@ -2613,14 +2650,24 @@ shortcut_cond_expr (tree expr)
   /* First do simple transformations.  */
   if (!else_se)
     {
   /* First do simple transformations.  */
   if (!else_se)
     {
-      /* If there is no 'else', turn (a && b) into if (a) if (b).  */
+      /* If there is no 'else', turn
+          if (a && b) then c
+        into
+          if (a) if (b) then c.  */
       while (TREE_CODE (pred) == TRUTH_ANDIF_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;
          TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
          TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
+         /* Set the source location of the && on the second 'if'.  */
+         if (EXPR_HAS_LOCATION (pred))
+           SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
          then_ = shortcut_cond_expr (expr);
          then_se = then_ && TREE_SIDE_EFFECTS (then_);
          pred = TREE_OPERAND (pred, 0);
          expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
          then_ = shortcut_cond_expr (expr);
          then_se = then_ && TREE_SIDE_EFFECTS (then_);
          pred = TREE_OPERAND (pred, 0);
          expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
+         SET_EXPR_LOCATION (expr, locus);
        }
     }
 
        }
     }
 
@@ -2632,11 +2679,18 @@ shortcut_cond_expr (tree expr)
           if (a); else if (b); else d.  */
       while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
        {
           if (a); else if (b); else d.  */
       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;
          TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
          TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
+         /* Set the source location of the || on the second 'if'.  */
+         if (EXPR_HAS_LOCATION (pred))
+           SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
          else_ = shortcut_cond_expr (expr);
          else_se = else_ && TREE_SIDE_EFFECTS (else_);
          pred = TREE_OPERAND (pred, 0);
          expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
          else_ = shortcut_cond_expr (expr);
          else_se = else_ && TREE_SIDE_EFFECTS (else_);
          pred = TREE_OPERAND (pred, 0);
          expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
+         SET_EXPR_LOCATION (expr, locus);
        }
     }
 
        }
     }
 
@@ -2690,17 +2744,19 @@ shortcut_cond_expr (tree expr)
 
   /* If there was nothing else in our arms, just forward the label(s).  */
   if (!then_se && !else_se)
 
   /* 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);
+    return shortcut_cond_r (pred, true_label_p, false_label_p,
+                           EXPR_HAS_LOCATION (expr)
+                           ? EXPR_LOCATION (expr) : input_location);
 
   /* If our last subexpression already has a terminal label, reuse it.  */
   if (else_se)
 
   /* If our last subexpression already has a terminal label, reuse it.  */
   if (else_se)
-    expr = expr_last (else_);
+    t = expr_last (else_);
   else if (then_se)
   else if (then_se)
-    expr = expr_last (then_);
+    t = expr_last (then_);
   else
   else
-    expr = NULL;
-  if (expr && TREE_CODE (expr) == LABEL_EXPR)
-    end_label = LABEL_EXPR_LABEL (expr);
+    t = NULL;
+  if (t && TREE_CODE (t) == LABEL_EXPR)
+    end_label = LABEL_EXPR_LABEL (t);
 
   /* If we don't care about jumping to the 'else' branch, jump to the end
      if the condition is false.  */
 
   /* If we don't care about jumping to the 'else' branch, jump to the end
      if the condition is false.  */
@@ -2721,7 +2777,9 @@ shortcut_cond_expr (tree expr)
      non-void function.  */
   jump_over_else = block_may_fallthru (then_);
 
      non-void function.  */
   jump_over_else = block_may_fallthru (then_);
 
-  pred = shortcut_cond_r (pred, true_label_p, false_label_p);
+  pred = shortcut_cond_r (pred, true_label_p, false_label_p,
+                         EXPR_HAS_LOCATION (expr)
+                         ? EXPR_LOCATION (expr) : input_location);
 
   expr = NULL;
   append_to_statement_list (pred, &expr);
 
   expr = NULL;
   append_to_statement_list (pred, &expr);
@@ -2731,7 +2789,10 @@ shortcut_cond_expr (tree expr)
     {
       if (jump_over_else)
        {
     {
       if (jump_over_else)
        {
+         tree last = expr_last (expr);
          t = build_and_jump (&end_label);
          t = build_and_jump (&end_label);
+         if (EXPR_HAS_LOCATION (last))
+           SET_EXPR_LOCATION (t, EXPR_LOCATION (last));
          append_to_statement_list (t, &expr);
        }
       if (emit_false)
          append_to_statement_list (t, &expr);
        }
       if (emit_false)
@@ -2990,7 +3051,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
       have_then_clause_p = true;
     }
   else
       have_then_clause_p = true;
     }
   else
-    label_true = create_artificial_label ();
+    label_true = create_artificial_label (UNKNOWN_LOCATION);
   if (TREE_OPERAND (expr, 2) != NULL
       && TREE_CODE (TREE_OPERAND (expr, 2)) == GOTO_EXPR
       && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 2))) == LABEL_DECL
   if (TREE_OPERAND (expr, 2) != NULL
       && TREE_CODE (TREE_OPERAND (expr, 2)) == GOTO_EXPR
       && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 2))) == LABEL_DECL
@@ -3008,7 +3069,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
       have_else_clause_p = true;
     }
   else
       have_else_clause_p = true;
     }
   else
-    label_false = create_artificial_label ();
+    label_false = create_artificial_label (UNKNOWN_LOCATION);
 
   gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
                                 &arm2);
 
   gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
                                 &arm2);
@@ -3039,7 +3100,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
              && gimple_seq_may_fallthru (seq))
            {
              gimple g;
              && gimple_seq_may_fallthru (seq))
            {
              gimple g;
-             label_cont = create_artificial_label ();
+             label_cont = create_artificial_label (UNKNOWN_LOCATION);
 
              g = gimple_build_goto (label_cont);
 
 
              g = gimple_build_goto (label_cont);
 
@@ -3094,11 +3155,13 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
   to = TREE_OPERAND (*expr_p, 0);
   from = TREE_OPERAND (*expr_p, 1);
 
   to = TREE_OPERAND (*expr_p, 0);
   from = TREE_OPERAND (*expr_p, 1);
 
+  mark_addressable (from);
   from_ptr = build_fold_addr_expr (from);
   from_ptr = build_fold_addr_expr (from);
-  gimplify_arg (&from_ptr, seq_p);
+  gimplify_arg (&from_ptr, seq_p, EXPR_LOCATION (*expr_p));
 
 
+  mark_addressable (to);
   to_ptr = build_fold_addr_expr (to);
   to_ptr = build_fold_addr_expr (to);
-  gimplify_arg (&to_ptr, seq_p);
+  gimplify_arg (&to_ptr, seq_p, EXPR_LOCATION (*expr_p));
 
   t = implicit_built_in_decls[BUILT_IN_MEMCPY];
 
 
   t = implicit_built_in_decls[BUILT_IN_MEMCPY];
 
@@ -3145,7 +3208,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
   to = TREE_OPERAND (*expr_p, 0);
 
   to_ptr = build_fold_addr_expr (to);
   to = TREE_OPERAND (*expr_p, 0);
 
   to_ptr = build_fold_addr_expr (to);
-  gimplify_arg (&to_ptr, seq_p);
+  gimplify_arg (&to_ptr, seq_p, EXPR_LOCATION (*expr_p));
   t = implicit_built_in_decls[BUILT_IN_MEMSET];
 
   gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
   t = implicit_built_in_decls[BUILT_IN_MEMSET];
 
   gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
@@ -3320,9 +3383,9 @@ gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
   tree loop_entry_label, loop_exit_label, fall_thru_label;
   tree var, var_type, cref, tmp;
 
   tree loop_entry_label, loop_exit_label, fall_thru_label;
   tree var, var_type, cref, tmp;
 
-  loop_entry_label = create_artificial_label ();
-  loop_exit_label = create_artificial_label ();
-  fall_thru_label = create_artificial_label ();
+  loop_entry_label = create_artificial_label (UNKNOWN_LOCATION);
+  loop_exit_label = create_artificial_label (UNKNOWN_LOCATION);
+  fall_thru_label = create_artificial_label (UNKNOWN_LOCATION);
 
   /* Create and initialize the index variable.  */
   var_type = TREE_TYPE (upper);
 
   /* Create and initialize the index variable.  */
   var_type = TREE_TYPE (upper);
@@ -3482,14 +3545,89 @@ gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
 gimple_predicate
 rhs_predicate_for (tree lhs)
 {
 gimple_predicate
 rhs_predicate_for (tree lhs)
 {
-  if (is_gimple_formal_tmp_var (lhs))
-    return is_gimple_formal_tmp_or_call_rhs;
-  else if (is_gimple_reg (lhs))
-    return is_gimple_reg_or_call_rhs;
+  if (is_gimple_reg (lhs))
+    return is_gimple_reg_rhs_or_call;
   else
   else
-    return is_gimple_mem_or_call_rhs;
+    return is_gimple_mem_rhs_or_call;
 }
 
 }
 
+/* Gimplify a C99 compound literal expression.  This just means adding
+   the DECL_EXPR before the current statement and using its anonymous
+   decl instead.  */
+
+static enum gimplify_status
+gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p)
+{
+  tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
+  tree decl = DECL_EXPR_DECL (decl_s);
+  /* Mark the decl as addressable if the compound literal
+     expression is addressable now, otherwise it is marked too late
+     after we gimplify the initialization expression.  */
+  if (TREE_ADDRESSABLE (*expr_p))
+    TREE_ADDRESSABLE (decl) = 1;
+
+  /* Preliminarily mark non-addressed complex variables as eligible
+     for promotion to gimple registers.  We'll transform their uses
+     as we find them.  */
+  if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE
+       || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE)
+      && !TREE_THIS_VOLATILE (decl)
+      && !needs_to_live_in_memory (decl))
+    DECL_GIMPLE_REG_P (decl) = 1;
+
+  /* This decl isn't mentioned in the enclosing block, so add it to the
+     list of temps.  FIXME it seems a bit of a kludge to say that
+     anonymous artificial vars aren't pushed, but everything else is.  */
+  if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
+    gimple_add_tmp_var (decl);
+
+  gimplify_and_add (decl_s, pre_p);
+  *expr_p = decl;
+  return GS_OK;
+}
+
+/* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR,
+   return a new CONSTRUCTOR if something changed.  */
+
+static tree
+optimize_compound_literals_in_ctor (tree orig_ctor)
+{
+  tree ctor = orig_ctor;
+  VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (ctor);
+  unsigned int idx, num = VEC_length (constructor_elt, elts);
+
+  for (idx = 0; idx < num; idx++)
+    {
+      tree value = VEC_index (constructor_elt, elts, idx)->value;
+      tree newval = value;
+      if (TREE_CODE (value) == CONSTRUCTOR)
+       newval = optimize_compound_literals_in_ctor (value);
+      else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
+       {
+         tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value);
+         tree decl = DECL_EXPR_DECL (decl_s);
+         tree init = DECL_INITIAL (decl);
+
+         if (!TREE_ADDRESSABLE (value)
+             && !TREE_ADDRESSABLE (decl)
+             && init)
+           newval = optimize_compound_literals_in_ctor (init);
+       }
+      if (newval == value)
+       continue;
+
+      if (ctor == orig_ctor)
+       {
+         ctor = copy_node (orig_ctor);
+         CONSTRUCTOR_ELTS (ctor) = VEC_copy (constructor_elt, gc, elts);
+         elts = CONSTRUCTOR_ELTS (ctor);
+       }
+      VEC_index (constructor_elt, elts, idx)->value = newval;
+    }
+  return ctor;
+}
+
+
 
 /* A subroutine of gimplify_modify_expr.  Break out elements of a
    CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
 
 /* A subroutine of gimplify_modify_expr.  Break out elements of a
    CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
@@ -3508,14 +3646,11 @@ static enum gimplify_status
 gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                           bool want_value, bool notify_temp_creation)
 {
 gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                           bool want_value, bool notify_temp_creation)
 {
-  tree object;
-  tree ctor = TREE_OPERAND (*expr_p, 1);
-  tree type = TREE_TYPE (ctor);
+  tree object, ctor, type;
   enum gimplify_status ret;
   VEC(constructor_elt,gc) *elts;
 
   enum gimplify_status ret;
   VEC(constructor_elt,gc) *elts;
 
-  if (TREE_CODE (ctor) != CONSTRUCTOR)
-    return GS_UNHANDLED;
+  gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
 
   if (!notify_temp_creation)
     {
 
   if (!notify_temp_creation)
     {
@@ -3526,6 +3661,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
     }
 
   object = TREE_OPERAND (*expr_p, 0);
     }
 
   object = TREE_OPERAND (*expr_p, 0);
+  ctor = TREE_OPERAND (*expr_p, 1) =
+    optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1));
+  type = TREE_TYPE (ctor);
   elts = CONSTRUCTOR_ELTS (ctor);
   ret = GS_ALL_DONE;
 
   elts = CONSTRUCTOR_ELTS (ctor);
   ret = GS_ALL_DONE;
 
@@ -3563,7 +3701,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        if (valid_const_initializer
            && num_nonzero_elements > 1
            && TREE_READONLY (object)
        if (valid_const_initializer
            && num_nonzero_elements > 1
            && TREE_READONLY (object)
-           && TREE_CODE (object) == VAR_DECL)
+           && TREE_CODE (object) == VAR_DECL
+           && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)))
          {
            if (notify_temp_creation)
              return GS_ERROR;
          {
            if (notify_temp_creation)
              return GS_ERROR;
@@ -3619,8 +3758,13 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
           be dropped to memory, and then memcpy'd out.  Don't do this
           for sparse arrays, though, as it's more efficient to follow
           the standard CONSTRUCTOR behavior of memset followed by
           be dropped to memory, and then memcpy'd out.  Don't do this
           for sparse arrays, though, as it's more efficient to follow
           the standard CONSTRUCTOR behavior of memset followed by
-          individual element initialization.  */
-       if (valid_const_initializer && !cleared)
+          individual element initialization.  Also don't do this for small
+          all-zero initializers (which aren't big enough to merit
+          clearing), and don't try to make bitwise copies of
+          TREE_ADDRESSABLE types.  */
+       if (valid_const_initializer
+           && !(cleared || num_nonzero_elements == 0)
+           && !TREE_ADDRESSABLE (type))
          {
            HOST_WIDE_INT size = int_size_in_bytes (type);
            unsigned int align;
          {
            HOST_WIDE_INT size = int_size_in_bytes (type);
            unsigned int align;
@@ -3642,7 +3786,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            else
              align = TYPE_ALIGN (type);
 
            else
              align = TYPE_ALIGN (type);
 
-           if (size > 0 && !can_move_by_pieces (size, align))
+           if (size > 0
+               && num_nonzero_elements > 1
+               && !can_move_by_pieces (size, align))
              {
                tree new_tree;
 
              {
                tree new_tree;
 
@@ -3918,11 +4064,14 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
     switch (TREE_CODE (*from_p))
       {
       case VAR_DECL:
     switch (TREE_CODE (*from_p))
       {
       case VAR_DECL:
-       /* If we're assigning from a constant constructor, move the
-          constructor expression to the RHS of the MODIFY_EXPR.  */
+       /* 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)
        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;
            && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR)
          {
            tree old_from = *from_p;
@@ -4068,11 +4217,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
                     || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
              /* Don't force regs into memory.  */
              use_target = false;
                     || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
              /* Don't force regs into memory.  */
              use_target = false;
-           else if (TREE_CODE (*to_p) == VAR_DECL
-                    && DECL_GIMPLE_FORMAL_TEMP_P (*to_p))
-             /* Don't use the original target if it's a formal temp; we
-                don't want to take their addresses.  */
-             use_target = false;
            else if (TREE_CODE (*expr_p) == INIT_EXPR)
              /* It's OK to use the target directly if it's being
                 initialized. */
            else if (TREE_CODE (*expr_p) == INIT_EXPR)
              /* It's OK to use the target directly if it's being
                 initialized. */
@@ -4125,6 +4269,26 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
          return GS_OK;
        }
        
          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:
        ret = GS_UNHANDLED;
        break;
       default:
        ret = GS_UNHANDLED;
        break;
@@ -4318,7 +4482,10 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       gimple_call_set_lhs (assign, *to_p);
     }
   else
       gimple_call_set_lhs (assign, *to_p);
     }
   else
-    assign = gimple_build_assign (*to_p, *from_p);
+    {
+      assign = gimple_build_assign (*to_p, *from_p);
+      gimple_set_location (assign, EXPR_LOCATION (*expr_p));
+    }
 
   gimplify_seq_add_stmt (pre_p, assign);
 
 
   gimplify_seq_add_stmt (pre_p, assign);
 
@@ -4393,13 +4560,11 @@ gimplify_scalar_mode_aggregate_compare (tree *expr_p)
 
        a && b ? true : false
 
 
        a && b ? true : false
 
-    gimplify_cond_expr will do the rest.
-
-    PRE_P points to the list where side effects that must happen before
-       *EXPR_P should be stored.  */
+    LOCUS is the source location to be put on the generated COND_EXPR.
+    gimplify_cond_expr will do the rest.  */
 
 static enum gimplify_status
 
 static enum gimplify_status
-gimplify_boolean_expr (tree *expr_p)
+gimplify_boolean_expr (tree *expr_p, location_t locus)
 {
   /* Preserve the original type of the expression.  */
   tree type = TREE_TYPE (*expr_p);
 {
   /* Preserve the original type of the expression.  */
   tree type = TREE_TYPE (*expr_p);
@@ -4408,6 +4573,8 @@ gimplify_boolean_expr (tree *expr_p)
                    fold_convert (type, boolean_true_node),
                    fold_convert (type, boolean_false_node));
 
                    fold_convert (type, boolean_true_node),
                    fold_convert (type, boolean_false_node));
 
+  SET_EXPR_LOCATION (*expr_p, locus);
+
   return GS_OK;
 }
 
   return GS_OK;
 }
 
@@ -4572,7 +4739,7 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
         This mostly happens if the frontend passed us something that
         it could not mark addressable yet, like a fortran
         pass-by-reference parameter (int) floatvar.  */
         This mostly happens if the frontend passed us something that
         it could not mark addressable yet, like a fortran
         pass-by-reference parameter (int) floatvar.  */
-      if (is_gimple_formal_tmp_var (TREE_OPERAND (expr, 0)))
+      if (is_gimple_reg (TREE_OPERAND (expr, 0)))
        TREE_OPERAND (expr, 0)
          = get_initialized_tmp_var (TREE_OPERAND (expr, 0), pre_p, post_p);
 
        TREE_OPERAND (expr, 0)
          = get_initialized_tmp_var (TREE_OPERAND (expr, 0), pre_p, post_p);
 
@@ -5276,8 +5443,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
       switch (default_kind)
        {
        case OMP_CLAUSE_DEFAULT_NONE:
       switch (default_kind)
        {
        case OMP_CLAUSE_DEFAULT_NONE:
-         error ("%qs not specified in enclosing parallel",
-                IDENTIFIER_POINTER (DECL_NAME (decl)));
+         error ("%qE not specified in enclosing parallel",
+                DECL_NAME (decl));
          error ("%Henclosing parallel", &ctx->location);
          /* FALLTHRU */
        case OMP_CLAUSE_DEFAULT_SHARED:
          error ("%Henclosing parallel", &ctx->location);
          /* FALLTHRU */
        case OMP_CLAUSE_DEFAULT_SHARED:
@@ -5334,6 +5501,20 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
       goto do_outer;
     }
 
       goto do_outer;
     }
 
+  if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
+      && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
+      && DECL_SIZE (decl)
+      && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
+    {
+      splay_tree_node n2;
+      tree t = DECL_VALUE_EXPR (decl);
+      gcc_assert (TREE_CODE (t) == INDIRECT_REF);
+      t = TREE_OPERAND (t, 0);
+      gcc_assert (DECL_P (t));
+      n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
+      n2->value |= GOVD_SEEN;
+    }
+
   shared = ((flags | n->value) & GOVD_SHARED) != 0;
   ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
 
   shared = ((flags | n->value) & GOVD_SHARED) != 0;
   ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
 
@@ -5369,8 +5550,8 @@ omp_is_private (struct gimplify_omp_ctx *ctx, tree decl)
        {
          if (ctx == gimplify_omp_ctxp)
            {
        {
          if (ctx == gimplify_omp_ctxp)
            {
-             error ("iteration variable %qs should be private",
-                    IDENTIFIER_POINTER (DECL_NAME (decl)));
+             error ("iteration variable %qE should be private",
+                    DECL_NAME (decl));
              n->value = GOVD_PRIVATE;
              return true;
            }
              n->value = GOVD_PRIVATE;
              return true;
            }
@@ -5383,11 +5564,11 @@ omp_is_private (struct gimplify_omp_ctx *ctx, tree decl)
                       && gimplify_omp_ctxp->outer_context == ctx)))
        {
          if ((n->value & GOVD_FIRSTPRIVATE) != 0)
                       && gimplify_omp_ctxp->outer_context == ctx)))
        {
          if ((n->value & GOVD_FIRSTPRIVATE) != 0)
-           error ("iteration variable %qs should not be firstprivate",
-                  IDENTIFIER_POINTER (DECL_NAME (decl)));
+           error ("iteration variable %qE should not be firstprivate",
+                  DECL_NAME (decl));
          else if ((n->value & GOVD_REDUCTION) != 0)
          else if ((n->value & GOVD_REDUCTION) != 0)
-           error ("iteration variable %qs should not be reduction",
-                  IDENTIFIER_POINTER (DECL_NAME (decl)));
+           error ("iteration variable %qE should not be reduction",
+                  DECL_NAME (decl));
        }
       return (ctx == gimplify_omp_ctxp
              || (ctx->region_type == ORT_COMBINED_PARALLEL
        }
       return (ctx == gimplify_omp_ctxp
              || (ctx->region_type == ORT_COMBINED_PARALLEL
@@ -5549,8 +5730,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
              && region_type == ORT_WORKSHARE
              && omp_check_private (ctx, decl))
            {
              && region_type == ORT_WORKSHARE
              && omp_check_private (ctx, decl))
            {
-             error ("%s variable %qs is private in outer context",
-                    check_non_private, IDENTIFIER_POINTER (DECL_NAME (decl)));
+             error ("%s variable %qE is private in outer context",
+                    check_non_private, DECL_NAME (decl));
              remove = true;
            }
          break;
              remove = true;
            }
          break;
@@ -5644,7 +5825,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
   else
     gcc_unreachable ();
 
   else
     gcc_unreachable ();
 
-  clause = build_omp_clause (code);
+  clause = build_omp_clause (input_location, code);
   OMP_CLAUSE_DECL (clause) = decl;
   OMP_CLAUSE_CHAIN (clause) = *list_p;
   if (private_debug)
   OMP_CLAUSE_DECL (clause) = decl;
   OMP_CLAUSE_CHAIN (clause) = *list_p;
   if (private_debug)
@@ -5806,7 +5987,8 @@ static enum gimplify_status
 gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 {
   tree for_stmt, decl, var, t;
 gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
 {
   tree for_stmt, decl, var, t;
-  enum gimplify_status ret = GS_OK;
+  enum gimplify_status ret = GS_ALL_DONE;
+  enum gimplify_status tret;
   gimple gfor;
   gimple_seq for_body, for_pre_body;
   int i;
   gimple gfor;
   gimple_seq for_body, for_pre_body;
   int i;
@@ -5856,8 +6038,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
       else
        var = decl;
 
       else
        var = decl;
 
-      ret |= gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
+      tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
                            is_gimple_val, fb_rvalue);
                            is_gimple_val, fb_rvalue);
+      ret = MIN (ret, tret);
       if (ret == GS_ERROR)
        return ret;
 
       if (ret == GS_ERROR)
        return ret;
 
@@ -5866,8 +6049,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
       gcc_assert (COMPARISON_CLASS_P (t));
       gcc_assert (TREE_OPERAND (t, 0) == decl);
 
       gcc_assert (COMPARISON_CLASS_P (t));
       gcc_assert (TREE_OPERAND (t, 0) == decl);
 
-      ret |= gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
+      tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
                            is_gimple_val, fb_rvalue);
                            is_gimple_val, fb_rvalue);
+      ret = MIN (ret, tret);
 
       /* Handle OMP_FOR_INCR.  */
       t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
 
       /* Handle OMP_FOR_INCR.  */
       t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
@@ -5914,8 +6098,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
              gcc_unreachable ();
            }
 
              gcc_unreachable ();
            }
 
-         ret |= gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
+         tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
                                is_gimple_val, fb_rvalue);
                                is_gimple_val, fb_rvalue);
+         ret = MIN (ret, tret);
          break;
 
        default:
          break;
 
        default:
@@ -6059,12 +6244,27 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
+    case tcc_comparison:
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
                                     lhs_var);
     case tcc_unary:
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
                                     lhs_var);
       break;
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
                                     lhs_var);
     case tcc_unary:
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
                                     lhs_var);
       break;
+    case tcc_expression:
+      switch (TREE_CODE (expr))
+       {
+       case TRUTH_ANDIF_EXPR:
+       case TRUTH_ORIF_EXPR:
+         saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
+                                        lhs_addr, lhs_var);
+         saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+                                        lhs_addr, lhs_var);
+         break;
+       default:
+         break;
+       }
+      break;
     default:
       break;
     }
     default:
       break;
     }
@@ -6215,16 +6415,12 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   if (gimple_test_f == is_gimple_reg)
     gcc_assert (fallback & (fb_rvalue | fb_lvalue));
   else if (gimple_test_f == is_gimple_val
   if (gimple_test_f == is_gimple_reg)
     gcc_assert (fallback & (fb_rvalue | fb_lvalue));
   else if (gimple_test_f == is_gimple_val
-           || gimple_test_f == is_gimple_formal_tmp_rhs
-           || gimple_test_f == is_gimple_formal_tmp_or_call_rhs
-           || gimple_test_f == is_gimple_formal_tmp_reg
-           || gimple_test_f == is_gimple_formal_tmp_var
            || gimple_test_f == is_gimple_call_addr
            || gimple_test_f == is_gimple_condexpr
            || gimple_test_f == is_gimple_mem_rhs
            || gimple_test_f == is_gimple_call_addr
            || gimple_test_f == is_gimple_condexpr
            || gimple_test_f == is_gimple_mem_rhs
-           || gimple_test_f == is_gimple_mem_or_call_rhs
+           || gimple_test_f == is_gimple_mem_rhs_or_call
            || gimple_test_f == is_gimple_reg_rhs
            || gimple_test_f == is_gimple_reg_rhs
-           || gimple_test_f == is_gimple_reg_or_call_rhs
+           || gimple_test_f == is_gimple_reg_rhs_or_call
            || gimple_test_f == is_gimple_asm_val)
     gcc_assert (fallback & fb_rvalue);
   else if (gimple_test_f == is_gimple_min_lval
            || gimple_test_f == is_gimple_asm_val)
     gcc_assert (fallback & fb_rvalue);
   else if (gimple_test_f == is_gimple_min_lval
@@ -6289,7 +6485,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        }
 
       /* Do any language-specific gimplification.  */
        }
 
       /* Do any language-specific gimplification.  */
-      ret = lang_hooks.gimplify_expr (expr_p, pre_p, post_p);
+      ret = ((enum gimplify_status)
+            lang_hooks.gimplify_expr (expr_p, pre_p, post_p));
       if (ret == GS_OK)
        {
          if (*expr_p == NULL_TREE)
       if (ret == GS_OK)
        {
          if (*expr_p == NULL_TREE)
@@ -6358,6 +6555,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
          break;
 
          ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
          break;
 
+       case COMPOUND_LITERAL_EXPR:
+         ret = gimplify_compound_literal_expr (expr_p, pre_p);
+         break;
+
        case MODIFY_EXPR:
        case INIT_EXPR:
          ret = gimplify_modify_expr (expr_p, pre_p, post_p,
        case MODIFY_EXPR:
        case INIT_EXPR:
          ret = gimplify_modify_expr (expr_p, pre_p, post_p,
@@ -6366,7 +6567,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
        case TRUTH_ANDIF_EXPR:
        case TRUTH_ORIF_EXPR:
 
        case TRUTH_ANDIF_EXPR:
        case TRUTH_ORIF_EXPR:
-         ret = gimplify_boolean_expr (expr_p);
+         /* Pass the source location of the outer expression.  */
+         ret = gimplify_boolean_expr (expr_p, saved_location);
          break;
 
        case TRUTH_NOT_EXPR:
          break;
 
        case TRUTH_NOT_EXPR:
@@ -6573,6 +6775,24 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          }
          break;
 
          }
          break;
 
+       case TARGET_MEM_REF:
+         {
+           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))
+             r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
+                                 post_p, is_gimple_val, fb_either);
+           if (TMR_INDEX (*expr_p))
+             r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
+                                 post_p, is_gimple_val, fb_rvalue);
+           /* TMR_STEP and TMR_OFFSET are always integer constants.  */
+           ret = MIN (r0, r1);
+         }
+         break;
+
        case NON_LVALUE_EXPR:
          /* This should have been stripped above.  */
          gcc_unreachable ();
        case NON_LVALUE_EXPR:
          /* This should have been stripped above.  */
          gcc_unreachable ();
@@ -6642,19 +6862,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            break;
          }
 
            break;
          }
 
-       case CHANGE_DYNAMIC_TYPE_EXPR:
-         {
-           gimple cdt;
-
-           ret = gimplify_expr (&CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p),
-                                pre_p, post_p, is_gimple_reg, fb_lvalue);
-           cdt = gimple_build_cdt (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*expr_p),
-                                   CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p));
-           gimplify_seq_add_stmt (pre_p, cdt);
-           ret = GS_ALL_DONE;
-         }
-         break;
-
        case OBJ_TYPE_REF:
          {
            enum gimplify_status r0, r1;
        case OBJ_TYPE_REF:
          {
            enum gimplify_status r0, r1;
@@ -6768,8 +6975,9 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
           */
          if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
              && (tmp = maybe_fold_offset_to_address
           */
          if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
              && (tmp = maybe_fold_offset_to_address
-                        (TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
-                         TREE_TYPE (*expr_p))))
+                 (EXPR_LOCATION (*expr_p),
+                  TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
+                  TREE_TYPE (*expr_p))))
            {
              *expr_p = tmp;
              break;
            {
              *expr_p = tmp;
              break;
@@ -6780,10 +6988,11 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
                                                                        0),0)))
              && (tmp = maybe_fold_offset_to_address
              && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
                                                                        0),0)))
              && (tmp = maybe_fold_offset_to_address
-                        (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0),
-                         TREE_OPERAND (*expr_p, 1),
-                         TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0),
-                                                  0)))))
+                 (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);
               break;
             {
                *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp);
               break;
@@ -6978,7 +7187,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  && code != ASM_EXPR
                  && code != BIND_EXPR
                  && code != CATCH_EXPR
                  && code != ASM_EXPR
                  && code != BIND_EXPR
                  && code != CATCH_EXPR
-                 && code != COND_EXPR
+                 && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
                  && code != EH_FILTER_EXPR
                  && code != GOTO_EXPR
                  && code != LABEL_EXPR
                  && code != EH_FILTER_EXPR
                  && code != GOTO_EXPR
                  && code != LABEL_EXPR
@@ -7023,7 +7232,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
       *expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp);
     }
       gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
       *expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp);
     }
-  else if ((fallback & fb_rvalue) && is_gimple_formal_tmp_or_call_rhs (*expr_p))
+  else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
     {
       /* An rvalue will do.  Assign the gimplified expression into a
         new temporary TMP and replace the original expression with
     {
       /* An rvalue will do.  Assign the gimplified expression into a
         new temporary TMP and replace the original expression with
@@ -7035,12 +7244,14 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        /* The postqueue might change the value of the expression between
           the initialization and use of the temporary, so we can't use a
           formal temp.  FIXME do we care?  */
        /* The postqueue might change the value of the expression between
           the initialization and use of the temporary, so we can't use a
           formal temp.  FIXME do we care?  */
-       *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
+       {
+         *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
+         if (TREE_CODE (TREE_TYPE (*expr_p)) == COMPLEX_TYPE
+             || TREE_CODE (TREE_TYPE (*expr_p)) == VECTOR_TYPE)
+           DECL_GIMPLE_REG_P (*expr_p) = 1;
+       }
       else
        *expr_p = get_formal_tmp_var (*expr_p, pre_p);
       else
        *expr_p = get_formal_tmp_var (*expr_p, pre_p);
-
-      if (TREE_CODE (*expr_p) != SSA_NAME)
-       DECL_GIMPLE_FORMAL_TEMP_P (*expr_p) = 1;
     }
   else
     {
     }
   else
     {
@@ -7117,6 +7328,18 @@ 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);
       /* 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)
+         && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
+       {
+         t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
+         if (t && TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t))
+           DECL_IGNORED_P (t) = 0;
+         t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
+         if (t && TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t))
+           DECL_IGNORED_P (t) = 0;
+       }
       break;
 
     case RECORD_TYPE:
       break;
 
     case RECORD_TYPE:
@@ -7126,6 +7349,8 @@ gimplify_type_sizes (tree type, gimple_seq *list_p)
        if (TREE_CODE (field) == FIELD_DECL)
          {
            gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
        if (TREE_CODE (field) == FIELD_DECL)
          {
            gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
+           gimplify_one_sizepos (&DECL_SIZE (field), list_p);
+           gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
            gimplify_type_sizes (TREE_TYPE (field), list_p);
          }
       break;
            gimplify_type_sizes (TREE_TYPE (field), list_p);
          }
       break;
@@ -7239,6 +7464,9 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
   unshare_body (body_p, fndecl);
   unvisit_body (body_p, fndecl);
 
   unshare_body (body_p, fndecl);
   unvisit_body (body_p, fndecl);
 
+  if (cgraph_node (fndecl)->origin)
+    nonlocal_vlas = pointer_set_create ();
+
   /* Make sure input_location isn't set to something weird.  */
   input_location = DECL_SOURCE_LOCATION (fndecl);
 
   /* Make sure input_location isn't set to something weird.  */
   input_location = DECL_SOURCE_LOCATION (fndecl);
 
@@ -7274,6 +7502,12 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
       gimple_bind_set_body (outer_bind, parm_stmts);
     }
 
       gimple_bind_set_body (outer_bind, parm_stmts);
     }
 
+  if (nonlocal_vlas)
+    {
+      pointer_set_destroy (nonlocal_vlas);
+      nonlocal_vlas = NULL;
+    }
+
   pop_gimplify_context (outer_bind);
   gcc_assert (gimplify_ctxp == NULL);
 
   pop_gimplify_context (outer_bind);
   gcc_assert (gimplify_ctxp == NULL);
 
@@ -7354,10 +7588,10 @@ gimplify_function_tree (tree fndecl)
       x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
       gimplify_seq_add_stmt (&body, gimple_build_call (x, 0));
       gimplify_seq_add_stmt (&body, tf);
       x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
       gimplify_seq_add_stmt (&body, gimple_build_call (x, 0));
       gimplify_seq_add_stmt (&body, tf);
-      new_bind = gimple_build_bind (NULL, body, gimple_block (bind));
+      new_bind = gimple_build_bind (NULL, body, gimple_bind_block (bind));
       /* Clear the block for BIND, since it is no longer directly inside
          the function, but within a try block.  */
       /* Clear the block for BIND, since it is no longer directly inside
          the function, but within a try block.  */
-      gimple_set_block (bind, NULL);
+      gimple_bind_set_block (bind, NULL);
 
       /* Replace the current function body with the body
          wrapped in the try/finally TF.  */
 
       /* Replace the current function body with the body
          wrapped in the try/finally TF.  */
@@ -7398,6 +7632,10 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
       gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL,
                     is_gimple_val, fb_rvalue);
       break;
       gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL,
                     is_gimple_val, fb_rvalue);
       break;
+    case GIMPLE_SWITCH:
+      gimplify_expr (gimple_switch_index_ptr (stmt), &pre, NULL,
+                    is_gimple_val, fb_rvalue);
+      break;
     case GIMPLE_OMP_ATOMIC_LOAD:
       gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL,
                     is_gimple_val, fb_rvalue);
     case GIMPLE_OMP_ATOMIC_LOAD:
       gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL,
                     is_gimple_val, fb_rvalue);
@@ -7472,9 +7710,9 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
        }
 
       lhs = gimple_get_lhs (stmt);
        }
 
       lhs = gimple_get_lhs (stmt);
-      /* If regimplification of the LHS changed it in a way that requires
-        a simple RHS, create temporary.  */
-      if (orig_lhs != lhs && !is_gimple_formal_tmp_var (lhs))
+      /* If the LHS changed it in a way that requires a simple RHS,
+        create temporary.  */
+      if (lhs && !is_gimple_reg (lhs))
        {
          bool need_temp = false;
 
        {
          bool need_temp = false;
 
@@ -7523,7 +7761,6 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
            {
              tree temp = create_tmp_var (TREE_TYPE (lhs), NULL);
 
            {
              tree temp = create_tmp_var (TREE_TYPE (lhs), NULL);
 
-             DECL_GIMPLE_FORMAL_TEMP_P (temp) = 1;
              if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
                  || TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
                DECL_GIMPLE_REG_P (temp) = 1;
              if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
                  || TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
                DECL_GIMPLE_REG_P (temp) = 1;
@@ -7548,6 +7785,10 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
       break;
     }
 
       break;
     }
 
+  if (gimple_referenced_vars (cfun))
+    for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
+      add_referenced_var (t);
+
   if (!gimple_seq_empty_p (pre))
     {
       if (gimple_in_ssa_p (cfun))
   if (!gimple_seq_empty_p (pre))
     {
       if (gimple_in_ssa_p (cfun))
@@ -7562,10 +7803,6 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
   if (post_stmt)
     gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
 
   if (post_stmt)
     gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
 
-  if (gimple_referenced_vars (cfun))
-    for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
-      add_referenced_var (t);
-
   pop_gimplify_context (NULL);
 }
 
   pop_gimplify_context (NULL);
 }