This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix too-large constants pushed as reload
- From: Ulrich Weigand <weigand at i1 dot informatik dot uni-erlangen dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 29 Sep 2004 21:42:01 +0200 (CEST)
- Subject: [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