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]

[PATCH] Fix s390 fallout from PR11271 patch


Hello,

I've finally found a way to get s390 back to bootstrap, while
still keeping both arm and sparc working.

While this patch is probably not a really clean solution,
it has the advantage that it is very low-impact and unlikely
to break other platforms; thus I'd ask that this patch is
approved at least as temporary solution for the 3.4 release.

To explain the patch, I'll start with a little overview of the
history of this piece of code.  We are talking about the 
fragment of find_reloads_address that fixes up invalid addresses
of the form REG+REG+CONST by reloading REG+CONST into a temporary.

This needs to be triggered if the invalid REG+REG+CONST is the
result of either register elimination or of fixing up subreg
offsets (in find_reloads_subreg_address).  However, it is also
crucial that it is *not* triggered on addresses of the form
REG+REG+CONST that are invalid merely because one of the registers
needs a reload -- in this case, we would introduce a non-canonical
address into the real insn stream, which never gets fixed up
afterwards (this is the s390 problem at the moment).

[ Note that if the address was result of register elimination,
  the changes are applied to a temporary copy created by the
  elimination code; likewise if the address was result of 
  subreg offset adjustment. ]

The code originally *used* to trigger if one of the registers
was one of stack frame related special registers (sp/fp/ap).
This, together with the other tests, ensured that we had a
situation generated by register elimination.

However, this meant that R+R+CONST were not split as required
(on sparc) if this address was result of subreg adjustment.
In March 2003, Eric Botcazou committed a patch that replaced
the test for sp/fp/ap with a test for general base registers.
As far as I can see, this was intended to *widen* the range
of accepted registers, not restrict them.

Unfortunately, it seems that on the arm, in some cases the
specical registers (sp/fp/ap) that were accepted previously
were now rejected because they are sometimes not valid base
registers.  Richard Earnshaw recently committed a patch that
removed the base register test so that *all* hard registers
now cause the R+R+CONST split.

This fixed arm again, but now breaks s390, because on our
platform R+R+CONST are valid addresses provided the CONST
is in range; however it may be that R+R+CONST is not strictly
valid simply because one of the registers needs a reload
into a base register.  In this case, as mentioned above,
it is crucial that the R+R+CONST split *not* be applied.


The patch below tries to fix all three platforms in the
most conservative manner by re-introducing the test for
base registers, but accepting *in addition* to base registers
the special registers (sp/fp/ap).   This should keep arm
working, because it worked when only sp/fp/ap were accepted;
it should keep sparc working (and it gets s390 back working), 
because there sp/fp/ap are base registers anyway.

What do you think?


Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux.
OK?


ChangeLog:

	* reload.c (find_reloads_address): Split addresses of type
	(plus (plus (reg) (reg)) (const_int)) only if one register
	is either a valid base register or else one of the stack
	frame related registers (sp/fp/ap).

Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.225
diff -c -p -r1.225 reload.c
*** gcc/reload.c	20 Nov 2003 00:18:46 -0000	1.225
--- gcc/reload.c	1 Dec 2003 01:50:01 -0000
*************** find_reloads_address (enum machine_mode 
*** 4905,4910 ****
--- 4905,4919 ----
  	   && GET_CODE (XEXP (ad, 0)) == PLUS
  	   && GET_CODE (XEXP (XEXP (ad, 0), 0)) == REG
  	   && REGNO (XEXP (XEXP (ad, 0), 0)) < FIRST_PSEUDO_REGISTER
+ 	   && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 0), mode)
+ 	       || XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx
+ #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ 	       || XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx
+ #endif
+ #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ 	       || XEXP (XEXP (ad, 0), 0) == arg_pointer_rtx
+ #endif
+ 	       || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
  	   && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1)))
      {
        *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
*************** find_reloads_address (enum machine_mode 
*** 4924,4929 ****
--- 4933,4947 ----
  	   && GET_CODE (XEXP (ad, 0)) == PLUS
  	   && GET_CODE (XEXP (XEXP (ad, 0), 1)) == REG
  	   && REGNO (XEXP (XEXP (ad, 0), 1)) < FIRST_PSEUDO_REGISTER
+ 	   && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 1), mode)
+ 	       || XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx
+ #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ 	       || XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx
+ #endif
+ #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ 	       || XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx
+ #endif
+ 	       || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
  	   && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0)))
      {
        *loc = ad = gen_rtx_PLUS (GET_MODE (ad),


-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de


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