This is the mail archive of the gcc@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] Re: Use-and-clobber insns and some ancient combine.c code


Joern Rennecke wrote:

> If (reg X) is a fixed register, the pattern shouldn't be recognized
> if it is not safe.  Hence the combination should be allowed for fixed
> registers.

Ah, that's a good point, and this is in fact enough to solve my
particular problem.  Thanks for the tip!

The following patch relaxes the combine.c checks to allow creating
use-and-clobber patterns for fixed hard registers.  This enables
all the combinations I was looking for; in fact, gcc will now
convert the default implementation of add_ssaaaa and sub_ddmmss
in longlong.h to the optimial assembler sequences using ALC ...

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

Bye,
Ulrich


ChangeLog:

	* combine.c (can_combine_p): Do not prevent building insns that use
	and clobber the same fixed hard register.
	(reg_dead_at_p): Likewise.

Index: gcc/combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.432
diff -c -p -r1.432 combine.c
*** gcc/combine.c	5 Jun 2004 07:59:39 -0000	1.432
--- gcc/combine.c	19 Jun 2004 01:08:13 -0000
*************** can_combine_p (rtx insn, rtx i3, rtx pre
*** 1129,1144 ****
    else if (GET_CODE (dest) != CC0)
      return 0;
  
!   /* Don't substitute for a register intended as a clobberable operand.
!      Similarly, don't substitute an expression containing a register that
!      will be clobbered in I3.  */
    if (GET_CODE (PATTERN (i3)) == PARALLEL)
      for (i = XVECLEN (PATTERN (i3), 0) - 1; i >= 0; i--)
!       if (GET_CODE (XVECEXP (PATTERN (i3), 0, i)) == CLOBBER
! 	  && (reg_overlap_mentioned_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0),
! 				       src)
! 	      || rtx_equal_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0), dest)))
! 	return 0;
  
    /* If INSN contains anything volatile, or is an `asm' (whether volatile
       or not), reject, unless nothing volatile comes between it and I3 */
--- 1129,1158 ----
    else if (GET_CODE (dest) != CC0)
      return 0;
  
! 
    if (GET_CODE (PATTERN (i3)) == PARALLEL)
      for (i = XVECLEN (PATTERN (i3), 0) - 1; i >= 0; i--)
!       if (GET_CODE (XVECEXP (PATTERN (i3), 0, i)) == CLOBBER)
! 	{
!           /* Don't substitute for a register intended as a clobberable
! 	     operand. */
! 	  rtx reg = XEXP (XVECEXP (PATTERN (i3), 0, i), 0);
! 	  if (rtx_equal_p (reg, dest))
! 	    return 0;
! 
! 	  /* If the clobber represents an earlyclobber operand, we must not
! 	     substitute an expression containing the clobbered register.
! 	     As we do not analyse the constraint strings here, we have to
! 	     make the conservative assumption.  However, if the register is
! 	     a fixed hard reg, the clobber cannot represent any operand;
! 	     we leave it up to the machine description to either accept or
! 	     reject use-and-clobber patterns.  */
! 	  if (!REG_P (reg)
! 	      || REGNO (reg) >= FIRST_PSEUDO_REGISTER
! 	      || !fixed_regs[REGNO (reg)])
! 	    if (reg_overlap_mentioned_p (reg, src))
! 	      return 0;
! 	}
  
    /* If INSN contains anything volatile, or is an `asm' (whether volatile
       or not), reject, unless nothing volatile comes between it and I3 */
*************** reg_dead_at_p (rtx reg, rtx insn)
*** 11142,11152 ****
  
    reg_dead_flag = 0;
  
!   /* Check that reg isn't mentioned in NEWPAT_USED_REGS.  */
    if (reg_dead_regno < FIRST_PSEUDO_REGISTER)
      {
        for (i = reg_dead_regno; i < reg_dead_endregno; i++)
! 	if (TEST_HARD_REG_BIT (newpat_used_regs, i))
  	  return 0;
      }
  
--- 11156,11168 ----
  
    reg_dead_flag = 0;
  
!   /* Check that reg isn't mentioned in NEWPAT_USED_REGS.  For fixed registers
!      we allow the machine description to decide whether use-and-clobber
!      patterns are OK.  */
    if (reg_dead_regno < FIRST_PSEUDO_REGISTER)
      {
        for (i = reg_dead_regno; i < reg_dead_endregno; i++)
! 	if (!fixed_regs[i] && TEST_HARD_REG_BIT (newpat_used_regs, i))
  	  return 0;
      }
  

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