public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] Improve MIPS register move costs (for IRA)
@ 2008-10-24  8:54 Richard Sandiford
  0 siblings, 0 replies; only message in thread
From: Richard Sandiford @ 2008-10-24  8:54 UTC (permalink / raw)
  To: gcc-patches

This patch improves the register move costs for MIPS.  It's part of
fixing the dspr2-MULT{,U}.c problems that Chao-Ying and Adam noticed.  

The MIPS implementation of REGISTER_MOVE_COST has traditionally
returned:

  - a specific value for moves that can be done directly
  - 4 for MIPS16 moves between non-MIPS16 GPRs
  - 12 for everything else

Returning 12 is flawed for two reasons:

  - It overestimates the costs of some moves that can be done with
    secondary reloads.  E.g. MD_REGS->FPR_REGS involves a GPR scratch,
    and is actually cheaper than 12.

  - More importantly, it means that we return 12 for all moves
    involving union classes.  The cost of such moves should really
    be the maximum of the move costs for the constituent classes.

    E.g. the maximum cost of GR_AND_ACC_REGS->GR_REGS is the maximum
    of GR_REGS->GR_REGS and ACC_REGS->GR_REGS.  regclass already knows
    this, and actually sets the move cost to the maximum of:

       REGISTER_MOVE_COST (MODE, GR_REGS, GR_REGS)
       REGISTER_MOVE_COST (MODE, ACC_REGS, GR_REGS)
       ...
       REGISTER_MOVE_COST (MODE, GR_AND_ACC_REGS, GR_REGS)

    But MIPS screws up the calculation by making the last value 12.
    It should return 0 instead and let regclass do the right thing.

Overestimating the cost didn't hurt too much with the old RA,
but it can convince IRA that spilling to memory is more profitable
than using an accumulator register.

As I've said before, the basic consituent costs aren't right for all
MIPS processors, and ought to be part of the costs structure.  I haven't
changed that here.  Instead, the idea is to keep the same constituent
costs but to make the values derived from them more accurate.

The CSiBE results are as follows:

-Os -EB -mips16 -mabi=32 -mhard-float          2840801  2840753 :  100.00%
-Os -EB -mips16 -mabi=32 -msoft-float          2823197  2823149 :  100.00%
-Os -EB -mips16 -mabi=o64 -mhard-float         2855585  2855493 :  100.00%
-Os -EB -mips16 -mabi=o64 -msoft-float         2837037  2836977 :  100.00%
-Os -EB -mno-mips16 -mabi=32 -mhard-float      3502597  3501041 :   99.96%
-Os -EB -mno-mips16 -mabi=32 -msoft-float      3974577  3973149 :   99.96%
-Os -EB -mno-mips16 -mabi=o64 -mhard-float     3503329  3501693 :   99.95%
-Os -EB -mno-mips16 -mabi=o64 -msoft-float     3766561  3765197 :   99.96%
-Os -EL -mips16 -mabi=32 -mhard-float          2840325  2840293 :  100.00%
-Os -EL -mips16 -mabi=32 -msoft-float          2822353  2822321 :  100.00%
-Os -EL -mips16 -mabi=o64 -mhard-float         2855409  2855333 :  100.00%
-Os -EL -mips16 -mabi=o64 -msoft-float         2836861  2836801 :  100.00%
-Os -EL -mno-mips16 -mabi=32 -mhard-float      3501989  3500529 :   99.96%
-Os -EL -mno-mips16 -mabi=32 -msoft-float      3971089  3970013 :   99.97%
-Os -EL -mno-mips16 -mabi=o64 -mhard-float     3502561  3500925 :   99.95%
-Os -EL -mno-mips16 -mabi=o64 -msoft-float     3765777  3764397 :   99.96%

Regression-tested on mipsisa64-elfoabi and applied.

The DSP tests aren't fixed by this patch alone.  They need another
couple of changes that I'm still working on.

Richard


gcc/
	* config/mips/mips.c (mips_canonicalize_move_class): New function.
	(mips_move_to_gpr_cost): Likewise.
	(mips_move_from_gpr_cost): Likewise.
	(mips_register_move_cost): Make more fine-grained.

Index: gcc/config/mips/mips.c
===================================================================
*** gcc/config/mips/mips.c	2008-10-23 20:11:19.000000000 +0100
--- gcc/config/mips/mips.c	2008-10-23 21:24:39.000000000 +0100
*************** mips_preferred_reload_class (rtx x, enum
*** 9689,9750 ****
    return rclass;
  }
  
! /* Implement REGISTER_MOVE_COST.  */
  
! int
! mips_register_move_cost (enum machine_mode mode,
! 			 enum reg_class to, enum reg_class from)
  {
!   if (TARGET_MIPS16)
!     {
!       if (reg_class_subset_p (from, GENERAL_REGS)
! 	  && reg_class_subset_p (to, GENERAL_REGS))
! 	{
! 	  if (reg_class_subset_p (from, M16_REGS)
! 	      || reg_class_subset_p (to, M16_REGS))
! 	    return 2;
! 	  /* Two MOVEs.  */
! 	  return 4;
! 	}
!     }
!   else if (reg_class_subset_p (from, GENERAL_REGS))
      {
!       if (reg_class_subset_p (to, GENERAL_REGS))
! 	return 2;
!       if (reg_class_subset_p (to, FP_REGS))
! 	return 4;
!       if (reg_class_subset_p (to, COP0_REGS)
! 	  || reg_class_subset_p (to, COP2_REGS)
! 	  || reg_class_subset_p (to, COP3_REGS))
! 	return 5;
!       if (reg_class_subset_p (to, ACC_REGS))
! 	return 6;
      }
!   else if (reg_class_subset_p (to, GENERAL_REGS))
      {
!       if (reg_class_subset_p (from, FP_REGS))
! 	return 4;
!       if (reg_class_subset_p (from, ST_REGS))
! 	/* LUI followed by MOVF.  */
! 	return 4;
!       if (reg_class_subset_p (from, COP0_REGS)
! 	  || reg_class_subset_p (from, COP2_REGS)
! 	  || reg_class_subset_p (from, COP3_REGS))
! 	return 5;
!       if (reg_class_subset_p (from, ACC_REGS))
! 	return 6;
      }
!   else if (reg_class_subset_p (from, FP_REGS))
      {
!       if (reg_class_subset_p (to, FP_REGS)
! 	  && mips_mode_ok_for_mov_fmt_p (mode))
  	return 4;
!       if (reg_class_subset_p (to, ST_REGS))
! 	/* An expensive sequence.  */
  	return 8;
      }
  
!   return 12;
  }
  
  /* Implement TARGET_IRA_COVER_CLASSES.  */
--- 9689,9830 ----
    return rclass;
  }
  
! /* RCLASS is a class involved in a REGISTER_MOVE_COST calculation.
!    Return a "canonical" class to represent it in later calculations.  */
  
! static enum reg_class
! mips_canonicalize_move_class (enum reg_class rclass)
  {
!   /* All moves involving accumulator registers have the same cost.  */
!   if (reg_class_subset_p (rclass, ACC_REGS))
!     rclass = ACC_REGS;
! 
!   /* Likewise promote subclasses of general registers to the most
!      interesting containing class.  */
!   if (TARGET_MIPS16 && reg_class_subset_p (rclass, M16_REGS))
!     rclass = M16_REGS;
!   else if (reg_class_subset_p (rclass, GENERAL_REGS))
!     rclass = GENERAL_REGS;
! 
!   return rclass;
! }
! 
! /* Return the cost of moving a value of mode MODE from a register of
!    class FROM to a GPR.  Return 0 for classes that are unions of other
!    classes handled by this function.  */
! 
! static int
! mips_move_to_gpr_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
! 		       enum reg_class from)
! {
!   switch (from)
      {
!     case GENERAL_REGS:
!       /* A MIPS16 MOVE instruction, or a non-MIPS16 MOVE macro.  */
!       return 2;
! 
!     case ACC_REGS:
!       /* MFLO and MFHI.  */
!       return 6;
! 
!     case FP_REGS:
!       /* MFC1, etc.  */
!       return 4;
! 
!     case ST_REGS:
!       /* LUI followed by MOVF.  */
!       return 4;
! 
!     case COP0_REGS:
!     case COP2_REGS:
!     case COP3_REGS:
!       /* This choice of value is historical.  */
!       return 5;
! 
!     default:
!       return 0;
      }
! }
! 
! /* Return the cost of moving a value of mode MODE from a GPR to a
!    register of class TO.  Return 0 for classes that are unions of
!    other classes handled by this function.  */
! 
! static int
! mips_move_from_gpr_cost (enum machine_mode mode, enum reg_class to)
! {
!   switch (to)
      {
!     case GENERAL_REGS:
!       /* A MIPS16 MOVE instruction, or a non-MIPS16 MOVE macro.  */
!       return 2;
! 
!     case ACC_REGS:
!       /* MTLO and MTHI.  */
!       return 6;
! 
!     case FP_REGS:
!       /* MTC1, etc.  */
!       return 4;
! 
!     case ST_REGS:
!       /* A secondary reload through an FPR scratch.  */
!       return (mips_register_move_cost (mode, GENERAL_REGS, FP_REGS)
! 	      + mips_register_move_cost (mode, FP_REGS, ST_REGS));
! 
!     case COP0_REGS:
!     case COP2_REGS:
!     case COP3_REGS:
!       /* This choice of value is historical.  */
!       return 5;
! 
!     default:
!       return 0;
      }
! }
! 
! /* Implement REGISTER_MOVE_COST.  Return 0 for classes that are the
!    maximum of the move costs for subclasses; regclass will work out
!    the maximum for us.  */
! 
! int
! mips_register_move_cost (enum machine_mode mode,
! 			 enum reg_class from, enum reg_class to)
! {
!   enum reg_class dregs;
!   int cost1, cost2;
! 
!   from = mips_canonicalize_move_class (from);
!   to = mips_canonicalize_move_class (to);
! 
!   /* Handle moves that can be done without using general-purpose registers.  */
!   if (from == FP_REGS)
      {
!       if (to == FP_REGS && mips_mode_ok_for_mov_fmt_p (mode))
! 	/* MOV.FMT.  */
  	return 4;
!       if (to == ST_REGS)
! 	/* The sequence generated by mips_expand_fcc_reload.  */
  	return 8;
      }
  
!   /* Handle cases in which only one class deviates from the ideal.  */
!   dregs = TARGET_MIPS16 ? M16_REGS : GENERAL_REGS;
!   if (from == dregs)
!     return mips_move_from_gpr_cost (mode, to);
!   if (to == dregs)
!     return mips_move_to_gpr_cost (mode, from);
! 
!   /* Handles cases that require a GPR temporary.  */
!   cost1 = mips_move_to_gpr_cost (mode, from);
!   if (cost1 != 0)
!     {
!       cost2 = mips_move_from_gpr_cost (mode, to);
!       if (cost2 != 0)
! 	return cost1 + cost2;
!     }
! 
!   return 0;
  }
  
  /* Implement TARGET_IRA_COVER_CLASSES.  */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-10-24  8:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-24  8:54 [committed] Improve MIPS register move costs (for IRA) Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).