This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Improve Thumb code when loading QI and HI values from memory
- From: Richard Earnshaw <Richard dot Earnshaw at buzzard dot freeserve dot co dot uk>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Richard dot Earnshaw at buzzard dot freeserve dot co dot uk
- Date: Fri, 30 Sep 2005 22:42:36 +0100
- Subject: Improve Thumb code when loading QI and HI values from memory
This patch improves thumb code slightly by more accurately describing what
the hardware does when loading a value from memory. The ldrb and ldrh
instructions both zero-extend the value into a 32-bit register, so by
generating RTL that describes this we get slightly better code than just
emitting a simple set since we can then often avoid a completely redundant
zero-extension of a value that is already zero-extended. We've been doing
something similar on ARM for a long time now. Tests show this is probably
worth about 0.3% in code size, but it obviously depends on the mix of
char/short operations in your source code.
tested on arm-elf and bootstrapped in Thumb code on arm-netbsdelf.
R.
2005-09-30 Richard Earnshaw <richard.earnshaw@arm.com>
* arm.md (movqi): On thumb when optimizing, handle loading from
memory by describing this as taking a subreg of a zero-extended load
into an SImode register.
(movhi): Likewise.
Index: arm.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.md,v
retrieving revision 1.206
diff -p -p -r1.206 arm.md
*** arm.md 10 Sep 2005 08:28:32 -0000 1.206
--- arm.md 30 Sep 2005 21:31:57 -0000
***************
*** 4729,4736 ****
{
if (!no_new_pseudos)
{
! if (GET_CODE (operands[0]) != REG)
! operands[1] = force_reg (HImode, operands[1]);
/* ??? We shouldn't really get invalid addresses here, but this can
happen if we are passed a SP (never OK for HImode/QImode) or
--- 4729,4741 ----
{
if (!no_new_pseudos)
{
! if (GET_CODE (operands[1]) == CONST_INT)
! {
! rtx reg = gen_reg_rtx (SImode);
!
! emit_insn (gen_movsi (reg, operands[1]));
! operands[1] = gen_lowpart (HImode, reg);
! }
/* ??? We shouldn't really get invalid addresses here, but this can
happen if we are passed a SP (never OK for HImode/QImode) or
***************
*** 4753,4763 ****
operands[1]
= replace_equiv_address (operands[1],
copy_to_reg (XEXP (operands[1], 0)));
}
- /* Handle loading a large integer during reload. */
else if (GET_CODE (operands[1]) == CONST_INT
&& !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
{
/* Writing a constant to memory needs a scratch, which should
be handled with SECONDARY_RELOADs. */
gcc_assert (GET_CODE (operands[0]) == REG);
--- 4758,4780 ----
operands[1]
= replace_equiv_address (operands[1],
copy_to_reg (XEXP (operands[1], 0)));
+
+ if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
+
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (HImode, operands[1]);
}
else if (GET_CODE (operands[1]) == CONST_INT
&& !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
{
+ /* Handle loading a large integer during reload. */
+
/* Writing a constant to memory needs a scratch, which should
be handled with SECONDARY_RELOADs. */
gcc_assert (GET_CODE (operands[0]) == REG);
***************
*** 4938,4974 ****
(match_operand:QI 1 "general_operand" ""))]
"TARGET_EITHER"
"
! if (TARGET_ARM)
! {
! /* Everything except mem = const or mem = mem can be done easily */
!
! if (!no_new_pseudos)
! {
! if (GET_CODE (operands[1]) == CONST_INT)
! {
! rtx reg = gen_reg_rtx (SImode);
!
! emit_insn (gen_movsi (reg, operands[1]));
! operands[1] = gen_lowpart (QImode, reg);
! }
! if (GET_CODE (operands[1]) == MEM && optimize > 0)
! {
! rtx reg = gen_reg_rtx (SImode);
! emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
! operands[1] = gen_lowpart (QImode, reg);
! }
! if (GET_CODE (operands[0]) == MEM)
! operands[1] = force_reg (QImode, operands[1]);
! }
! }
! else /* TARGET_THUMB */
{
! if (!no_new_pseudos)
! {
! if (GET_CODE (operands[0]) != REG)
! operands[1] = force_reg (QImode, operands[1]);
/* ??? We shouldn't really get invalid addresses here, but this can
happen if we are passed a SP (never OK for HImode/QImode) or
virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
--- 4955,4974 ----
(match_operand:QI 1 "general_operand" ""))]
"TARGET_EITHER"
"
! /* Everything except mem = const or mem = mem can be done easily */
! if (!no_new_pseudos)
{
! if (GET_CODE (operands[1]) == CONST_INT)
! {
! rtx reg = gen_reg_rtx (SImode);
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+
+ if (TARGET_THUMB)
+ {
/* ??? We shouldn't really get invalid addresses here, but this can
happen if we are passed a SP (never OK for HImode/QImode) or
virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
***************
*** 4989,5007 ****
operands[1]
= replace_equiv_address (operands[1],
copy_to_reg (XEXP (operands[1], 0)));
! }
/* Handle loading a large integer during reload. */
- else if (GET_CODE (operands[1]) == CONST_INT
- && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- gcc_assert (GET_CODE (operands[0]) == REG);
! operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
! emit_insn (gen_movsi (operands[0], operands[1]));
! DONE;
! }
}
"
)
--- 4989,5020 ----
operands[1]
= replace_equiv_address (operands[1],
copy_to_reg (XEXP (operands[1], 0)));
! }
!
! if (GET_CODE (operands[1]) == MEM && optimize > 0)
! {
! rtx reg = gen_reg_rtx (SImode);
!
! emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
! operands[1] = gen_lowpart (QImode, reg);
! }
!
! if (GET_CODE (operands[0]) == MEM)
! operands[1] = force_reg (QImode, operands[1]);
! }
! else if (TARGET_THUMB
! && GET_CODE (operands[1]) == CONST_INT
! && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
! {
/* Handle loading a large integer during reload. */
! /* Writing a constant to memory needs a scratch, which should
! be handled with SECONDARY_RELOADs. */
! gcc_assert (GET_CODE (operands[0]) == REG);
!
! operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
! emit_insn (gen_movsi (operands[0], operands[1]));
! DONE;
}
"
)