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)
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
25 #include "coretypes.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
55 #define MULTILIB_LIST_LEN (sizeof (tm_multilib_list) / sizeof (int) / 2)
56 static const int tm_multilib_list
[] = { TM_MULTILIB_LIST
};
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])
63 is_multilib_enabled (struct loongarch_abi abi
)
65 return enabled_abi_types
[abi
.base
][abi
.ext
];
69 init_enabled_abi_types ()
71 #ifdef LA_DISABLE_MULTILIB
72 enabled_abi_types
[DEFAULT_ABI_BASE
][DEFAULT_ABI_EXT
] = 1;
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;
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 ();
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}.
111 #ifndef DEFAULT_ABI_EXT
112 #error missing definition of DEFAULT_ABI_EXT in ${tm_defines}.
115 #ifndef DEFAULT_CPU_ARCH
116 #error missing definition of DEFAULT_CPU_ARCH in ${tm_defines}.
119 /* Optional configure-time defaults. */
120 #ifdef DEFAULT_CPU_TUNE
121 static int with_default_tune
= 1;
123 #define DEFAULT_CPU_TUNE -1
124 static int with_default_tune
= 0;
127 #ifdef DEFAULT_ISA_EXT_FPU
128 static int with_default_fpu
= 1;
130 #define DEFAULT_ISA_EXT_FPU -1
131 static int with_default_fpu
= 0;
134 #ifdef DEFAULT_ISA_EXT_SIMD
135 static int with_default_simd
= 1;
137 #define DEFAULT_ISA_EXT_SIMD -1
138 static int with_default_simd
= 0;
142 /* Initialize loongarch_target from separate option variables. */
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
,
149 HOST_WIDE_INT isa_evolution
,
150 HOST_WIDE_INT isa_evolution_set
)
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). */
171 loongarch_config_target (struct loongarch_target
*target
,
172 struct loongarch_flags
*flags
,
173 int follow_multilib_list_p
)
175 struct loongarch_target t
;
181 init_enabled_abi_types ();
182 obstack_init (&msg_obstack
);
185 int arch
, tune
, fpu
, simd
, abi_base
, abi_ext
, cmodel
,
186 tls_dialect
, abi_flt
;
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
;
203 if (constrained
.abi_base
)
204 t
.abi
.base
= target
->abi
.base
;
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
;
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
));
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
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 */
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
);
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
);
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 */
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
)
322 /* apply -m[no-]lsx and -m[no-]lasx 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)
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
;
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
;
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
,
390 loongarch_isa_ext_strings
[ISA_EXT_FPU64
]);
392 t
.isa
.simd
= ISA_EXT_NONE
;
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%>",
402 loongarch_isa_ext_strings
[t
.isa
.fpu
],
403 loongarch_isa_ext_strings
[t
.isa
.simd
],
405 loongarch_isa_ext_strings
[ISA_EXT_FPU64
]);
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 */
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
;
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
]);
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
;
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
;
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
));
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
),
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
));
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
;
548 case CMODEL_TINY_STATIC
:
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
;
564 t
.tls_dialect
= constrained
.tls_dialect
? target
->tls_dialect
567 /* Cleanup and return. */
568 obstack_free (&msg_obstack
, NULL
);
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
;
581 if (isa
->base
>= ISA_BASE_LA64
)
582 abi
.base
= ABI_BASE_LP64D
;
586 if (isa
->base
>= ISA_BASE_LA64
)
587 abi
.base
= ABI_BASE_LP64F
;
591 if (isa
->base
>= ISA_BASE_LA64
)
592 abi
.base
= ABI_BASE_LP64S
;
599 abi
.ext
= ABI_EXT_BASE
;
603 /* Check if set2 is a subset of set1. */
605 isa_base_compat_p (const struct loongarch_isa
*set1
,
606 const struct loongarch_isa
*set2
)
611 return (set1
->base
>= ISA_BASE_LA64
);
619 isa_fpu_compat_p (const struct loongarch_isa
*set1
,
620 const struct loongarch_isa
*set2
)
625 return set1
->fpu
== ISA_EXT_FPU64
;
628 return set1
->fpu
== ISA_EXT_FPU32
|| set1
->fpu
== ISA_EXT_FPU64
;
640 abi_compat_p (const struct loongarch_isa
*isa
, struct loongarch_abi abi
)
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
);
651 /* The behavior of this function should be consistent
654 abi_default_cpu_arch (struct loongarch_abi abi
,
655 struct loongarch_isa
*isa
)
657 static struct loongarch_isa tmp
;
661 if (abi
.ext
== ABI_EXT_BASE
)
667 *isa
= isa_required (abi
);
668 return ARCH_LOONGARCH64
;
674 default_tune_for_arch (int arch
, int fallback
)
680 #define TUNE_FOR_ARCH(NAME) \
685 TUNE_FOR_ARCH(NATIVE
)
686 TUNE_FOR_ARCH(LOONGARCH64
)
692 case ARCH_ABI_DEFAULT
:
698 gcc_assert (0 <= ret
&& ret
< N_TUNE_TYPES
);
703 abi_str (struct loongarch_abi abi
)
705 /* "/base" can be omitted. */
706 if (abi
.ext
== ABI_EXT_BASE
)
708 obstack_copy0 (&msg_obstack
, loongarch_abi_base_strings
[abi
.base
],
709 strlen (loongarch_abi_base_strings
[abi
.base
]));
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])
718 APPEND_STRING (loongarch_abi_ext_strings[abi.ext])
721 return XOBFINISH (&msg_obstack, const char *);
728 isa_str (const struct loongarch_isa
*isa
, char separator
)
730 APPEND_STRING (loongarch_isa_base_strings
[isa
->base
])
733 if (isa
->fpu
== ISA_EXT_NONE
)
735 APPEND_STRING ("no" OPTSTR_ISA_EXT_FPU
)
739 APPEND_STRING (OPTSTR_ISA_EXT_FPU
)
740 APPEND_STRING (loongarch_isa_ext_strings
[isa
->fpu
])
745 case ISA_EXT_SIMD_LSX
:
746 case ISA_EXT_SIMD_LASX
:
748 APPEND_STRING (loongarch_isa_ext_strings
[isa
->simd
]);
752 gcc_assert (isa
->simd
== 0);
758 return XOBFINISH (&msg_obstack
, 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
)
774 APPEND_STRING (loongarch_arch_strings
[target
->cpu_arch
]);
777 return XOBFINISH (&msg_obstack
, 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
};
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
])
807 APPEND_STRING (enabled_abi_str
[j
- 1])
810 return XOBFINISH (&msg_obstack
, const char *);
813 /* option status feedback for "gcc --help=target -Q" */
815 loongarch_update_gcc_opt_status (struct loongarch_target
*target
,
816 struct gcc_options
*opts
,
817 struct gcc_options
*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 */
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>. */
863 loongarch_parse_mrecip_scheme (const char *recip_string
)
865 unsigned int result_mask
= RECIP_MASK_NONE
;
869 char *p
= ASTRDUP (recip_string
);
871 unsigned int mask
, i
;
874 while ((q
= strtok (p
, ",")) != NULL
)
885 if (!strcmp (q
, "default"))
886 mask
= RECIP_MASK_ALL
;
889 for (i
= 0; i
< ARRAY_SIZE (recip_options
); i
++)
890 if (!strcmp (q
, recip_options
[i
].string
))
892 mask
= recip_options
[i
].mask
;
896 if (i
== ARRAY_SIZE (recip_options
))
898 error ("unknown option for %<-mrecip=%s%>", q
);
900 mask
= RECIP_MASK_NONE
;
905 result_mask
&= ~mask
;
913 /* Generate -mrecip= argument based on the mask. */
915 loongarch_generate_mrecip_scheme (unsigned int mask
)
917 static char recip_scheme_str
[128];
925 case RECIP_MASK_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
)
936 recip_scheme_str
[p
] = ',';
937 strcpy (recip_scheme_str
+ p
+ 1, recip_options
[i
].string
);
941 recip_scheme_str
[p
] = '\0';
942 return recip_scheme_str
+ 1;
947 /* Refresh the switches acccording to the resolved loongarch_target struct. */
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
)
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;
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
;
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
1010 if (!opts_set
->x_la_branch_cost
)
1011 opts
->x_la_branch_cost
= loongarch_cost
->branch_cost
;
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;
1029 case CMODEL_TINY_STATIC
:
1042 /* Resolve options that's not covered by la_target. */
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)) \
1058 opts->x_target_flags |= MASK_##NAME; \
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
1094 SET_OPTION_IF_UNSET (opts
, opts_set
,
1095 param_stack_clash_protection_probe_interval
,
1096 param_stack_clash_protection_guard_size
);