[PATCH] Reduce cost of Athlon multiplication sequences

Roger Sayle roger@eyesopen.com
Thu Jan 5 16:12:00 GMT 2006


Hi Jan,

Sorry to take a while.  Unfortunately, my big Athlon box is running
RedHat 7.2, and I had to get my patch to fix GCC bootstrap on this
system into the tree :)

The following patch addresses the strange problem we noticed in the
generated -march=athlon multiplication sequences.  The issue is that
we have an ashift splitter that blissfully converts shifts into leas
even on targets where lea is significantly more expensive than the
shift.  Enabling this splitter only when its profitable, then
exposed a (latent?) bug in the fall-back splitter, where a typo
in emit_move_insn caused us to move the source into the destination!


The logic is that "x = y << n" can be converted into either the
current "lea" instruction, or alternatively into "x = y; x <<= n",
which we assume costs const_shift + COSTS_N_INSNS(1) [for the move].
This only affects AMD targets.  If the costs are equal, I assume
that the move and shift can be usefully scheduled/dispatched and
is preferrable to the slow/monolithic lea.


With this change all of the multiplication sequences we generate
with -march=athlon, have a total rtx_costs for all non-move
instructions equal to (and sometimes less than!) the rtx_costs
of the sequences recommended by AMD's SWOP manual.  Given that
SWOP accounts that moves are zero cost, this is near optimal.
For example, our multiplication by 15 outperforms AMD's, but
requires an extra register.


This patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.

Ok for mainline?  I've a follow up patch to clean-up related
aspects of the i386 backend, but that won't affect athlon code
generation.



2006-01-04  Roger Sayle  <roger@eyesopen.com>

	* config/i386/i386.md (shift spliters): Don't convert a shift into
	an lea when the lea isn't cheaper than a shift and a move.  Fix
	a typo in splitter for shifts where the source and destination
	registers are different.


Index: i386.md
===================================================================
*** i386.md	(revision 109283)
--- i386.md	(working copy)
***************
*** 10532,10538 ****
     (clobber (reg:CC FLAGS_REG))]
    "reload_completed
     && true_regnum (operands[0]) != true_regnum (operands[1])
!    && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4"
    [(const_int 0)]
  {
    rtx pat;
--- 10532,10539 ----
     (clobber (reg:CC FLAGS_REG))]
    "reload_completed
     && true_regnum (operands[0]) != true_regnum (operands[1])
!    && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4
!    && ix86_cost->lea < ix86_cost->shift_const + COSTS_N_INSNS (1)"
    [(const_int 0)]
  {
    rtx pat;
***************
*** 10562,10568 ****
    [(const_int 0)]
  {
    rtx pat, clob;
!   emit_move_insn (operands[1], operands[0]);
    pat = gen_rtx_SET (VOIDmode, operands[0],
  		     gen_rtx_ASHIFT (GET_MODE (operands[0]),
  				     operands[0], operands[2]));
--- 10563,10569 ----
    [(const_int 0)]
  {
    rtx pat, clob;
!   emit_move_insn (operands[0], operands[1]);
    pat = gen_rtx_SET (VOIDmode, operands[0],
  		     gen_rtx_ASHIFT (GET_MODE (operands[0]),
  				     operands[0], operands[2]));

Roger
--




More information about the Gcc-patches mailing list