{
/* 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;
}
}
}
- /* 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;
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;
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
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);
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;
}
}
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;
{
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);
}
}
-/* 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;
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;
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))
{
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"