Message ID | 20240221033619.1011766-1-yangyujie@loongson.cn |
---|---|
State | New |
Headers | show |
Series | [v2] LoongArch: Split loongarch_option_override_internal into smaller procedures | expand |
v1 -> v2: - Rebased to master. - Specifies "(void)" for the empty parameter list of loongarch_global_init.
Hi,yujie: When using this patch to compile test cases, ICE will be reported. test.c float foo(float a, float b) { return a / b; } # ./gcc/cc1 test.c -o - -O2 -ffast-math -mrecip recip.c: 在函数‘foo’中: recip.c:5:1: 错误:无法识别的指令: 5 | } | ^ (insn 9 8 10 2 (set (reg:SF 84) (unspec:SF [ (reg/v:SF 82 [ b ]) ] UNSPEC_RECIPE)) "recip.c":4:12 -1 (nil)) during RTL pass: vregs recip.c:5:1: 编译器内部错误:在 extract_insn 中,于 recog.cc:2812 0x135d1d4 _fatal_insn(char const*, rtx_def const*, char const*, int, char const*) /home/chenglulu/work/loongisa-toolchain/gcc-upstream/gcc/rtl-error.cc:108 0x135d215 _fatal_insn_not_found(rtx_def const*, char const*, int, char const*) /home/chenglulu/work/loongisa-toolchain/gcc-upstream/gcc/rtl-error.cc:116 0x13111b6 extract_insn(rtx_insn*) /home/chenglulu/work/loongisa-toolchain/gcc-upstream/gcc/recog.cc:2812 0xf84e72 instantiate_virtual_regs_in_insn /home/chenglulu/work/loongisa-toolchain/gcc-upstream/gcc/function.cc:1611 0xf85e90 instantiate_virtual_regs /home/chenglulu/work/loongisa-toolchain/gcc-upstream/gcc/function.cc:1994 0xf85f56 execute /home/chenglulu/work/loongisa-toolchain/gcc-upstream/gcc/function.cc:2041 Please submit a full bug report, with preprocessed source (by using -freport-bug). Please include the complete backtrace with any bug report. 参阅 <https://gcc.gnu.org/bugs/> 以获取指示。 在 2024/2/21 上午11:36, Yang Yujie 写道: > gcc/ChangeLog: > > * config/loongarch/genopts/loongarch.opt.in: Mark -m[no-]recip as > aliases to -mrecip={all,none}. > * config/loongarch/loongarch.opt: Same. > * config/loongarch/loongarch-def.h: Modify ABI condition macros for > convenience. > * config/loongarch/loongarch-opts.cc: Define option-handling > procedures split from the original loongarch_option_override_internal. > * config/loongarch/loongarch-opts.h: Same. > * config/loongarch/loongarch.cc: Clean up > loongarch_option_override_internal. > --- > gcc/config/loongarch/genopts/loongarch.opt.in | 8 +- > gcc/config/loongarch/loongarch-def.h | 11 +- > gcc/config/loongarch/loongarch-opts.cc | 248 +++++++++++++++++ > gcc/config/loongarch/loongarch-opts.h | 27 +- > gcc/config/loongarch/loongarch.cc | 253 +++--------------- > gcc/config/loongarch/loongarch.opt | 8 +- > 6 files changed, 325 insertions(+), 230 deletions(-) > > diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in > index 02f918053f5..a77893d31d9 100644 > --- a/gcc/config/loongarch/genopts/loongarch.opt.in > +++ b/gcc/config/loongarch/genopts/loongarch.opt.in > @@ -197,14 +197,14 @@ mexplicit-relocs > Target Alias(mexplicit-relocs=, always, none) > Use %reloc() assembly operators (for backward compatibility). > > -mrecip > -Target RejectNegative Var(la_recip) Save > -Generate approximate reciprocal divide and square root for better throughput. > - > mrecip= > Target RejectNegative Joined Var(la_recip_name) Save > Control generation of reciprocal estimates. > > +mrecip > +Target Alias(mrecip=, all, none) > +Generate approximate reciprocal divide and square root for better throughput. > + > ; The code model option names for -mcmodel. > Enum > Name(cmodel) Type(int) > diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h > index 2dbf006d013..0cbf9476690 100644 > --- a/gcc/config/loongarch/loongarch-def.h > +++ b/gcc/config/loongarch/loongarch-def.h > @@ -90,11 +90,16 @@ extern loongarch_def_array<const char *, N_ABI_BASE_TYPES> > > #define TO_LP64_ABI_BASE(C) (C) > > -#define ABI_FPU_64(abi_base) \ > +#define ABI_LP64_P(abi_base) \ > + (abi_base == ABI_BASE_LP64D \ > + || abi_base == ABI_BASE_LP64F \ > + || abi_base == ABI_BASE_LP64S) > + > +#define ABI_FPU64_P(abi_base) \ > (abi_base == ABI_BASE_LP64D) > -#define ABI_FPU_32(abi_base) \ > +#define ABI_FPU32_P(abi_base) \ > (abi_base == ABI_BASE_LP64F) > -#define ABI_FPU_NONE(abi_base) \ > +#define ABI_NOFPU_P(abi_base) \ > (abi_base == ABI_BASE_LP64S) > > > diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc > index 7eeac43ed2f..380208f38bf 100644 > --- a/gcc/config/loongarch/loongarch-opts.cc > +++ b/gcc/config/loongarch/loongarch-opts.cc > @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see > #include "coretypes.h" > #include "tm.h" > #include "obstack.h" > +#include "opts.h" > #include "diagnostic-core.h" > > #include "loongarch-cpu.h" > @@ -32,8 +33,12 @@ along with GCC; see the file COPYING3. If not see > #include "loongarch-str.h" > #include "loongarch-def.h" > > +/* Target configuration */ > struct loongarch_target la_target; > > +/* RTL cost information */ > +const struct loongarch_rtx_cost_data *loongarch_cost; > + > /* ABI-related configuration. */ > #define ABI_COUNT (sizeof(abi_priority_list)/sizeof(struct loongarch_abi)) > static const struct loongarch_abi > @@ -795,3 +800,246 @@ loongarch_update_gcc_opt_status (struct loongarch_target *target, > /* ISA evolution features */ > opts->x_la_isa_evolution = target->isa.evolution; > } > + > +/* -mrecip=<str> handling */ > +static struct > + { > + const char *string; /* option name. */ > + unsigned int mask; /* mask bits to set. */ > + } > +const recip_options[] = { > + { "all", RECIP_MASK_ALL }, > + { "none", RECIP_MASK_NONE }, > + { "div", RECIP_MASK_DIV }, > + { "sqrt", RECIP_MASK_SQRT }, > + { "rsqrt", RECIP_MASK_RSQRT }, > + { "vec-div", RECIP_MASK_VEC_DIV }, > + { "vec-sqrt", RECIP_MASK_VEC_SQRT }, > + { "vec-rsqrt", RECIP_MASK_VEC_RSQRT }, > +}; > + > +/* Parser for -mrecip=<recip_string>. */ > +unsigned int > +loongarch_parse_mrecip_scheme (const char *recip_string) > +{ > + unsigned int result_mask = RECIP_MASK_NONE; > + > + if (recip_string) > + { > + char *p = ASTRDUP (recip_string); > + char *q; > + unsigned int mask, i; > + bool invert; > + > + while ((q = strtok (p, ",")) != NULL) > + { > + p = NULL; > + if (*q == '!') > + { > + invert = true; > + q++; > + } > + else > + invert = false; > + > + if (!strcmp (q, "default")) > + mask = RECIP_MASK_ALL; > + else > + { > + for (i = 0; i < ARRAY_SIZE (recip_options); i++) > + if (!strcmp (q, recip_options[i].string)) > + { > + mask = recip_options[i].mask; > + break; > + } > + > + if (i == ARRAY_SIZE (recip_options)) > + { > + error ("unknown option for %<-mrecip=%s%>", q); > + invert = false; > + mask = RECIP_MASK_NONE; > + } > + } > + > + if (invert) > + result_mask &= ~mask; > + else > + result_mask |= mask; > + } > + } > + return result_mask; > +} > + > +/* Generate -mrecip= argument based on the mask. */ > +const char* > +loongarch_generate_mrecip_scheme (unsigned int mask) > +{ > + static char recip_scheme_str[128]; > + int p = 0, tmp; > + > + switch (mask) > + { > + case RECIP_MASK_ALL: > + return "all"; > + > + case RECIP_MASK_NONE: > + return "none"; > + } > + > + for (unsigned long i = 2; i < ARRAY_SIZE (recip_options); i++) > + { > + if (mask & recip_options[i].mask) > + { > + if ((tmp = strlen (recip_options[i].string) + 1) >= 127 - p) > + gcc_unreachable (); > + > + recip_scheme_str[p] = ','; > + strcpy (recip_scheme_str + p + 1, recip_options[i].string); > + p += tmp; > + } > + } > + recip_scheme_str[p] = '\0'; > + return recip_scheme_str + 1; > +} > + > + > + > +/* Refresh the switches acccording to the resolved loongarch_target struct. */ > +void > +loongarch_target_option_override (struct loongarch_target *target, > + struct gcc_options *opts, > + struct gcc_options *opts_set) > +{ > + loongarch_update_gcc_opt_status (target, opts, opts_set); > + > + /* alignments */ > + if (opts->x_flag_align_functions && !opts->x_str_align_functions) > + opts->x_str_align_functions > + = loongarch_cpu_align[target->cpu_tune].function; > + > + if (opts->x_flag_align_labels && !opts->x_str_align_labels) > + opts->x_str_align_labels = loongarch_cpu_align[target->cpu_tune].label; > + > + /* Set up parameters to be used in prefetching algorithm. */ > + int simultaneous_prefetches > + = loongarch_cpu_cache[target->cpu_tune].simultaneous_prefetches; > + > + SET_OPTION_IF_UNSET (opts, opts_set, param_simultaneous_prefetches, > + simultaneous_prefetches); > + > + SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_line_size, > + loongarch_cpu_cache[target->cpu_tune].l1d_line_size); > + > + SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_size, > + loongarch_cpu_cache[target->cpu_tune].l1d_size); > + > + SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size, > + loongarch_cpu_cache[target->cpu_tune].l2d_size); > + > + /* -mrecip= */ > + opts->x_la_recip_name > + = loongarch_generate_mrecip_scheme (opts->x_recip_mask); > + > + /* Decide which rtx_costs structure to use. */ > + if (opts->x_optimize_size) > + loongarch_cost = &loongarch_rtx_cost_optimize_size; > + else > + loongarch_cost = &loongarch_cpu_rtx_cost_data[target->cpu_tune]; > + > + /* If the user hasn't specified a branch cost, use the processor's > + default. */ > + if (!opts_set->x_la_branch_cost) > + opts->x_la_branch_cost = loongarch_cost->branch_cost; > + > + /* other stuff */ > + if (ABI_LP64_P (target->abi.base)) > + opts->x_flag_pcc_struct_return = 0; > + > + switch (target->cmodel) > + { > + case CMODEL_EXTREME: > + if (opts->x_flag_plt) > + { > + if (opts_set->x_flag_plt) > + error ("code model %qs is not compatible with %s", > + "extreme", "-fplt"); > + opts->x_flag_plt = 0; > + } > + break; > + > + case CMODEL_TINY_STATIC: > + case CMODEL_MEDIUM: > + case CMODEL_NORMAL: > + case CMODEL_TINY: > + case CMODEL_LARGE: > + break; > + > + default: > + gcc_unreachable (); > + } > +} > + > + > +/* Resolve options that's not covered by la_target. */ > +void > +loongarch_init_misc_options (struct gcc_options *opts, > + struct gcc_options *opts_set) > +{ > + if (opts->x_flag_pic) > + opts->x_g_switch_value = 0; > + > + /* -mrecip options. */ > + opts->x_recip_mask = loongarch_parse_mrecip_scheme (opts->x_la_recip_name); > + > + /* Enable -mfrecipe if -mrecip is given. */ > + if (opts_set->x_recip_mask && opts->x_recip_mask != RECIP_MASK_NONE) > + { > + opts->x_la_isa_evolution |= OPTION_MASK_ISA_FRECIPE; > + opts_set->x_la_isa_evolution |= OPTION_MASK_ISA_FRECIPE; > + } > + > +#define INIT_TARGET_FLAG(NAME, INIT) \ > + { \ > + if (!(opts_set->x_target_flags & MASK_##NAME)) \ > + { \ > + if (INIT) \ > + opts->x_target_flags |= MASK_##NAME; \ > + else \ > + opts->x_target_flags &= ~MASK_##NAME; \ > + } \ > + } > + > + /* Enable conditional moves for int and float by default. */ > + INIT_TARGET_FLAG (COND_MOVE_INT, 1) > + INIT_TARGET_FLAG (COND_MOVE_FLOAT, 1) > + > + /* Set mrelax default. */ > + INIT_TARGET_FLAG (LINKER_RELAXATION, > + HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION) > + > +#undef INIT_TARGET_FLAG > + > + /* Set mexplicit-relocs default. */ > + if (opts->x_la_opt_explicit_relocs == M_OPT_UNSET) > + opts->x_la_opt_explicit_relocs = (HAVE_AS_EXPLICIT_RELOCS > + ? (TARGET_LINKER_RELAXATION > + ? EXPLICIT_RELOCS_AUTO > + : EXPLICIT_RELOCS_ALWAYS) > + : EXPLICIT_RELOCS_NONE); > + > + /* Enable sw prefetching at -O3 and higher. */ > + if (opts->x_flag_prefetch_loop_arrays < 0 > + && (opts->x_optimize >= 3 || opts->x_flag_profile_use) > + && !opts->x_optimize_size) > + opts->x_flag_prefetch_loop_arrays = 1; > + > + if (TARGET_DIRECT_EXTERN_ACCESS_OPTS_P (opts) && opts->x_flag_shlib) > + error ("%qs cannot be used for compiling a shared library", > + "-mdirect-extern-access"); > + > + /* Enforce that interval is the same size as size so the mid-end does the > + right thing. */ > + SET_OPTION_IF_UNSET (opts, opts_set, > + param_stack_clash_protection_probe_interval, > + param_stack_clash_protection_guard_size); > +} > diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h > index 586e67e65ee..2d9f59296e7 100644 > --- a/gcc/config/loongarch/loongarch-opts.h > +++ b/gcc/config/loongarch/loongarch-opts.h > @@ -30,6 +30,10 @@ along with GCC; see the file COPYING3. If not see > /* Target configuration */ > extern struct loongarch_target la_target; > > +/* RTL cost information */ > +extern const struct loongarch_rtx_cost_data *loongarch_cost; > + > + > /* Initialize loongarch_target from separate option variables. */ > void > loongarch_init_target (struct loongarch_target *target, > @@ -46,11 +50,30 @@ loongarch_config_target (struct loongarch_target *target, > struct loongarch_flags *flags, > int follow_multilib_list_p); > > + > +/* Refresh the switches acccording to the resolved loongarch_target struct. */ > +void > +loongarch_target_option_override (struct loongarch_target *target, > + struct gcc_options *opts, > + struct gcc_options *opts_set); > + > + > /* option status feedback for "gcc --help=target -Q" */ > void > loongarch_update_gcc_opt_status (struct loongarch_target *target, > struct gcc_options *opts, > struct gcc_options *opts_set); > + > + > +/* Parser for -mrecip=<recip_string>. */ > +unsigned int > +loongarch_parse_mrecip_scheme (const char *recip_string); > + > + > +/* Resolve options that's not covered by la_target. */ > +void > +loongarch_init_misc_options (struct gcc_options *opts, > + struct gcc_options *opts_set); > #endif > > /* Flag status */ > @@ -80,9 +103,7 @@ struct loongarch_flags { > #define TARGET_DOUBLE_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64D) > > #define TARGET_64BIT (la_target.isa.base == ISA_BASE_LA64) > -#define TARGET_ABI_LP64 (la_target.abi.base == ABI_BASE_LP64D \ > - || la_target.abi.base == ABI_BASE_LP64F \ > - || la_target.abi.base == ABI_BASE_LP64S) > +#define TARGET_ABI_LP64 ABI_LP64_P(la_target.abi.base) > > #define ISA_HAS_LSX \ > (la_target.isa.simd == ISA_EXT_SIMD_LSX \ > diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc > index 0428b6e65d5..8f686ee4096 100644 > --- a/gcc/config/loongarch/loongarch.cc > +++ b/gcc/config/loongarch/loongarch.cc > @@ -208,9 +208,6 @@ const enum reg_class loongarch_regno_to_class[FIRST_PSEUDO_REGISTER] = { > FRAME_REGS, FRAME_REGS > }; > > -/* Which cost information to use. */ > -static const struct loongarch_rtx_cost_data *loongarch_cost; > - > /* Information about a single argument. */ > struct loongarch_arg_info > { > @@ -5905,17 +5902,6 @@ loongarch_print_operand_punctuation (FILE *file, int ch) > } > } > > -/* Initialize loongarch_print_operand_punct. */ > - > -static void > -loongarch_init_print_operand_punct (void) > -{ > - const char *p; > - > - for (p = ".$"; *p; p++) > - loongarch_print_operand_punct[(unsigned char) *p] = true; > -} > - > /* PRINT_OPERAND prefix LETTER refers to the integer branch instruction > associated with condition CODE. Print the condition part of the > opcode to FILE. */ > @@ -7606,118 +7592,15 @@ loongarch_init_machine_status (void) > } > > static void > -loongarch_cpu_option_override (struct loongarch_target *target, > - struct gcc_options *opts, > - struct gcc_options *opts_set) > -{ > - /* alignments */ > - if (opts->x_flag_align_functions && !opts->x_str_align_functions) > - opts->x_str_align_functions > - = loongarch_cpu_align[target->cpu_tune].function; > - > - if (opts->x_flag_align_labels && !opts->x_str_align_labels) > - opts->x_str_align_labels = loongarch_cpu_align[target->cpu_tune].label; > - > - /* Set up parameters to be used in prefetching algorithm. */ > - int simultaneous_prefetches > - = loongarch_cpu_cache[target->cpu_tune].simultaneous_prefetches; > - > - SET_OPTION_IF_UNSET (opts, opts_set, param_simultaneous_prefetches, > - simultaneous_prefetches); > - > - SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_line_size, > - loongarch_cpu_cache[target->cpu_tune].l1d_line_size); > - > - SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_size, > - loongarch_cpu_cache[target->cpu_tune].l1d_size); > - > - SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size, > - loongarch_cpu_cache[target->cpu_tune].l2d_size); > -} > - > -static void > -loongarch_option_override_internal (struct gcc_options *opts, > - struct gcc_options *opts_set) > +loongarch_global_init (void) > { > - int i, regno, mode; > - > - if (flag_pic) > - g_switch_value = 0; > - > - loongarch_init_target (&la_target, > - la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu, > - la_opt_simd, la_opt_abi_base, la_opt_abi_ext, > - la_opt_cmodel, opts->x_la_isa_evolution, > - opts_set->x_la_isa_evolution); > - > - /* Handle target-specific options: compute defaults/conflicts etc. */ > - loongarch_config_target (&la_target, NULL, 0); > - > - loongarch_update_gcc_opt_status (&la_target, opts, opts_set); > - loongarch_cpu_option_override (&la_target, opts, opts_set); > - > - if (TARGET_ABI_LP64) > - flag_pcc_struct_return = 0; > - > - /* Decide which rtx_costs structure to use. */ > - if (optimize_size) > - loongarch_cost = &loongarch_rtx_cost_optimize_size; > - else > - loongarch_cost = &loongarch_cpu_rtx_cost_data[la_target.cpu_tune]; > - > - /* If the user hasn't specified a branch cost, use the processor's > - default. */ > - if (la_branch_cost == 0) > - la_branch_cost = loongarch_cost->branch_cost; > - > - /* Enable sw prefetching at -O3 and higher. */ > - if (opts->x_flag_prefetch_loop_arrays < 0 > - && (opts->x_optimize >= 3 || opts->x_flag_profile_use) > - && !opts->x_optimize_size) > - opts->x_flag_prefetch_loop_arrays = 1; > - > - if (TARGET_DIRECT_EXTERN_ACCESS && flag_shlib) > - error ("%qs cannot be used for compiling a shared library", > - "-mdirect-extern-access"); > - > - switch (la_target.cmodel) > - { > - case CMODEL_EXTREME: > - if (opts->x_flag_plt) > - { > - if (global_options_set.x_flag_plt) > - error ("code model %qs is not compatible with %s", > - "extreme", "-fplt"); > - opts->x_flag_plt = 0; > - } > - break; > - > - case CMODEL_TINY_STATIC: > - case CMODEL_MEDIUM: > - case CMODEL_NORMAL: > - case CMODEL_TINY: > - case CMODEL_LARGE: > - break; > - > - default: > - gcc_unreachable (); > - } > - > - /* Validate the guard size. */ > - int guard_size = param_stack_clash_protection_guard_size; > - > - /* Enforce that interval is the same size as size so the mid-end does the > - right thing. */ > - SET_OPTION_IF_UNSET (opts, &global_options_set, > - param_stack_clash_protection_probe_interval, > - guard_size); > - > - loongarch_init_print_operand_punct (); > + /* Initialize loongarch_print_operand_punct. */ > + for (const char *p = ".$"; *p; p++) > + loongarch_print_operand_punct[(unsigned char) *p] = true; > > /* Set up array to map GCC register number to debug register number. > Ignore the special purpose register numbers. */ > - > - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) > + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > { > if (GP_REG_P (i) || FP_REG_P (i)) > loongarch_dwarf_regno[i] = i; > @@ -7726,115 +7609,53 @@ loongarch_option_override_internal (struct gcc_options *opts, > } > > /* Set up loongarch_hard_regno_mode_ok. */ > - for (mode = 0; mode < MAX_MACHINE_MODE; mode++) > - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) > + for (int mode = 0; mode < MAX_MACHINE_MODE; mode++) > + for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) > loongarch_hard_regno_mode_ok_p[mode][regno] > = loongarch_hard_regno_mode_ok_uncached (regno, (machine_mode) mode); > > /* Function to allocate machine-dependent function status. */ > init_machine_status = &loongarch_init_machine_status; > +}; > > - /* -mrecip options. */ > - static struct > - { > - const char *string; /* option name. */ > - unsigned int mask; /* mask bits to set. */ > - } > - const recip_options[] = { > - { "all", RECIP_MASK_ALL }, > - { "none", RECIP_MASK_NONE }, > - { "div", RECIP_MASK_DIV }, > - { "sqrt", RECIP_MASK_SQRT }, > - { "rsqrt", RECIP_MASK_RSQRT }, > - { "vec-div", RECIP_MASK_VEC_DIV }, > - { "vec-sqrt", RECIP_MASK_VEC_SQRT }, > - { "vec-rsqrt", RECIP_MASK_VEC_RSQRT }, > - }; > - > - if (la_recip_name) > - { > - char *p = ASTRDUP (la_recip_name); > - char *q; > - unsigned int mask, i; > - bool invert; > - > - while ((q = strtok (p, ",")) != NULL) > - { > - p = NULL; > - if (*q == '!') > - { > - invert = true; > - q++; > - } > - else > - invert = false; > - > - if (!strcmp (q, "default")) > - mask = RECIP_MASK_ALL; > - else > - { > - for (i = 0; i < ARRAY_SIZE (recip_options); i++) > - if (!strcmp (q, recip_options[i].string)) > - { > - mask = recip_options[i].mask; > - break; > - } > - > - if (i == ARRAY_SIZE (recip_options)) > - { > - error ("unknown option for %<-mrecip=%s%>", q); > - invert = false; > - mask = RECIP_MASK_NONE; > - } > - } > - > - if (invert) > - recip_mask &= ~mask; > - else > - recip_mask |= mask; > - } > - } > - if (la_recip) > - recip_mask |= RECIP_MASK_ALL; > - if (!ISA_HAS_FRECIPE) > - recip_mask = RECIP_MASK_NONE; > - > -#define INIT_TARGET_FLAG(NAME, INIT) \ > - { \ > - if (!(target_flags_explicit & MASK_##NAME)) \ > - { \ > - if (INIT) \ > - target_flags |= MASK_##NAME; \ > - else \ > - target_flags &= ~MASK_##NAME; \ > - } \ > - } > - > - /* Enable conditional moves for int and float by default. */ > - INIT_TARGET_FLAG (COND_MOVE_INT, 1) > - INIT_TARGET_FLAG (COND_MOVE_FLOAT, 1) > - > - /* Set mrelax default. */ > - INIT_TARGET_FLAG (LINKER_RELAXATION, > - HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION) > +static void > +loongarch_option_override_internal (struct loongarch_target *target, > + struct gcc_options *opts, > + struct gcc_options *opts_set) > +{ > + /* Handle options not covered by struct loongarch_target. */ > + loongarch_init_misc_options (opts, opts_set); > + > + /* Resolve the target struct. */ > + loongarch_init_target (target, > + opts->x_la_opt_cpu_arch, > + opts->x_la_opt_cpu_tune, > + opts->x_la_opt_fpu, > + opts->x_la_opt_simd, > + opts->x_la_opt_abi_base, > + opts->x_la_opt_abi_ext, > + opts->x_la_opt_cmodel, > + opts->x_la_isa_evolution, > + opts_set->x_la_isa_evolution); > > -#undef INIT_TARGET_FLAG > + loongarch_config_target (target, NULL, 0); > > - if (la_opt_explicit_relocs == M_OPT_UNSET) > - la_opt_explicit_relocs = (HAVE_AS_EXPLICIT_RELOCS > - ? (TARGET_LINKER_RELAXATION > - ? EXPLICIT_RELOCS_AUTO > - : EXPLICIT_RELOCS_ALWAYS) > - : EXPLICIT_RELOCS_NONE); > + /* Override some options according to the resolved target. */ > + loongarch_target_option_override (target, opts, opts_set); > } > > - > /* Implement TARGET_OPTION_OVERRIDE. */ > > static void > loongarch_option_override (void) > { > - loongarch_option_override_internal (&global_options, &global_options_set); > + /* Setting up the target configuration. */ > + loongarch_option_override_internal (&la_target, > + &global_options, > + &global_options_set); > + > + /* Global initializations. */ > + loongarch_global_init (); > } > > /* Implement TARGET_OPTION_SAVE. */ > diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt > index f10fcdd968c..317cd11a67c 100644 > --- a/gcc/config/loongarch/loongarch.opt > +++ b/gcc/config/loongarch/loongarch.opt > @@ -205,14 +205,14 @@ mexplicit-relocs > Target Alias(mexplicit-relocs=, always, none) > Use %reloc() assembly operators (for backward compatibility). > > -mrecip > -Target RejectNegative Var(la_recip) Save > -Generate approximate reciprocal divide and square root for better throughput. > - > mrecip= > Target RejectNegative Joined Var(la_recip_name) Save > Control generation of reciprocal estimates. > > +mrecip > +Target Alias(mrecip=, all, none) > +Generate approximate reciprocal divide and square root for better throughput. > + > ; The code model option names for -mcmodel. > Enum > Name(cmodel) Type(int)
diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in index 02f918053f5..a77893d31d9 100644 --- a/gcc/config/loongarch/genopts/loongarch.opt.in +++ b/gcc/config/loongarch/genopts/loongarch.opt.in @@ -197,14 +197,14 @@ mexplicit-relocs Target Alias(mexplicit-relocs=, always, none) Use %reloc() assembly operators (for backward compatibility). -mrecip -Target RejectNegative Var(la_recip) Save -Generate approximate reciprocal divide and square root for better throughput. - mrecip= Target RejectNegative Joined Var(la_recip_name) Save Control generation of reciprocal estimates. +mrecip +Target Alias(mrecip=, all, none) +Generate approximate reciprocal divide and square root for better throughput. + ; The code model option names for -mcmodel. Enum Name(cmodel) Type(int) diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h index 2dbf006d013..0cbf9476690 100644 --- a/gcc/config/loongarch/loongarch-def.h +++ b/gcc/config/loongarch/loongarch-def.h @@ -90,11 +90,16 @@ extern loongarch_def_array<const char *, N_ABI_BASE_TYPES> #define TO_LP64_ABI_BASE(C) (C) -#define ABI_FPU_64(abi_base) \ +#define ABI_LP64_P(abi_base) \ + (abi_base == ABI_BASE_LP64D \ + || abi_base == ABI_BASE_LP64F \ + || abi_base == ABI_BASE_LP64S) + +#define ABI_FPU64_P(abi_base) \ (abi_base == ABI_BASE_LP64D) -#define ABI_FPU_32(abi_base) \ +#define ABI_FPU32_P(abi_base) \ (abi_base == ABI_BASE_LP64F) -#define ABI_FPU_NONE(abi_base) \ +#define ABI_NOFPU_P(abi_base) \ (abi_base == ABI_BASE_LP64S) diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc index 7eeac43ed2f..380208f38bf 100644 --- a/gcc/config/loongarch/loongarch-opts.cc +++ b/gcc/config/loongarch/loongarch-opts.cc @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "obstack.h" +#include "opts.h" #include "diagnostic-core.h" #include "loongarch-cpu.h" @@ -32,8 +33,12 @@ along with GCC; see the file COPYING3. If not see #include "loongarch-str.h" #include "loongarch-def.h" +/* Target configuration */ struct loongarch_target la_target; +/* RTL cost information */ +const struct loongarch_rtx_cost_data *loongarch_cost; + /* ABI-related configuration. */ #define ABI_COUNT (sizeof(abi_priority_list)/sizeof(struct loongarch_abi)) static const struct loongarch_abi @@ -795,3 +800,246 @@ loongarch_update_gcc_opt_status (struct loongarch_target *target, /* ISA evolution features */ opts->x_la_isa_evolution = target->isa.evolution; } + +/* -mrecip=<str> handling */ +static struct + { + const char *string; /* option name. */ + unsigned int mask; /* mask bits to set. */ + } +const recip_options[] = { + { "all", RECIP_MASK_ALL }, + { "none", RECIP_MASK_NONE }, + { "div", RECIP_MASK_DIV }, + { "sqrt", RECIP_MASK_SQRT }, + { "rsqrt", RECIP_MASK_RSQRT }, + { "vec-div", RECIP_MASK_VEC_DIV }, + { "vec-sqrt", RECIP_MASK_VEC_SQRT }, + { "vec-rsqrt", RECIP_MASK_VEC_RSQRT }, +}; + +/* Parser for -mrecip=<recip_string>. */ +unsigned int +loongarch_parse_mrecip_scheme (const char *recip_string) +{ + unsigned int result_mask = RECIP_MASK_NONE; + + if (recip_string) + { + char *p = ASTRDUP (recip_string); + char *q; + unsigned int mask, i; + bool invert; + + while ((q = strtok (p, ",")) != NULL) + { + p = NULL; + if (*q == '!') + { + invert = true; + q++; + } + else + invert = false; + + if (!strcmp (q, "default")) + mask = RECIP_MASK_ALL; + else + { + for (i = 0; i < ARRAY_SIZE (recip_options); i++) + if (!strcmp (q, recip_options[i].string)) + { + mask = recip_options[i].mask; + break; + } + + if (i == ARRAY_SIZE (recip_options)) + { + error ("unknown option for %<-mrecip=%s%>", q); + invert = false; + mask = RECIP_MASK_NONE; + } + } + + if (invert) + result_mask &= ~mask; + else + result_mask |= mask; + } + } + return result_mask; +} + +/* Generate -mrecip= argument based on the mask. */ +const char* +loongarch_generate_mrecip_scheme (unsigned int mask) +{ + static char recip_scheme_str[128]; + int p = 0, tmp; + + switch (mask) + { + case RECIP_MASK_ALL: + return "all"; + + case RECIP_MASK_NONE: + return "none"; + } + + for (unsigned long i = 2; i < ARRAY_SIZE (recip_options); i++) + { + if (mask & recip_options[i].mask) + { + if ((tmp = strlen (recip_options[i].string) + 1) >= 127 - p) + gcc_unreachable (); + + recip_scheme_str[p] = ','; + strcpy (recip_scheme_str + p + 1, recip_options[i].string); + p += tmp; + } + } + recip_scheme_str[p] = '\0'; + return recip_scheme_str + 1; +} + + + +/* Refresh the switches acccording to the resolved loongarch_target struct. */ +void +loongarch_target_option_override (struct loongarch_target *target, + struct gcc_options *opts, + struct gcc_options *opts_set) +{ + loongarch_update_gcc_opt_status (target, opts, opts_set); + + /* alignments */ + if (opts->x_flag_align_functions && !opts->x_str_align_functions) + opts->x_str_align_functions + = loongarch_cpu_align[target->cpu_tune].function; + + if (opts->x_flag_align_labels && !opts->x_str_align_labels) + opts->x_str_align_labels = loongarch_cpu_align[target->cpu_tune].label; + + /* Set up parameters to be used in prefetching algorithm. */ + int simultaneous_prefetches + = loongarch_cpu_cache[target->cpu_tune].simultaneous_prefetches; + + SET_OPTION_IF_UNSET (opts, opts_set, param_simultaneous_prefetches, + simultaneous_prefetches); + + SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_line_size, + loongarch_cpu_cache[target->cpu_tune].l1d_line_size); + + SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_size, + loongarch_cpu_cache[target->cpu_tune].l1d_size); + + SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size, + loongarch_cpu_cache[target->cpu_tune].l2d_size); + + /* -mrecip= */ + opts->x_la_recip_name + = loongarch_generate_mrecip_scheme (opts->x_recip_mask); + + /* Decide which rtx_costs structure to use. */ + if (opts->x_optimize_size) + loongarch_cost = &loongarch_rtx_cost_optimize_size; + else + loongarch_cost = &loongarch_cpu_rtx_cost_data[target->cpu_tune]; + + /* If the user hasn't specified a branch cost, use the processor's + default. */ + if (!opts_set->x_la_branch_cost) + opts->x_la_branch_cost = loongarch_cost->branch_cost; + + /* other stuff */ + if (ABI_LP64_P (target->abi.base)) + opts->x_flag_pcc_struct_return = 0; + + switch (target->cmodel) + { + case CMODEL_EXTREME: + if (opts->x_flag_plt) + { + if (opts_set->x_flag_plt) + error ("code model %qs is not compatible with %s", + "extreme", "-fplt"); + opts->x_flag_plt = 0; + } + break; + + case CMODEL_TINY_STATIC: + case CMODEL_MEDIUM: + case CMODEL_NORMAL: + case CMODEL_TINY: + case CMODEL_LARGE: + break; + + default: + gcc_unreachable (); + } +} + + +/* Resolve options that's not covered by la_target. */ +void +loongarch_init_misc_options (struct gcc_options *opts, + struct gcc_options *opts_set) +{ + if (opts->x_flag_pic) + opts->x_g_switch_value = 0; + + /* -mrecip options. */ + opts->x_recip_mask = loongarch_parse_mrecip_scheme (opts->x_la_recip_name); + + /* Enable -mfrecipe if -mrecip is given. */ + if (opts_set->x_recip_mask && opts->x_recip_mask != RECIP_MASK_NONE) + { + opts->x_la_isa_evolution |= OPTION_MASK_ISA_FRECIPE; + opts_set->x_la_isa_evolution |= OPTION_MASK_ISA_FRECIPE; + } + +#define INIT_TARGET_FLAG(NAME, INIT) \ + { \ + if (!(opts_set->x_target_flags & MASK_##NAME)) \ + { \ + if (INIT) \ + opts->x_target_flags |= MASK_##NAME; \ + else \ + opts->x_target_flags &= ~MASK_##NAME; \ + } \ + } + + /* Enable conditional moves for int and float by default. */ + INIT_TARGET_FLAG (COND_MOVE_INT, 1) + INIT_TARGET_FLAG (COND_MOVE_FLOAT, 1) + + /* Set mrelax default. */ + INIT_TARGET_FLAG (LINKER_RELAXATION, + HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION) + +#undef INIT_TARGET_FLAG + + /* Set mexplicit-relocs default. */ + if (opts->x_la_opt_explicit_relocs == M_OPT_UNSET) + opts->x_la_opt_explicit_relocs = (HAVE_AS_EXPLICIT_RELOCS + ? (TARGET_LINKER_RELAXATION + ? EXPLICIT_RELOCS_AUTO + : EXPLICIT_RELOCS_ALWAYS) + : EXPLICIT_RELOCS_NONE); + + /* Enable sw prefetching at -O3 and higher. */ + if (opts->x_flag_prefetch_loop_arrays < 0 + && (opts->x_optimize >= 3 || opts->x_flag_profile_use) + && !opts->x_optimize_size) + opts->x_flag_prefetch_loop_arrays = 1; + + if (TARGET_DIRECT_EXTERN_ACCESS_OPTS_P (opts) && opts->x_flag_shlib) + error ("%qs cannot be used for compiling a shared library", + "-mdirect-extern-access"); + + /* Enforce that interval is the same size as size so the mid-end does the + right thing. */ + SET_OPTION_IF_UNSET (opts, opts_set, + param_stack_clash_protection_probe_interval, + param_stack_clash_protection_guard_size); +} diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h index 586e67e65ee..2d9f59296e7 100644 --- a/gcc/config/loongarch/loongarch-opts.h +++ b/gcc/config/loongarch/loongarch-opts.h @@ -30,6 +30,10 @@ along with GCC; see the file COPYING3. If not see /* Target configuration */ extern struct loongarch_target la_target; +/* RTL cost information */ +extern const struct loongarch_rtx_cost_data *loongarch_cost; + + /* Initialize loongarch_target from separate option variables. */ void loongarch_init_target (struct loongarch_target *target, @@ -46,11 +50,30 @@ loongarch_config_target (struct loongarch_target *target, struct loongarch_flags *flags, int follow_multilib_list_p); + +/* Refresh the switches acccording to the resolved loongarch_target struct. */ +void +loongarch_target_option_override (struct loongarch_target *target, + struct gcc_options *opts, + struct gcc_options *opts_set); + + /* option status feedback for "gcc --help=target -Q" */ void loongarch_update_gcc_opt_status (struct loongarch_target *target, struct gcc_options *opts, struct gcc_options *opts_set); + + +/* Parser for -mrecip=<recip_string>. */ +unsigned int +loongarch_parse_mrecip_scheme (const char *recip_string); + + +/* Resolve options that's not covered by la_target. */ +void +loongarch_init_misc_options (struct gcc_options *opts, + struct gcc_options *opts_set); #endif /* Flag status */ @@ -80,9 +103,7 @@ struct loongarch_flags { #define TARGET_DOUBLE_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64D) #define TARGET_64BIT (la_target.isa.base == ISA_BASE_LA64) -#define TARGET_ABI_LP64 (la_target.abi.base == ABI_BASE_LP64D \ - || la_target.abi.base == ABI_BASE_LP64F \ - || la_target.abi.base == ABI_BASE_LP64S) +#define TARGET_ABI_LP64 ABI_LP64_P(la_target.abi.base) #define ISA_HAS_LSX \ (la_target.isa.simd == ISA_EXT_SIMD_LSX \ diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 0428b6e65d5..8f686ee4096 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -208,9 +208,6 @@ const enum reg_class loongarch_regno_to_class[FIRST_PSEUDO_REGISTER] = { FRAME_REGS, FRAME_REGS }; -/* Which cost information to use. */ -static const struct loongarch_rtx_cost_data *loongarch_cost; - /* Information about a single argument. */ struct loongarch_arg_info { @@ -5905,17 +5902,6 @@ loongarch_print_operand_punctuation (FILE *file, int ch) } } -/* Initialize loongarch_print_operand_punct. */ - -static void -loongarch_init_print_operand_punct (void) -{ - const char *p; - - for (p = ".$"; *p; p++) - loongarch_print_operand_punct[(unsigned char) *p] = true; -} - /* PRINT_OPERAND prefix LETTER refers to the integer branch instruction associated with condition CODE. Print the condition part of the opcode to FILE. */ @@ -7606,118 +7592,15 @@ loongarch_init_machine_status (void) } static void -loongarch_cpu_option_override (struct loongarch_target *target, - struct gcc_options *opts, - struct gcc_options *opts_set) -{ - /* alignments */ - if (opts->x_flag_align_functions && !opts->x_str_align_functions) - opts->x_str_align_functions - = loongarch_cpu_align[target->cpu_tune].function; - - if (opts->x_flag_align_labels && !opts->x_str_align_labels) - opts->x_str_align_labels = loongarch_cpu_align[target->cpu_tune].label; - - /* Set up parameters to be used in prefetching algorithm. */ - int simultaneous_prefetches - = loongarch_cpu_cache[target->cpu_tune].simultaneous_prefetches; - - SET_OPTION_IF_UNSET (opts, opts_set, param_simultaneous_prefetches, - simultaneous_prefetches); - - SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_line_size, - loongarch_cpu_cache[target->cpu_tune].l1d_line_size); - - SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_size, - loongarch_cpu_cache[target->cpu_tune].l1d_size); - - SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size, - loongarch_cpu_cache[target->cpu_tune].l2d_size); -} - -static void -loongarch_option_override_internal (struct gcc_options *opts, - struct gcc_options *opts_set) +loongarch_global_init (void) { - int i, regno, mode; - - if (flag_pic) - g_switch_value = 0; - - loongarch_init_target (&la_target, - la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu, - la_opt_simd, la_opt_abi_base, la_opt_abi_ext, - la_opt_cmodel, opts->x_la_isa_evolution, - opts_set->x_la_isa_evolution); - - /* Handle target-specific options: compute defaults/conflicts etc. */ - loongarch_config_target (&la_target, NULL, 0); - - loongarch_update_gcc_opt_status (&la_target, opts, opts_set); - loongarch_cpu_option_override (&la_target, opts, opts_set); - - if (TARGET_ABI_LP64) - flag_pcc_struct_return = 0; - - /* Decide which rtx_costs structure to use. */ - if (optimize_size) - loongarch_cost = &loongarch_rtx_cost_optimize_size; - else - loongarch_cost = &loongarch_cpu_rtx_cost_data[la_target.cpu_tune]; - - /* If the user hasn't specified a branch cost, use the processor's - default. */ - if (la_branch_cost == 0) - la_branch_cost = loongarch_cost->branch_cost; - - /* Enable sw prefetching at -O3 and higher. */ - if (opts->x_flag_prefetch_loop_arrays < 0 - && (opts->x_optimize >= 3 || opts->x_flag_profile_use) - && !opts->x_optimize_size) - opts->x_flag_prefetch_loop_arrays = 1; - - if (TARGET_DIRECT_EXTERN_ACCESS && flag_shlib) - error ("%qs cannot be used for compiling a shared library", - "-mdirect-extern-access"); - - switch (la_target.cmodel) - { - case CMODEL_EXTREME: - if (opts->x_flag_plt) - { - if (global_options_set.x_flag_plt) - error ("code model %qs is not compatible with %s", - "extreme", "-fplt"); - opts->x_flag_plt = 0; - } - break; - - case CMODEL_TINY_STATIC: - case CMODEL_MEDIUM: - case CMODEL_NORMAL: - case CMODEL_TINY: - case CMODEL_LARGE: - break; - - default: - gcc_unreachable (); - } - - /* Validate the guard size. */ - int guard_size = param_stack_clash_protection_guard_size; - - /* Enforce that interval is the same size as size so the mid-end does the - right thing. */ - SET_OPTION_IF_UNSET (opts, &global_options_set, - param_stack_clash_protection_probe_interval, - guard_size); - - loongarch_init_print_operand_punct (); + /* Initialize loongarch_print_operand_punct. */ + for (const char *p = ".$"; *p; p++) + loongarch_print_operand_punct[(unsigned char) *p] = true; /* Set up array to map GCC register number to debug register number. Ignore the special purpose register numbers. */ - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) { if (GP_REG_P (i) || FP_REG_P (i)) loongarch_dwarf_regno[i] = i; @@ -7726,115 +7609,53 @@ loongarch_option_override_internal (struct gcc_options *opts, } /* Set up loongarch_hard_regno_mode_ok. */ - for (mode = 0; mode < MAX_MACHINE_MODE; mode++) - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + for (int mode = 0; mode < MAX_MACHINE_MODE; mode++) + for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) loongarch_hard_regno_mode_ok_p[mode][regno] = loongarch_hard_regno_mode_ok_uncached (regno, (machine_mode) mode); /* Function to allocate machine-dependent function status. */ init_machine_status = &loongarch_init_machine_status; +}; - /* -mrecip options. */ - static struct - { - const char *string; /* option name. */ - unsigned int mask; /* mask bits to set. */ - } - const recip_options[] = { - { "all", RECIP_MASK_ALL }, - { "none", RECIP_MASK_NONE }, - { "div", RECIP_MASK_DIV }, - { "sqrt", RECIP_MASK_SQRT }, - { "rsqrt", RECIP_MASK_RSQRT }, - { "vec-div", RECIP_MASK_VEC_DIV }, - { "vec-sqrt", RECIP_MASK_VEC_SQRT }, - { "vec-rsqrt", RECIP_MASK_VEC_RSQRT }, - }; - - if (la_recip_name) - { - char *p = ASTRDUP (la_recip_name); - char *q; - unsigned int mask, i; - bool invert; - - while ((q = strtok (p, ",")) != NULL) - { - p = NULL; - if (*q == '!') - { - invert = true; - q++; - } - else - invert = false; - - if (!strcmp (q, "default")) - mask = RECIP_MASK_ALL; - else - { - for (i = 0; i < ARRAY_SIZE (recip_options); i++) - if (!strcmp (q, recip_options[i].string)) - { - mask = recip_options[i].mask; - break; - } - - if (i == ARRAY_SIZE (recip_options)) - { - error ("unknown option for %<-mrecip=%s%>", q); - invert = false; - mask = RECIP_MASK_NONE; - } - } - - if (invert) - recip_mask &= ~mask; - else - recip_mask |= mask; - } - } - if (la_recip) - recip_mask |= RECIP_MASK_ALL; - if (!ISA_HAS_FRECIPE) - recip_mask = RECIP_MASK_NONE; - -#define INIT_TARGET_FLAG(NAME, INIT) \ - { \ - if (!(target_flags_explicit & MASK_##NAME)) \ - { \ - if (INIT) \ - target_flags |= MASK_##NAME; \ - else \ - target_flags &= ~MASK_##NAME; \ - } \ - } - - /* Enable conditional moves for int and float by default. */ - INIT_TARGET_FLAG (COND_MOVE_INT, 1) - INIT_TARGET_FLAG (COND_MOVE_FLOAT, 1) - - /* Set mrelax default. */ - INIT_TARGET_FLAG (LINKER_RELAXATION, - HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION) +static void +loongarch_option_override_internal (struct loongarch_target *target, + struct gcc_options *opts, + struct gcc_options *opts_set) +{ + /* Handle options not covered by struct loongarch_target. */ + loongarch_init_misc_options (opts, opts_set); + + /* Resolve the target struct. */ + loongarch_init_target (target, + opts->x_la_opt_cpu_arch, + opts->x_la_opt_cpu_tune, + opts->x_la_opt_fpu, + opts->x_la_opt_simd, + opts->x_la_opt_abi_base, + opts->x_la_opt_abi_ext, + opts->x_la_opt_cmodel, + opts->x_la_isa_evolution, + opts_set->x_la_isa_evolution); -#undef INIT_TARGET_FLAG + loongarch_config_target (target, NULL, 0); - if (la_opt_explicit_relocs == M_OPT_UNSET) - la_opt_explicit_relocs = (HAVE_AS_EXPLICIT_RELOCS - ? (TARGET_LINKER_RELAXATION - ? EXPLICIT_RELOCS_AUTO - : EXPLICIT_RELOCS_ALWAYS) - : EXPLICIT_RELOCS_NONE); + /* Override some options according to the resolved target. */ + loongarch_target_option_override (target, opts, opts_set); } - /* Implement TARGET_OPTION_OVERRIDE. */ static void loongarch_option_override (void) { - loongarch_option_override_internal (&global_options, &global_options_set); + /* Setting up the target configuration. */ + loongarch_option_override_internal (&la_target, + &global_options, + &global_options_set); + + /* Global initializations. */ + loongarch_global_init (); } /* Implement TARGET_OPTION_SAVE. */ diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt index f10fcdd968c..317cd11a67c 100644 --- a/gcc/config/loongarch/loongarch.opt +++ b/gcc/config/loongarch/loongarch.opt @@ -205,14 +205,14 @@ mexplicit-relocs Target Alias(mexplicit-relocs=, always, none) Use %reloc() assembly operators (for backward compatibility). -mrecip -Target RejectNegative Var(la_recip) Save -Generate approximate reciprocal divide and square root for better throughput. - mrecip= Target RejectNegative Joined Var(la_recip_name) Save Control generation of reciprocal estimates. +mrecip +Target Alias(mrecip=, all, none) +Generate approximate reciprocal divide and square root for better throughput. + ; The code model option names for -mcmodel. Enum Name(cmodel) Type(int)