libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / config / loongarch / loongarch-opts.cc
blob8408a70e5caeea768b52b03f17257fb06220a52b
1 /* Subroutines for loongarch-specific option handling.
2 Copyright (C) 2021-2024 Free Software Foundation, Inc.
3 Contributed by Loongson Ltd.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public 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 #define IN_TARGET_CODE 1
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "obstack.h"
28 #include "opts.h"
29 #include "diagnostic-core.h"
31 #include "loongarch-cpu.h"
32 #include "loongarch-opts.h"
33 #include "loongarch-str.h"
34 #include "loongarch-def.h"
36 /* Target configuration */
37 struct loongarch_target la_target;
39 /* RTL cost information */
40 const struct loongarch_rtx_cost_data *loongarch_cost;
42 /* ABI-related configuration. */
43 #define ABI_COUNT (sizeof(abi_priority_list)/sizeof(struct loongarch_abi))
44 static const struct loongarch_abi
45 abi_priority_list[] = {
46 {ABI_BASE_LP64D, ABI_EXT_BASE},
47 {ABI_BASE_LP64F, ABI_EXT_BASE},
48 {ABI_BASE_LP64S, ABI_EXT_BASE},
51 /* Initialize enabled_abi_types from TM_MULTILIB_LIST. */
52 #ifdef LA_DISABLE_MULTILIB
53 #define MULTILIB_LIST_LEN 1
54 #else
55 #define MULTILIB_LIST_LEN (sizeof (tm_multilib_list) / sizeof (int) / 2)
56 static const int tm_multilib_list[] = { TM_MULTILIB_LIST };
57 #endif
58 static int enabled_abi_types[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = { 0 };
60 #define isa_required(ABI) (abi_minimal_isa[(ABI).base][(ABI).ext])
62 static inline int
63 is_multilib_enabled (struct loongarch_abi abi)
65 return enabled_abi_types[abi.base][abi.ext];
68 static void
69 init_enabled_abi_types ()
71 #ifdef LA_DISABLE_MULTILIB
72 enabled_abi_types[DEFAULT_ABI_BASE][DEFAULT_ABI_EXT] = 1;
73 #else
74 int abi_base, abi_ext;
75 for (unsigned int i = 0; i < MULTILIB_LIST_LEN; i++)
77 abi_base = tm_multilib_list[i << 1];
78 abi_ext = tm_multilib_list[(i << 1) + 1];
79 enabled_abi_types[abi_base][abi_ext] = 1;
81 #endif
84 /* String processing. */
85 static struct obstack msg_obstack;
86 #define APPEND_STRING(STR) obstack_grow (&msg_obstack, STR, strlen(STR));
87 #define APPEND1(CH) obstack_1grow(&msg_obstack, CH);
89 static const char* abi_str (struct loongarch_abi abi);
90 static const char* isa_str (const struct loongarch_isa *isa, char separator);
91 static const char* arch_str (const struct loongarch_target *target);
92 static const char* multilib_enabled_abi_list ();
94 /* Misc */
95 static struct loongarch_abi isa_default_abi (const struct loongarch_isa *isa);
96 static int isa_base_compat_p (const struct loongarch_isa *set1,
97 const struct loongarch_isa *set2);
98 static int isa_fpu_compat_p (const struct loongarch_isa *set1,
99 const struct loongarch_isa *set2);
100 static int abi_compat_p (const struct loongarch_isa *isa,
101 struct loongarch_abi abi);
102 static int abi_default_cpu_arch (struct loongarch_abi abi,
103 struct loongarch_isa *isa);
104 static int default_tune_for_arch (int arch, int fallback);
106 /* Mandatory configure-time defaults. */
107 #ifndef DEFAULT_ABI_BASE
108 #error missing definition of DEFAULT_ABI_BASE in ${tm_defines}.
109 #endif
111 #ifndef DEFAULT_ABI_EXT
112 #error missing definition of DEFAULT_ABI_EXT in ${tm_defines}.
113 #endif
115 #ifndef DEFAULT_CPU_ARCH
116 #error missing definition of DEFAULT_CPU_ARCH in ${tm_defines}.
117 #endif
119 /* Optional configure-time defaults. */
120 #ifdef DEFAULT_CPU_TUNE
121 static int with_default_tune = 1;
122 #else
123 #define DEFAULT_CPU_TUNE -1
124 static int with_default_tune = 0;
125 #endif
127 #ifdef DEFAULT_ISA_EXT_FPU
128 static int with_default_fpu = 1;
129 #else
130 #define DEFAULT_ISA_EXT_FPU -1
131 static int with_default_fpu = 0;
132 #endif
134 #ifdef DEFAULT_ISA_EXT_SIMD
135 static int with_default_simd = 1;
136 #else
137 #define DEFAULT_ISA_EXT_SIMD -1
138 static int with_default_simd = 0;
139 #endif
142 /* Initialize loongarch_target from separate option variables. */
144 void
145 loongarch_init_target (struct loongarch_target *target,
146 int cpu_arch, int cpu_tune, int fpu, int simd,
147 int abi_base, int abi_ext, int cmodel,
148 int tls_dialect,
149 HOST_WIDE_INT isa_evolution,
150 HOST_WIDE_INT isa_evolution_set)
152 if (!target)
153 return;
154 target->cpu_arch = cpu_arch;
155 target->cpu_tune = cpu_tune;
156 target->isa.fpu = fpu;
157 target->isa.simd = simd;
158 target->isa.evolution = isa_evolution;
159 target->isa.evolution_set = isa_evolution_set;
160 target->abi.base = abi_base;
161 target->abi.ext = abi_ext;
162 target->cmodel = cmodel;
163 target->tls_dialect = tls_dialect;
167 /* Handle combinations of -m parameters
168 (see loongarch.opt and loongarch-opts.h). */
170 void
171 loongarch_config_target (struct loongarch_target *target,
172 struct loongarch_flags *flags,
173 int follow_multilib_list_p)
175 struct loongarch_target t;
177 if (!target)
178 return;
180 /* Initialization */
181 init_enabled_abi_types ();
182 obstack_init (&msg_obstack);
184 struct {
185 int arch, tune, fpu, simd, abi_base, abi_ext, cmodel,
186 tls_dialect, abi_flt;
187 } constrained = {
188 M_OPT_ABSENT (target->cpu_arch) ? 0 : 1,
189 M_OPT_ABSENT (target->cpu_tune) ? 0 : 1,
190 M_OPT_ABSENT (target->isa.fpu) ? 0 : 1,
191 M_OPT_ABSENT (target->isa.simd) ? 0 : 1,
192 M_OPT_ABSENT (target->abi.base) ? 0 : 1,
193 M_OPT_ABSENT (target->abi.ext) ? 0 : 1,
194 M_OPT_ABSENT (target->cmodel) ? 0 : 1,
195 M_OPT_ABSENT (target->tls_dialect) ? 0 : 1,
196 M_OPT_ABSENT (target->abi.base) ? 0 : 1,
199 int64_t isa_evolution = target->isa.evolution;
200 int64_t isa_evolution_set = target->isa.evolution_set;
202 /* 1. Target ABI */
203 if (constrained.abi_base)
204 t.abi.base = target->abi.base;
205 else
206 t.abi.base = DEFAULT_ABI_BASE;
208 t.abi.ext = constrained.abi_ext ? target->abi.ext : DEFAULT_ABI_EXT;
210 /* Process -m*-float flags */
211 if (flags && !M_OPT_ABSENT (flags->flt))
213 /* Modifying the original "target" here makes it easier to write the
214 t.isa.fpu assignment below, because otherwise there would be three
215 levels of precedence (-m*-float / -mfpu / -march) to be handled
216 (now the first two are merged). */
218 target->isa.fpu = flags->flt;
219 constrained.fpu = 1;
221 /* The target ISA is not ready yet, but (isa_required (t.abi)
222 + forced fpu) is enough for computing the forced base ABI. */
224 struct loongarch_isa force_isa = isa_required (t.abi);
225 force_isa.fpu = flags->flt;
227 struct loongarch_abi force_abi;
228 force_abi.base = isa_default_abi (&force_isa).base;
230 if (constrained.abi_base && constrained.abi_flt
231 && (t.abi.base != force_abi.base))
233 force_abi.ext = t.abi.ext;
234 inform (UNKNOWN_LOCATION,
235 "%<-m%s%> overrides %<-m%s=%s%>, adjusting ABI to %qs",
236 flags->flt_str, OPTSTR_ABI_BASE,
237 loongarch_abi_base_strings[t.abi.base],
238 abi_str (force_abi));
241 t.abi.base = force_abi.base;
242 constrained.abi_flt = 1;
245 #ifdef LA_DISABLE_MULTILIB
246 if (follow_multilib_list_p)
247 if (t.abi.base != DEFAULT_ABI_BASE || t.abi.ext != DEFAULT_ABI_EXT)
249 static const struct loongarch_abi default_abi
250 = {DEFAULT_ABI_BASE, DEFAULT_ABI_EXT};
252 warning (0, "ABI changed (%qs to %qs) while multilib is disabled",
253 abi_str (default_abi), abi_str (t.abi));
255 #endif
257 /* 2. Target CPU */
258 t.cpu_arch = constrained.arch ? target->cpu_arch : DEFAULT_CPU_ARCH;
260 /* If cpu_tune is not set using neither -mtune nor --with-tune,
261 the current cpu_arch is used as its default. */
262 t.cpu_tune = constrained.tune ? target->cpu_tune
263 : (constrained.arch
264 ? default_tune_for_arch (target->cpu_arch, with_default_tune
265 ? DEFAULT_CPU_TUNE : TUNE_GENERIC)
266 : (with_default_tune ? DEFAULT_CPU_TUNE
267 : default_tune_for_arch (DEFAULT_CPU_ARCH, TUNE_GENERIC)));
270 /* Handle -march/tune=native */
271 #ifdef __loongarch__
272 /* For native compilers, gather local CPU information
273 and fill the "ARCH_NATIVE/TUNE_NATIVE" index of arrays
274 defined in loongarch-cpu.c. */
276 fill_native_cpu_config (&t);
278 #else
279 if (t.cpu_arch == ARCH_NATIVE)
280 fatal_error (UNKNOWN_LOCATION,
281 "%qs does not work on a cross compiler",
282 "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
284 else if (t.cpu_tune == TUNE_NATIVE)
285 fatal_error (UNKNOWN_LOCATION,
286 "%qs does not work on a cross compiler",
287 "-m" OPTSTR_TUNE "=" STR_CPU_NATIVE);
288 #endif
290 /* Handle -march=abi-default */
291 if (t.cpu_arch == ARCH_ABI_DEFAULT)
293 t.cpu_arch = abi_default_cpu_arch (t.abi, &(t.isa));
294 loongarch_cpu_default_isa[t.cpu_arch] = t.isa;
297 /* 3. Target base ISA */
298 config_target_isa:
300 /* Get default ISA from "-march" or its default value. */
301 t.isa = loongarch_cpu_default_isa[t.cpu_arch];
303 /* Apply incremental changes. */
304 /* "-march=native" overrides the default FPU type. */
306 t.isa.fpu = constrained.fpu ? target->isa.fpu :
307 (constrained.arch ? t.isa.fpu :
308 (with_default_fpu ? DEFAULT_ISA_EXT_FPU : t.isa.fpu));
310 int simd_base = (constrained.arch ? t.isa.simd :
311 (with_default_simd ? DEFAULT_ISA_EXT_SIMD : t.isa.simd));
313 t.isa.simd = constrained.simd ? target->isa.simd : simd_base;
315 /* If fallback_lsx is set, using -mno-lasx would cause
316 a fall-back to -msimd=lsx instead of -msimd=none. */
318 int fallback_lsx = 0;
319 if (t.isa.simd == ISA_EXT_SIMD_LSX || simd_base != ISA_EXT_NONE)
320 fallback_lsx = 1;
322 /* apply -m[no-]lsx and -m[no-]lasx flags */
323 if (flags)
324 for (int i = 0; i < 2; i++)
326 switch (SX_FLAG_TYPE (flags->sx[i]))
328 case ISA_EXT_SIMD_LSX:
329 constrained.simd = 1;
331 if (flags->sx[i] > 0)
332 fallback_lsx = 1;
334 if (flags->sx[i] > 0 && t.isa.simd != ISA_EXT_SIMD_LASX)
335 t.isa.simd = ISA_EXT_SIMD_LSX;
336 else if (flags->sx[i] < 0)
337 t.isa.simd = ISA_EXT_NONE;
338 break;
340 case ISA_EXT_SIMD_LASX:
341 constrained.simd = 1;
342 /* If -mlsx or simd=lsx (msimd or march-default) was not
343 involved, do not fall back to simd=lsx. */
344 if (flags->sx[i] < 0 && t.isa.simd == ISA_EXT_SIMD_LASX)
345 t.isa.simd = fallback_lsx ? ISA_EXT_SIMD_LSX : ISA_EXT_NONE;
346 else if (flags->sx[i] > 0)
347 t.isa.simd = ISA_EXT_SIMD_LASX;
348 break;
350 case 0:
351 break;
353 default:
354 gcc_unreachable ();
358 /* All SIMD extensions imply a 64-bit FPU:
359 - silently adjust t.isa.fpu to "fpu64" if it is unconstrained.
360 - warn if -msingle-float / -msoft-float is on,
361 then disable SIMD extensions (done in driver)
362 - abort if -mfpu=0 / -mfpu=32 is forced. */
364 if (t.isa.simd != ISA_EXT_NONE && t.isa.fpu != ISA_EXT_FPU64)
366 if (!constrained.fpu)
368 /* As long as the arch-default "t.isa.simd" is set to non-zero
369 for an element "t" in loongarch_cpu_default_isa, "t.isa.fpu"
370 should be set to "ISA_EXT_FPU64" accordingly. Thus reaching
371 here must be the result of forcing -mlsx/-mlasx explicitly. */
372 gcc_assert (constrained.simd);
374 inform (UNKNOWN_LOCATION,
375 "enabling %qs promotes %<%s%s%> to %<%s%s%>",
376 loongarch_isa_ext_strings[t.isa.simd],
377 OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[t.isa.fpu],
378 OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[ISA_EXT_FPU64]);
380 t.isa.fpu = ISA_EXT_FPU64;
382 else if (flags && (flags->flt == ISA_EXT_NONE
383 || flags->flt == ISA_EXT_FPU32))
385 if (constrained.simd)
386 inform (UNKNOWN_LOCATION,
387 "%qs is disabled by %<-m%s%>, because it requires %<%s%s%>",
388 loongarch_isa_ext_strings[t.isa.simd], flags->flt_str,
389 OPTSTR_ISA_EXT_FPU,
390 loongarch_isa_ext_strings[ISA_EXT_FPU64]);
392 t.isa.simd = ISA_EXT_NONE;
394 else
396 /* -mfpu=0 / -mfpu=32 is set. */
397 if (constrained.simd)
398 fatal_error (UNKNOWN_LOCATION,
399 "%<-m%s=%s%> conflicts with %qs, "
400 "which requires %<%s%s%>",
401 OPTSTR_ISA_EXT_FPU,
402 loongarch_isa_ext_strings[t.isa.fpu],
403 loongarch_isa_ext_strings[t.isa.simd],
404 OPTSTR_ISA_EXT_FPU,
405 loongarch_isa_ext_strings[ISA_EXT_FPU64]);
407 /* Same as above. */
408 t.isa.simd = ISA_EXT_NONE;
412 /* Apply the ISA evolution feature switches from the user. */
413 HOST_WIDE_INT isa_evolution_orig = t.isa.evolution;
414 t.isa.evolution &= ~(~isa_evolution & isa_evolution_set);
415 t.isa.evolution |= isa_evolution & isa_evolution_set;
417 /* evolution_set means "what's different from the -march default". */
418 t.isa.evolution_set = isa_evolution_orig ^ t.isa.evolution;
420 /* 4. ABI-ISA compatibility */
421 /* Note:
422 - There IS a unique default -march value for each ABI type
423 (config.gcc: triplet -> abi -> default arch).
425 - If the base ABI is incompatible with the default arch,
426 try using the default -march it implies (and mark it
427 as "constrained" this time), then re-apply step 3. */
429 struct loongarch_abi abi_tmp;
430 const struct loongarch_isa* isa_min;
432 abi_tmp = t.abi;
433 isa_min = &isa_required (abi_tmp);
435 if (isa_base_compat_p (&t.isa, isa_min)); /* OK. */
436 else if (!constrained.arch)
438 /* Base architecture can only be implied by -march,
439 so we adjust that first if it is not constrained. */
440 int fallback_arch = abi_default_cpu_arch (t.abi, NULL);
442 if (t.cpu_arch == ARCH_NATIVE)
443 warning (0, "your native CPU architecture (%qs) "
444 "does not support %qs ABI, falling back to %<-m%s=%s%>",
445 arch_str (&t), abi_str (t.abi), OPTSTR_ARCH,
446 loongarch_arch_strings[fallback_arch]);
447 else
448 warning (0, "default CPU architecture (%qs) "
449 "does not support %qs ABI, falling back to %<-m%s=%s%>",
450 arch_str (&t), abi_str (t.abi), OPTSTR_ARCH,
451 loongarch_arch_strings[fallback_arch]);
453 t.cpu_arch = fallback_arch;
454 constrained.arch = 1;
455 goto config_target_isa;
457 else if (!constrained.abi_base)
459 /* If -march is given while -mabi is not,
460 try selecting another base ABI type. */
461 abi_tmp.base = isa_default_abi (&t.isa).base;
463 else
464 goto fatal;
466 if (isa_fpu_compat_p (&t.isa, isa_min)); /* OK. */
467 else if (!constrained.fpu)
468 t.isa.fpu = isa_min->fpu;
469 else if (!constrained.abi_base)
470 /* If -march is compatible with the default ABI
471 while -mfpu is not. */
472 abi_tmp.base = isa_default_abi (&t.isa).base;
473 else
474 goto fatal;
476 if (0)
477 fatal:
478 fatal_error (UNKNOWN_LOCATION,
479 "unable to implement ABI %qs with instruction set %qs",
480 abi_str (t.abi), isa_str (&t.isa, '/'));
483 /* Using the fallback ABI. */
484 if (abi_tmp.base != t.abi.base || abi_tmp.ext != t.abi.ext)
486 /* This flag is only set in the GCC driver. */
487 if (follow_multilib_list_p)
490 /* Continue falling back until we find a feasible ABI type
491 enabled by TM_MULTILIB_LIST. */
492 if (!is_multilib_enabled (abi_tmp))
494 for (unsigned int i = 0; i < ABI_COUNT; i++)
496 if (is_multilib_enabled (abi_priority_list[i])
497 && abi_compat_p (&t.isa, abi_priority_list[i]))
499 abi_tmp = abi_priority_list[i];
501 warning (0, "ABI %qs cannot be implemented due to "
502 "limited instruction set %qs, "
503 "falling back to %qs", abi_str (t.abi),
504 isa_str (&t.isa, '/'), abi_str (abi_tmp));
506 goto fallback;
510 /* Otherwise, keep using abi_tmp with a warning. */
511 #ifdef LA_DISABLE_MULTILIB
512 warning (0, "instruction set %qs cannot implement "
513 "default ABI %qs, falling back to %qs",
514 isa_str (&t.isa, '/'), abi_str (t.abi),
515 abi_str (abi_tmp));
516 #else
517 warning (0, "no multilib-enabled ABI (%qs) can be implemented "
518 "with instruction set %qs, falling back to %qs",
519 multilib_enabled_abi_list (),
520 isa_str (&t.isa, '/'), abi_str (abi_tmp));
521 #endif
525 fallback:
526 t.abi = abi_tmp;
528 else if (follow_multilib_list_p)
530 if (!is_multilib_enabled (t.abi))
532 inform (UNKNOWN_LOCATION,
533 "ABI %qs is not enabled at configure-time, "
534 "the linker might report an error", abi_str (t.abi));
536 inform (UNKNOWN_LOCATION, "ABI with startfiles: %s",
537 multilib_enabled_abi_list ());
542 /* 5. Target code model */
543 t.cmodel = constrained.cmodel ? target->cmodel : CMODEL_NORMAL;
545 switch (t.cmodel)
547 case CMODEL_TINY:
548 case CMODEL_TINY_STATIC:
549 case CMODEL_LARGE:
550 warning (0, "%qs is not supported, now cmodel is set to %qs",
551 loongarch_cmodel_strings[t.cmodel], "normal");
552 t.cmodel = CMODEL_NORMAL;
553 break;
555 case CMODEL_NORMAL:
556 case CMODEL_MEDIUM:
557 case CMODEL_EXTREME:
558 break;
560 default:
561 gcc_unreachable ();
564 t.tls_dialect = constrained.tls_dialect ? target->tls_dialect
565 : DEFAULT_TLS_TYPE;
567 /* Cleanup and return. */
568 obstack_free (&msg_obstack, NULL);
569 *target = t;
572 /* Returns the default ABI for the given instruction set. */
573 static inline struct loongarch_abi
574 isa_default_abi (const struct loongarch_isa *isa)
576 struct loongarch_abi abi;
578 switch (isa->fpu)
580 case ISA_EXT_FPU64:
581 if (isa->base >= ISA_BASE_LA64)
582 abi.base = ABI_BASE_LP64D;
583 break;
585 case ISA_EXT_FPU32:
586 if (isa->base >= ISA_BASE_LA64)
587 abi.base = ABI_BASE_LP64F;
588 break;
590 case ISA_EXT_NONE:
591 if (isa->base >= ISA_BASE_LA64)
592 abi.base = ABI_BASE_LP64S;
593 break;
595 default:
596 gcc_unreachable ();
599 abi.ext = ABI_EXT_BASE;
600 return abi;
603 /* Check if set2 is a subset of set1. */
604 static inline int
605 isa_base_compat_p (const struct loongarch_isa *set1,
606 const struct loongarch_isa *set2)
608 switch (set2->base)
610 case ISA_BASE_LA64:
611 return (set1->base >= ISA_BASE_LA64);
613 default:
614 gcc_unreachable ();
618 static inline int
619 isa_fpu_compat_p (const struct loongarch_isa *set1,
620 const struct loongarch_isa *set2)
622 switch (set2->fpu)
624 case ISA_EXT_FPU64:
625 return set1->fpu == ISA_EXT_FPU64;
627 case ISA_EXT_FPU32:
628 return set1->fpu == ISA_EXT_FPU32 || set1->fpu == ISA_EXT_FPU64;
630 case ISA_EXT_NONE:
631 return 1;
633 default:
634 gcc_unreachable ();
639 static inline int
640 abi_compat_p (const struct loongarch_isa *isa, struct loongarch_abi abi)
642 int compatible = 1;
643 const struct loongarch_isa *isa2 = &isa_required (abi);
645 /* Append conditionals for new ISA components below. */
646 compatible = compatible && isa_base_compat_p (isa, isa2);
647 compatible = compatible && isa_fpu_compat_p (isa, isa2);
648 return compatible;
651 /* The behavior of this function should be consistent
652 with config.gcc. */
653 static inline int
654 abi_default_cpu_arch (struct loongarch_abi abi,
655 struct loongarch_isa *isa)
657 static struct loongarch_isa tmp;
658 if (!isa)
659 isa = &tmp;
661 if (abi.ext == ABI_EXT_BASE)
662 switch (abi.base)
664 case ABI_BASE_LP64D:
665 case ABI_BASE_LP64F:
666 case ABI_BASE_LP64S:
667 *isa = isa_required (abi);
668 return ARCH_LOONGARCH64;
670 gcc_unreachable ();
673 static inline int
674 default_tune_for_arch (int arch, int fallback)
676 int ret;
677 switch (arch)
680 #define TUNE_FOR_ARCH(NAME) \
681 case ARCH_##NAME: \
682 ret = TUNE_##NAME; \
683 break;
685 TUNE_FOR_ARCH(NATIVE)
686 TUNE_FOR_ARCH(LOONGARCH64)
687 TUNE_FOR_ARCH(LA464)
688 TUNE_FOR_ARCH(LA664)
690 #undef TUNE_FOR_ARCH
692 case ARCH_ABI_DEFAULT:
693 case ARCH_LA64V1_0:
694 case ARCH_LA64V1_1:
695 ret = fallback;
698 gcc_assert (0 <= ret && ret < N_TUNE_TYPES);
699 return ret;
702 static const char*
703 abi_str (struct loongarch_abi abi)
705 /* "/base" can be omitted. */
706 if (abi.ext == ABI_EXT_BASE)
707 return (const char*)
708 obstack_copy0 (&msg_obstack, loongarch_abi_base_strings[abi.base],
709 strlen (loongarch_abi_base_strings[abi.base]));
710 else
712 /* This situation has not yet occurred, so in order to avoid the
713 -Warray-bounds warning during C++ syntax checking, this part
714 of the code is commented first. */
716 APPEND_STRING (loongarch_abi_base_strings[abi.base])
717 APPEND1 ('/')
718 APPEND_STRING (loongarch_abi_ext_strings[abi.ext])
719 APPEND1 ('\0')
721 return XOBFINISH (&msg_obstack, const char *);
723 gcc_unreachable ();
727 static const char*
728 isa_str (const struct loongarch_isa *isa, char separator)
730 APPEND_STRING (loongarch_isa_base_strings[isa->base])
731 APPEND1 (separator)
733 if (isa->fpu == ISA_EXT_NONE)
735 APPEND_STRING ("no" OPTSTR_ISA_EXT_FPU)
737 else
739 APPEND_STRING (OPTSTR_ISA_EXT_FPU)
740 APPEND_STRING (loongarch_isa_ext_strings[isa->fpu])
743 switch (isa->simd)
745 case ISA_EXT_SIMD_LSX:
746 case ISA_EXT_SIMD_LASX:
747 APPEND1 (separator);
748 APPEND_STRING (loongarch_isa_ext_strings[isa->simd]);
749 break;
751 default:
752 gcc_assert (isa->simd == 0);
754 APPEND1 ('\0')
756 /* Add more here. */
758 return XOBFINISH (&msg_obstack, const char *);
761 static const char*
762 arch_str (const struct loongarch_target *target)
764 if (target->cpu_arch == ARCH_NATIVE)
766 /* Describe a native CPU with unknown PRID. */
767 const char* isa_string = isa_str (&target->isa, ',');
768 APPEND_STRING ("PRID: 0x")
769 APPEND_STRING (get_native_prid_str ())
770 APPEND_STRING (", ISA features: ")
771 APPEND_STRING (isa_string)
773 else
774 APPEND_STRING (loongarch_arch_strings[target->cpu_arch]);
776 APPEND1 ('\0')
777 return XOBFINISH (&msg_obstack, const char *);
780 static const char*
781 multilib_enabled_abi_list ()
783 int enabled_abi_idx[MULTILIB_LIST_LEN] = { 0 };
784 const char* enabled_abi_str[MULTILIB_LIST_LEN] = { NULL };
785 unsigned int j = 0;
787 for (unsigned int i = 0; i < ABI_COUNT && j < MULTILIB_LIST_LEN; i++)
789 if (enabled_abi_types[abi_priority_list[i].base]
790 [abi_priority_list[i].ext])
792 enabled_abi_idx[j++] = i;
796 for (unsigned int k = 0; k < j; k++)
798 enabled_abi_str[k] = abi_str (abi_priority_list[enabled_abi_idx[k]]);
801 for (unsigned int k = 0; k < j - 1; k++)
803 APPEND_STRING (enabled_abi_str[k])
804 APPEND1 (',')
805 APPEND1 (' ')
807 APPEND_STRING (enabled_abi_str[j - 1])
808 APPEND1 ('\0')
810 return XOBFINISH (&msg_obstack, const char *);
813 /* option status feedback for "gcc --help=target -Q" */
814 void
815 loongarch_update_gcc_opt_status (struct loongarch_target *target,
816 struct gcc_options *opts,
817 struct gcc_options *opts_set)
819 (void) opts_set;
821 /* status of -mabi */
822 opts->x_la_opt_abi_base = target->abi.base;
824 /* status of -march and -mtune */
825 opts->x_la_opt_cpu_arch = target->cpu_arch;
826 opts->x_la_opt_cpu_tune = target->cpu_tune;
828 /* status of -mcmodel */
829 opts->x_la_opt_cmodel = target->cmodel;
831 /* status of -mtls-dialect */
832 opts->x_la_opt_tls_dialect = target->tls_dialect;
834 /* status of -mfpu */
835 opts->x_la_opt_fpu = target->isa.fpu;
837 /* status of -msimd */
838 opts->x_la_opt_simd = target->isa.simd;
840 /* ISA evolution features */
841 opts->x_la_isa_evolution = target->isa.evolution;
844 /* -mrecip=<str> handling */
845 static struct
847 const char *string; /* option name. */
848 unsigned int mask; /* mask bits to set. */
850 const recip_options[] = {
851 { "all", RECIP_MASK_ALL },
852 { "none", RECIP_MASK_NONE },
853 { "div", RECIP_MASK_DIV },
854 { "sqrt", RECIP_MASK_SQRT },
855 { "rsqrt", RECIP_MASK_RSQRT },
856 { "vec-div", RECIP_MASK_VEC_DIV },
857 { "vec-sqrt", RECIP_MASK_VEC_SQRT },
858 { "vec-rsqrt", RECIP_MASK_VEC_RSQRT },
861 /* Parser for -mrecip=<recip_string>. */
862 unsigned int
863 loongarch_parse_mrecip_scheme (const char *recip_string)
865 unsigned int result_mask = RECIP_MASK_NONE;
867 if (recip_string)
869 char *p = ASTRDUP (recip_string);
870 char *q;
871 unsigned int mask, i;
872 bool invert;
874 while ((q = strtok (p, ",")) != NULL)
876 p = NULL;
877 if (*q == '!')
879 invert = true;
880 q++;
882 else
883 invert = false;
885 if (!strcmp (q, "default"))
886 mask = RECIP_MASK_ALL;
887 else
889 for (i = 0; i < ARRAY_SIZE (recip_options); i++)
890 if (!strcmp (q, recip_options[i].string))
892 mask = recip_options[i].mask;
893 break;
896 if (i == ARRAY_SIZE (recip_options))
898 error ("unknown option for %<-mrecip=%s%>", q);
899 invert = false;
900 mask = RECIP_MASK_NONE;
904 if (invert)
905 result_mask &= ~mask;
906 else
907 result_mask |= mask;
910 return result_mask;
913 /* Generate -mrecip= argument based on the mask. */
914 const char*
915 loongarch_generate_mrecip_scheme (unsigned int mask)
917 static char recip_scheme_str[128];
918 int p = 0, tmp;
920 switch (mask)
922 case RECIP_MASK_ALL:
923 return "all";
925 case RECIP_MASK_NONE:
926 return "none";
929 for (unsigned long i = 2; i < ARRAY_SIZE (recip_options); i++)
931 if (mask & recip_options[i].mask)
933 if ((tmp = strlen (recip_options[i].string) + 1) >= 127 - p)
934 gcc_unreachable ();
936 recip_scheme_str[p] = ',';
937 strcpy (recip_scheme_str + p + 1, recip_options[i].string);
938 p += tmp;
941 recip_scheme_str[p] = '\0';
942 return recip_scheme_str + 1;
947 /* Refresh the switches acccording to the resolved loongarch_target struct. */
948 void
949 loongarch_target_option_override (struct loongarch_target *target,
950 struct gcc_options *opts,
951 struct gcc_options *opts_set)
953 loongarch_update_gcc_opt_status (target, opts, opts_set);
955 /* If not optimizing for size, set the default
956 alignment to what the target wants. */
957 if (!opts->x_optimize_size)
959 if (opts->x_flag_align_functions && !opts->x_str_align_functions)
960 opts->x_str_align_functions
961 = loongarch_cpu_align[target->cpu_tune].function;
963 if (opts->x_flag_align_loops && !opts->x_str_align_loops)
964 opts->x_str_align_loops = loongarch_cpu_align[target->cpu_tune].loop;
966 if (opts->x_flag_align_jumps && !opts->x_str_align_jumps)
967 opts->x_str_align_jumps = loongarch_cpu_align[target->cpu_tune].jump;
970 /* Set up parameters to be used in prefetching algorithm. */
971 int simultaneous_prefetches
972 = loongarch_cpu_cache[target->cpu_tune].simultaneous_prefetches;
974 SET_OPTION_IF_UNSET (opts, opts_set, param_simultaneous_prefetches,
975 simultaneous_prefetches);
977 SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_line_size,
978 loongarch_cpu_cache[target->cpu_tune].l1d_line_size);
980 SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_size,
981 loongarch_cpu_cache[target->cpu_tune].l1d_size);
983 SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size,
984 loongarch_cpu_cache[target->cpu_tune].l2d_size);
986 /* Other arch-specific overrides. */
987 switch (target->cpu_arch)
989 case ARCH_LA664:
990 /* Enable -mrecipe=all for LA664 by default. */
991 if (!opts_set->x_recip_mask)
993 opts->x_recip_mask = RECIP_MASK_ALL;
994 opts_set->x_recip_mask = 1;
998 /* -mrecip= */
999 opts->x_la_recip_name
1000 = loongarch_generate_mrecip_scheme (opts->x_recip_mask);
1002 /* Decide which rtx_costs structure to use. */
1003 if (opts->x_optimize_size)
1004 loongarch_cost = &loongarch_rtx_cost_optimize_size;
1005 else
1006 loongarch_cost = &loongarch_cpu_rtx_cost_data[target->cpu_tune];
1008 /* If the user hasn't specified a branch cost, use the processor's
1009 default. */
1010 if (!opts_set->x_la_branch_cost)
1011 opts->x_la_branch_cost = loongarch_cost->branch_cost;
1013 /* other stuff */
1014 if (ABI_LP64_P (target->abi.base))
1015 opts->x_flag_pcc_struct_return = 0;
1017 switch (target->cmodel)
1019 case CMODEL_EXTREME:
1020 if (opts->x_flag_plt)
1022 if (opts_set->x_flag_plt)
1023 error ("code model %qs is not compatible with %s",
1024 "extreme", "-fplt");
1025 opts->x_flag_plt = 0;
1027 break;
1029 case CMODEL_TINY_STATIC:
1030 case CMODEL_MEDIUM:
1031 case CMODEL_NORMAL:
1032 case CMODEL_TINY:
1033 case CMODEL_LARGE:
1034 break;
1036 default:
1037 gcc_unreachable ();
1042 /* Resolve options that's not covered by la_target. */
1043 void
1044 loongarch_init_misc_options (struct gcc_options *opts,
1045 struct gcc_options *opts_set)
1047 if (opts->x_flag_pic)
1048 opts->x_g_switch_value = 0;
1050 /* -mrecip options. */
1051 opts->x_recip_mask = loongarch_parse_mrecip_scheme (opts->x_la_recip_name);
1053 #define INIT_TARGET_FLAG(NAME, INIT) \
1055 if (!(opts_set->x_target_flags & MASK_##NAME)) \
1057 if (INIT) \
1058 opts->x_target_flags |= MASK_##NAME; \
1059 else \
1060 opts->x_target_flags &= ~MASK_##NAME; \
1064 /* Enable conditional moves for int and float by default. */
1065 INIT_TARGET_FLAG (COND_MOVE_INT, 1)
1066 INIT_TARGET_FLAG (COND_MOVE_FLOAT, 1)
1068 /* Set mrelax default. */
1069 INIT_TARGET_FLAG (LINKER_RELAXATION,
1070 HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION)
1072 #undef INIT_TARGET_FLAG
1074 /* Set mexplicit-relocs default. */
1075 if (opts->x_la_opt_explicit_relocs == M_OPT_UNSET)
1076 opts->x_la_opt_explicit_relocs = (HAVE_AS_EXPLICIT_RELOCS
1077 ? (TARGET_LINKER_RELAXATION
1078 ? EXPLICIT_RELOCS_AUTO
1079 : EXPLICIT_RELOCS_ALWAYS)
1080 : EXPLICIT_RELOCS_NONE);
1082 /* Enable sw prefetching at -O3 and higher. */
1083 if (opts->x_flag_prefetch_loop_arrays < 0
1084 && (opts->x_optimize >= 3 || opts->x_flag_profile_use)
1085 && !opts->x_optimize_size)
1086 opts->x_flag_prefetch_loop_arrays = 1;
1088 if (TARGET_DIRECT_EXTERN_ACCESS_OPTS_P (opts) && opts->x_flag_shlib)
1089 error ("%qs cannot be used for compiling a shared library",
1090 "-mdirect-extern-access");
1092 /* Enforce that interval is the same size as size so the mid-end does the
1093 right thing. */
1094 SET_OPTION_IF_UNSET (opts, opts_set,
1095 param_stack_clash_protection_probe_interval,
1096 param_stack_clash_protection_guard_size);