Commit 8f2bf9f1 by Roger Sayle Committed by Roger Sayle

re PR target/19597 (avr-gcc 4.0, multiplication by constant, very long code)


	PR target/19597
	* config/avr/avr.c (default_rtx_costs): Delete.
	(avr_operand_rtx_cost): New function.
	(avr_rtx_costs): Completely rewrite.

From-SVN: r94766
parent 3ee79d96
2005-02-09 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.
2005-02-08 Hans-Peter Nilsson <hp@axis.com> 2005-02-08 Hans-Peter Nilsson <hp@axis.com>
PR target/19806 PR target/19806
......
...@@ -74,7 +74,7 @@ static unsigned int avr_section_type_flags (tree, const char *, int); ...@@ -74,7 +74,7 @@ static unsigned int avr_section_type_flags (tree, const char *, int);
static void avr_reorg (void); static void avr_reorg (void);
static void avr_asm_out_ctor (rtx, int); static void avr_asm_out_ctor (rtx, int);
static void avr_asm_out_dtor (rtx, int); static void avr_asm_out_dtor (rtx, int);
static int default_rtx_costs (rtx, enum rtx_code, enum rtx_code); static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code);
static bool avr_rtx_costs (rtx, int, int, int *); static bool avr_rtx_costs (rtx, int, int, int *);
static int avr_address_cost (rtx); static int avr_address_cost (rtx);
static bool avr_return_in_memory (tree, tree); static bool avr_return_in_memory (tree, tree);
...@@ -4820,110 +4820,558 @@ order_regs_for_local_alloc (void) ...@@ -4820,110 +4820,558 @@ order_regs_for_local_alloc (void)
reg_alloc_order[i] = order[i]; reg_alloc_order[i] = order[i];
} }
/* Calculate the cost of X code of the expression in which it is contained,
found in OUTER_CODE */ /* 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 static int
default_rtx_costs (rtx X, enum rtx_code code, enum rtx_code outer_code) avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer)
{ {
int cost=0; enum rtx_code code = GET_CODE (x);
int total;
switch (code) switch (code)
{ {
case SYMBOL_REF: case REG:
case LABEL_REF: case SUBREG:
cost = 2 * GET_MODE_SIZE (GET_MODE (X)); return 0;
case CONST_INT:
case CONST_DOUBLE:
return COSTS_N_INSNS (GET_MODE_SIZE (mode));
default:
break; 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 MEM:
if (outer_code != SET) case CONST:
cost = 1; case LABEL_REF:
if (GET_CODE (XEXP (X,0)) == SYMBOL_REF) case SYMBOL_REF:
cost += 2 * GET_MODE_SIZE (GET_MODE (X)); *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
else return true;
cost += GET_MODE_SIZE (GET_MODE (X));
case NEG:
switch (mode)
{
case QImode:
case SFmode:
*total = COSTS_N_INSNS (1);
break; break;
case CONST_INT:
cost = 0; case HImode:
*total = COSTS_N_INSNS (3);
break;
case SImode:
*total = COSTS_N_INSNS (7);
break; 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: case SIGN_EXTEND:
if (outer_code == SET) *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
cost = GET_MODE_SIZE (GET_MODE (X)); - 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 else
cost = -GET_MODE_SIZE (GET_MODE (X)); *total = COSTS_N_INSNS (2);
break; break;
case ZERO_EXTEND:
if (outer_code == SET) case SImode:
cost = GET_MODE_SIZE (GET_MODE (X)); 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 else
cost = -1; *total = COSTS_N_INSNS (4);
break; break;
case PLUS:
default:
return false;
}
*total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
return true;
case MINUS: case MINUS:
if (outer_code == SET) 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)
{ {
if (X == stack_pointer_rtx) case QImode:
cost = -10; if (AVR_ENHANCED)
else if (GET_CODE (XEXP (X,1)) == CONST_INT) *total = COSTS_N_INSNS (optimize_size ? 3 : 4);
cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 : else if (optimize_size)
GET_MODE_SIZE (GET_MODE (X))); *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
else else
cost = GET_MODE_SIZE (GET_MODE (X)); 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; break;
case COMPARE:
if (GET_CODE (XEXP (X,1)) == CONST_INT) case HImode:
cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0))); 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; break;
default: default:
*total = COSTS_N_INSNS (optimize_size ? 5 : 41);
*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
}
break; 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);
} }
return cost; 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;
static bool default:
avr_rtx_costs (rtx x, int code, int outer_code, int *total) return false;
{ }
int cst; *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
return true;
switch (code) case ASHIFTRT:
switch (mode)
{ {
case CONST_INT: case QImode:
if (outer_code == PLUS if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|| outer_code == IOR {
|| outer_code == AND *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
|| outer_code == MINUS *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
|| outer_code == SET
|| INTVAL (x) == 0)
{
*total = 2;
return true;
} }
if (outer_code == COMPARE else
&& INTVAL (x) >= 0
&& INTVAL (x) <= 255)
{ {
*total = 2; val = INTVAL (XEXP (x, 1));
return true; 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);
} }
/* FALLTHRU */ break;
case CONST: case HImode:
case LABEL_REF: if (GET_CODE (XEXP (x, 1)) != CONST_INT)
case SYMBOL_REF: {
case CONST_DOUBLE: *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
*total = 4; *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; 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: default:
cst = default_rtx_costs (x, code, outer_code); *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
if (cst > 0) *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
}
break;
case SImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{ {
*total = cst; *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
return true; *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
} }
else if (cst < 0) else
*total += -cst; 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; 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. */ /* Calculate the cost of a memory address. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment