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]

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;
      }
    "
  )

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