OSDN Git Service

* tree.h (TREE_THIS_NOTRAP): Use TREE_CHECK5.
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index 52d83f6..029ad03 100644 (file)
@@ -2479,8 +2479,11 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
     {
       /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
         have to do is replicate it as a GIMPLE_CALL tuple.  */
+      gimple_stmt_iterator gsi;
       call = gimple_build_call_from_tree (*expr_p);
       gimplify_seq_add_stmt (pre_p, call);
+      gsi = gsi_last (*pre_p);
+      fold_stmt (&gsi);
       *expr_p = NULL_TREE;
     }
 
@@ -3824,11 +3827,12 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
              }
          }
 
-       /* If the target is volatile and we have non-zero elements
-          initialize the target from a temporary.  */
+       /* If the target is volatile, we have non-zero elements and more than
+          one field to assign, initialize the target from a temporary.  */
        if (TREE_THIS_VOLATILE (object)
            && !TREE_ADDRESSABLE (type)
-           && num_nonzero_elements > 0)
+           && num_nonzero_elements > 0
+           && VEC_length (constructor_elt, elts) > 1)
          {
            tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type), NULL);
            TREE_OPERAND (*expr_p, 0) = temp;
@@ -4196,9 +4200,18 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
             This kind of code arises in C++ when an object is bound
             to a const reference, and if "x" is a TARGET_EXPR we want
             to take advantage of the optimization below.  */
+           bool volatile_p = TREE_THIS_VOLATILE (*from_p);
            tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0));
            if (t)
              {
+               if (TREE_THIS_VOLATILE (t) != volatile_p)
+                 {
+                   if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
+                     t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
+                                                   build_fold_addr_expr (t));
+                   if (REFERENCE_CLASS_P (t))
+                     TREE_THIS_VOLATILE (t) = volatile_p;
+                 }
                *from_p = t;
                ret = GS_OK;
                changed = true;
@@ -4790,7 +4803,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
@@ -6783,17 +6795,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          recalculate_side_effects (*expr_p);
          break;
 
-       case MISALIGNED_INDIRECT_REF:
-         /* We can only reach this through re-gimplification from
-            tree optimizers.  */
-         ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-                              is_gimple_reg, fb_rvalue);
-         recalculate_side_effects (*expr_p);
-         break;
-
        case INDIRECT_REF:
          {
            bool volatilep = TREE_THIS_VOLATILE (*expr_p);
+           bool notrap = TREE_THIS_NOTRAP (*expr_p);
            tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
 
            *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
@@ -6805,13 +6810,16 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
            ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
                                 is_gimple_reg, fb_rvalue);
-           recalculate_side_effects (*expr_p);
+           if (ret == GS_ERROR)
+             break;
 
+           recalculate_side_effects (*expr_p);
            *expr_p = fold_build2_loc (input_location, MEM_REF,
                                       TREE_TYPE (*expr_p),
                                       TREE_OPERAND (*expr_p, 0),
                                       build_int_cst (saved_ptr_type, 0));
            TREE_THIS_VOLATILE (*expr_p) = volatilep;
+           TREE_THIS_NOTRAP (*expr_p) = notrap;
            ret = GS_OK;
            break;
          }
@@ -6831,6 +6839,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
            }
          ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
                               is_gimple_mem_ref_addr, fb_rvalue);
+         if (ret == GS_ERROR)
+           break;
          recalculate_side_effects (*expr_p);
          ret = GS_ALL_DONE;
          break;
@@ -6976,15 +6986,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);
          }
@@ -8007,17 +8017,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;
@@ -8025,8 +8034,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;
@@ -8055,20 +8062,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))
     {
@@ -8089,4 +8110,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"