From 8f2bf9f18d96cfdda037ee14619ff866bc021e73 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Wed, 9 Feb 2005 14:43:28 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 + gcc/config/avr/avr.c | 602 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 532 insertions(+), 77 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 13f8d9a9928..b8675fb4a5f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-02-09 Roger Sayle + + 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 PR target/19806 diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index fffb7badabe..42dbf0295c7 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -74,7 +74,7 @@ static unsigned int avr_section_type_flags (tree, const char *, int); 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 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); @@ -4820,110 +4820,558 @@ order_regs_for_local_alloc (void) 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 -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) { - 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 REG: + case SUBREG: + return 0; + 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; + case CONST_DOUBLE: + return COSTS_N_INSNS (GET_MODE_SIZE (mode)); + default: 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 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) { case CONST_INT: - if (outer_code == PLUS - || outer_code == IOR - || outer_code == AND - || outer_code == MINUS - || outer_code == SET - || INTVAL (x) == 0) + 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) { - *total = 2; - return true; + 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; } - if (outer_code == COMPARE - && INTVAL (x) >= 0 - && INTVAL (x) <= 255) + *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code); + return true; + + case ABS: + switch (mode) { - *total = 2; - return true; + case QImode: + 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 LABEL_REF: - case SYMBOL_REF: - case CONST_DOUBLE: - *total = 4; + case NOT: + *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)); + *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code); return true; - default: - cst = default_rtx_costs (x, code, outer_code); - if (cst > 0) + 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))) { - *total = cst; - return true; + 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; } - else if (cst < 0) - *total += -cst; - 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. */ -- 2.30.2