diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2012-09-15 13:24:30 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2012-09-15 13:24:30 +0000 |
commit | 8385420c4f45090a3393557783d8c7c73ef9a9b7 (patch) | |
tree | 2dedca1f1de4cef97fbcc5696371bb47ed5260e8 /gcc | |
parent | 29454ff5257a3a074e868790dc4f6bcdfb1b0b03 (diff) | |
download | gcc-8385420c4f45090a3393557783d8c7c73ef9a9b7.zip gcc-8385420c4f45090a3393557783d8c7c73ef9a9b7.tar.gz gcc-8385420c4f45090a3393557783d8c7c73ef9a9b7.tar.bz2 |
sh.c (sh_rtx_costs): Add handling of MEM, SIGN_EXTEND, ZERO_EXTEND and PARALLEL cases.
* config/sh/sh.c (sh_rtx_costs): Add handling of MEM, SIGN_EXTEND,
ZERO_EXTEND and PARALLEL cases.
(sh_address_cost): Correct rtx parsing and tweak cost estimations.
From-SVN: r191342
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 115 |
2 files changed, 102 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e4330b3..ae8bf34 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-09-15 Oleg Endo <olegendo@gcc.gnu.org> + + * config/sh/sh.c (sh_rtx_costs): Add handling of MEM, SIGN_EXTEND, + ZERO_EXTEND and PARALLEL cases. + (sh_address_cost): Correct rtx parsing and tweak cost estimations. + 2012-09-14 Sandra Loosemore <sandra@codesourcery.com> * doc/tm.texi.in (Stack Arguments): Update obsolete references diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 7f8ded0..b54bf2f 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -3196,6 +3196,78 @@ sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, } return false; + /* The cost of a mem access is mainly the cost of the address mode. */ + case MEM: + *total = sh_address_cost (XEXP (x, 0), GET_MODE (x), MEM_ADDR_SPACE (x), + true); + return true; + + /* The cost of a sign or zero extend depends on whether the source is a + reg or a mem. In case of a mem take the address into acount. */ + case SIGN_EXTEND: + if (REG_P (XEXP (x, 0))) + { + *total = COSTS_N_INSNS (1); + return true; + } + if (MEM_P (XEXP (x, 0))) + { + *total = sh_address_cost (XEXP (XEXP (x, 0), 0), + GET_MODE (XEXP (x, 0)), + MEM_ADDR_SPACE (XEXP (x, 0)), true); + return true; + } + return false; + + case ZERO_EXTEND: + if (REG_P (XEXP (x, 0))) + { + *total = COSTS_N_INSNS (1); + return true; + } + else if (TARGET_SH2A && MEM_P (XEXP (x, 0)) + && (GET_MODE (XEXP (x, 0)) == QImode + || GET_MODE (XEXP (x, 0)) == HImode)) + { + /* Handle SH2A's movu.b and movu.w insn. */ + *total = sh_address_cost (XEXP (XEXP (x, 0), 0), + GET_MODE (XEXP (x, 0)), + MEM_ADDR_SPACE (XEXP (x, 0)), true); + return true; + } + return false; + + /* mems for SFmode and DFmode can be inside a parallel due to + the way the fpscr is handled. */ + case PARALLEL: + for (int i = 0; i < XVECLEN (x, 0); i++) + { + rtx xx = XVECEXP (x, 0, i); + if (GET_CODE (xx) == SET && MEM_P (XEXP (xx, 0))) + { + *total = sh_address_cost (XEXP (XEXP (xx, 0), 0), + GET_MODE (XEXP (xx, 0)), + MEM_ADDR_SPACE (XEXP (xx, 0)), true); + return true; + } + if (GET_CODE (xx) == SET && MEM_P (XEXP (xx, 1))) + { + *total = sh_address_cost (XEXP (XEXP (xx, 1), 0), + GET_MODE (XEXP (xx, 1)), + MEM_ADDR_SPACE (XEXP (xx, 1)), true); + return true; + } + } + + if (sh_1el_vec (x, VOIDmode)) + *total = outer_code != SET; + else if (sh_rep_vec (x, VOIDmode)) + *total = ((GET_MODE_UNIT_SIZE (GET_MODE (x)) + 3) / 4 + + (outer_code != SET)); + else + *total = COSTS_N_INSNS (3) + (outer_code != SET); + return true; + case CONST_INT: if (TARGET_SHMEDIA) { @@ -3271,7 +3343,10 @@ sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, else *total = 10; return true; + case CONST_VECTOR: + /* FIXME: This looks broken. Only the last statement has any effect. + Probably this could be folded with the PARALLEL case? */ if (x == CONST0_RTX (GET_MODE (x))) *total = 0; else if (sh_1el_vec (x, VOIDmode)) @@ -3339,15 +3414,6 @@ sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, *total = COSTS_N_INSNS (20); return true; - case PARALLEL: - if (sh_1el_vec (x, VOIDmode)) - *total = outer_code != SET; - if (sh_rep_vec (x, VOIDmode)) - *total = ((GET_MODE_UNIT_SIZE (GET_MODE (x)) + 3) / 4 - + (outer_code != SET)); - *total = COSTS_N_INSNS (3) + (outer_code != SET); - return true; - case FLOAT: case FIX: *total = 100; @@ -3430,36 +3496,47 @@ disp_addr_displacement (rtx x) /* Compute the cost of an address. */ static int -sh_address_cost (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED, +sh_address_cost (rtx x, enum machine_mode mode, addr_space_t as ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED) { + /* Simple reg, post-inc, pre-dec addressing. */ + if (REG_P (x) || GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC) + return 1; + /* 'reg + disp' addressing. */ - if (satisfies_constraint_Sdd (x)) + if (GET_CODE (x) == PLUS + && REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) { - const HOST_WIDE_INT offset = disp_addr_displacement (x); - const enum machine_mode mode = GET_MODE (x); + const HOST_WIDE_INT offset = INTVAL (XEXP (x, 1)); + + if (offset == 0) + return 1; - /* The displacement would fit into a 2 byte move insn. */ + /* The displacement would fit into a 2 byte move insn. + HImode and QImode loads/stores with displacement put pressure on + R0 which will most likely require another reg copy. Thus account + a higher cost for that. */ if (offset > 0 && offset <= max_mov_insn_displacement (mode, false)) - return 0; + return (mode == HImode || mode == QImode) ? 2 : 1; /* The displacement would fit into a 4 byte move insn (SH2A). */ if (TARGET_SH2A && offset > 0 && offset <= max_mov_insn_displacement (mode, true)) - return 1; + return 2; /* The displacement is probably out of range and will require extra calculations. */ - return 2; + return 3; } /* 'reg + reg' addressing. Account a slightly higher cost because of increased pressure on R0. */ if (GET_CODE (x) == PLUS && ! CONSTANT_P (XEXP (x, 1)) && ! TARGET_SHMEDIA) - return 1; + return 3; - return 0; + /* Not sure what it is - probably expensive. */ + return 10; } /* Code to expand a shift. */ |