From: Lulu Cheng <chengl...@loongson.cn>

gcc/ChangeLog:

        * config/loongarch/genopts/loongarch-strings: Add 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(-)

diff --git a/gcc/config/loongarch/genopts/loongarch-strings 
b/gcc/config/loongarch/genopts/loongarch-strings
index a40998ead97..24a5025061f 100644
--- a/gcc/config/loongarch/genopts/loongarch-strings
+++ b/gcc/config/loongarch/genopts/loongarch-strings
@@ -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
diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in 
b/gcc/config/loongarch/genopts/loongarch.opt.in
index 4b9b4ac273e..338d77a7e40 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -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.
diff --git a/gcc/config/loongarch/loongarch-c.cc 
b/gcc/config/loongarch/loongarch-c.cc
index 67911b78f28..b065921adc3 100644
--- a/gcc/config/loongarch/loongarch-c.cc
+++ b/gcc/config/loongarch/loongarch-c.cc
@@ -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);
diff --git a/gcc/config/loongarch/loongarch-def.c 
b/gcc/config/loongarch/loongarch-def.c
index 6729c857f7c..28e24c62249 100644
--- a/gcc/config/loongarch/loongarch-def.c
+++ b/gcc/config/loongarch/loongarch-def.c
@@ -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,
 };
 
 
diff --git a/gcc/config/loongarch/loongarch-def.h 
b/gcc/config/loongarch/loongarch-def.h
index fb8bb88eb52..f34cffcfb9b 100644
--- a/gcc/config/loongarch/loongarch-def.h
+++ b/gcc/config/loongarch/loongarch-def.h
@@ -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
diff --git a/gcc/config/loongarch/loongarch-driver.cc 
b/gcc/config/loongarch/loongarch-driver.cc
index 11ce082417f..aa5011bd86a 100644
--- a/gcc/config/loongarch/loongarch-driver.cc
+++ b/gcc/config/loongarch/loongarch-driver.cc
@@ -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]);
 
diff --git a/gcc/config/loongarch/loongarch-driver.h 
b/gcc/config/loongarch/loongarch-driver.h
index ba8817a4621..db663818b7c 100644
--- a/gcc/config/loongarch/loongarch-driver.h
+++ b/gcc/config/loongarch/loongarch-driver.h
@@ -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 \
diff --git a/gcc/config/loongarch/loongarch-opts.cc 
b/gcc/config/loongarch/loongarch-opts.cc
index a52e25236ea..9753cf1290b 100644
--- a/gcc/config/loongarch/loongarch-opts.cc
+++ b/gcc/config/loongarch/loongarch-opts.cc
@@ -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.  */
diff --git a/gcc/config/loongarch/loongarch-opts.h 
b/gcc/config/loongarch/loongarch-opts.h
index b1ff54426e4..d067c05dfc9 100644
--- a/gcc/config/loongarch/loongarch-opts.h
+++ b/gcc/config/loongarch/loongarch-opts.h
@@ -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 \
diff --git a/gcc/config/loongarch/loongarch-str.h 
b/gcc/config/loongarch/loongarch-str.h
index af2e82a321f..6fa1b1571c5 100644
--- a/gcc/config/loongarch/loongarch-str.h
+++ b/gcc/config/loongarch/loongarch-str.h
@@ -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"
diff --git a/gcc/config/loongarch/loongarch.opt 
b/gcc/config/loongarch/loongarch.opt
index 68018ade73f..5c7e6d37220 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -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.
-- 
2.31.1

Reply via email to