aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/expr.c43
2 files changed, 47 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c4098af..8d3238b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2004-03-22 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR middle-end/14470
+ * expr.c (mark_queue): New function.
+ (emit_insns_enqueued_after_mark): New function replacing
+ emit_queue. Clear the body of emitted queued insns.
+ (emit_queue): Call emit_insns_enqueued_after_mark.
+ (store_expr): Mark the increment queue on entry. Emit
+ only the incrementations queued when expanding the source.
+
2004-03-22 Nathanael Nerode <neroden@gcc.gnu.org>
* configure.ac: Allow --disable-coverage-flags (for the future benefit
diff --git a/gcc/expr.c b/gcc/expr.c
index 80647265..d77b6e5 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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)