[NDS32] Rewrite cost model.
[official-gcc.git] / gcc / config / nds32 / nds32-cost.c
blob979000fcc45b255a45a32ee725af56b43fcc95de
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
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "memmodel.h"
33 #include "tm_p.h"
34 #include "optabs.h" /* For GEN_FCN. */
35 #include "recog.h"
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;
53 static bool
54 nds32_rtx_costs_speed_prefer (rtx x ATTRIBUTE_UNUSED,
55 int code,
56 int outer_code ATTRIBUTE_UNUSED,
57 int opno ATTRIBUTE_UNUSED,
58 int *total)
60 rtx op0;
61 rtx op1;
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));
66 switch (code)
68 case USE:
69 /* Used in combine.c as a marker. */
70 *total = 0;
71 return true;
73 case CONST_INT:
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;
90 else
91 *total = COSTS_N_INSNS (1);
92 return true;
94 case CONST:
95 case LO_SUM:
96 case HIGH:
97 case SYMBOL_REF:
98 *total = COSTS_N_INSNS (1);
99 return true;
101 case MEM:
102 *total = COSTS_N_INSNS (1);
103 return true;
105 case SET:
106 op0 = SET_DEST (x);
107 op1 = SET_SRC (x);
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))
114 case REG:
115 case SUBREG:
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);
120 else
121 *total = cost;
122 return true;
124 case MEM:
125 /* Load instructions. */
126 if (REG_P (op0) && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (DImode))
127 *total = COSTS_N_INSNS (1);
128 else
129 *total = cost;
130 return true;
132 case CONST_INT:
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;
138 else
139 *total = COSTS_N_INSNS (2);
141 else
142 *total = cost;
143 return true;
145 case CONST:
146 case SYMBOL_REF:
147 case LABEL_REF:
148 /* la instruction. */
149 if (REG_P (op0) && GET_MODE_SIZE (mode) < GET_MODE_SIZE (DImode))
150 *total = COSTS_N_INSNS (1) - 1;
151 else
152 *total = cost;
153 return true;
154 case VEC_SELECT:
155 *total = cost;
156 return true;
158 default:
159 *total = cost;
160 return true;
163 case PLUS:
164 op0 = XEXP (x, 0);
165 op1 = XEXP (x, 1);
167 if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
168 *total = cost;
169 else if (GET_CODE (op0) == MULT || GET_CODE (op0) == LSHIFTRT
170 || GET_CODE (op1) == MULT || GET_CODE (op1) == LSHIFTRT)
171 /* ALU_SHIFT */
172 *total = COSTS_N_INSNS (2);
174 else if ((GET_CODE (op1) == CONST_INT
175 && satisfies_constraint_Is15 (op1))
176 || REG_P (op1))
177 /* ADD instructions */
178 *total = COSTS_N_INSNS (1);
179 else
180 /* ADD instructions: IMM out of range. */
181 *total = COSTS_N_INSNS (2);
182 return true;
184 case MINUS:
185 op0 = XEXP (x, 0);
186 op1 = XEXP (x, 1);
188 if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
189 *total = cost;
190 else if (GET_CODE (op0) == MULT || GET_CODE (op0) == LSHIFTRT
191 || GET_CODE (op1) == MULT || GET_CODE (op1) == LSHIFTRT)
192 /* ALU_SHIFT */
193 *total = COSTS_N_INSNS (2);
194 else if ((GET_CODE (op0) == CONST_INT
195 && satisfies_constraint_Is15 (op0))
196 || REG_P (op0))
197 /* SUB instructions */
198 *total = COSTS_N_INSNS (1);
199 else
200 /* SUB instructions: IMM out of range. */
201 *total = COSTS_N_INSNS (2);
202 return true;
204 case TRUNCATE:
205 /* TRUNCATE and AND behavior is same. */
206 *total = COSTS_N_INSNS (1);
207 return true;
209 case AND:
210 case IOR:
211 case XOR:
212 op0 = XEXP (x, 0);
213 op1 = XEXP (x, 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))
227 *total = cost;
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))
232 || REG_P (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);
238 else
239 /* AND, OR, XOR instructions: IMM out of range. */
240 *total = COSTS_N_INSNS (2);
241 return true;
243 case MULT:
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))
250 *total = cost;
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);
258 else
259 /* MUL instructions: IMM out of range. */
260 *total = COSTS_N_INSNS (2);
262 if (TARGET_MUL_SLOW)
263 *total += COSTS_N_INSNS (4);
265 return true;
267 case LSHIFTRT:
268 if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
269 *total = cost;
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);
279 else
280 /* SRL instructions: IMM out of range. */
281 *total = COSTS_N_INSNS (2);
282 return true;
284 case ASHIFT:
285 if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
286 *total = cost;
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);
295 else
296 /* SLL instructions: IMM out of range. */
297 *total = COSTS_N_INSNS (2);
298 return true;
300 case ASHIFTRT:
301 case ROTATERT:
302 if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
303 *total = cost;
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);
309 else
310 /* ROTR, SLL instructions: IMM out of range. */
311 *total = COSTS_N_INSNS (2);
312 return true;
314 case LT:
315 case LTU:
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);
323 else
324 /* SLT, SLT instructions: IMM out of range. */
325 *total = COSTS_N_INSNS (2);
327 else
328 /* branch */
329 *total = COSTS_N_INSNS (2);
330 return true;
332 case EQ:
333 case NE:
334 case GE:
335 case LE:
336 case GT:
337 /* branch */
338 *total = COSTS_N_INSNS (2);
339 return true;
341 case IF_THEN_ELSE:
342 if (GET_CODE (XEXP (x, 1)) == LABEL_REF)
343 /* branch */
344 *total = COSTS_N_INSNS (2);
345 else
346 /* cmovz, cmovn instructions */
347 *total = COSTS_N_INSNS (1);
348 return true;
350 case LABEL_REF:
351 if (outer_code == IF_THEN_ELSE)
352 /* branch */
353 *total = COSTS_N_INSNS (2);
354 else
355 *total = COSTS_N_INSNS (1);
356 return true;
358 case ZERO_EXTEND:
359 case SIGN_EXTEND:
360 if (MEM_P (XEXP (x, 0)))
361 /* Using memory access. */
362 *total = COSTS_N_INSNS (1);
363 else
364 /* Zero extend and sign extend instructions. */
365 *total = COSTS_N_INSNS (1);
366 return true;
368 case NEG:
369 case NOT:
370 *total = COSTS_N_INSNS (1);
371 return true;
373 case DIV:
374 case UDIV:
375 case MOD:
376 case UMOD:
377 *total = COSTS_N_INSNS (20);
378 return true;
380 case CALL:
381 *total = COSTS_N_INSNS (2);
382 return true;
384 case CLZ:
385 case SMIN:
386 case SMAX:
387 case ZERO_EXTRACT:
388 if (TARGET_EXT_PERF)
389 *total = COSTS_N_INSNS (1);
390 else
391 *total = COSTS_N_INSNS (3);
392 return true;
393 case VEC_SELECT:
394 *total = COSTS_N_INSNS (1);
395 return true;
397 default:
398 *total = COSTS_N_INSNS (3);
399 return true;
403 static bool
404 nds32_rtx_costs_size_prefer (rtx x,
405 int code,
406 int outer_code,
407 int opno ATTRIBUTE_UNUSED,
408 int *total)
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. */
413 switch (code)
415 case SET:
416 /* For 'SET' rtx, we need to return false
417 so that it can recursively calculate costs. */
418 return false;
420 case USE:
421 /* Used in combine.c as a marker. */
422 *total = 0;
423 break;
425 case CONST_INT:
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;
437 else
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;
446 else
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;
455 else
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;
464 else
465 *total = insn_size_32bit;
467 else
469 /* For other cases, simply set it 4-byte cost. */
470 *total = insn_size_32bit;
472 break;
474 case CONST_DOUBLE:
475 /* It requires high part and low part processing, set it 8-byte cost. */
476 *total = insn_size_32bit * 2;
477 break;
479 case CONST:
480 case SYMBOL_REF:
481 *total = insn_size_32bit * 2;
482 break;
484 default:
485 /* For other cases, generally we set it 4-byte cost
486 and stop resurively traversing. */
487 *total = insn_size_32bit;
488 break;
491 return true;
494 void
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;
500 if (TARGET_16_BIT)
501 insn_size_16bit = 2;
502 else
503 insn_size_16bit = 4;
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. */
510 bool
511 nds32_rtx_costs_impl (rtx x,
512 machine_mode mode ATTRIBUTE_UNUSED,
513 int outer_code,
514 int opno,
515 int *total,
516 bool speed)
518 int code = GET_CODE (x);
520 /* According to 'speed', use suitable cost model section. */
521 if (speed)
522 return rtx_cost_model.speed_prefer(x, code, outer_code, opno, total);
523 else
524 return rtx_cost_model.size_prefer(x, code, outer_code, opno, total);
528 int nds32_address_cost_speed_prefer (rtx address)
530 rtx plus0, plus1;
531 enum rtx_code code;
533 code = GET_CODE (address);
535 switch (code)
537 case POST_MODIFY:
538 case POST_INC:
539 case POST_DEC:
540 /* We encourage that rtx contains
541 POST_MODIFY/POST_INC/POST_DEC behavior. */
542 return COSTS_N_INSNS (1) - 2;
544 case SYMBOL_REF:
545 /* We can have gp-relative load/store for symbol_ref.
546 Have it 4-byte cost. */
547 return COSTS_N_INSNS (2);
549 case CONST:
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);
554 case REG:
555 /* Simply return 4-byte costs. */
556 return COSTS_N_INSNS (1) - 2;
558 case PLUS:
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);
576 default:
577 break;
580 return COSTS_N_INSNS (4);
584 int nds32_address_cost_speed_fwprop (rtx address)
586 rtx plus0, plus1;
587 enum rtx_code code;
589 code = GET_CODE (address);
591 switch (code)
593 case POST_MODIFY:
594 case POST_INC:
595 case POST_DEC:
596 /* We encourage that rtx contains
597 POST_MODIFY/POST_INC/POST_DEC behavior. */
598 return 0;
600 case SYMBOL_REF:
601 /* We can have gp-relative load/store for symbol_ref.
602 Have it 4-byte cost. */
603 return COSTS_N_INSNS (2);
605 case CONST:
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);
610 case REG:
611 /* Simply return 4-byte costs. */
612 return COSTS_N_INSNS (1);
614 case PLUS:
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);
628 else
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);
639 default:
640 break;
643 return COSTS_N_INSNS (4);
647 int nds32_address_cost_size_prefer (rtx address)
649 rtx plus0, plus1;
650 enum rtx_code code;
652 code = GET_CODE (address);
654 switch (code)
656 case POST_MODIFY:
657 case POST_INC:
658 case POST_DEC:
659 /* We encourage that rtx contains
660 POST_MODIFY/POST_INC/POST_DEC behavior. */
661 return 0;
663 case SYMBOL_REF:
664 /* We can have gp-relative load/store for symbol_ref.
665 Have it 4-byte cost. */
666 return COSTS_N_INSNS (2);
668 case CONST:
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);
673 case REG:
674 /* Simply return 4-byte costs. */
675 return COSTS_N_INSNS (1) - 1;
677 case PLUS:
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);
691 else
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);
702 default:
703 break;
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,
713 bool speed_p)
715 if (speed_p)
717 if (current_pass->tv_id == TV_FWPROP)
718 return nds32_address_cost_speed_fwprop (address);
719 else
720 return nds32_address_cost_speed_prefer (address);
722 else
723 return nds32_address_cost_size_prefer (address);
726 /* ------------------------------------------------------------------------ */