[v2] LoongArch: Implement option save/restore

Message ID 20240111010710.354540-1-yangyujie@loongson.cn
State Committed
Commit ea2a9c76a1dcffbbec6e53655bef9236d3a8e691
Headers
Series [v2] LoongArch: Implement option save/restore |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 pending Patch applied

Commit Message

Yang Yujie Jan. 11, 2024, 1:07 a.m. UTC
  LTO option streaming and target attributes both require per-function
target configuration, which is achieved via option save/restore.

We implement TARGET_OPTION_{SAVE,RESTORE} to switch the la_target
context in addition to other automatically maintained option states
(via the "Save" option property in the .opt files).

Tested on loongarch64-linux-gnu without regression.

	PR target/113233

gcc/ChangeLog:

	* config/loongarch/genopts/loongarch.opt.in: Mark options with
	the "Save" property.
	* config/loongarch/loongarch.opt: Same.
	* config/loongarch/loongarch-opts.cc: Refresh -mcmodel= state
	according to la_target.
	* config/loongarch/loongarch.cc: Implement TARGET_OPTION_{SAVE,
	RESTORE} for the la_target structure; Rename option conditions
	to have the same "la_" prefix.
	* config/loongarch/loongarch.h: Same.
---
 gcc/config/loongarch/genopts/loongarch.opt.in | 38 ++++-----
 gcc/config/loongarch/loongarch-opts.cc        |  7 ++
 gcc/config/loongarch/loongarch.cc             | 80 +++++++++++++++----
 gcc/config/loongarch/loongarch.h              |  2 +-
 gcc/config/loongarch/loongarch.opt            | 38 ++++-----
 5 files changed, 111 insertions(+), 54 deletions(-)
  

Comments

Yang Yujie Jan. 11, 2024, 1:10 a.m. UTC | #1
v1 -> v2:
Do not save la_target directly to struct cl_target_options in
TARGET_OPTION_SAVE, update to *opts first instead, since
it is getting saved later.
  
Lulu Cheng Jan. 11, 2024, 11:05 a.m. UTC | #2
Pushed to r14-7134.

在 2024/1/11 上午9:07, Yang Yujie 写道:
> LTO option streaming and target attributes both require per-function
> target configuration, which is achieved via option save/restore.
>
> We implement TARGET_OPTION_{SAVE,RESTORE} to switch the la_target
> context in addition to other automatically maintained option states
> (via the "Save" option property in the .opt files).
>
> Tested on loongarch64-linux-gnu without regression.
>
> 	PR target/113233
>
> gcc/ChangeLog:
>
> 	* config/loongarch/genopts/loongarch.opt.in: Mark options with
> 	the "Save" property.
> 	* config/loongarch/loongarch.opt: Same.
> 	* config/loongarch/loongarch-opts.cc: Refresh -mcmodel= state
> 	according to la_target.
> 	* config/loongarch/loongarch.cc: Implement TARGET_OPTION_{SAVE,
> 	RESTORE} for the la_target structure; Rename option conditions
> 	to have the same "la_" prefix.
> 	* config/loongarch/loongarch.h: Same.
> ---
>   gcc/config/loongarch/genopts/loongarch.opt.in | 38 ++++-----
>   gcc/config/loongarch/loongarch-opts.cc        |  7 ++
>   gcc/config/loongarch/loongarch.cc             | 80 +++++++++++++++----
>   gcc/config/loongarch/loongarch.h              |  2 +-
>   gcc/config/loongarch/loongarch.opt            | 38 ++++-----
>   5 files changed, 111 insertions(+), 54 deletions(-)
>
> diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in
> index 1dbd3ad1e3f..02f918053f5 100644
> --- a/gcc/config/loongarch/genopts/loongarch.opt.in
> +++ b/gcc/config/loongarch/genopts/loongarch.opt.in
> @@ -50,7 +50,7 @@ EnumValue
>   Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU64@@) Value(ISA_EXT_FPU64)
>   
>   m@@OPTSTR_ISA_EXT_FPU@@=
> -Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET)
> +Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET) Save
>   -m@@OPTSTR_ISA_EXT_FPU@@=FPU	Generate code for the given FPU.
>   
>   m@@OPTSTR_ISA_EXT_FPU@@=@@STR_ISA_EXT_FPU0@@
> @@ -82,7 +82,7 @@ EnumValue
>   Enum(isa_ext_simd) String(@@STR_ISA_EXT_LASX@@) Value(ISA_EXT_SIMD_LASX)
>   
>   m@@OPTSTR_ISA_EXT_SIMD@@=
> -Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET)
> +Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET) Save
>   -m@@OPTSTR_ISA_EXT_SIMD@@=SIMD	Generate code for the given SIMD extension.
>   
>   m@@STR_ISA_EXT_LSX@@
> @@ -114,11 +114,11 @@ EnumValue
>   Enum(cpu_type) String(@@STR_CPU_LA664@@) Value(CPU_LA664)
>   
>   m@@OPTSTR_ARCH@@=
> -Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET)
> +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET) Save
>   -m@@OPTSTR_ARCH@@=PROCESSOR	Generate code for the given PROCESSOR ISA.
>   
>   m@@OPTSTR_TUNE@@=
> -Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET)
> +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET) Save
>   -m@@OPTSTR_TUNE@@=PROCESSOR	Generate optimized code for PROCESSOR.
>   
>   
> @@ -149,31 +149,31 @@ Variable
>   int la_opt_abi_ext = M_OPT_UNSET
>   
>   mbranch-cost=
> -Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
> +Target RejectNegative Joined UInteger Var(la_branch_cost) Save
>   -mbranch-cost=COST	Set the cost of branches to roughly COST instructions.
>   
>   mcheck-zero-division
> -Target Mask(CHECK_ZERO_DIV)
> +Target Mask(CHECK_ZERO_DIV) Save
>   Trap on integer divide by zero.
>   
>   mcond-move-int
> -Target Var(TARGET_COND_MOVE_INT) Init(1)
> +Target Mask(COND_MOVE_INT) Save
>   Conditional moves for integral are enabled.
>   
>   mcond-move-float
> -Target Var(TARGET_COND_MOVE_FLOAT) Init(1)
> +Target Mask(COND_MOVE_FLOAT) Save
>   Conditional moves for float are enabled.
>   
>   mmemcpy
> -Target Mask(MEMCPY)
> +Target Mask(MEMCPY) Save
>   Prevent optimizing block moves, which is also the default behavior of -Os.
>   
>   mstrict-align
> -Target Var(TARGET_STRICT_ALIGN) Init(0)
> +Target Mask(STRICT_ALIGN) Save
>   Do not generate unaligned memory accesses.
>   
>   mmax-inline-memcpy-size=
> -Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024)
> +Target Joined RejectNegative UInteger Var(la_max_inline_memcpy_size) Init(1024) Save
>   -mmax-inline-memcpy-size=SIZE	Set the max size of memcpy to inline, default is 1024.
>   
>   Enum
> @@ -198,11 +198,11 @@ Target Alias(mexplicit-relocs=, always, none)
>   Use %reloc() assembly operators (for backward compatibility).
>   
>   mrecip
> -Target RejectNegative Var(loongarch_recip)
> +Target RejectNegative Var(la_recip) Save
>   Generate approximate reciprocal divide and square root for better throughput.
>   
>   mrecip=
> -Target RejectNegative Joined Var(loongarch_recip_name)
> +Target RejectNegative Joined Var(la_recip_name) Save
>   Control generation of reciprocal estimates.
>   
>   ; The code model option names for -mcmodel.
> @@ -229,29 +229,29 @@ EnumValue
>   Enum(cmodel) String(@@STR_CMODEL_EXTREME@@) Value(CMODEL_EXTREME)
>   
>   mcmodel=
> -Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET)
> +Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET) Save
>   Specify the code model.
>   
>   mdirect-extern-access
> -Target Var(TARGET_DIRECT_EXTERN_ACCESS) Init(0)
> +Target Mask(DIRECT_EXTERN_ACCESS) Save
>   Avoid using the GOT to access external symbols.
>   
>   mrelax
> -Target Var(loongarch_mrelax) Init(HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION)
> +Target Mask(LINKER_RELAXATION)
>   Take advantage of linker relaxations to reduce the number of instructions
>   required to materialize symbol addresses.
>   
>   mpass-mrelax-to-as
> -Target Var(loongarch_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
> +Driver Var(la_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
>   Pass -mrelax or -mno-relax option to the assembler.
>   
>   -param=loongarch-vect-unroll-limit=
> -Target Joined UInteger Var(loongarch_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
> +Target Joined UInteger Var(la_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
>   Used to limit unroll factor which indicates how much the autovectorizer may
>   unroll a loop.  The default value is 6.
>   
>   -param=loongarch-vect-issue-info=
> -Target Undocumented Joined UInteger Var(loongarch_vect_issue_info) Init(4) IntegerRange(1, 64) Param
> +Target Undocumented Joined UInteger Var(la_vect_issue_info) Init(4) IntegerRange(1, 64) Param
>   Indicate how many non memory access vector instructions can be issued per
>   cycle, it's used in unroll factor determination for autovectorizer.  The
>   default value is 4.
> diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
> index 7eb1f2d4f2e..b87299513c9 100644
> --- a/gcc/config/loongarch/loongarch-opts.cc
> +++ b/gcc/config/loongarch/loongarch-opts.cc
> @@ -785,8 +785,15 @@ loongarch_update_gcc_opt_status (struct loongarch_target *target,
>     opts->x_la_opt_cpu_arch = target->cpu_arch;
>     opts->x_la_opt_cpu_tune = target->cpu_tune;
>   
> +  /* status of -mcmodel */
> +  opts->x_la_opt_cmodel = target->cmodel;
> +
>     /* status of -mfpu */
>     opts->x_la_opt_fpu = target->isa.fpu;
> +
> +  /* status of -msimd */
>     opts->x_la_opt_simd = target->isa.simd;
> +
> +  /* ISA evolution features */
>     opts->x_la_isa_evolution = target->isa.evolution;
>   }
> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
> index 594e5a00c98..90cfdb8effe 100644
> --- a/gcc/config/loongarch/loongarch.cc
> +++ b/gcc/config/loongarch/loongarch.cc
> @@ -4094,10 +4094,10 @@ loongarch_vector_costs::determine_suggested_unroll_factor (loop_vec_info loop_vi
>   
>     /* Use this simple hardware resource model that how many non vld/vst
>        vector instructions can be issued per cycle.  */
> -  unsigned int issue_info = loongarch_vect_issue_info;
> +  unsigned int issue_info = la_vect_issue_info;
>     unsigned int reduc_factor = m_reduc_factor > 1 ? m_reduc_factor : 1;
>     unsigned int uf = CEIL (reduc_factor * issue_info, nstmts_nonldst);
> -  uf = MIN ((unsigned int) loongarch_vect_unroll_limit, uf);
> +  uf = MIN ((unsigned int) la_vect_unroll_limit, uf);
>   
>     return 1 << ceil_log2 (uf);
>   }
> @@ -5555,7 +5555,7 @@ loongarch_expand_block_move (rtx dest, rtx src, rtx r_length, rtx r_align)
>       return false;
>   
>     HOST_WIDE_INT length = INTVAL (r_length);
> -  if (length > loongarch_max_inline_memcpy_size)
> +  if (length > la_max_inline_memcpy_size)
>       return false;
>   
>     HOST_WIDE_INT align = INTVAL (r_align);
> @@ -7533,13 +7533,6 @@ loongarch_option_override_internal (struct gcc_options *opts,
>     loongarch_update_gcc_opt_status (&la_target, opts, opts_set);
>     loongarch_cpu_option_override (&la_target, opts, opts_set);
>   
> -  if (la_opt_explicit_relocs == M_OPT_UNSET)
> -    la_opt_explicit_relocs = (HAVE_AS_EXPLICIT_RELOCS
> -			      ? (loongarch_mrelax
> -				 ? EXPLICIT_RELOCS_AUTO
> -				 : EXPLICIT_RELOCS_ALWAYS)
> -			      : EXPLICIT_RELOCS_NONE);
> -
>     if (TARGET_ABI_LP64)
>       flag_pcc_struct_return = 0;
>   
> @@ -7551,8 +7544,8 @@ loongarch_option_override_internal (struct gcc_options *opts,
>   
>     /* If the user hasn't specified a branch cost, use the processor's
>        default.  */
> -  if (loongarch_branch_cost == 0)
> -    loongarch_branch_cost = loongarch_cost->branch_cost;
> +  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
> @@ -7639,9 +7632,9 @@ loongarch_option_override_internal (struct gcc_options *opts,
>   	{ "vec-rsqrt", RECIP_MASK_VEC_RSQRT },
>     };
>   
> -  if (loongarch_recip_name)
> +  if (la_recip_name)
>       {
> -      char *p = ASTRDUP (loongarch_recip_name);
> +      char *p = ASTRDUP (la_recip_name);
>         char *q;
>         unsigned int mask, i;
>         bool invert;
> @@ -7682,10 +7675,38 @@ loongarch_option_override_internal (struct gcc_options *opts,
>   	    recip_mask |= mask;
>   	}
>       }
> -  if (loongarch_recip)
> +  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)
> +
> +#undef INIT_TARGET_FLAG
> +
> +  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);
>   }
>   
>   
> @@ -7697,6 +7718,31 @@ loongarch_option_override (void)
>     loongarch_option_override_internal (&global_options, &global_options_set);
>   }
>   
> +/* Implement TARGET_OPTION_SAVE.  */
> +static void
> +loongarch_option_save (struct cl_target_option *,
> +		       struct gcc_options *opts,
> +		       struct gcc_options *opts_set)
> +{
> +  loongarch_update_gcc_opt_status (&la_target, opts, opts_set);
> +}
> +
> +/* Implement TARGET_OPTION_RESTORE.  */
> +static void
> +loongarch_option_restore (struct gcc_options *,
> +			  struct gcc_options *,
> +			  struct cl_target_option *ptr)
> +{
> +  la_target.cpu_arch = ptr->x_la_opt_cpu_arch;
> +  la_target.cpu_tune = ptr->x_la_opt_cpu_tune;
> +
> +  la_target.isa.fpu = ptr->x_la_opt_fpu;
> +  la_target.isa.simd = ptr->x_la_opt_simd;
> +  la_target.isa.evolution = ptr->x_la_isa_evolution;
> +
> +  la_target.cmodel = ptr->x_la_opt_cmodel;
> +}
> +
>   /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
>   
>   static void
> @@ -11748,6 +11794,10 @@ loongarch_asm_code_end (void)
>   
>   #undef TARGET_OPTION_OVERRIDE
>   #define TARGET_OPTION_OVERRIDE loongarch_option_override
> +#undef TARGET_OPTION_SAVE
> +#define TARGET_OPTION_SAVE loongarch_option_save
> +#undef TARGET_OPTION_RESTORE
> +#define TARGET_OPTION_RESTORE loongarch_option_restore
>   
>   #undef TARGET_LEGITIMIZE_ADDRESS
>   #define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address
> diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
> index aee334b8fab..4e6ede926d3 100644
> --- a/gcc/config/loongarch/loongarch.h
> +++ b/gcc/config/loongarch/loongarch.h
> @@ -868,7 +868,7 @@ typedef struct {
>   /* A C expression for the cost of a branch instruction.  A value of
>      1 is the default; other values are interpreted relative to that.  */
>   
> -#define BRANCH_COST(speed_p, predictable_p) loongarch_branch_cost
> +#define BRANCH_COST(speed_p, predictable_p) la_branch_cost
>   
>   /* Return the asm template for a conditional branch instruction.
>      OPCODE is the opcode's mnemonic and OPERANDS is the asm template for
> diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt
> index adb2304fbd5..f10fcdd968c 100644
> --- a/gcc/config/loongarch/loongarch.opt
> +++ b/gcc/config/loongarch/loongarch.opt
> @@ -58,7 +58,7 @@ EnumValue
>   Enum(isa_ext_fpu) String(64) Value(ISA_EXT_FPU64)
>   
>   mfpu=
> -Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET)
> +Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET) Save
>   -mfpu=FPU	Generate code for the given FPU.
>   
>   mfpu=0
> @@ -90,7 +90,7 @@ EnumValue
>   Enum(isa_ext_simd) String(lasx) Value(ISA_EXT_SIMD_LASX)
>   
>   msimd=
> -Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET)
> +Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET) Save
>   -msimd=SIMD	Generate code for the given SIMD extension.
>   
>   mlsx
> @@ -122,11 +122,11 @@ EnumValue
>   Enum(cpu_type) String(la664) Value(CPU_LA664)
>   
>   march=
> -Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET)
> +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET) Save
>   -march=PROCESSOR	Generate code for the given PROCESSOR ISA.
>   
>   mtune=
> -Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET)
> +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET) Save
>   -mtune=PROCESSOR	Generate optimized code for PROCESSOR.
>   
>   
> @@ -157,31 +157,31 @@ Variable
>   int la_opt_abi_ext = M_OPT_UNSET
>   
>   mbranch-cost=
> -Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
> +Target RejectNegative Joined UInteger Var(la_branch_cost) Save
>   -mbranch-cost=COST	Set the cost of branches to roughly COST instructions.
>   
>   mcheck-zero-division
> -Target Mask(CHECK_ZERO_DIV)
> +Target Mask(CHECK_ZERO_DIV) Save
>   Trap on integer divide by zero.
>   
>   mcond-move-int
> -Target Var(TARGET_COND_MOVE_INT) Init(1)
> +Target Mask(COND_MOVE_INT) Save
>   Conditional moves for integral are enabled.
>   
>   mcond-move-float
> -Target Var(TARGET_COND_MOVE_FLOAT) Init(1)
> +Target Mask(COND_MOVE_FLOAT) Save
>   Conditional moves for float are enabled.
>   
>   mmemcpy
> -Target Mask(MEMCPY)
> +Target Mask(MEMCPY) Save
>   Prevent optimizing block moves, which is also the default behavior of -Os.
>   
>   mstrict-align
> -Target Var(TARGET_STRICT_ALIGN) Init(0)
> +Target Mask(STRICT_ALIGN) Save
>   Do not generate unaligned memory accesses.
>   
>   mmax-inline-memcpy-size=
> -Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024)
> +Target Joined RejectNegative UInteger Var(la_max_inline_memcpy_size) Init(1024) Save
>   -mmax-inline-memcpy-size=SIZE	Set the max size of memcpy to inline, default is 1024.
>   
>   Enum
> @@ -206,11 +206,11 @@ Target Alias(mexplicit-relocs=, always, none)
>   Use %reloc() assembly operators (for backward compatibility).
>   
>   mrecip
> -Target RejectNegative Var(loongarch_recip)
> +Target RejectNegative Var(la_recip) Save
>   Generate approximate reciprocal divide and square root for better throughput.
>   
>   mrecip=
> -Target RejectNegative Joined Var(loongarch_recip_name)
> +Target RejectNegative Joined Var(la_recip_name) Save
>   Control generation of reciprocal estimates.
>   
>   ; The code model option names for -mcmodel.
> @@ -237,29 +237,29 @@ EnumValue
>   Enum(cmodel) String(extreme) Value(CMODEL_EXTREME)
>   
>   mcmodel=
> -Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET)
> +Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET) Save
>   Specify the code model.
>   
>   mdirect-extern-access
> -Target Var(TARGET_DIRECT_EXTERN_ACCESS) Init(0)
> +Target Mask(DIRECT_EXTERN_ACCESS) Save
>   Avoid using the GOT to access external symbols.
>   
>   mrelax
> -Target Var(loongarch_mrelax) Init(HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION)
> +Target Mask(LINKER_RELAXATION)
>   Take advantage of linker relaxations to reduce the number of instructions
>   required to materialize symbol addresses.
>   
>   mpass-mrelax-to-as
> -Target Var(loongarch_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
> +Driver Var(la_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
>   Pass -mrelax or -mno-relax option to the assembler.
>   
>   -param=loongarch-vect-unroll-limit=
> -Target Joined UInteger Var(loongarch_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
> +Target Joined UInteger Var(la_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
>   Used to limit unroll factor which indicates how much the autovectorizer may
>   unroll a loop.  The default value is 6.
>   
>   -param=loongarch-vect-issue-info=
> -Target Undocumented Joined UInteger Var(loongarch_vect_issue_info) Init(4) IntegerRange(1, 64) Param
> +Target Undocumented Joined UInteger Var(la_vect_issue_info) Init(4) IntegerRange(1, 64) Param
>   Indicate how many non memory access vector instructions can be issued per
>   cycle, it's used in unroll factor determination for autovectorizer.  The
>   default value is 4.
  

Patch

diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in
index 1dbd3ad1e3f..02f918053f5 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -50,7 +50,7 @@  EnumValue
 Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU64@@) Value(ISA_EXT_FPU64)
 
 m@@OPTSTR_ISA_EXT_FPU@@=
-Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET)
+Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET) Save
 -m@@OPTSTR_ISA_EXT_FPU@@=FPU	Generate code for the given FPU.
 
 m@@OPTSTR_ISA_EXT_FPU@@=@@STR_ISA_EXT_FPU0@@
@@ -82,7 +82,7 @@  EnumValue
 Enum(isa_ext_simd) String(@@STR_ISA_EXT_LASX@@) Value(ISA_EXT_SIMD_LASX)
 
 m@@OPTSTR_ISA_EXT_SIMD@@=
-Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET)
+Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET) Save
 -m@@OPTSTR_ISA_EXT_SIMD@@=SIMD	Generate code for the given SIMD extension.
 
 m@@STR_ISA_EXT_LSX@@
@@ -114,11 +114,11 @@  EnumValue
 Enum(cpu_type) String(@@STR_CPU_LA664@@) Value(CPU_LA664)
 
 m@@OPTSTR_ARCH@@=
-Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET)
+Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET) Save
 -m@@OPTSTR_ARCH@@=PROCESSOR	Generate code for the given PROCESSOR ISA.
 
 m@@OPTSTR_TUNE@@=
-Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET)
+Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET) Save
 -m@@OPTSTR_TUNE@@=PROCESSOR	Generate optimized code for PROCESSOR.
 
 
@@ -149,31 +149,31 @@  Variable
 int la_opt_abi_ext = M_OPT_UNSET
 
 mbranch-cost=
-Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
+Target RejectNegative Joined UInteger Var(la_branch_cost) Save
 -mbranch-cost=COST	Set the cost of branches to roughly COST instructions.
 
 mcheck-zero-division
-Target Mask(CHECK_ZERO_DIV)
+Target Mask(CHECK_ZERO_DIV) Save
 Trap on integer divide by zero.
 
 mcond-move-int
-Target Var(TARGET_COND_MOVE_INT) Init(1)
+Target Mask(COND_MOVE_INT) Save
 Conditional moves for integral are enabled.
 
 mcond-move-float
-Target Var(TARGET_COND_MOVE_FLOAT) Init(1)
+Target Mask(COND_MOVE_FLOAT) Save
 Conditional moves for float are enabled.
 
 mmemcpy
-Target Mask(MEMCPY)
+Target Mask(MEMCPY) Save
 Prevent optimizing block moves, which is also the default behavior of -Os.
 
 mstrict-align
-Target Var(TARGET_STRICT_ALIGN) Init(0)
+Target Mask(STRICT_ALIGN) Save
 Do not generate unaligned memory accesses.
 
 mmax-inline-memcpy-size=
-Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024)
+Target Joined RejectNegative UInteger Var(la_max_inline_memcpy_size) Init(1024) Save
 -mmax-inline-memcpy-size=SIZE	Set the max size of memcpy to inline, default is 1024.
 
 Enum
@@ -198,11 +198,11 @@  Target Alias(mexplicit-relocs=, always, none)
 Use %reloc() assembly operators (for backward compatibility).
 
 mrecip
-Target RejectNegative Var(loongarch_recip)
+Target RejectNegative Var(la_recip) Save
 Generate approximate reciprocal divide and square root for better throughput.
 
 mrecip=
-Target RejectNegative Joined Var(loongarch_recip_name)
+Target RejectNegative Joined Var(la_recip_name) Save
 Control generation of reciprocal estimates.
 
 ; The code model option names for -mcmodel.
@@ -229,29 +229,29 @@  EnumValue
 Enum(cmodel) String(@@STR_CMODEL_EXTREME@@) Value(CMODEL_EXTREME)
 
 mcmodel=
-Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET)
+Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET) Save
 Specify the code model.
 
 mdirect-extern-access
-Target Var(TARGET_DIRECT_EXTERN_ACCESS) Init(0)
+Target Mask(DIRECT_EXTERN_ACCESS) Save
 Avoid using the GOT to access external symbols.
 
 mrelax
-Target Var(loongarch_mrelax) Init(HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION)
+Target Mask(LINKER_RELAXATION)
 Take advantage of linker relaxations to reduce the number of instructions
 required to materialize symbol addresses.
 
 mpass-mrelax-to-as
-Target Var(loongarch_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
+Driver Var(la_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
 Pass -mrelax or -mno-relax option to the assembler.
 
 -param=loongarch-vect-unroll-limit=
-Target Joined UInteger Var(loongarch_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
+Target Joined UInteger Var(la_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
 Used to limit unroll factor which indicates how much the autovectorizer may
 unroll a loop.  The default value is 6.
 
 -param=loongarch-vect-issue-info=
-Target Undocumented Joined UInteger Var(loongarch_vect_issue_info) Init(4) IntegerRange(1, 64) Param
+Target Undocumented Joined UInteger Var(la_vect_issue_info) Init(4) IntegerRange(1, 64) Param
 Indicate how many non memory access vector instructions can be issued per
 cycle, it's used in unroll factor determination for autovectorizer.  The
 default value is 4.
diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
index 7eb1f2d4f2e..b87299513c9 100644
--- a/gcc/config/loongarch/loongarch-opts.cc
+++ b/gcc/config/loongarch/loongarch-opts.cc
@@ -785,8 +785,15 @@  loongarch_update_gcc_opt_status (struct loongarch_target *target,
   opts->x_la_opt_cpu_arch = target->cpu_arch;
   opts->x_la_opt_cpu_tune = target->cpu_tune;
 
+  /* status of -mcmodel */
+  opts->x_la_opt_cmodel = target->cmodel;
+
   /* status of -mfpu */
   opts->x_la_opt_fpu = target->isa.fpu;
+
+  /* status of -msimd */
   opts->x_la_opt_simd = target->isa.simd;
+
+  /* ISA evolution features */
   opts->x_la_isa_evolution = target->isa.evolution;
 }
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 594e5a00c98..90cfdb8effe 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -4094,10 +4094,10 @@  loongarch_vector_costs::determine_suggested_unroll_factor (loop_vec_info loop_vi
 
   /* Use this simple hardware resource model that how many non vld/vst
      vector instructions can be issued per cycle.  */
-  unsigned int issue_info = loongarch_vect_issue_info;
+  unsigned int issue_info = la_vect_issue_info;
   unsigned int reduc_factor = m_reduc_factor > 1 ? m_reduc_factor : 1;
   unsigned int uf = CEIL (reduc_factor * issue_info, nstmts_nonldst);
-  uf = MIN ((unsigned int) loongarch_vect_unroll_limit, uf);
+  uf = MIN ((unsigned int) la_vect_unroll_limit, uf);
 
   return 1 << ceil_log2 (uf);
 }
@@ -5555,7 +5555,7 @@  loongarch_expand_block_move (rtx dest, rtx src, rtx r_length, rtx r_align)
     return false;
 
   HOST_WIDE_INT length = INTVAL (r_length);
-  if (length > loongarch_max_inline_memcpy_size)
+  if (length > la_max_inline_memcpy_size)
     return false;
 
   HOST_WIDE_INT align = INTVAL (r_align);
@@ -7533,13 +7533,6 @@  loongarch_option_override_internal (struct gcc_options *opts,
   loongarch_update_gcc_opt_status (&la_target, opts, opts_set);
   loongarch_cpu_option_override (&la_target, opts, opts_set);
 
-  if (la_opt_explicit_relocs == M_OPT_UNSET)
-    la_opt_explicit_relocs = (HAVE_AS_EXPLICIT_RELOCS
-			      ? (loongarch_mrelax
-				 ? EXPLICIT_RELOCS_AUTO
-				 : EXPLICIT_RELOCS_ALWAYS)
-			      : EXPLICIT_RELOCS_NONE);
-
   if (TARGET_ABI_LP64)
     flag_pcc_struct_return = 0;
 
@@ -7551,8 +7544,8 @@  loongarch_option_override_internal (struct gcc_options *opts,
 
   /* If the user hasn't specified a branch cost, use the processor's
      default.  */
-  if (loongarch_branch_cost == 0)
-    loongarch_branch_cost = loongarch_cost->branch_cost;
+  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
@@ -7639,9 +7632,9 @@  loongarch_option_override_internal (struct gcc_options *opts,
 	{ "vec-rsqrt", RECIP_MASK_VEC_RSQRT },
   };
 
-  if (loongarch_recip_name)
+  if (la_recip_name)
     {
-      char *p = ASTRDUP (loongarch_recip_name);
+      char *p = ASTRDUP (la_recip_name);
       char *q;
       unsigned int mask, i;
       bool invert;
@@ -7682,10 +7675,38 @@  loongarch_option_override_internal (struct gcc_options *opts,
 	    recip_mask |= mask;
 	}
     }
-  if (loongarch_recip)
+  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)
+
+#undef INIT_TARGET_FLAG
+
+  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);
 }
 
 
@@ -7697,6 +7718,31 @@  loongarch_option_override (void)
   loongarch_option_override_internal (&global_options, &global_options_set);
 }
 
+/* Implement TARGET_OPTION_SAVE.  */
+static void
+loongarch_option_save (struct cl_target_option *,
+		       struct gcc_options *opts,
+		       struct gcc_options *opts_set)
+{
+  loongarch_update_gcc_opt_status (&la_target, opts, opts_set);
+}
+
+/* Implement TARGET_OPTION_RESTORE.  */
+static void
+loongarch_option_restore (struct gcc_options *,
+			  struct gcc_options *,
+			  struct cl_target_option *ptr)
+{
+  la_target.cpu_arch = ptr->x_la_opt_cpu_arch;
+  la_target.cpu_tune = ptr->x_la_opt_cpu_tune;
+
+  la_target.isa.fpu = ptr->x_la_opt_fpu;
+  la_target.isa.simd = ptr->x_la_opt_simd;
+  la_target.isa.evolution = ptr->x_la_isa_evolution;
+
+  la_target.cmodel = ptr->x_la_opt_cmodel;
+}
+
 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
 
 static void
@@ -11748,6 +11794,10 @@  loongarch_asm_code_end (void)
 
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE loongarch_option_override
+#undef TARGET_OPTION_SAVE
+#define TARGET_OPTION_SAVE loongarch_option_save
+#undef TARGET_OPTION_RESTORE
+#define TARGET_OPTION_RESTORE loongarch_option_restore
 
 #undef TARGET_LEGITIMIZE_ADDRESS
 #define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index aee334b8fab..4e6ede926d3 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -868,7 +868,7 @@  typedef struct {
 /* A C expression for the cost of a branch instruction.  A value of
    1 is the default; other values are interpreted relative to that.  */
 
-#define BRANCH_COST(speed_p, predictable_p) loongarch_branch_cost
+#define BRANCH_COST(speed_p, predictable_p) la_branch_cost
 
 /* Return the asm template for a conditional branch instruction.
    OPCODE is the opcode's mnemonic and OPERANDS is the asm template for
diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt
index adb2304fbd5..f10fcdd968c 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -58,7 +58,7 @@  EnumValue
 Enum(isa_ext_fpu) String(64) Value(ISA_EXT_FPU64)
 
 mfpu=
-Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET)
+Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET) Save
 -mfpu=FPU	Generate code for the given FPU.
 
 mfpu=0
@@ -90,7 +90,7 @@  EnumValue
 Enum(isa_ext_simd) String(lasx) Value(ISA_EXT_SIMD_LASX)
 
 msimd=
-Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET)
+Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET) Save
 -msimd=SIMD	Generate code for the given SIMD extension.
 
 mlsx
@@ -122,11 +122,11 @@  EnumValue
 Enum(cpu_type) String(la664) Value(CPU_LA664)
 
 march=
-Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET)
+Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET) Save
 -march=PROCESSOR	Generate code for the given PROCESSOR ISA.
 
 mtune=
-Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET)
+Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET) Save
 -mtune=PROCESSOR	Generate optimized code for PROCESSOR.
 
 
@@ -157,31 +157,31 @@  Variable
 int la_opt_abi_ext = M_OPT_UNSET
 
 mbranch-cost=
-Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
+Target RejectNegative Joined UInteger Var(la_branch_cost) Save
 -mbranch-cost=COST	Set the cost of branches to roughly COST instructions.
 
 mcheck-zero-division
-Target Mask(CHECK_ZERO_DIV)
+Target Mask(CHECK_ZERO_DIV) Save
 Trap on integer divide by zero.
 
 mcond-move-int
-Target Var(TARGET_COND_MOVE_INT) Init(1)
+Target Mask(COND_MOVE_INT) Save
 Conditional moves for integral are enabled.
 
 mcond-move-float
-Target Var(TARGET_COND_MOVE_FLOAT) Init(1)
+Target Mask(COND_MOVE_FLOAT) Save
 Conditional moves for float are enabled.
 
 mmemcpy
-Target Mask(MEMCPY)
+Target Mask(MEMCPY) Save
 Prevent optimizing block moves, which is also the default behavior of -Os.
 
 mstrict-align
-Target Var(TARGET_STRICT_ALIGN) Init(0)
+Target Mask(STRICT_ALIGN) Save
 Do not generate unaligned memory accesses.
 
 mmax-inline-memcpy-size=
-Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024)
+Target Joined RejectNegative UInteger Var(la_max_inline_memcpy_size) Init(1024) Save
 -mmax-inline-memcpy-size=SIZE	Set the max size of memcpy to inline, default is 1024.
 
 Enum
@@ -206,11 +206,11 @@  Target Alias(mexplicit-relocs=, always, none)
 Use %reloc() assembly operators (for backward compatibility).
 
 mrecip
-Target RejectNegative Var(loongarch_recip)
+Target RejectNegative Var(la_recip) Save
 Generate approximate reciprocal divide and square root for better throughput.
 
 mrecip=
-Target RejectNegative Joined Var(loongarch_recip_name)
+Target RejectNegative Joined Var(la_recip_name) Save
 Control generation of reciprocal estimates.
 
 ; The code model option names for -mcmodel.
@@ -237,29 +237,29 @@  EnumValue
 Enum(cmodel) String(extreme) Value(CMODEL_EXTREME)
 
 mcmodel=
-Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET)
+Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET) Save
 Specify the code model.
 
 mdirect-extern-access
-Target Var(TARGET_DIRECT_EXTERN_ACCESS) Init(0)
+Target Mask(DIRECT_EXTERN_ACCESS) Save
 Avoid using the GOT to access external symbols.
 
 mrelax
-Target Var(loongarch_mrelax) Init(HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION)
+Target Mask(LINKER_RELAXATION)
 Take advantage of linker relaxations to reduce the number of instructions
 required to materialize symbol addresses.
 
 mpass-mrelax-to-as
-Target Var(loongarch_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
+Driver Var(la_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
 Pass -mrelax or -mno-relax option to the assembler.
 
 -param=loongarch-vect-unroll-limit=
-Target Joined UInteger Var(loongarch_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
+Target Joined UInteger Var(la_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
 Used to limit unroll factor which indicates how much the autovectorizer may
 unroll a loop.  The default value is 6.
 
 -param=loongarch-vect-issue-info=
-Target Undocumented Joined UInteger Var(loongarch_vect_issue_info) Init(4) IntegerRange(1, 64) Param
+Target Undocumented Joined UInteger Var(la_vect_issue_info) Init(4) IntegerRange(1, 64) Param
 Indicate how many non memory access vector instructions can be issued per
 cycle, it's used in unroll factor determination for autovectorizer.  The
 default value is 4.