This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR target/19597: Rewrite AVR backend's rtx_costs (take 3)
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Bernardo Innocenti <bernie at develer dot com>
- Date: Sun, 30 Jan 2005 15:18:48 -0700 (MST)
- Subject: [PATCH] PR target/19597: Rewrite AVR backend's rtx_costs (take 3)
The following patch is the next iteration of my patch to resolve PR
target/19597: http://gcc.gnu.org/ml/gcc-patches/2005-01/msg01698.html
There are several minor tweaks and improvements to my previous version,
the most important of which is that CONST_INT and CONST_DOUBLE at the
top-level now have an rtx_cost of zero. Generally, on AVR, immediate
constants have the same cost (in speed and size) as using a register.
This keeps the cost of integer costant, less than COSTS_N_INSNS(1), as
it was prior to this patch, which resolves the minor (0.5%) code size
regression in the earlier versions of this patch.
To confirm that this change is now a net code size win, I attempted to
compile all the modules of the CSiBE benchmark that were compatible with
a 16-bit word size, and evaluate code growth on this standard metric:
flex cc1 1150 1156
dfa 8769 8827
ecs 1082 1030
gen 16583 16533
initscan 36277 36281
libmain 16 20
main 16646 16830
nfa 4533 4469
parse 9178 9244
sym 1089 1121
tblcmp 4938 4686
yylex 1314 1338 101575 101535
G.723 g711 828 822
g721 780 800
g723_24 700 716
g723_40 868 884
g72x 4370 4390 7546 7612
gsm code 540 542
debug 1292 1296
decode 758 658
GSM 1099 1117
gsm_encode 2068 2028
gsm_implode 1916 1874
gsm_lpc 7615 7509
long_term 7158 6868
preprocess 1295 1155
rpe 6742 6202
short_term 5012 4538 35495 33787
mpeg2decgetbits 1060 1030
getblk 3973 3905
gethdr 4675 4667
getpic 5429 5443
getvlc 4065 4001
idct 2716 1800
idctref 1482 1506
motion 1304 1358
mpeg2dec 5561 5471
recon 4530 4482
spatscal 4059 4111
store 8138 7244
subspic 1862 1888
systems 1043 1045 49897 47951
sed compile 9300 9164
execute 6988 7022
fmt 3359 3291
regex 769 763
sed 2829 2843
strverscmp 430 434
utils 2296 2300 25971 25817
220484 216702
The first column represents the CSiBE module, the second the source file,
the third the original size (as reported in result.csv), the fourth column
the size after this patch, the fifth and six represent subtotals and
totals of the previous two columns respectively. Only those files/objects
that changed size are listed, so the absolute numbers shouldn't be over
interpreted, but it can be seen that CSiBE on avr-elf for the subset that
builds "make -k" decreases in size by nearly 4K. Bernardo, could you
confirm that this fixes the code growth issues you were seeing?
The following patch has been tested by building a cross-compiler for C
and C++ to avr-elf from i686-pc-linux-gnu.
Ok for mainline?
2005-01-30 Roger Sayle <roger@eyesopen.com>
PR target/19597
* config/avr/avr.c (default_rtx_costs): Delete.
(avr_operand_rtx_cost): New function.
(avr_rtx_costs): Completely rewrite.
Index: avr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/avr.c,v
retrieving revision 1.128
diff -c -3 -p -r1.128 avr.c
*** avr.c 26 Jan 2005 21:44:24 -0000 1.128
--- avr.c 30 Jan 2005 21:21:39 -0000
*************** static unsigned int avr_section_type_fla
*** 74,80 ****
static void avr_reorg (void);
static void avr_asm_out_ctor (rtx, int);
static void avr_asm_out_dtor (rtx, int);
! static int default_rtx_costs (rtx, enum rtx_code, enum rtx_code);
static bool avr_rtx_costs (rtx, int, int, int *);
static int avr_address_cost (rtx);
static bool avr_return_in_memory (tree, tree);
--- 74,80 ----
static void avr_reorg (void);
static void avr_asm_out_ctor (rtx, int);
static void avr_asm_out_dtor (rtx, int);
! static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code);
static bool avr_rtx_costs (rtx, int, int, int *);
static int avr_address_cost (rtx);
static bool avr_return_in_memory (tree, tree);
*************** order_regs_for_local_alloc (void)
*** 4820,4929 ****
reg_alloc_order[i] = order[i];
}
! /* Calculate the cost of X code of the expression in which it is contained,
! found in OUTER_CODE */
static int
! default_rtx_costs (rtx X, enum rtx_code code, enum rtx_code outer_code)
{
! int cost=0;
switch (code)
{
! case SYMBOL_REF:
! case LABEL_REF:
! cost = 2 * GET_MODE_SIZE (GET_MODE (X));
! break;
! case MEM:
! if (outer_code != SET)
! cost = 1;
! if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
! cost += 2 * GET_MODE_SIZE (GET_MODE (X));
! else
! cost += GET_MODE_SIZE (GET_MODE (X));
! break;
case CONST_INT:
! cost = 0;
! break;
! case SIGN_EXTEND:
! if (outer_code == SET)
! cost = GET_MODE_SIZE (GET_MODE (X));
! else
! cost = -GET_MODE_SIZE (GET_MODE (X));
! break;
! case ZERO_EXTEND:
! if (outer_code == SET)
! cost = GET_MODE_SIZE (GET_MODE (X));
! else
! cost = -1;
! break;
! case PLUS:
! case MINUS:
! if (outer_code == SET)
! {
! if (X == stack_pointer_rtx)
! cost = -10;
! else if (GET_CODE (XEXP (X,1)) == CONST_INT)
! cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
! GET_MODE_SIZE (GET_MODE (X)));
! else
! cost = GET_MODE_SIZE (GET_MODE (X));
! }
! break;
! case COMPARE:
! if (GET_CODE (XEXP (X,1)) == CONST_INT)
! cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
! break;
default:
break;
}
! return cost;
}
static bool
avr_rtx_costs (rtx x, int code, int outer_code, int *total)
{
! int cst;
switch (code)
{
case CONST_INT:
! if (outer_code == PLUS
! || outer_code == IOR
! || outer_code == AND
! || outer_code == MINUS
! || outer_code == SET
! || INTVAL (x) == 0)
! {
! *total = 2;
! return true;
! }
! if (outer_code == COMPARE
! && INTVAL (x) >= 0
! && INTVAL (x) <= 255)
! {
! *total = 2;
! return true;
! }
! /* FALLTHRU */
case CONST:
case LABEL_REF:
case SYMBOL_REF:
! case CONST_DOUBLE:
! *total = 4;
return true;
! default:
! cst = default_rtx_costs (x, code, outer_code);
! if (cst > 0)
{
! *total = cst;
! return true;
}
! else if (cst < 0)
! *total += -cst;
! return false;
}
}
/* Calculate the cost of a memory address. */
--- 4820,5377 ----
reg_alloc_order[i] = order[i];
}
!
! /* Mutually recursive subroutine of avr_rtx_cost for calculating the
! cost of an RTX operand given its context. X is the rtx of the
! operand, MODE is its mode, and OUTER is the rtx_code of this
! operand's parent operator. */
static int
! avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer)
{
! enum rtx_code code = GET_CODE (x);
! int total;
!
switch (code)
{
! case REG:
! case SUBREG:
! return 0;
!
case CONST_INT:
! case CONST_DOUBLE:
! return COSTS_N_INSNS (GET_MODE_SIZE (mode));
!
default:
break;
}
!
! total = 0;
! avr_rtx_costs (x, code, outer, &total);
! return total;
}
+ /* The AVR backend's rtx_cost function. X is rtx expression whose cost
+ is to be calculated. Return true if the complete cost has been
+ computed, and false if subexpressions should be scanned. In either
+ case, *TOTAL contains the cost result. */
+
static bool
avr_rtx_costs (rtx x, int code, int outer_code, int *total)
{
! enum machine_mode mode = GET_MODE (x);
! HOST_WIDE_INT val;
switch (code)
{
case CONST_INT:
! case CONST_DOUBLE:
! /* Immediate constants are as cheap as registers. */
! *total = 0;
! return true;
+ case MEM:
case CONST:
case LABEL_REF:
case SYMBOL_REF:
! *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
return true;
! case NEG:
! switch (mode)
! {
! case QImode:
! case SFmode:
! *total = COSTS_N_INSNS (1);
! break;
!
! case HImode:
! *total = COSTS_N_INSNS (3);
! break;
!
! case SImode:
! *total = COSTS_N_INSNS (7);
! break;
!
! default:
! return false;
! }
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case ABS:
! switch (mode)
! {
! case QImode:
! case SFmode:
! *total = COSTS_N_INSNS (1);
! break;
!
! default:
! return false;
! }
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case NOT:
! *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case ZERO_EXTEND:
! *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
! - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case SIGN_EXTEND:
! *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
! - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case PLUS:
! switch (mode)
! {
! case QImode:
! *total = COSTS_N_INSNS (1);
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! break;
!
! case HImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (2);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
! *total = COSTS_N_INSNS (1);
! else
! *total = COSTS_N_INSNS (2);
! break;
!
! case SImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (4);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
! *total = COSTS_N_INSNS (1);
! else
! *total = COSTS_N_INSNS (4);
! break;
!
! default:
! return false;
! }
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case MINUS:
! case AND:
! case IOR:
! *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! return true;
!
! case XOR:
! *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! return true;
!
! case MULT:
! switch (mode)
! {
! case QImode:
! if (AVR_ENHANCED)
! *total = COSTS_N_INSNS (optimize_size ? 3 : 4);
! else if (optimize_size)
! *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
! else
! return false;
!
! case HImode:
! if (AVR_ENHANCED)
! *total = COSTS_N_INSNS (optimize_size ? 7 : 10);
! else if (optimize_size)
! *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
! else
! return false;
!
! default:
! return false;
! }
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! return true;
!
! case DIV:
! case MOD:
! case UDIV:
! case UMOD:
! if (optimize_size)
! *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
! else
! return false;
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! return true;
!
! case ASHIFT:
! switch (mode)
! {
! case QImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! {
! val = INTVAL (XEXP (x, 1));
! if (val == 7)
! *total = COSTS_N_INSNS (3);
! else if (val >= 0 && val <= 7)
! *total = COSTS_N_INSNS (val);
! else
! *total = COSTS_N_INSNS (1);
! }
! break;
!
! case HImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! switch (INTVAL (XEXP (x, 1)))
! {
! case 0:
! *total = 0;
! break;
! case 1:
! case 8:
! *total = COSTS_N_INSNS (2);
! break;
! case 9:
! *total = COSTS_N_INSNS (3);
! break;
! case 2:
! case 3:
! case 10:
! case 15:
! *total = COSTS_N_INSNS (4);
! break;
! case 7:
! case 11:
! case 12:
! *total = COSTS_N_INSNS (5);
! break;
! case 4:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
! break;
! case 6:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
! break;
! case 5:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 10);
! break;
! default:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! break;
!
! case SImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! switch (INTVAL (XEXP (x, 1)))
! {
! case 0:
! *total = 0;
! break;
! case 24:
! *total = COSTS_N_INSNS (3);
! break;
! case 1:
! case 8:
! case 16:
! *total = COSTS_N_INSNS (4);
! break;
! case 31:
! *total = COSTS_N_INSNS (6);
! break;
! case 2:
! *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
! break;
! default:
! *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! break;
!
! default:
! return false;
! }
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case ASHIFTRT:
! switch (mode)
! {
! case QImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! {
! val = INTVAL (XEXP (x, 1));
! if (val == 6)
! *total = COSTS_N_INSNS (4);
! else if (val == 7)
! *total = COSTS_N_INSNS (2);
! else if (val >= 0 && val <= 7)
! *total = COSTS_N_INSNS (val);
! else
! *total = COSTS_N_INSNS (1);
! }
! break;
!
! case HImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! switch (INTVAL (XEXP (x, 1)))
! {
! case 0:
! *total = 0;
! break;
! case 1:
! *total = COSTS_N_INSNS (2);
! break;
! case 15:
! *total = COSTS_N_INSNS (3);
! break;
! case 2:
! case 7:
! case 8:
! case 9:
! *total = COSTS_N_INSNS (4);
! break;
! case 10:
! case 14:
! *total = COSTS_N_INSNS (5);
! break;
! case 11:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
! break;
! case 12:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
! break;
! case 6:
! case 13:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
! break;
! default:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! break;
!
! case SImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! switch (INTVAL (XEXP (x, 1)))
! {
! case 0:
! *total = 0;
! break;
! case 1:
! *total = COSTS_N_INSNS (4);
! break;
! case 8:
! case 16:
! case 24:
! *total = COSTS_N_INSNS (6);
! break;
! case 2:
! *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
! break;
! case 31:
! *total = COSTS_N_INSNS (AVR_ENHANCED ? 4 : 5);
! break;
! default:
! *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! break;
!
! default:
! return false;
! }
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case LSHIFTRT:
! switch (mode)
! {
! case QImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! {
! val = INTVAL (XEXP (x, 1));
! if (val == 7)
! *total = COSTS_N_INSNS (3);
! else if (val >= 0 && val <= 7)
! *total = COSTS_N_INSNS (val);
! else
! *total = COSTS_N_INSNS (1);
! }
! break;
!
! case HImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! switch (INTVAL (XEXP (x, 1)))
! {
! case 0:
! *total = 0;
! break;
! case 1:
! case 8:
! *total = COSTS_N_INSNS (2);
! break;
! case 9:
! *total = COSTS_N_INSNS (3);
! break;
! case 2:
! case 10:
! case 15:
! *total = COSTS_N_INSNS (4);
! break;
! case 7:
! case 11:
! *total = COSTS_N_INSNS (5);
! break;
! case 3:
! case 12:
! case 13:
! case 14:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
! break;
! case 4:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
! break;
! case 5:
! case 6:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
! break;
! default:
! *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! break;
!
! case SImode:
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! {
! *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! else
! switch (INTVAL (XEXP (x, 1)))
! {
! case 0:
! *total = 0;
! break;
! case 1:
! *total = COSTS_N_INSNS (4);
! break;
! case 2:
! *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
! break;
! case 8:
! case 16:
! case 24:
! *total = COSTS_N_INSNS (4);
! break;
! case 31:
! *total = COSTS_N_INSNS (6);
! break;
! default:
! *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! }
! break;
!
! default:
! return false;
! }
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! case COMPARE:
! switch (GET_MODE (XEXP (x, 0)))
{
! case QImode:
! *total = COSTS_N_INSNS (1);
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! break;
!
! case HImode:
! *total = COSTS_N_INSNS (2);
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! else if (INTVAL (XEXP (x, 1)) != 0)
! *total += COSTS_N_INSNS (1);
! break;
!
! case SImode:
! *total = COSTS_N_INSNS (4);
! if (GET_CODE (XEXP (x, 1)) != CONST_INT)
! *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
! else if (INTVAL (XEXP (x, 1)) != 0)
! *total += COSTS_N_INSNS (3);
! break;
!
! default:
! return false;
}
! *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
! return true;
!
! default:
! break;
}
+ return false;
}
/* Calculate the cost of a memory address. */
Roger
--