Fix for mainline build on mips64el-linux
Joseph S. Myers
joseph@codesourcery.com
Tue May 23 17:59:00 GMT 2006
On Fri, 5 May 2006, Roger Sayle wrote:
>
> On Fri, 5 May 2006, Richard Sandiford wrote:
> > I might be worrying unduly, but I'm a little concerned about this patch.
> > I think simplify_subreg currently only returns lvalues when given an lvalue.
> > This patch appears to be the first time that we'll return an rvalue for an
> > lvalue input.
>
> Do were ever interpret paradoxical SUBREGs are lvalues? I thought that
> we use STRICT_LOW_PART as the destination of a SET in these cases. But
> I'll admit that I wouldn't be surprised if we abused paradoxical SUBREGs
> somewhere, and then relied on conservation on lvalue-ness later. Grrr.
>
> Joseph, any chance we could go with the ultra-safe alternative of
> defining an undefined_operand_subword_p and using it in expr.c's
> emit_move_multi_word? I suspect that this would help other code,
> and the new predicate might be useful in other areas.
How about the following patch? It fixes build for mips64el-linux and
passed testing with no regressions on x86_64-unknown-linux-gnu.
2006-05-23 Joseph Myers <joseph@codesourcery.com>
* expr.c (undefined_operand_subword_p): New.
(emit_move_multi_word): Do not generate move from undefined bits
of a paradoxical subreg.
Index: expr.c
===================================================================
--- expr.c (revision 113993)
+++ expr.c (working copy)
@@ -3096,6 +3096,38 @@
return ret;
}
+/* Return true if word I of OP (mode MODE) lies entirely in the
+ undefined bits of a paradoxical subreg. */
+
+static bool
+undefined_operand_subword_p (rtx op, int i)
+{
+ enum machine_mode innermode, innermostmode;
+ int offset;
+ if (GET_CODE (op) != SUBREG)
+ return false;
+ innermode = GET_MODE (op);
+ innermostmode = GET_MODE (SUBREG_REG (op));
+ offset = i * UNITS_PER_WORD + SUBREG_BYTE (op);
+ /* The SUBREG_BYTE represents offset, as if the value were stored in
+ memory, except for a paradoxical subreg where we define
+ SUBREG_BYTE to be 0; undo this exception as in
+ simplify_subreg. */
+ if (SUBREG_BYTE (op) == 0
+ && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode))
+ {
+ int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode));
+ if (WORDS_BIG_ENDIAN)
+ offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ offset += difference % UNITS_PER_WORD;
+ }
+ if (offset >= GET_MODE_SIZE (innermostmode)
+ || offset <= -GET_MODE_SIZE (word_mode))
+ return true;
+ return false;
+}
+
/* A subroutine of emit_move_insn_1. Generate a move from Y into X.
MODE is any multi-word or full-word mode that lacks a move_insn
pattern. Note that you will get better code if you define such
@@ -3133,8 +3165,15 @@
i++)
{
rtx xpart = operand_subword (x, i, 1, mode);
- rtx ypart = operand_subword (y, i, 1, mode);
+ rtx ypart;
+ /* Do not generate code for a move if it would come entirely
+ from the undefined bits of a paradoxical subreg. */
+ if (undefined_operand_subword_p (y, i))
+ continue;
+
+ ypart = operand_subword (y, i, 1, mode);
+
/* If we can't get a part of Y, put Y into memory if it is a
constant. Otherwise, force it into a register. Then we must
be able to get a part of Y. */
--
Joseph S. Myers http://www.srcf.ucam.org/~jsm28/gcc/
jsm@polyomino.org.uk (personal mail)
joseph@codesourcery.com (CodeSourcery mail)
jsm28@gcc.gnu.org (Bugzilla assignments and CCs)
More information about the Gcc-patches
mailing list