Skip to content

Commit 953587a

Browse files
committed
MSP430: Implement TARGET_MEMORY_MOVE_COST
The cycle and size cost of a MOV instruction in different addressing modes can be used to calculate the TARGET_MEMORY_MOVE_COST relative to TARGET_REGISTER_MOVE_COST. gcc/ChangeLog: * config/msp430/msp430.c (struct single_op_cost): New struct. (struct double_op_cost): Likewise. (TARGET_REGISTER_MOVE_COST): Don't define but add comment. (TARGET_MEMORY_MOVE_COST): Define to... (msp430_memory_move_cost): New function. (BRANCH_COST): Don't define but add comment.
1 parent 602c6cf commit 953587a

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

gcc/config/msp430/msp430.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,135 @@ msp430_legitimate_constant (machine_mode mode, rtx x)
10311031
}
10321032

10331033

1034+
/* Describing Relative Costs of Operations
1035+
To model the cost of an instruction, use the number of cycles when
1036+
optimizing for speed, and the number of words when optimizing for size.
1037+
The cheapest instruction will execute in one cycle and cost one word.
1038+
The cycle and size costs correspond to 430 ISA instructions, not 430X
1039+
instructions or 430X "address" instructions. The relative costs of 430X
1040+
instructions is accurately modeled with the 430 costs. The relative costs
1041+
of some "address" instructions can differ, but these are not yet handled.
1042+
Adding support for this could improve performance/code size. */
1043+
1044+
struct single_op_cost
1045+
{
1046+
const int reg;
1047+
/* Indirect register (@Rn) or indirect autoincrement (@Rn+). */
1048+
const int ind;
1049+
const int mem;
1050+
};
1051+
1052+
static const struct single_op_cost cycle_cost_single_op =
1053+
{
1054+
1, 3, 4
1055+
};
1056+
1057+
static const struct single_op_cost size_cost_single_op =
1058+
{
1059+
1, 1, 2
1060+
};
1061+
1062+
/* When the destination of an insn is memory, the cost is always the same
1063+
regardless of whether that memory is accessed using indirect register,
1064+
indexed or absolute addressing.
1065+
When the source operand is memory, indirect register and post-increment have
1066+
the same cost, which is lower than indexed and absolute, which also have
1067+
the same cost. */
1068+
struct double_op_cost
1069+
{
1070+
/* Source operand is a register. */
1071+
const int r2r;
1072+
const int r2pc;
1073+
const int r2m;
1074+
1075+
/* Source operand is memory, using indirect register (@Rn) or indirect
1076+
autoincrement (@Rn+) addressing modes. */
1077+
const int ind2r;
1078+
const int ind2pc;
1079+
const int ind2m;
1080+
1081+
/* Source operand is an immediate. */
1082+
const int imm2r;
1083+
const int imm2pc;
1084+
const int imm2m;
1085+
1086+
/* Source operand is memory, using indexed (x(Rn)) or absolute (&ADDR)
1087+
addressing modes. */
1088+
const int mem2r;
1089+
const int mem2pc;
1090+
const int mem2m;
1091+
};
1092+
1093+
/* These structures describe the cost of MOV, BIT and CMP instructions, in terms
1094+
of clock cycles or words. */
1095+
static const struct double_op_cost cycle_cost_double_op_mov =
1096+
{
1097+
1, 3, 3,
1098+
2, 4, 4,
1099+
2, 3, 4,
1100+
3, 5, 5
1101+
};
1102+
1103+
/* Cycle count when memory is the destination operand is one larger than above
1104+
for instructions that aren't MOV, BIT or CMP. */
1105+
static const struct double_op_cost cycle_cost_double_op =
1106+
{
1107+
1, 3, 4,
1108+
2, 4, 5,
1109+
2, 3, 5,
1110+
3, 5, 6
1111+
};
1112+
1113+
static const struct double_op_cost size_cost_double_op =
1114+
{
1115+
1, 1, 2,
1116+
1, 1, 2,
1117+
2, 2, 3,
1118+
2, 2, 3
1119+
};
1120+
1121+
/* TARGET_REGISTER_MOVE_COST
1122+
There is only one class of general-purpose, non-fixed registers, and the
1123+
relative cost of moving data between them is always the same.
1124+
Therefore, the default of 2 is optimal. */
1125+
1126+
#undef TARGET_MEMORY_MOVE_COST
1127+
#define TARGET_MEMORY_MOVE_COST msp430_memory_move_cost
1128+
1129+
/* Return the cost of moving data between registers and memory.
1130+
The returned cost must be relative to the default TARGET_REGISTER_MOVE_COST
1131+
of 2.
1132+
IN is false if the value is to be written to memory. */
1133+
static int
1134+
msp430_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
1135+
reg_class_t rclass ATTRIBUTE_UNUSED,
1136+
bool in)
1137+
{
1138+
int cost;
1139+
const struct double_op_cost *cost_p;
1140+
/* Optimize with a code size focus by default, unless -O2 or above is
1141+
specified. */
1142+
bool speed = (!optimize_size && optimize >= 2);
1143+
1144+
cost_p = (speed ? &cycle_cost_double_op_mov : &size_cost_double_op);
1145+
1146+
if (in)
1147+
/* Reading from memory using indirect addressing is assumed to be the more
1148+
common case. */
1149+
cost = cost_p->ind2r;
1150+
else
1151+
cost = cost_p->r2m;
1152+
1153+
/* All register to register moves cost 1 cycle or 1 word, so multiply by 2
1154+
to get the costs relative to TARGET_REGISTER_MOVE_COST of 2. */
1155+
return 2 * cost;
1156+
}
1157+
1158+
/* BRANCH_COST
1159+
Changing from the default of 1 doesn't affect code generation, presumably
1160+
because there are no conditional move insns - when a condition is involved,
1161+
the only option is to use a cbranch. */
1162+
10341163
#undef TARGET_RTX_COSTS
10351164
#define TARGET_RTX_COSTS msp430_rtx_costs
10361165

0 commit comments

Comments
 (0)