This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]