1 /* Subroutines used for calculate rtx costs of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* ------------------------------------------------------------------------ */
23 #define IN_TARGET_CODE 1
27 #include "coretypes.h"
34 #include "optabs.h" /* For GEN_FCN. */
36 #include "tm-constrs.h"
37 #include "tree-pass.h"
39 /* ------------------------------------------------------------------------ */
41 typedef bool (*rtx_cost_func
) (rtx
, int, int, int, int*);
43 struct rtx_cost_model_t
{
44 rtx_cost_func speed_prefer
;
45 rtx_cost_func size_prefer
;
48 static rtx_cost_model_t rtx_cost_model
;
50 static int insn_size_16bit
; /* Initial at nds32_init_rtx_costs. */
51 static const int insn_size_32bit
= 4;
54 nds32_rtx_costs_speed_prefer (rtx x ATTRIBUTE_UNUSED
,
56 int outer_code ATTRIBUTE_UNUSED
,
57 int opno ATTRIBUTE_UNUSED
,
62 machine_mode mode
= GET_MODE (x
);
63 /* Scale cost by mode size. */
64 int cost
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) / GET_MODE_SIZE (SImode
));
69 /* Used in combine.c as a marker. */
74 /* When not optimizing for size, we care more about the cost
75 of hot code, and hot code is often in a loop. If a constant
76 operand needs to be forced into a register, we will often be
77 able to hoist the constant load out of the loop, so the load
78 should not contribute to the cost. */
79 if (outer_code
== SET
|| outer_code
== PLUS
)
80 *total
= satisfies_constraint_Is20 (x
) ? 0 : 4;
81 else if (outer_code
== AND
|| outer_code
== IOR
|| outer_code
== XOR
82 || outer_code
== MINUS
)
83 *total
= satisfies_constraint_Iu15 (x
) ? 0 : 4;
84 else if (outer_code
== ASHIFT
|| outer_code
== ASHIFTRT
85 || outer_code
== LSHIFTRT
)
86 *total
= satisfies_constraint_Iu05 (x
) ? 0 : 4;
87 else if (GET_RTX_CLASS (outer_code
) == RTX_COMPARE
88 || GET_RTX_CLASS (outer_code
) == RTX_COMM_COMPARE
)
89 *total
= satisfies_constraint_Is16 (x
) ? 0 : 4;
91 *total
= COSTS_N_INSNS (1);
98 *total
= COSTS_N_INSNS (1);
102 *total
= COSTS_N_INSNS (1);
108 mode
= GET_MODE (op0
);
109 /* Scale cost by mode size. */
110 cost
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) / GET_MODE_SIZE (SImode
));
112 switch (GET_CODE (op1
))
116 /* Register move and Store instructions. */
117 if ((REG_P (op0
) || MEM_P (op0
))
118 && GET_MODE_SIZE (mode
) <= GET_MODE_SIZE (DImode
))
119 *total
= COSTS_N_INSNS (1);
125 /* Load instructions. */
126 if (REG_P (op0
) && GET_MODE_SIZE (mode
) <= GET_MODE_SIZE (DImode
))
127 *total
= COSTS_N_INSNS (1);
133 /* movi instruction. */
134 if (REG_P (op0
) && GET_MODE_SIZE (mode
) < GET_MODE_SIZE (DImode
))
136 if (satisfies_constraint_Is20 (op1
))
137 *total
= COSTS_N_INSNS (1) - 1;
139 *total
= COSTS_N_INSNS (2);
148 /* la instruction. */
149 if (REG_P (op0
) && GET_MODE_SIZE (mode
) < GET_MODE_SIZE (DImode
))
150 *total
= COSTS_N_INSNS (1) - 1;
167 if (GET_MODE_SIZE (mode
) >= GET_MODE_SIZE (DImode
))
169 else if (GET_CODE (op0
) == MULT
|| GET_CODE (op0
) == LSHIFTRT
170 || GET_CODE (op1
) == MULT
|| GET_CODE (op1
) == LSHIFTRT
)
172 *total
= COSTS_N_INSNS (2);
174 else if ((GET_CODE (op1
) == CONST_INT
175 && satisfies_constraint_Is15 (op1
))
177 /* ADD instructions */
178 *total
= COSTS_N_INSNS (1);
180 /* ADD instructions: IMM out of range. */
181 *total
= COSTS_N_INSNS (2);
188 if (GET_MODE_SIZE (mode
) >= GET_MODE_SIZE (DImode
))
190 else if (GET_CODE (op0
) == MULT
|| GET_CODE (op0
) == LSHIFTRT
191 || GET_CODE (op1
) == MULT
|| GET_CODE (op1
) == LSHIFTRT
)
193 *total
= COSTS_N_INSNS (2);
194 else if ((GET_CODE (op0
) == CONST_INT
195 && satisfies_constraint_Is15 (op0
))
197 /* SUB instructions */
198 *total
= COSTS_N_INSNS (1);
200 /* SUB instructions: IMM out of range. */
201 *total
= COSTS_N_INSNS (2);
205 /* TRUNCATE and AND behavior is same. */
206 *total
= COSTS_N_INSNS (1);
215 if (NDS32_EXT_DSP_P ())
217 /* We prefer (and (ior) (ior)) than (ior (and) (and)) for
218 synthetize pk** and insb instruction. */
219 if (code
== AND
&& GET_CODE (op0
) == IOR
&& GET_CODE (op1
) == IOR
)
220 return COSTS_N_INSNS (1);
222 if (code
== IOR
&& GET_CODE (op0
) == AND
&& GET_CODE (op1
) == AND
)
223 return COSTS_N_INSNS (10);
226 if (GET_MODE_SIZE (mode
) >= GET_MODE_SIZE (DImode
))
228 else if (GET_CODE (op0
) == ASHIFT
|| GET_CODE (op0
) == LSHIFTRT
)
229 *total
= COSTS_N_INSNS (2);
230 else if ((GET_CODE (op1
) == CONST_INT
231 && satisfies_constraint_Iu15 (op1
))
233 /* AND, OR, XOR instructions */
234 *total
= COSTS_N_INSNS (1);
235 else if (code
== AND
|| GET_CODE (op0
) == NOT
)
236 /* BITC instruction */
237 *total
= COSTS_N_INSNS (1);
239 /* AND, OR, XOR instructions: IMM out of range. */
240 *total
= COSTS_N_INSNS (2);
244 if (GET_MODE (x
) == DImode
245 || GET_CODE (XEXP (x
, 1)) == SIGN_EXTEND
246 || GET_CODE (XEXP (x
, 1)) == ZERO_EXTEND
)
247 /* MUL instructions */
248 *total
= COSTS_N_INSNS (1);
249 else if (GET_MODE_SIZE (mode
) >= GET_MODE_SIZE (DImode
))
251 else if (outer_code
== PLUS
|| outer_code
== MINUS
)
252 *total
= COSTS_N_INSNS (2);
253 else if ((GET_CODE (XEXP (x
, 1)) == CONST_INT
254 && satisfies_constraint_Iu05 (XEXP (x
, 1)))
255 || REG_P (XEXP (x
, 1)))
256 /* MUL instructions */
257 *total
= COSTS_N_INSNS (1);
259 /* MUL instructions: IMM out of range. */
260 *total
= COSTS_N_INSNS (2);
263 *total
+= COSTS_N_INSNS (4);
268 if (GET_MODE_SIZE (mode
) >= GET_MODE_SIZE (DImode
))
270 else if (outer_code
== PLUS
|| outer_code
== MINUS
271 || outer_code
== AND
|| outer_code
== IOR
272 || outer_code
== XOR
)
273 *total
= COSTS_N_INSNS (2);
274 else if ((GET_CODE (XEXP (x
, 1)) == CONST_INT
275 && satisfies_constraint_Iu05 (XEXP (x
, 1)))
276 || REG_P (XEXP (x
, 1)))
277 /* SRL instructions */
278 *total
= COSTS_N_INSNS (1);
280 /* SRL instructions: IMM out of range. */
281 *total
= COSTS_N_INSNS (2);
285 if (GET_MODE_SIZE (mode
) >= GET_MODE_SIZE (DImode
))
287 else if (outer_code
== AND
|| outer_code
== IOR
288 || outer_code
== XOR
)
289 *total
= COSTS_N_INSNS (2);
290 else if ((GET_CODE (XEXP (x
, 1)) == CONST_INT
291 && satisfies_constraint_Iu05 (XEXP (x
, 1)))
292 || REG_P (XEXP (x
, 1)))
293 /* SLL instructions */
294 *total
= COSTS_N_INSNS (1);
296 /* SLL instructions: IMM out of range. */
297 *total
= COSTS_N_INSNS (2);
302 if (GET_MODE_SIZE (mode
) >= GET_MODE_SIZE (DImode
))
304 else if ((GET_CODE (XEXP (x
, 1)) == CONST_INT
305 && satisfies_constraint_Iu05 (XEXP (x
, 1)))
306 || REG_P (XEXP (x
, 1)))
307 /* ROTR, SLL instructions */
308 *total
= COSTS_N_INSNS (1);
310 /* ROTR, SLL instructions: IMM out of range. */
311 *total
= COSTS_N_INSNS (2);
316 if (outer_code
== SET
)
318 if ((GET_CODE (XEXP (x
, 1)) == CONST_INT
319 && satisfies_constraint_Iu15 (XEXP (x
, 1)))
320 || REG_P (XEXP (x
, 1)))
321 /* SLT, SLTI instructions */
322 *total
= COSTS_N_INSNS (1);
324 /* SLT, SLT instructions: IMM out of range. */
325 *total
= COSTS_N_INSNS (2);
329 *total
= COSTS_N_INSNS (2);
338 *total
= COSTS_N_INSNS (2);
342 if (GET_CODE (XEXP (x
, 1)) == LABEL_REF
)
344 *total
= COSTS_N_INSNS (2);
346 /* cmovz, cmovn instructions */
347 *total
= COSTS_N_INSNS (1);
351 if (outer_code
== IF_THEN_ELSE
)
353 *total
= COSTS_N_INSNS (2);
355 *total
= COSTS_N_INSNS (1);
360 if (MEM_P (XEXP (x
, 0)))
361 /* Using memory access. */
362 *total
= COSTS_N_INSNS (1);
364 /* Zero extend and sign extend instructions. */
365 *total
= COSTS_N_INSNS (1);
370 *total
= COSTS_N_INSNS (1);
377 *total
= COSTS_N_INSNS (20);
381 *total
= COSTS_N_INSNS (2);
389 *total
= COSTS_N_INSNS (1);
391 *total
= COSTS_N_INSNS (3);
394 *total
= COSTS_N_INSNS (1);
398 *total
= COSTS_N_INSNS (3);
404 nds32_rtx_costs_size_prefer (rtx x
,
407 int opno ATTRIBUTE_UNUSED
,
410 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
411 We treat it as 4-byte cost for each instruction
412 under code size consideration. */
416 /* For 'SET' rtx, we need to return false
417 so that it can recursively calculate costs. */
421 /* Used in combine.c as a marker. */
426 /* All instructions involving constant operation
427 need to be considered for cost evaluation. */
428 if (outer_code
== SET
)
430 /* (set X imm5s), use movi55, 2-byte cost.
431 (set X imm20s), use movi, 4-byte cost.
432 (set X BIG_INT), use sethi/ori, 8-byte cost. */
433 if (satisfies_constraint_Is05 (x
))
434 *total
= insn_size_16bit
;
435 else if (satisfies_constraint_Is20 (x
))
436 *total
= insn_size_32bit
;
438 *total
= insn_size_32bit
* 2;
440 else if (outer_code
== PLUS
|| outer_code
== MINUS
)
442 /* Possible addi333/subi333 or subi45/addi45, 2-byte cost.
443 General case, cost 1 instruction with 4-byte. */
444 if (satisfies_constraint_Iu05 (x
))
445 *total
= insn_size_16bit
;
447 *total
= insn_size_32bit
;
449 else if (outer_code
== ASHIFT
)
451 /* Possible slli333, 2-byte cost.
452 General case, cost 1 instruction with 4-byte. */
453 if (satisfies_constraint_Iu03 (x
))
454 *total
= insn_size_16bit
;
456 *total
= insn_size_32bit
;
458 else if (outer_code
== ASHIFTRT
|| outer_code
== LSHIFTRT
)
460 /* Possible srai45 or srli45, 2-byte cost.
461 General case, cost 1 instruction with 4-byte. */
462 if (satisfies_constraint_Iu05 (x
))
463 *total
= insn_size_16bit
;
465 *total
= insn_size_32bit
;
469 /* For other cases, simply set it 4-byte cost. */
470 *total
= insn_size_32bit
;
475 /* It requires high part and low part processing, set it 8-byte cost. */
476 *total
= insn_size_32bit
* 2;
481 *total
= insn_size_32bit
* 2;
485 /* For other cases, generally we set it 4-byte cost
486 and stop resurively traversing. */
487 *total
= insn_size_32bit
;
495 nds32_init_rtx_costs (void)
497 rtx_cost_model
.speed_prefer
= nds32_rtx_costs_speed_prefer
;
498 rtx_cost_model
.size_prefer
= nds32_rtx_costs_size_prefer
;
506 /* This target hook describes the relative costs of RTL expressions.
507 Return 'true' when all subexpressions of x have been processed.
508 Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
509 Refer to gcc/rtlanal.c for more information. */
511 nds32_rtx_costs_impl (rtx x
,
512 machine_mode mode ATTRIBUTE_UNUSED
,
518 int code
= GET_CODE (x
);
520 /* According to 'speed', use suitable cost model section. */
522 return rtx_cost_model
.speed_prefer(x
, code
, outer_code
, opno
, total
);
524 return rtx_cost_model
.size_prefer(x
, code
, outer_code
, opno
, total
);
528 int nds32_address_cost_speed_prefer (rtx address
)
533 code
= GET_CODE (address
);
540 /* We encourage that rtx contains
541 POST_MODIFY/POST_INC/POST_DEC behavior. */
542 return COSTS_N_INSNS (1) - 2;
545 /* We can have gp-relative load/store for symbol_ref.
546 Have it 4-byte cost. */
547 return COSTS_N_INSNS (2);
550 /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
551 Have it 4-byte cost. */
552 return COSTS_N_INSNS (2);
555 /* Simply return 4-byte costs. */
556 return COSTS_N_INSNS (1) - 2;
559 /* We do not need to check if the address is a legitimate address,
560 because this hook is never called with an invalid address.
561 But we better check the range of
562 const_int value for cost, if it exists. */
563 plus0
= XEXP (address
, 0);
564 plus1
= XEXP (address
, 1);
566 if (REG_P (plus0
) && CONST_INT_P (plus1
))
567 return COSTS_N_INSNS (1) - 2;
568 else if (ARITHMETIC_P (plus0
) || ARITHMETIC_P (plus1
))
569 return COSTS_N_INSNS (1) - 1;
570 else if (REG_P (plus0
) && REG_P (plus1
))
571 return COSTS_N_INSNS (1);
573 /* For other 'plus' situation, make it cost 4-byte. */
574 return COSTS_N_INSNS (1);
580 return COSTS_N_INSNS (4);
584 int nds32_address_cost_speed_fwprop (rtx address
)
589 code
= GET_CODE (address
);
596 /* We encourage that rtx contains
597 POST_MODIFY/POST_INC/POST_DEC behavior. */
601 /* We can have gp-relative load/store for symbol_ref.
602 Have it 4-byte cost. */
603 return COSTS_N_INSNS (2);
606 /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
607 Have it 4-byte cost. */
608 return COSTS_N_INSNS (2);
611 /* Simply return 4-byte costs. */
612 return COSTS_N_INSNS (1);
615 /* We do not need to check if the address is a legitimate address,
616 because this hook is never called with an invalid address.
617 But we better check the range of
618 const_int value for cost, if it exists. */
619 plus0
= XEXP (address
, 0);
620 plus1
= XEXP (address
, 1);
622 if (REG_P (plus0
) && CONST_INT_P (plus1
))
624 /* If it is possible to be lwi333/swi333 form,
625 make it 2-byte cost. */
626 if (satisfies_constraint_Iu03 (plus1
))
627 return (COSTS_N_INSNS (1) - 2);
629 return COSTS_N_INSNS (1);
631 if (ARITHMETIC_P (plus0
) || ARITHMETIC_P (plus1
))
632 return COSTS_N_INSNS (1) - 2;
633 else if (REG_P (plus0
) && REG_P (plus1
))
634 return COSTS_N_INSNS (1);
636 /* For other 'plus' situation, make it cost 4-byte. */
637 return COSTS_N_INSNS (1);
643 return COSTS_N_INSNS (4);
647 int nds32_address_cost_size_prefer (rtx address
)
652 code
= GET_CODE (address
);
659 /* We encourage that rtx contains
660 POST_MODIFY/POST_INC/POST_DEC behavior. */
664 /* We can have gp-relative load/store for symbol_ref.
665 Have it 4-byte cost. */
666 return COSTS_N_INSNS (2);
669 /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
670 Have it 4-byte cost. */
671 return COSTS_N_INSNS (2);
674 /* Simply return 4-byte costs. */
675 return COSTS_N_INSNS (1) - 1;
678 /* We do not need to check if the address is a legitimate address,
679 because this hook is never called with an invalid address.
680 But we better check the range of
681 const_int value for cost, if it exists. */
682 plus0
= XEXP (address
, 0);
683 plus1
= XEXP (address
, 1);
685 if (REG_P (plus0
) && CONST_INT_P (plus1
))
687 /* If it is possible to be lwi333/swi333 form,
688 make it 2-byte cost. */
689 if (satisfies_constraint_Iu03 (plus1
))
690 return (COSTS_N_INSNS (1) - 2);
692 return COSTS_N_INSNS (1) - 1;
695 /* (plus (reg) (mult (reg) (const))) */
696 if (ARITHMETIC_P (plus0
) || ARITHMETIC_P (plus1
))
697 return (COSTS_N_INSNS (1) - 1);
699 /* For other 'plus' situation, make it cost 4-byte. */
700 return COSTS_N_INSNS (1);
706 return COSTS_N_INSNS (4);
710 int nds32_address_cost_impl (rtx address
,
711 machine_mode mode ATTRIBUTE_UNUSED
,
712 addr_space_t as ATTRIBUTE_UNUSED
,
717 if (current_pass
->tv_id
== TV_FWPROP
)
718 return nds32_address_cost_speed_fwprop (address
);
720 return nds32_address_cost_speed_prefer (address
);
723 return nds32_address_cost_size_prefer (address
);
726 /* ------------------------------------------------------------------------ */