MSP430: Implement TARGET_INSN_COST

The length of an insn can be used to calculate its cost, when optimizing
for size. When optimizing for speed, this is a good estimate, since the
cycle cost of an MSP430 instruction increases with its length.

gcc/ChangeLog:

	* config/msp430/msp430.c (TARGET_INSN_COST): Define.
	(msp430_insn_cost): New function.
	* config/msp430/msp430.h (BRANCH_COST): Define.
	(LOGICAL_OP_NON_SHORT_CIRCUIT): Define.

gcc/testsuite/ChangeLog:

	* gcc.target/msp430/rtx-cost-O3-default.c: New test.
	* gcc.target/msp430/rtx-cost-O3-f5series.c: New test.
	* gcc.target/msp430/rtx-cost-Os-default.c: New test.
	* gcc.target/msp430/rtx-cost-Os-f5series.c: New test.
This commit is contained in:
Jozef Lawrynowicz 2020-11-13 15:35:52 +00:00
parent 546c8f9558
commit 54896b10db
6 changed files with 189 additions and 5 deletions

View File

@ -1181,11 +1181,6 @@ msp430_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
return 2 * cost;
}
/* BRANCH_COST
Changing from the default of 1 doesn't affect code generation, presumably
because there are no conditional move insns - when a condition is involved,
the only option is to use a cbranch. */
/* For X, which must be a MEM RTX, return TRUE if it is an indirect memory
reference, @Rn or @Rn+. */
static bool
@ -1650,6 +1645,26 @@ msp430_rtx_costs (rtx x,
return false;
}
}
#undef TARGET_INSN_COST
#define TARGET_INSN_COST msp430_insn_cost
static int
msp430_insn_cost (rtx_insn *insn, bool speed ATTRIBUTE_UNUSED)
{
if (recog_memoized (insn) < 0)
return 0;
/* The returned cost must be relative to COSTS_N_INSNS (1). An insn with a
length of 2 bytes is the smallest possible size and so must be equivalent
to COSTS_N_INSNS (1). */
return COSTS_N_INSNS (get_attr_length (insn) / 2);
/* FIXME Add more detailed costs when optimizing for speed.
For now the length of the instruction is a good approximiation and roughly
correlates with cycle cost. */
}
/* Function Entry and Exit */

View File

@ -243,6 +243,14 @@ extern const char *msp430_get_linker_devices_include_path (int, const char **);
#define HAS_LONG_COND_BRANCH 0
#define HAS_LONG_UNCOND_BRANCH 0
/* The cost of a branch sequence is roughly 3 "cheap" instructions. */
#define BRANCH_COST(speed_p, predictable_p) 3
/* Override the default BRANCH_COST heuristic to indicate that it is preferable
to retain short-circuit operations, this results in significantly better
codesize and performance. */
#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
#define LOAD_EXTEND_OP(M) ZERO_EXTEND
#define WORD_REGISTER_OPERATIONS 1

View File

@ -0,0 +1,42 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
/* { dg-final { check-function-bodies "**" "" } } */
/* Verify the MSP430 cost model is working as expected for the default ISA
(msp430x) and hwmult (none), when compiling at -O3. */
char arr[2];
char a;
char *ptr;
/*
** foo:
** ...
** MOV.B \&a, \&arr\+1
** MOV.* #arr\+2, \&ptr
** ...
*/
void
foo (void)
{
arr[1] = a;
ptr = arr + 2;
}
extern void ext (void);
/*
** bar:
** ...
** CALL.* #ext
** CALL.* #ext
** ...
*/
void
bar (void)
{
ext ();
ext ();
}

View File

@ -0,0 +1,38 @@
/* { dg-do compile } */
/* { dg-options "-O3 -mhwmult=f5series" } */
/* { dg-final { check-function-bodies "**" "" } } */
/* Verify the MSP430 cost model is working as expected for the default ISA
(msp430x) and f5series hwmult, when compiling at -O3. */
volatile unsigned long a;
volatile unsigned int b;
volatile unsigned long c;
unsigned long res1;
unsigned long res2;
unsigned long res3;
/*
** foo:
** ...
** MOV.B #16, R14
** CALL.* #__mspabi_slll
** ...
** MOV.* \&res2.*
** ...
** RLA.*RLC.*
** ...
** MOV.* \&res3.*
** ...
** RLA.*RLC.*
** ...
*/
void foo (void)
{
/* Use the shift library function for this. */
res1 = (a << 16) | b;
/* Emit 7 inline shifts for this. */
res2 *= 128;
/* Perform this multiplication inline, using addition and shifts. */
res3 *= 100;
}

View File

@ -0,0 +1,43 @@
/* { dg-do compile } */
/* { dg-options "-Os" } */
/* { dg-final { check-function-bodies "**" "" } } */
/* Verify the MSP430 cost model is working as expected for the default ISA
(msp430x) and hwmult (none), when compiling at -Os. */
char arr[2];
char a;
char *ptr;
/*
** foo:
** ...
** MOV.B \&a, \&arr\+1
** MOV.* #arr\+2, \&ptr
** ...
*/
void
foo (void)
{
arr[1] = a;
ptr = arr + 2;
}
extern void ext (void);
/*
** bar:
** ...
** MOV.* #ext, R10
** CALL.* R10
** CALL.* R10
** ...
*/
void
bar (void)
{
ext ();
ext ();
}

View File

@ -0,0 +1,38 @@
/* { dg-do compile } */
/* { dg-options "-Os -mhwmult=f5series" } */
/* { dg-final { check-function-bodies "**" "" } } */
/* Verify the MSP430 cost model is working as expected for the default ISA
(msp430x) and f5series hwmult, when compiling at -Os. */
volatile unsigned long a;
volatile unsigned int b;
volatile unsigned long c;
unsigned long res1;
unsigned long res2;
unsigned long res3;
/*
** foo:
** ...
** MOV.B #16, R14
** CALL.* #__mspabi_slll
** ...
** MOV.B #7, R14
** CALL.* #__mspabi_slll
** ...
** MOV.B #100, R14
** MOV.B #0, R15
** ...
** CALL.* #__mulsi2_f5
** ...
*/
void foo (void)
{
/* Use the shift library function for this. */
res1 = (a << 16) | b;
/* Likewise. */
res2 *= 128;
/* Use the hardware multiply library function for this. */
res3 *= 100;
}