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 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


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