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;
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: case CONST_INT:
cost = 0; case CONST_DOUBLE:
break; return COSTS_N_INSNS (GET_MODE_SIZE (mode));
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: default:
break; break;
} }
return cost;
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 static bool
avr_rtx_costs (rtx x, int code, int outer_code, int *total) avr_rtx_costs (rtx x, int code, int outer_code, int *total)
{ {
int cst; enum machine_mode mode = GET_MODE (x);
HOST_WIDE_INT val;
switch (code) switch (code)
{ {
case CONST_INT: case CONST_INT:
if (outer_code == PLUS case CONST_DOUBLE:
|| outer_code == IOR /* Immediate constants are as cheap as registers. */
|| outer_code == AND *total = 0;
|| outer_code == MINUS return true;
|| outer_code == SET
|| INTVAL (x) == 0) case MEM:
case CONST:
case LABEL_REF:
case SYMBOL_REF:
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
return true;
case NEG:
switch (mode)
{ {
*total = 2; case QImode:
return true; 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;
} }
if (outer_code == COMPARE *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
&& INTVAL (x) >= 0 return true;
&& INTVAL (x) <= 255)
case ABS:
switch (mode)
{ {
*total = 2; case QImode:
return true; case SFmode:
*total = COSTS_N_INSNS (1);
break;
default:
return false;
} }
/* FALLTHRU */ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
return true;
case CONST: case NOT:
case LABEL_REF: *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
case SYMBOL_REF: *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
case CONST_DOUBLE:
*total = 4;
return true; return true;
default: case ZERO_EXTEND:
cst = default_rtx_costs (x, code, outer_code); *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
if (cst > 0) - 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)))
{ {
*total = cst; case QImode:
return true; *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;
} }
else if (cst < 0) *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
*total += -cst; return true;
return false;
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