This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[4.0 PATCH] Fix PR 20927 (was: PR19683: Fix a use of REG_CANNOT_CHANGE_MODE_P)
- From: Ulrich Weigand <uweigand at de dot ibm dot com>
- To: rsandifo at redhat dot com, rth at redhat dot com, mark at codesourcery dot com
- Cc: gcc-patches at gcc dot gnu dot org, aj at suse dot de
- Date: Tue, 12 Apr 2005 00:11:57 +0200 (CEST)
- Subject: [4.0 PATCH] Fix PR 20927 (was: PR19683: Fix a use of REG_CANNOT_CHANGE_MODE_P)
Richard Sandiford wrote:
> PR rtl-optimization/19683
> * reload1.c (choose_reload_regs): Pass the number of bits, not the
> number of bytes, to smallest_int_for_mode. Fix arguments to
> REG_CANNOT_CHANGE_MODE_P.
Unfortunately, this change triggers PR 20927, an ICE on s390x
(a regression of 4.0 over 3.4).
The problematic case is where we reload:
(subreg:DF (reg:TI pseudo) 8)
When computing the "needed mode", choose_reload_regs now calls
smallest_mode_for_size (128, MODE_FLOAT)
which ICEs because the largest floating-point mode on s390x is DFmode.
The patch below is a minimal fix, which might be suitable for 4.0.
It simply inlines the smallest_mode_for_size function, but instead of
ICEing when the requested mode isn't found, this particular inheritance
is simply skipped.
As real fix, I think the computation of a "needed mode" may be
completely superfluous in the first place; instead, the first
clause of the 'if' could just be replaced by
if ((GET_MODE_SIZE (GET_MODE (last_reg))
>= GET_MODE_SIZE (mode) + byte)
What do you think?
Mark, would the patch below be OK for 4.0 if there is a second RC?
Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux on 4.0.
Bye,
Ulrich
ChangeLog:
* reload1.c (choose_reload_regs): Inline smallest_mode_for_size,
but do not abort if requested mode does not exist.
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.466
diff -c -p -r1.466 reload1.c
*** gcc/reload1.c 23 Mar 2005 15:59:40 -0000 1.466
--- gcc/reload1.c 11 Apr 2005 19:40:16 -0000
*************** choose_reload_regs (struct insn_chain *c
*** 5423,5435 ****
if (byte == 0)
need_mode = mode;
else
! need_mode
! = smallest_mode_for_size (GET_MODE_BITSIZE (mode)
! + byte * BITS_PER_UNIT,
! GET_MODE_CLASS (mode));
! if ((GET_MODE_SIZE (GET_MODE (last_reg))
! >= GET_MODE_SIZE (need_mode))
#ifdef CANNOT_CHANGE_MODE_CLASS
/* Verify that the register in "i" can be obtained
from LAST_REG. */
--- 5423,5439 ----
if (byte == 0)
need_mode = mode;
else
! for (need_mode =
! GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (mode));
! need_mode != VOIDmode;
! need_mode = GET_MODE_WIDER_MODE (need_mode))
! if (GET_MODE_PRECISION (need_mode)
! >= GET_MODE_BITSIZE (mode) + byte * BITS_PER_UNIT)
! break;
! if (need_mode != VOIDmode
! && (GET_MODE_SIZE (GET_MODE (last_reg))
! >= GET_MODE_SIZE (need_mode))
#ifdef CANNOT_CHANGE_MODE_CLASS
/* Verify that the register in "i" can be obtained
from LAST_REG. */
*** /dev/null Tue Oct 26 21:09:21 2004
--- gcc/testsuite/gcc.dg/pr20927.c Mon Apr 11 21:45:12 2005
***************
*** 0 ****
--- 1,23 ----
+ /* This caused an ICE on s390x due to a reload inheritance bug. */
+
+ /* { dg-do compile { target s390*-*-* } } */
+ /* { dg-options "-O2" } */
+
+ struct point { double x, y; };
+ extern void use (struct point);
+
+ void test (struct point *pc, struct point p1)
+ {
+ struct point p0 = *pc;
+
+ if (p0.x == p1.x && p0.y == p1.y)
+ use (p0);
+
+ asm ("" : : : "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
+
+ p1.y -= p0.y;
+
+ use (p0);
+ use (p1);
+ }
+
--
Dr. Ulrich Weigand
Linux on zSeries Development
Ulrich.Weigand@de.ibm.com