I hope the following patch fixes
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57604
Although I have no specific hardware to check this.
The patch also adds a comment about one recent change as it was done in
the same function.
The patch was successfully bootstrapped and tested on x86/x86-64 and
s390x (including building java).
Committed as rev. 200227.
2013-06-19 Vladimir Makarov <vmaka...@redhat.com>
PR bootstrap/57604
* lra.c (emit_add3_insn, emit_add2_insn): New functions.
(lra_emit_add): Use the functions. Add comment about Y as an
address segment.
Index: lra.c
===================================================================
--- lra.c (revision 200174)
+++ lra.c (working copy)
@@ -242,6 +242,42 @@ lra_delete_dead_insn (rtx insn)
lra_set_insn_deleted (insn);
}
+/* Emit insn x = y + z. Return NULL if we failed to do it.
+ Otherwise, return the insn. We don't use gen_add3_insn as it might
+ clobber CC. */
+static rtx
+emit_add3_insn (rtx x, rtx y, rtx z)
+{
+ rtx insn, last;
+
+ last = get_last_insn ();
+ insn = emit_insn (gen_rtx_SET (VOIDmode, x,
+ gen_rtx_PLUS (GET_MODE (y), y, z)));
+ if (recog_memoized (insn) < 0)
+ {
+ delete_insns_since (last);
+ insn = NULL_RTX;
+ }
+ return insn;
+}
+
+/* Emit insn x = x + y. Return the insn. We use gen_add2_insn as the
+ last resort. */
+static rtx
+emit_add2_insn (rtx x, rtx y)
+{
+ rtx insn;
+
+ insn = emit_add3_insn (x, x, y);
+ if (insn == NULL_RTX)
+ {
+ insn = gen_add2_insn (x, y);
+ if (insn != NULL_RTX)
+ emit_insn (insn);
+ }
+ return insn;
+}
+
/* Target checks operands through operand predicates to recognize an
insn. We should have a special precaution to generate add insns
which are frequent results of elimination.
@@ -260,10 +296,10 @@ lra_emit_add (rtx x, rtx y, rtx z)
rtx a1, a2, base, index, disp, scale, index_scale;
bool ok_p;
- insn = gen_add3_insn (x, y, z);
+ insn = emit_add3_insn (x, y, z);
old = max_reg_num ();
if (insn != NULL_RTX)
- emit_insn (insn);
+ ;
else
{
disp = a2 = NULL_RTX;
@@ -306,12 +342,14 @@ lra_emit_add (rtx x, rtx y, rtx z)
|| (disp != NULL_RTX && ! CONSTANT_P (disp))
|| (scale != NULL_RTX && ! CONSTANT_P (scale)))
{
- /* It is not an address generation. Probably we have no 3 op
- add. Last chance is to use 2-op add insn. */
+ /* Probably we have no 3 op add. Last chance is to use 2-op
+ add insn. To succeed, don't move Z to X as an address
+ segment always comes in Y. Otherwise, we might fail when
+ adding the address segment to register. */
lra_assert (x != y && x != z);
emit_move_insn (x, y);
- insn = gen_add2_insn (x, z);
- emit_insn (insn);
+ insn = emit_add2_insn (x, z);
+ lra_assert (insn != NULL_RTX);
}
else
{
@@ -322,8 +360,8 @@ lra_emit_add (rtx x, rtx y, rtx z)
/* Generate x = index_scale; x = x + base. */
lra_assert (index_scale != NULL_RTX && base != NULL_RTX);
emit_move_insn (x, index_scale);
- insn = gen_add2_insn (x, base);
- emit_insn (insn);
+ insn = emit_add2_insn (x, base);
+ lra_assert (insn != NULL_RTX);
}
else if (scale == NULL_RTX)
{
@@ -337,14 +375,14 @@ lra_emit_add (rtx x, rtx y, rtx z)
delete_insns_since (last);
/* Generate x = disp; x = x + base. */
emit_move_insn (x, disp);
- insn = gen_add2_insn (x, base);
- emit_insn (insn);
+ insn = emit_add2_insn (x, base);
+ lra_assert (insn != NULL_RTX);
}
/* Generate x = x + index. */
if (index != NULL_RTX)
{
- insn = gen_add2_insn (x, index);
- emit_insn (insn);
+ insn = emit_add2_insn (x, index);
+ lra_assert (insn != NULL_RTX);
}
}
else
@@ -355,16 +393,12 @@ lra_emit_add (rtx x, rtx y, rtx z)
ok_p = false;
if (recog_memoized (insn) >= 0)
{
- insn = gen_add2_insn (x, disp);
+ insn = emit_add2_insn (x, disp);
if (insn != NULL_RTX)
{
- emit_insn (insn);
- insn = gen_add2_insn (x, disp);
+ insn = emit_add2_insn (x, disp);
if (insn != NULL_RTX)
- {
- emit_insn (insn);
- ok_p = true;
- }
+ ok_p = true;
}
}
if (! ok_p)
@@ -372,10 +406,10 @@ lra_emit_add (rtx x, rtx y, rtx z)
delete_insns_since (last);
/* Generate x = disp; x = x + base; x = x + index_scale. */
emit_move_insn (x, disp);
- insn = gen_add2_insn (x, base);
- emit_insn (insn);
- insn = gen_add2_insn (x, index_scale);
- emit_insn (insn);
+ insn = emit_add2_insn (x, base);
+ lra_assert (insn != NULL_RTX);
+ insn = emit_add2_insn (x, index_scale);
+ lra_assert (insn != NULL_RTX);
}
}
}