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 too-large constants pushed as reload


Hello,

there is a path in reload where it can push a PLUS reload that has
as operand a constant that is too large to be used as immediate
operand:  this happens when a register is eliminated by a stack
address with large displacement.

In all other cases, reload takes care to force such constants to
the constant pool, but this particular case appears to have been
overlooked.  (This situation occurs rarely, only the multi-ix.c
test case shows the problem.)

When the reload insn is output later on, we cannot handle the
constant -- it is now too late to add to the constant pool,
since we may have already decided we do not need to save the
constant pool base register.

While the current s390 back end (accidentally) does handle
this late constant pool addition, it will actually break
with a patch I'm currently working on that would track 
register save slots more precisely.

Thus I propose the following patch to find_reloads that would
ensure such constants are pushed to the constant pool even
in this particular case.

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

Bye,
Ulrich

ChangeLog:

	* reload.c (find_reloads): When reloading a PLUS with constant
	operand, make sure the constant is pushed to the constant pool
	if required.


Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.255
diff -c -p -r1.255 reload.c
*** gcc/reload.c	15 Sep 2004 20:47:47 -0000	1.255
--- gcc/reload.c	29 Sep 2004 11:08:32 -0000
*************** find_reloads (rtx insn, int replace, int
*** 3786,3791 ****
--- 3786,3813 ----
  	  goal_alternative_win[i] = 1;
        }
  
+   /* Likewise any invalid constants appearing as operand of a PLUS
+      that is to be reloaded.  */
+   for (i = 0; i < noperands; i++)
+     if (! goal_alternative_win[i]
+ 	&& GET_CODE (recog_data.operand[i]) == PLUS
+ 	&& CONST_POOL_OK_P (XEXP (recog_data.operand[i], 1))
+ 	&& ((PREFERRED_RELOAD_CLASS (XEXP (recog_data.operand[i], 1),
+ 				     (enum reg_class) goal_alternative[i])
+ 	     == NO_REGS)
+ 	    || no_input_reloads)
+ 	&& operand_mode[i] != VOIDmode)
+       {
+ 	rtx tem = force_const_mem (operand_mode[i],
+ 				   XEXP (recog_data.operand[i], 1));
+ 	tem = gen_rtx_PLUS (operand_mode[i],
+ 			    XEXP (recog_data.operand[i], 0), tem);
+ 
+ 	substed_operand[i] = recog_data.operand[i]
+ 	  = find_reloads_toplev (tem, i, address_type[i],
+ 				 ind_levels, 0, insn, NULL);
+       }
+ 
    /* Record the values of the earlyclobber operands for the caller.  */
    if (goal_earlyclobber)
      for (i = 0; i < noperands; i++)
-- 
  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]