diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 43 |
1 files changed, 37 insertions, 6 deletions
@@ -466,13 +466,30 @@ queued_subexp_p (rtx x) } } -/* Perform all the pending incrementations. */ +/* Retrieve a mark on the queue. */ + +static rtx +mark_queue (void) +{ + return pending_chain; +} -void -emit_queue (void) +/* Perform all the pending incrementations that have been enqueued + after MARK was retrieved. If MARK is null, perform all the + pending incrementations. */ + +static void +emit_insns_enqueued_after_mark (rtx mark) { rtx p; - while ((p = pending_chain)) + + /* The marked incrementation may have been emitted in the meantime + through a call to emit_queue. In this case, the mark is not valid + anymore so do nothing. */ + if (mark && ! QUEUED_BODY (mark)) + return; + + while ((p = pending_chain) != mark) { rtx body = QUEUED_BODY (p); @@ -499,9 +516,18 @@ emit_queue (void) break; } + QUEUED_BODY (p) = 0; pending_chain = QUEUED_NEXT (p); } } + +/* Perform all the pending incrementations. */ + +void +emit_queue (void) +{ + emit_insns_enqueued_after_mark (NULL_RTX); +} /* Copy data from FROM to TO, where the machine modes are not the same. Both modes may be integer, or both may be floating. @@ -4003,6 +4029,7 @@ store_expr (tree exp, rtx target, int want_value) { rtx temp; rtx alt_rtl = NULL_RTX; + rtx mark = mark_queue (); int dont_return_target = 0; int dont_store_target = 0; @@ -4214,7 +4241,11 @@ store_expr (tree exp, rtx target, int want_value) temp, TREE_UNSIGNED (TREE_TYPE (exp))); /* If value was not generated in the target, store it there. - Convert the value to TARGET's type first if necessary. + Convert the value to TARGET's type first if necessary and emit the + pending incrementations that have been queued when expanding EXP. + Note that we cannot emit the whole queue blindly because this will + effectively disable the POST_INC optimization later. + If TEMP and TARGET compare equal according to rtx_equal_p, but one or both of them are volatile memory refs, we have to distinguish two cases: @@ -4242,7 +4273,7 @@ store_expr (tree exp, rtx target, int want_value) bit-initialized. */ && expr_size (exp) != const0_rtx) { - emit_queue(); + emit_insns_enqueued_after_mark (mark); target = protect_from_queue (target, 1); temp = protect_from_queue (temp, 0); if (GET_MODE (temp) != GET_MODE (target) |