summaryrefslogtreecommitdiff
path: root/gcc/config/sh/sh.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/sh/sh.c')
-rw-r--r--gcc/config/sh/sh.c112
1 files changed, 107 insertions, 5 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index dbebd24fd6f..93e7978c020 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -214,7 +214,11 @@ static void sh_media_init_builtins PARAMS ((void));
static rtx sh_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
static int flow_dependent_p PARAMS ((rtx, rtx));
static void flow_dependent_p_1 PARAMS ((rtx, rtx, void *));
-
+static int shiftcosts PARAMS ((rtx));
+static int andcosts PARAMS ((rtx));
+static int addsubcosts PARAMS ((rtx));
+static int multcosts PARAMS ((rtx));
+static bool sh_rtx_costs PARAMS ((rtx, int, int, int *));
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
@@ -266,6 +270,9 @@ static void flow_dependent_p_1 PARAMS ((rtx, rtx, void *));
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL sh_function_ok_for_sibcall
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS sh_rtx_costs
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Print the operand address in x to the stream. */
@@ -1274,7 +1281,7 @@ shift_insns_rtx (insn)
/* Return the cost of a shift. */
-int
+static inline int
shiftcosts (x)
rtx x;
{
@@ -1314,7 +1321,7 @@ shiftcosts (x)
/* Return the cost of an AND operation. */
-int
+static inline int
andcosts (x)
rtx x;
{
@@ -1354,7 +1361,7 @@ andcosts (x)
/* Return the cost of an addition or a subtraction. */
-int
+static inline int
addsubcosts (x)
rtx x;
{
@@ -1395,7 +1402,7 @@ addsubcosts (x)
}
/* Return the cost of a multiply. */
-int
+static inline int
multcosts (x)
rtx x ATTRIBUTE_UNUSED;
{
@@ -1421,6 +1428,101 @@ multcosts (x)
return 20;
}
+/* Compute a (partial) cost for rtx X. 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
+sh_rtx_costs (x, code, outer_code, total)
+ rtx x;
+ int code, outer_code, *total;
+{
+ switch (code)
+ {
+ case CONST_INT:
+ if (TARGET_SHMEDIA)
+ {
+ if (INTVAL (x) == 0)
+ *total = 0;
+ else if (outer_code == AND && and_operand ((x), DImode))
+ *total = 0;
+ else if ((outer_code == IOR || outer_code == XOR
+ || outer_code == PLUS)
+ && CONST_OK_FOR_P (INTVAL (x)))
+ *total = 0;
+ else if (CONST_OK_FOR_J (INTVAL (x)))
+ *total = COSTS_N_INSNS (outer_code != SET);
+ else if (CONST_OK_FOR_J (INTVAL (x) >> 16))
+ *total = COSTS_N_INSNS (2);
+ else if (CONST_OK_FOR_J ((INTVAL (x) >> 16) >> 16))
+ *total = COSTS_N_INSNS (3);
+ else
+ *total = COSTS_N_INSNS (4);
+ return true;
+ }
+ if (CONST_OK_FOR_I (INTVAL (x)))
+ *total = 0;
+ else if ((outer_code == AND || outer_code == IOR || outer_code == XOR)
+ && CONST_OK_FOR_L (INTVAL (x)))
+ *total = 1;
+ else
+ *total = 8;
+ return true;
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ if (TARGET_SHMEDIA64)
+ *total = COSTS_N_INSNS (4);
+ else if (TARGET_SHMEDIA32)
+ *total = COSTS_N_INSNS (2);
+ else
+ *total = 5;
+ return true;
+
+ case CONST_DOUBLE:
+ if (TARGET_SHMEDIA)
+ *total = COSTS_N_INSNS (4);
+ else
+ *total = 10;
+ return true;
+
+ case PLUS:
+ *total = COSTS_N_INSNS (addsubcosts (x));
+ return true;
+
+ case AND:
+ *total = COSTS_N_INSNS (andcosts (x));
+ return true;
+
+ case MULT:
+ *total = COSTS_N_INSNS (multcosts (x));
+ return true;
+
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ *total = COSTS_N_INSNS (shiftcosts (x));
+ return true;
+
+ case DIV:
+ case UDIV:
+ case MOD:
+ case UMOD:
+ *total = COSTS_N_INSNS (20);
+ return true;
+
+ case FLOAT:
+ case FIX:
+ *total = 100;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+
/* Code to expand a shift. */
void