]>
Commit | Line | Data |
---|---|---|
c0c935b5 | 1 | /* Subroutines used for calculate rtx costs of Andes NDS32 cpu for GNU compiler |
8d9254fc | 2 | Copyright (C) 2012-2020 Free Software Foundation, Inc. |
c0c935b5 CJW |
3 | Contributed by Andes Technology Corporation. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
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. | |
11 | ||
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. | |
16 | ||
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/>. */ | |
89a4b547 CJW |
20 | |
21 | /* ------------------------------------------------------------------------ */ | |
22 | ||
8fcc61f8 RS |
23 | #define IN_TARGET_CODE 1 |
24 | ||
89a4b547 CJW |
25 | #include "config.h" |
26 | #include "system.h" | |
27 | #include "coretypes.h" | |
c7131fb2 | 28 | #include "backend.h" |
e11c4407 | 29 | #include "target.h" |
c7131fb2 | 30 | #include "rtl.h" |
e11c4407 | 31 | #include "tree.h" |
4d0cdd0c | 32 | #include "memmodel.h" |
89a4b547 | 33 | #include "tm_p.h" |
89a4b547 | 34 | #include "optabs.h" /* For GEN_FCN. */ |
e11c4407 AM |
35 | #include "recog.h" |
36 | #include "tm-constrs.h" | |
19c93809 | 37 | #include "tree-pass.h" |
89a4b547 CJW |
38 | |
39 | /* ------------------------------------------------------------------------ */ | |
40 | ||
19c93809 | 41 | typedef bool (*rtx_cost_func) (rtx, int, int, int, int*); |
e548c9df | 42 | |
19c93809 KC |
43 | struct rtx_cost_model_t { |
44 | rtx_cost_func speed_prefer; | |
45 | rtx_cost_func size_prefer; | |
46 | }; | |
89a4b547 | 47 | |
19c93809 | 48 | static rtx_cost_model_t rtx_cost_model; |
89a4b547 | 49 | |
19c93809 KC |
50 | static int insn_size_16bit; /* Initial at nds32_init_rtx_costs. */ |
51 | static const int insn_size_32bit = 4; | |
52 | ||
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) | |
59 | { | |
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)); | |
89a4b547 | 65 | |
89a4b547 CJW |
66 | switch (code) |
67 | { | |
89a4b547 CJW |
68 | case USE: |
69 | /* Used in combine.c as a marker. */ | |
70 | *total = 0; | |
19c93809 KC |
71 | return true; |
72 | ||
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; | |
93 | ||
94 | case CONST: | |
95 | case LO_SUM: | |
96 | case HIGH: | |
97 | case SYMBOL_REF: | |
98 | *total = COSTS_N_INSNS (1); | |
99 | return true; | |
100 | ||
101 | case MEM: | |
102 | *total = COSTS_N_INSNS (1); | |
103 | return true; | |
104 | ||
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)); | |
111 | ||
112 | switch (GET_CODE (op1)) | |
113 | { | |
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; | |
123 | ||
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; | |
131 | ||
132 | case CONST_INT: | |
133 | /* movi instruction. */ | |
134 | if (REG_P (op0) && GET_MODE_SIZE (mode) < GET_MODE_SIZE (DImode)) | |
135 | { | |
136 | if (satisfies_constraint_Is20 (op1)) | |
137 | *total = COSTS_N_INSNS (1) - 1; | |
138 | else | |
139 | *total = COSTS_N_INSNS (2); | |
140 | } | |
141 | else | |
142 | *total = cost; | |
143 | return true; | |
144 | ||
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; | |
157 | ||
158 | default: | |
159 | *total = cost; | |
160 | return true; | |
161 | } | |
162 | ||
163 | case PLUS: | |
164 | op0 = XEXP (x, 0); | |
165 | op1 = XEXP (x, 1); | |
166 | ||
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); | |
173 | ||
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; | |
183 | ||
184 | case MINUS: | |
185 | op0 = XEXP (x, 0); | |
186 | op1 = XEXP (x, 1); | |
187 | ||
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; | |
203 | ||
204 | case TRUNCATE: | |
205 | /* TRUNCATE and AND behavior is same. */ | |
206 | *total = COSTS_N_INSNS (1); | |
207 | return true; | |
208 | ||
209 | case AND: | |
210 | case IOR: | |
211 | case XOR: | |
212 | op0 = XEXP (x, 0); | |
213 | op1 = XEXP (x, 1); | |
214 | ||
215 | if (NDS32_EXT_DSP_P ()) | |
216 | { | |
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); | |
221 | ||
222 | if (code == IOR && GET_CODE (op0) == AND && GET_CODE (op1) == AND) | |
223 | return COSTS_N_INSNS (10); | |
224 | } | |
225 | ||
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; | |
89a4b547 CJW |
242 | |
243 | case MULT: | |
19c93809 KC |
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); | |
261 | ||
262 | if (TARGET_MUL_SLOW) | |
263 | *total += COSTS_N_INSNS (4); | |
264 | ||
265 | return true; | |
266 | ||
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; | |
283 | ||
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; | |
299 | ||
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; | |
313 | ||
314 | case LT: | |
315 | case LTU: | |
316 | if (outer_code == SET) | |
317 | { | |
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); | |
326 | } | |
327 | else | |
328 | /* branch */ | |
329 | *total = COSTS_N_INSNS (2); | |
330 | return true; | |
331 | ||
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; | |
340 | ||
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; | |
349 | ||
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; | |
357 | ||
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; | |
367 | ||
368 | case NEG: | |
369 | case NOT: | |
89a4b547 | 370 | *total = COSTS_N_INSNS (1); |
19c93809 | 371 | return true; |
89a4b547 CJW |
372 | |
373 | case DIV: | |
374 | case UDIV: | |
375 | case MOD: | |
376 | case UMOD: | |
19c93809 KC |
377 | *total = COSTS_N_INSNS (20); |
378 | return true; | |
89a4b547 | 379 | |
19c93809 KC |
380 | case CALL: |
381 | *total = COSTS_N_INSNS (2); | |
382 | return true; | |
383 | ||
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: | |
89a4b547 | 394 | *total = COSTS_N_INSNS (1); |
19c93809 | 395 | return true; |
89a4b547 | 396 | |
19c93809 KC |
397 | default: |
398 | *total = COSTS_N_INSNS (3); | |
399 | return true; | |
400 | } | |
401 | } | |
89a4b547 | 402 | |
19c93809 KC |
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) | |
409 | { | |
89a4b547 CJW |
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) | |
414 | { | |
415 | case SET: | |
416 | /* For 'SET' rtx, we need to return false | |
8a498f99 | 417 | so that it can recursively calculate costs. */ |
89a4b547 CJW |
418 | return false; |
419 | ||
420 | case USE: | |
421 | /* Used in combine.c as a marker. */ | |
422 | *total = 0; | |
423 | break; | |
424 | ||
425 | case CONST_INT: | |
426 | /* All instructions involving constant operation | |
8a498f99 | 427 | need to be considered for cost evaluation. */ |
89a4b547 CJW |
428 | if (outer_code == SET) |
429 | { | |
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)) | |
19c93809 | 434 | *total = insn_size_16bit; |
89a4b547 | 435 | else if (satisfies_constraint_Is20 (x)) |
19c93809 | 436 | *total = insn_size_32bit; |
89a4b547 | 437 | else |
19c93809 | 438 | *total = insn_size_32bit * 2; |
89a4b547 CJW |
439 | } |
440 | else if (outer_code == PLUS || outer_code == MINUS) | |
441 | { | |
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)) | |
19c93809 | 445 | *total = insn_size_16bit; |
89a4b547 | 446 | else |
19c93809 | 447 | *total = insn_size_32bit; |
89a4b547 CJW |
448 | } |
449 | else if (outer_code == ASHIFT) | |
450 | { | |
451 | /* Possible slli333, 2-byte cost. | |
452 | General case, cost 1 instruction with 4-byte. */ | |
453 | if (satisfies_constraint_Iu03 (x)) | |
19c93809 | 454 | *total = insn_size_16bit; |
89a4b547 | 455 | else |
19c93809 | 456 | *total = insn_size_32bit; |
89a4b547 CJW |
457 | } |
458 | else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT) | |
459 | { | |
460 | /* Possible srai45 or srli45, 2-byte cost. | |
461 | General case, cost 1 instruction with 4-byte. */ | |
462 | if (satisfies_constraint_Iu05 (x)) | |
19c93809 | 463 | *total = insn_size_16bit; |
89a4b547 | 464 | else |
19c93809 | 465 | *total = insn_size_32bit; |
89a4b547 CJW |
466 | } |
467 | else | |
468 | { | |
469 | /* For other cases, simply set it 4-byte cost. */ | |
19c93809 | 470 | *total = insn_size_32bit; |
89a4b547 CJW |
471 | } |
472 | break; | |
473 | ||
474 | case CONST_DOUBLE: | |
475 | /* It requires high part and low part processing, set it 8-byte cost. */ | |
19c93809 KC |
476 | *total = insn_size_32bit * 2; |
477 | break; | |
478 | ||
479 | case CONST: | |
480 | case SYMBOL_REF: | |
481 | *total = insn_size_32bit * 2; | |
89a4b547 CJW |
482 | break; |
483 | ||
484 | default: | |
485 | /* For other cases, generally we set it 4-byte cost | |
19c93809 KC |
486 | and stop resurively traversing. */ |
487 | *total = insn_size_32bit; | |
89a4b547 CJW |
488 | break; |
489 | } | |
490 | ||
491 | return true; | |
492 | } | |
493 | ||
19c93809 KC |
494 | void |
495 | nds32_init_rtx_costs (void) | |
496 | { | |
497 | rtx_cost_model.speed_prefer = nds32_rtx_costs_speed_prefer; | |
498 | rtx_cost_model.size_prefer = nds32_rtx_costs_size_prefer; | |
499 | ||
500 | if (TARGET_16_BIT) | |
501 | insn_size_16bit = 2; | |
502 | else | |
503 | insn_size_16bit = 4; | |
504 | } | |
505 | ||
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) | |
517 | { | |
518 | int code = GET_CODE (x); | |
519 | ||
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); | |
525 | } | |
526 | ||
527 | ||
528 | int nds32_address_cost_speed_prefer (rtx address) | |
89a4b547 CJW |
529 | { |
530 | rtx plus0, plus1; | |
531 | enum rtx_code code; | |
532 | ||
533 | code = GET_CODE (address); | |
534 | ||
19c93809 KC |
535 | switch (code) |
536 | { | |
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; | |
543 | ||
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); | |
548 | ||
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); | |
553 | ||
554 | case REG: | |
555 | /* Simply return 4-byte costs. */ | |
556 | return COSTS_N_INSNS (1) - 2; | |
557 | ||
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); | |
565 | ||
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); | |
572 | ||
573 | /* For other 'plus' situation, make it cost 4-byte. */ | |
574 | return COSTS_N_INSNS (1); | |
575 | ||
576 | default: | |
577 | break; | |
578 | } | |
579 | ||
580 | return COSTS_N_INSNS (4); | |
89a4b547 | 581 | |
19c93809 | 582 | } |
89a4b547 | 583 | |
19c93809 KC |
584 | int nds32_address_cost_speed_fwprop (rtx address) |
585 | { | |
586 | rtx plus0, plus1; | |
587 | enum rtx_code code; | |
89a4b547 | 588 | |
19c93809 | 589 | code = GET_CODE (address); |
89a4b547 CJW |
590 | |
591 | switch (code) | |
592 | { | |
593 | case POST_MODIFY: | |
594 | case POST_INC: | |
595 | case POST_DEC: | |
596 | /* We encourage that rtx contains | |
8a498f99 | 597 | POST_MODIFY/POST_INC/POST_DEC behavior. */ |
89a4b547 CJW |
598 | return 0; |
599 | ||
600 | case SYMBOL_REF: | |
601 | /* We can have gp-relative load/store for symbol_ref. | |
8a498f99 | 602 | Have it 4-byte cost. */ |
19c93809 | 603 | return COSTS_N_INSNS (2); |
89a4b547 CJW |
604 | |
605 | case CONST: | |
606 | /* It is supposed to be the pattern (const (plus symbol_ref const_int)). | |
8a498f99 | 607 | Have it 4-byte cost. */ |
19c93809 | 608 | return COSTS_N_INSNS (2); |
89a4b547 CJW |
609 | |
610 | case REG: | |
611 | /* Simply return 4-byte costs. */ | |
612 | return COSTS_N_INSNS (1); | |
613 | ||
614 | case PLUS: | |
615 | /* We do not need to check if the address is a legitimate address, | |
8a498f99 CJW |
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. */ | |
89a4b547 CJW |
619 | plus0 = XEXP (address, 0); |
620 | plus1 = XEXP (address, 1); | |
621 | ||
622 | if (REG_P (plus0) && CONST_INT_P (plus1)) | |
8a498f99 | 623 | { |
89a4b547 CJW |
624 | /* If it is possible to be lwi333/swi333 form, |
625 | make it 2-byte cost. */ | |
19c93809 | 626 | if (satisfies_constraint_Iu03 (plus1)) |
89a4b547 CJW |
627 | return (COSTS_N_INSNS (1) - 2); |
628 | else | |
629 | return COSTS_N_INSNS (1); | |
630 | } | |
19c93809 KC |
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); | |
89a4b547 CJW |
635 | |
636 | /* For other 'plus' situation, make it cost 4-byte. */ | |
637 | return COSTS_N_INSNS (1); | |
638 | ||
639 | default: | |
640 | break; | |
641 | } | |
642 | ||
643 | return COSTS_N_INSNS (4); | |
644 | } | |
645 | ||
19c93809 KC |
646 | |
647 | int nds32_address_cost_size_prefer (rtx address) | |
648 | { | |
649 | rtx plus0, plus1; | |
650 | enum rtx_code code; | |
651 | ||
652 | code = GET_CODE (address); | |
653 | ||
654 | switch (code) | |
655 | { | |
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; | |
662 | ||
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); | |
667 | ||
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); | |
672 | ||
673 | case REG: | |
674 | /* Simply return 4-byte costs. */ | |
675 | return COSTS_N_INSNS (1) - 1; | |
676 | ||
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); | |
684 | ||
685 | if (REG_P (plus0) && CONST_INT_P (plus1)) | |
686 | { | |
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; | |
693 | } | |
694 | ||
695 | /* (plus (reg) (mult (reg) (const))) */ | |
696 | if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1)) | |
697 | return (COSTS_N_INSNS (1) - 1); | |
698 | ||
699 | /* For other 'plus' situation, make it cost 4-byte. */ | |
700 | return COSTS_N_INSNS (1); | |
701 | ||
702 | default: | |
703 | break; | |
704 | } | |
705 | ||
706 | return COSTS_N_INSNS (4); | |
707 | ||
708 | } | |
709 | ||
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) | |
714 | { | |
715 | if (speed_p) | |
716 | { | |
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); | |
721 | } | |
722 | else | |
723 | return nds32_address_cost_size_prefer (address); | |
724 | } | |
725 | ||
89a4b547 | 726 | /* ------------------------------------------------------------------------ */ |