@@ -40,6 +40,9 @@ OPTSTR_SOFT_FLOAT soft-float
OPTSTR_SINGLE_FLOAT single-float
OPTSTR_DOUBLE_FLOAT double-float
+# SIMD extensions
+OPTSTR_LSX lsx
+
# -mabi=
OPTSTR_ABI_BASE abi
STR_ABI_BASE_LP64D lp64d
@@ -76,6 +76,9 @@ m@@OPTSTR_DOUBLE_FLOAT@@
Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(m@@OPTSTR_SOFT_FLOAT@@)
Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations.
+m@@OPTSTR_LSX@@
+Target RejectNegative Var(la_opt_switches) Mask(LSX) Negative(m@@OPTSTR_LSX@@)
+Enable LoongArch SIMD Extension (LSX).
;; Base target models (implies ISA & tune parameters)
Enum
@@ -125,11 +128,14 @@ Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_
Variable
int la_opt_abi_ext = M_OPTION_NOT_SEEN
-
mbranch-cost=
Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
-mbranch-cost=COST Set the cost of branches to roughly COST instructions.
+mmemvec-cost=
+Target RejectNegative Joined UInteger Var(loongarch_vector_access_cost) IntegerRange(1, 5)
+mmemvec-cost=COST Set the cost of vector memory access instructions.
+
mcheck-zero-division
Target Mask(CHECK_ZERO_DIV)
Trap on integer divide by zero.
@@ -99,6 +99,13 @@ loongarch_cpu_cpp_builtins (cpp_reader *pfile)
else
builtin_define ("__loongarch_frlen=0");
+ if (ISA_HAS_LSX)
+ {
+ builtin_define ("__loongarch_simd");
+ builtin_define ("__loongarch_sx");
+ builtin_define ("__loongarch_sx_width=128");
+ }
+
/* Native Data Sizes. */
builtin_define_with_int_value ("_LOONGARCH_SZINT", INT_TYPE_SIZE);
builtin_define_with_int_value ("_LOONGARCH_SZLONG", LONG_TYPE_SIZE);
@@ -49,10 +49,12 @@ loongarch_cpu_default_isa[N_ARCH_TYPES] = {
[CPU_LOONGARCH64] = {
.base = ISA_BASE_LA64V100,
.fpu = ISA_EXT_FPU64,
+ .simd = 0,
},
[CPU_LA464] = {
.base = ISA_BASE_LA64V100,
.fpu = ISA_EXT_FPU64,
+ .simd = ISA_EXT_SIMD_LSX,
},
};
@@ -147,6 +149,7 @@ loongarch_isa_ext_strings[N_ISA_EXT_TYPES] = {
[ISA_EXT_FPU64] = STR_ISA_EXT_FPU64,
[ISA_EXT_FPU32] = STR_ISA_EXT_FPU32,
[ISA_EXT_NOFPU] = STR_ISA_EXT_NOFPU,
+ [ISA_EXT_SIMD_LSX] = OPTSTR_LSX,
};
const char*
@@ -176,6 +179,7 @@ loongarch_switch_strings[] = {
[SW_SOFT_FLOAT] = OPTSTR_SOFT_FLOAT,
[SW_SINGLE_FLOAT] = OPTSTR_SINGLE_FLOAT,
[SW_DOUBLE_FLOAT] = OPTSTR_DOUBLE_FLOAT,
+ [SW_LSX] = OPTSTR_LSX,
};
@@ -63,7 +63,8 @@ extern const char* loongarch_isa_ext_strings[];
#define ISA_EXT_FPU32 1
#define ISA_EXT_FPU64 2
#define N_ISA_EXT_FPU_TYPES 3
-#define N_ISA_EXT_TYPES 3
+#define ISA_EXT_SIMD_LSX 3
+#define N_ISA_EXT_TYPES 4
/* enum abi_base */
extern const char* loongarch_abi_base_strings[];
@@ -97,7 +98,8 @@ extern const char* loongarch_switch_strings[];
#define SW_SOFT_FLOAT 0
#define SW_SINGLE_FLOAT 1
#define SW_DOUBLE_FLOAT 2
-#define N_SWITCH_TYPES 3
+#define SW_LSX 3
+#define N_SWITCH_TYPES 4
/* The common default value for variables whose assignments
are triggered by command-line options. */
@@ -111,6 +113,7 @@ struct loongarch_isa
{
unsigned char base; /* ISA_BASE_ */
unsigned char fpu; /* ISA_EXT_FPU_ */
+ unsigned char simd; /* ISA_EXT_SIMD_ */
};
struct loongarch_abi
@@ -160,6 +160,10 @@ driver_get_normalized_m_opts (int argc, const char **argv)
APPEND_LTR (" %<m" OPTSTR_##NAME "=* " \
" -m" OPTSTR_##NAME "=")
+#undef APPEND_SWITCH
+#define APPEND_SWITCH(S) \
+ APPEND_LTR (" %<m" S " -m" S)
+
for (int i = 0; i < N_SWITCH_TYPES; i++)
{
APPEND_LTR (" %<m");
@@ -175,6 +179,12 @@ driver_get_normalized_m_opts (int argc, const char **argv)
APPEND_OPT (ISA_EXT_FPU);
APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.fpu]);
+ if (la_target.isa.simd)
+ {
+ APPEND_LTR (" %<m" OPTSTR_LSX " -m");
+ APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.simd]);
+ }
+
APPEND_OPT (CMODEL);
APPEND_VAL (loongarch_cmodel_strings[la_target.cmodel]);
@@ -51,6 +51,7 @@ driver_get_normalized_m_opts (int argc, const char **argv);
LA_SET_FLAG_SPEC (SOFT_FLOAT) \
LA_SET_FLAG_SPEC (SINGLE_FLOAT) \
LA_SET_FLAG_SPEC (DOUBLE_FLOAT) \
+ LA_SET_FLAG_SPEC (LSX) \
" %:get_normalized_m_opts()"
#define DRIVER_SELF_SPECS \
@@ -83,6 +83,7 @@ const int loongarch_switch_mask[N_SWITCH_TYPES] = {
/* SW_SOFT_FLOAT */ M(FORCE_SOFTF),
/* SW_SINGLE_FLOAT */ M(FORCE_F32),
/* SW_DOUBLE_FLOAT */ M(FORCE_F64),
+ /* SW_LSX */ M(LSX),
};
#undef M
@@ -142,7 +143,7 @@ loongarch_config_target (struct loongarch_target *target,
obstack_init (&msg_obstack);
struct {
- int arch, tune, fpu, abi_base, abi_ext, cmodel;
+ int arch, tune, fpu, abi_base, abi_ext, cmodel, simd;
} constrained = {
M_OPT_ABSENT(opt_arch) ? 0 : 1,
M_OPT_ABSENT(opt_tune) ? 0 : 1,
@@ -150,6 +151,7 @@ loongarch_config_target (struct loongarch_target *target,
M_OPT_ABSENT(opt_abi_base) ? 0 : 1,
M_OPT_ABSENT(opt_abi_ext) ? 0 : 1,
M_OPT_ABSENT(opt_cmodel) ? 0 : 1,
+ 0
};
#define on(NAME) ((loongarch_switch_mask[(SW_##NAME)] & opt_switches) \
@@ -251,6 +253,73 @@ config_target_isa:
((t.cpu_arch == CPU_NATIVE && constrained.arch) ?
t.isa.fpu : DEFAULT_ISA_EXT_FPU);
+ /* LoongArch SIMD extensions. */
+ int simd_switch;
+ if (on (LSX))
+ {
+ constrained.simd = 1;
+ switch (on_switch)
+ {
+ case SW_LSX:
+ t.isa.simd = ISA_EXT_SIMD_LSX;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+ simd_switch = on_switch;
+
+ /* All SIMD extensions imply a 64-bit FPU:
+ - silently adjust t.isa.fpu to "fpu64" if it is unconstrained.
+ - warn if -msingle-float / -msoft-float is on, then disable SIMD extensions
+ - abort if -mfpu=0 / -mfpu=32 is forced. */
+
+ if (t.isa.simd != 0 && t.isa.fpu != ISA_EXT_FPU64)
+ {
+ if (!constrained.fpu)
+ {
+ /* As long as the arch-default "t.isa.simd" is set to non-zero
+ for an element "t" in loongarch_cpu_default_isa, "t.isa.fpu"
+ should be set to "ISA_EXT_FPU64" accordingly. Thus reaching
+ here must be the result of forcing -mlsx/-mlasx explicitly. */
+ gcc_assert (constrained.simd);
+
+ inform (UNKNOWN_LOCATION,
+ "%<-m%s%> promotes %<%s%> to %<%s%s%>",
+ OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[t.isa.fpu],
+ OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[ISA_EXT_FPU64]);
+
+ t.isa.fpu = ISA_EXT_FPU64;
+ }
+ else if (on (SOFT_FLOAT) || on (SINGLE_FLOAT))
+ {
+ if (constrained.simd)
+ inform (UNKNOWN_LOCATION,
+ "%<-m%s%> is disabled by %<-m%s%>, because it requires %<%s%s%>",
+ loongarch_switch_strings[simd_switch],
+ loongarch_switch_strings[on_switch],
+ OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[ISA_EXT_FPU64]);
+
+ /* SIMD that comes from arch default. */
+ t.isa.simd = 0;
+ }
+ else
+ {
+ /* -mfpu=0 / -mfpu=32 is set. */
+ if (constrained.simd)
+ fatal_error (UNKNOWN_LOCATION,
+ "%<-m%s=%s%> conflicts with %<-m%s%>,"
+ "which requires %<%s%s%>",
+ OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[t.isa.fpu],
+ loongarch_switch_strings[simd_switch],
+ OPTSTR_ISA_EXT_FPU,
+ loongarch_isa_ext_strings[ISA_EXT_FPU64]);
+
+ /* Same as above. */
+ t.isa.simd = 0;
+ }
+ }
/* 4. ABI-ISA compatibility */
/* Note:
@@ -530,6 +599,17 @@ isa_str (const struct loongarch_isa *isa, char separator)
APPEND_STRING (OPTSTR_ISA_EXT_FPU)
APPEND_STRING (loongarch_isa_ext_strings[isa->fpu])
}
+
+ switch (isa->simd)
+ {
+ case ISA_EXT_SIMD_LSX:
+ APPEND1 (separator);
+ APPEND_STRING (loongarch_isa_ext_strings[isa->simd]);
+ break;
+
+ default:
+ gcc_assert (isa->simd == 0);
+ }
APPEND1 ('\0')
/* Add more here. */
@@ -66,6 +66,7 @@ loongarch_config_target (struct loongarch_target *target,
|| la_target.abi.base == ABI_BASE_LP64F \
|| la_target.abi.base == ABI_BASE_LP64S)
+#define ISA_HAS_LSX (la_target.isa.simd == ISA_EXT_SIMD_LSX)
#define TARGET_ARCH_NATIVE (la_target.cpu_arch == CPU_NATIVE)
#define LARCH_ACTUAL_ARCH (TARGET_ARCH_NATIVE \
? (la_target.cpu_native < N_ARCH_TYPES \
@@ -42,6 +42,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTSTR_SINGLE_FLOAT "single-float"
#define OPTSTR_DOUBLE_FLOAT "double-float"
+#define OPTSTR_LSX "lsx"
+
#define OPTSTR_ABI_BASE "abi"
#define STR_ABI_BASE_LP64D "lp64d"
#define STR_ABI_BASE_LP64F "lp64f"
@@ -83,6 +83,9 @@ mdouble-float
Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(msoft-float)
Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations.
+mlsx
+Target RejectNegative Var(la_opt_switches) Mask(LSX) Negative(mlsx)
+Enable LoongArch SIMD Extension (LSX).
;; Base target models (implies ISA & tune parameters)
Enum
@@ -132,11 +135,14 @@ Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_
Variable
int la_opt_abi_ext = M_OPTION_NOT_SEEN
-
mbranch-cost=
Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
-mbranch-cost=COST Set the cost of branches to roughly COST instructions.
+mmemvec-cost=
+Target RejectNegative Joined UInteger Var(loongarch_vector_access_cost) IntegerRange(1, 5)
+mmemvec-cost=COST Set the cost of vector memory access instructions.
+
mcheck-zero-division
Target Mask(CHECK_ZERO_DIV)
Trap on integer divide by zero.
From: Lulu Cheng <chenglulu@loongson.cn> gcc/ChangeLog: * config/loongarch/genopts/loongarch-strings: Added compilation framework. * config/loongarch/genopts/loongarch.opt.in: Ditto. * config/loongarch/loongarch-c.cc (loongarch_cpu_cpp_builtins): Ditto. * config/loongarch/loongarch-def.c: Ditto. * config/loongarch/loongarch-def.h (N_ISA_EXT_TYPES): Ditto. (ISA_EXT_SIMD_LSX): Ditto. (N_SWITCH_TYPES): Ditto. (SW_LSX): Ditto. (struct loongarch_isa): Ditto. * config/loongarch/loongarch-driver.cc (APPEND_SWITCH): Ditto. (driver_get_normalized_m_opts): Ditto. * config/loongarch/loongarch-driver.h (driver_get_normalized_m_opts): Ditto. * config/loongarch/loongarch-opts.cc (loongarch_config_target): Ditto. (isa_str): Ditto. * config/loongarch/loongarch-opts.h (ISA_HAS_LSX): Ditto. * config/loongarch/loongarch-str.h (OPTSTR_LSX): Ditto. * config/loongarch/loongarch.opt: Ditto. --- .../loongarch/genopts/loongarch-strings | 3 + gcc/config/loongarch/genopts/loongarch.opt.in | 8 +- gcc/config/loongarch/loongarch-c.cc | 7 ++ gcc/config/loongarch/loongarch-def.c | 4 + gcc/config/loongarch/loongarch-def.h | 7 +- gcc/config/loongarch/loongarch-driver.cc | 10 +++ gcc/config/loongarch/loongarch-driver.h | 1 + gcc/config/loongarch/loongarch-opts.cc | 82 ++++++++++++++++++- gcc/config/loongarch/loongarch-opts.h | 1 + gcc/config/loongarch/loongarch-str.h | 2 + gcc/config/loongarch/loongarch.opt | 8 +- 11 files changed, 128 insertions(+), 5 deletions(-)