This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: match constraints with different modes in big endian => reload ICE
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 02 Mar 2003 08:47:20 -0300
- Subject: Re: match constraints with different modes in big endian => reload ICE
- Organization: GCC Team, Red Hat
- References: <oradgopwmp.fsf@free.redhat.lsd.ic.unicamp.br>
On Feb 22, 2003, Alexandre Oliva <aoliva at redhat dot com> wrote:
> * reload.h (reload_adjust_reg_for_mode): Declare.
Oops, I noticed by chance that I'd missed this change in the patch
file I posted. Here's the complete patch. Ok to install?
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva at redhat dot com>
* reload.c (reload_adjust_reg_for_mode): New function.
(subst_reloads): Call it.
(operands_match_p): Adjust registers using HARD_REGNO_NREGS.
* reload.h (reload_adjust_reg_for_mode): Declare.
* reload1.c (emit_input_reload_insns, emit_output_reload_insns):
Call it.
Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.209
diff -u -p -r1.209 reload.c
--- gcc/reload.c 4 Feb 2003 22:47:23 -0000 1.209
+++ gcc/reload.c 22 Feb 2003 08:02:45 -0000
@@ -2137,10 +2137,10 @@ operands_match_p (x, y)
(reg:SI 1) will be considered the same register. */
if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
&& i < FIRST_PSEUDO_REGISTER)
- i += (GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD) - 1;
+ i += HARD_REGNO_NREGS (i, GET_MODE (x)) - 1;
if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
&& j < FIRST_PSEUDO_REGISTER)
- j += (GET_MODE_SIZE (GET_MODE (y)) / UNITS_PER_WORD) - 1;
+ j += HARD_REGNO_NREGS (j, GET_MODE (y)) - 1;
return i == j;
}
@@ -5954,7 +5954,7 @@ subst_reloads (insn)
do the wrong thing if RELOADREG is multi-word. RELOADREG
will always be a REG here. */
if (GET_MODE (reloadreg) != r->mode && r->mode != VOIDmode)
- reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
+ reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
/* If we are putting this into a SUBREG and RELOADREG is a
SUBREG, we would be making nested SUBREGs, so we have to fix
@@ -6932,6 +6932,26 @@ regno_clobbered_p (regno, insn, mode, se
}
return 0;
+}
+
+/* Find the low part, with mode MODE, of a hard regno RELOADREG. */
+rtx
+reload_adjust_reg_for_mode (reloadreg, mode)
+ rtx reloadreg;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (reloadreg) == mode)
+ return reloadreg;
+
+ regno = REGNO (reloadreg);
+
+ if (WORDS_BIG_ENDIAN)
+ regno += HARD_REGNO_NREGS (regno, GET_MODE (reloadreg))
+ - HARD_REGNO_NREGS (regno, mode);
+
+ return gen_rtx_REG (mode, regno);
}
static const char *const reload_when_needed_name[] =
Index: gcc/reload.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.h,v
retrieving revision 1.42
diff -u -p -r1.42 reload.h
--- gcc/reload.h 17 Jan 2003 03:28:09 -0000 1.42
+++ gcc/reload.h 2 Mar 2003 11:45:03 -0000
@@ -1,6 +1,6 @@
/* Communication between reload.c and reload1.c.
Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -385,3 +385,7 @@ extern void cleanup_subreg_operands PARA
/* Debugging support. */
extern void debug_reload_to_stream PARAMS ((FILE *));
extern void debug_reload PARAMS ((void));
+
+/* Compute the actual register we should reload to, in case we're
+ reloading to/from a register that is wider than a word. */
+extern rtx reload_adjust_reg_for_mode PARAMS ((rtx, enum machine_mode));
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.379
diff -u -p -r1.379 reload1.c
--- gcc/reload1.c 14 Feb 2003 22:23:48 -0000 1.379
+++ gcc/reload1.c 22 Feb 2003 08:02:52 -0000
@@ -6321,7 +6321,7 @@ emit_input_reload_insns (chain, rl, old,
must always be a REG here. */
if (GET_MODE (reloadreg) != mode)
- reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+ reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
while (GET_CODE (oldequiv) == SUBREG && GET_MODE (oldequiv) != mode)
oldequiv = SUBREG_REG (oldequiv);
if (GET_MODE (oldequiv) != VOIDmode
@@ -6570,8 +6570,8 @@ emit_input_reload_insns (chain, rl, old,
oldequiv = old, real_oldequiv = real_old;
else
second_reload_reg
- = gen_rtx_REG (new_mode,
- REGNO (second_reload_reg));
+ = reload_adjust_reg_for_mode (second_reload_reg,
+ new_mode);
}
}
}
@@ -6693,7 +6693,7 @@ emit_output_reload_insns (chain, rl, j)
}
if (GET_MODE (reloadreg) != mode)
- reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+ reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
@@ -6734,7 +6734,7 @@ emit_output_reload_insns (chain, rl, j)
= rld[secondary_reload].secondary_out_icode;
if (GET_MODE (reloadreg) != mode)
- reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+ reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
if (tertiary_icode != CODE_FOR_nothing)
{
Index: gcc/testsuite/ChangeLog
from Alexandre Oliva <aoliva at redhat dot com>
* gcc.c-torture/execute/20030222-1.c: New test.
Index: gcc/testsuite/gcc.c-torture/execute/20030222-1.c
===================================================================
RCS file: gcc/testsuite/gcc.c-torture/execute/20030222-1.c
diff -N gcc/testsuite/gcc.c-torture/execute/20030222-1.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.c-torture/execute/20030222-1.c 22 Feb 2003 08:03:00 -0000
@@ -0,0 +1,27 @@
+/* Verify that we get the low part of the long long as an int. We
+ used to get it wrong on big-endian machines, if register allocation
+ succeeded at all. We use volatile to make sure the long long is
+ actually truncated to int, in case a single register is wide enough
+ for a long long. */
+
+#include <limits.h>
+
+void
+ll_to_int (long long x, volatile int *p)
+{
+ int i;
+ asm ("" : "=r" (i) : "0" (x));
+ *p = i;
+}
+
+int val = INT_MIN + 1;
+
+int main() {
+ volatile int i;
+
+ ll_to_int ((long long)val, &i);
+ if (i != val)
+ abort ();
+
+ exit (0);
+}
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva at {redhat dot com, gcc.gnu.org}
CS PhD student at IC-Unicamp oliva at {lsd dot ic dot unicamp dot br, gnu.org}
Free Software Evangelist Professional serial bug killer