This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR 24621 (find_reloads problem)
- From: Ulrich Weigand <uweigand at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 3 Nov 2005 22:30:02 +0100 (CET)
- Subject: [PATCH] Fix PR 24621 (find_reloads problem)
Hello,
this patch fixes PR 24621, which is a bug in find_reloads. The
problem occurs with an insn of type
(set (reg:SI 115)
(minus:SI (reg:SI 2 %r2 [+4 ])
(subreg:SI (reg/f:DI 150) 4)))
where reg 150 is reg_equiv_constant to a stack address. The
replacement of that constant leads to
(set (reg:SI 2 %r2 [115])
(minus:SI (reg:SI 2 %r2 [+4 ])
(subreg:SI (plus:DI (reg/f:DI 15 %r15)
(const_int 65748 [0x100d4])) 4)))
Now this const_int is too large (on s390) to be reloaded on its
own, so it needs to be pushed into the literal pool.
This very problem is solved by this patch of mine:
http://gcc.gnu.org/ml/gcc-patches/2004-10/msg01133.html
however, that patch neglects to handle the possibility that the
PLUS can be inside an outer SUBREG.
The following patch extends the solution in find_reloads to
handle that case as well, fixing the test case from PR 24621.
Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux.
OK for mainline?
Bye,
Ulrich
ChangeLog:
PR target/24621
* reload.c (find_reloads): When handling invalid constants
appearing as operand of a PLUS, also allow an outer SUBREG.
Index: gcc/reload.c
===================================================================
*** gcc/reload.c (revision 106419)
--- gcc/reload.c (working copy)
*************** find_reloads (rtx insn, int replace, int
*** 3835,3856 ****
/* 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)
! && 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. */
--- 3835,3869 ----
/* 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])
{
! rtx operand = recog_data.operand[i];
! enum machine_mode mode = operand_mode[i];
!
! if (GET_CODE (operand) == SUBREG)
! {
! operand = SUBREG_REG (operand);
! mode = GET_MODE (operand);
! }
!
! if (GET_CODE (operand) == PLUS
! && CONST_POOL_OK_P (XEXP (operand, 1))
! && (PREFERRED_RELOAD_CLASS (XEXP (operand, 1),
! (enum reg_class) goal_alternative[i])
! == NO_REGS)
! && mode != VOIDmode)
! {
! rtx tem = force_const_mem (mode, XEXP (operand, 1));
! tem = gen_rtx_PLUS (mode, XEXP (operand, 0), tem);
!
! if (GET_CODE (recog_data.operand[i]) == SUBREG)
! tem = gen_rtx_SUBREG (GET_MODE (recog_data.operand[i]), tem,
! SUBREG_BYTE (recog_data.operand[i]));
!
! 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. */
--
Dr. Ulrich Weigand
Linux on zSeries Development
Ulrich.Weigand@de.ibm.com