aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorOleg Endo <olegendo@gcc.gnu.org>2012-09-15 13:24:30 +0000
committerOleg Endo <olegendo@gcc.gnu.org>2012-09-15 13:24:30 +0000
commit8385420c4f45090a3393557783d8c7c73ef9a9b7 (patch)
tree2dedca1f1de4cef97fbcc5696371bb47ed5260e8 /gcc
parent29454ff5257a3a074e868790dc4f6bcdfb1b0b03 (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/config/sh/sh.c115
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. */