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]

IA64 performance patch



I submitted a patch a while back to allow const functions (like integer
division) with loop invariant arguments to be hoisted out of a loop on
IA64.  That patch was fine as far as it went but I failed to notice that
it only worked when the loop contained no more then one function call in
it.  When there are more function calls (hoistable or not) nothing gets
hoisted because IA64 uses a single (saved) virtual register to save and
restore the gp register during all calls in a function.  With more then
one call in a loop this virtual register gets set multiple times and it
does not look like a loop invariant value to the optimizer.

Here is an IA64 specific patch that fixes this by using different
virtual registers to save/restore the gp for each function call.  When
not optimizing or when there are setjumps we still use a single fixed
register.

I have a copyright assignment in place but no write permission so if
someone could approve this and check it in I would appreciate it.  I am
not proposing this for the GCC 3.1 branch but I suppose it might be OK
to check it in there since it is specific to IA64.  Built and tested
on IA64 HP-UX with no regressions.

Steve Ellcey
sje@cup.hp.com


2002-03-04  Steve Ellcey  <sje@cup.hp.com>
	* config/ia64/ia64-protos.h (ia64_gp_save_reg): Add argument.
	* config/ia64/ia64.c (ia64_gp_save_reg): Add argument save_virtual_reg.
	(ia64_expand_call): Call ia64_gp_save_reg with save_virtual_reg of 0 so
	we do not save it.
	* config/ia64/ia64.md (builtin_setjmp_setup): Call ia64_gp_save_reg
	with save_virtual_reg of 1 to save it for next use.
	(builtin_setjmp_receiver): Ditto.


*** gcc.orig/gcc/config/ia64/ia64-protos.h	Mon Mar  4 15:02:16 2002
--- gcc/gcc/config/ia64/ia64-protos.h	Mon Mar  4 15:02:43 2002
*************** extern int tfreg_or_fp01_operand PARAMS(
*** 69,75 ****
  
  extern int ia64_move_ok PARAMS((rtx, rtx));
  extern int ia64_depz_field_mask PARAMS((rtx, rtx));
! extern rtx ia64_gp_save_reg PARAMS((int));
  extern rtx ia64_split_timode PARAMS((rtx[], rtx, rtx));
  extern rtx spill_tfmode_operand PARAMS((rtx, int));
  extern rtx ia64_expand_compare PARAMS((enum rtx_code, enum machine_mode));
--- 69,75 ----
  
  extern int ia64_move_ok PARAMS((rtx, rtx));
  extern int ia64_depz_field_mask PARAMS((rtx, rtx));
! extern rtx ia64_gp_save_reg PARAMS((int, int));
  extern rtx ia64_split_timode PARAMS((rtx[], rtx, rtx));
  extern rtx spill_tfmode_operand PARAMS((rtx, int));
  extern rtx ia64_expand_compare PARAMS((enum rtx_code, enum machine_mode));
*** gcc.orig/gcc/config/ia64/ia64.c	Mon Mar  4 14:58:21 2002
--- gcc/gcc/config/ia64/ia64.c	Mon Mar  4 15:12:14 2002
*************** ia64_expand_load_address (dest, src, scr
*** 958,965 ****
  }
  
  rtx
! ia64_gp_save_reg (setjmp_p)
       int setjmp_p;
  {
    rtx save = cfun->machine->ia64_gp_save;
  
--- 958,966 ----
  }
  
  rtx
! ia64_gp_save_reg (setjmp_p, save_virtual_reg)
       int setjmp_p;
+      int save_virtual_reg;
  {
    rtx save = cfun->machine->ia64_gp_save;
  
*************** ia64_gp_save_reg (setjmp_p)
*** 986,997 ****
    else
      {
        if (setjmp_p)
! 	save = gen_rtx_REG (DImode, GR_REG (4));
        else if (! optimize)
! 	save = gen_rtx_REG (DImode, LOC_REG (0));
        else
! 	save = gen_reg_rtx (DImode);
!       cfun->machine->ia64_gp_save = save;
      }
  
    return save;
--- 987,1007 ----
    else
      {
        if (setjmp_p)
! 	{
! 	  save = gen_rtx_REG (DImode, GR_REG (4));
! 	  cfun->machine->ia64_gp_save = save;
! 	}
        else if (! optimize)
! 	{
! 	  save = gen_rtx_REG (DImode, LOC_REG (0));
! 	  cfun->machine->ia64_gp_save = save;
! 	}
        else
! 	{
! 	  save = gen_reg_rtx (DImode);
! 	  if (save_virtual_reg)
! 	    cfun->machine->ia64_gp_save = save;
! 	}
      }
  
    return save;
*************** ia64_expand_call (retval, addr, nextarg,
*** 1167,1173 ****
    if (sibcall_p)
      gp_save = NULL_RTX;
    else
!     gp_save = ia64_gp_save_reg (setjmp_operand (addr, VOIDmode));
  
    /* If this is an indirect call, then we have the address of a descriptor.  */
    if (! symbolic_operand (addr, VOIDmode))
--- 1177,1183 ----
    if (sibcall_p)
      gp_save = NULL_RTX;
    else
!     gp_save = ia64_gp_save_reg (setjmp_operand (addr, VOIDmode), 0);
  
    /* If this is an indirect call, then we have the address of a descriptor.  */
    if (! symbolic_operand (addr, VOIDmode))
*** gcc.orig/gcc/config/ia64/ia64.md	Mon Mar  4 14:58:19 2002
--- gcc/gcc/config/ia64/ia64.md	Mon Mar  4 14:59:25 2002
***************
*** 5121,5127 ****
    ""
    "
  {
!   emit_move_insn (ia64_gp_save_reg (0), gen_rtx_REG (DImode, GR_REG (1)));
    DONE;
  }")
  
--- 5121,5127 ----
    ""
    "
  {
!   emit_move_insn (ia64_gp_save_reg (0, 1), gen_rtx_REG (DImode, GR_REG (1)));
    DONE;
  }")
  
***************
*** 5130,5136 ****
    ""
    "
  {
!   emit_move_insn (gen_rtx_REG (DImode, GR_REG (1)), ia64_gp_save_reg (0));
    DONE;
  }")
  
--- 5130,5136 ----
    ""
    "
  {
!   emit_move_insn (gen_rtx_REG (DImode, GR_REG (1)), ia64_gp_save_reg (0, 1));
    DONE;
  }")
  


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