This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Re: Use-and-clobber insns and some ancient combine.c code
- From: Ulrich Weigand <weigand at i1 dot informatik dot uni-erlangen dot de>
- To: joern dot rennecke at superh dot com (Joern Rennecke), gcc-patches at gcc dot gnu dot org
- Cc: kenner at vlsi1 dot ultra dot nyu dot edu (Richard Kenner), weigand at i1 dot informatik dot uni-erlangen dot de, gcc at gcc dot gnu dot org
- Date: Sat, 19 Jun 2004 16:09:08 +0200 (CEST)
- Subject: [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