From 0cae10595a7521e2c430c605c1f830570b3c9682 Mon Sep 17 00:00:00 2001
From: Lu Weining <luweining@loongson.cn>
Date: Thu, 30 Nov 2023 14:08:45 +0800
Subject: [PATCH 1/9] [Driver] Support -mcmodel= for LoongArch (#72514)

7e42545 rejects unsupported mcmodel options, but normal/medium/extreme
should be supported models for LoongArch according to [gcc
document](https://gcc.gnu.org/onlinedocs/gcc/LoongArch-Options.html).

The mappings among `gcc`, `clang driver`, `clang cc1` and `LLVM (i.e.
llc --code-model=)` are:

|     gcc      |  clang driver |  clang cc1   |    LLVM    |
| -------------  | ------------------ | ----------------- | -------------- |
| normal    |      normal     |   small        |    small    |
| medium  |     medium     |   medium    |    medium |
| extreme  |     extreme     |  large         |     large     |

(cherry picked from commit 1296d20adfb0978afe38d67efab9818079d870ca)
---
 clang/lib/Driver/ToolChains/Clang.cpp | 38 ++++++++++++++++++++-------
 clang/test/Driver/mcmodel.c           | 15 +++++++++++
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index fac4f03d6193..4e5f689498d6 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5773,18 +5773,38 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
     StringRef CM = A->getValue();
-    if (CM == "small" || CM == "kernel" || CM == "medium" || CM == "large" ||
-        CM == "tiny") {
-      if (Triple.isOSAIX() && CM == "medium")
-        CmdArgs.push_back("-mcmodel=large");
-      else if (Triple.isAArch64() && (CM == "kernel" || CM == "medium"))
+    if (Triple.isLoongArch()) {
+      bool Ok = false;
+      if (CM == "extreme" &&
+          Args.hasFlagNoClaim(options::OPT_fplt, options::OPT_fno_plt, false))
+        D.Diag(diag::err_drv_argument_not_allowed_with)
+            << A->getAsString(Args) << "-fplt";
+      Ok = CM == "normal" || CM == "medium" || CM == "extreme";
+      // Convert to LLVM recognizable names.
+      if (Ok) {
+        CM = llvm::StringSwitch<StringRef>(CM)
+                 .Case("normal", "small")
+                 .Case("extreme", "large")
+                 .Default(CM);
+        CmdArgs.push_back(Args.MakeArgString("-mcmodel=" + CM));
+      } else {
         D.Diag(diag::err_drv_invalid_argument_to_option)
             << CM << A->getOption().getName();
-      else
-        A->render(Args, CmdArgs);
+      }
     } else {
-      D.Diag(diag::err_drv_invalid_argument_to_option)
-          << CM << A->getOption().getName();
+      if (CM == "small" || CM == "kernel" || CM == "medium" || CM == "large" ||
+          CM == "tiny") {
+        if (Triple.isOSAIX() && CM == "medium")
+          CmdArgs.push_back("-mcmodel=large");
+        else if (Triple.isAArch64() && (CM == "kernel" || CM == "medium"))
+          D.Diag(diag::err_drv_invalid_argument_to_option)
+              << CM << A->getOption().getName();
+        else
+          A->render(Args, CmdArgs);
+      } else {
+        D.Diag(diag::err_drv_invalid_argument_to_option)
+            << CM << A->getOption().getName();
+      }
     }
   }
 
diff --git a/clang/test/Driver/mcmodel.c b/clang/test/Driver/mcmodel.c
index 63b432036159..4aada126cf06 100644
--- a/clang/test/Driver/mcmodel.c
+++ b/clang/test/Driver/mcmodel.c
@@ -8,6 +8,14 @@
 // RUN: not %clang -c -mcmodel=lager %s 2>&1 | FileCheck --check-prefix=INVALID %s
 // RUN: not %clang -c --target=aarch64 -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=AARCH64-MEDIUM %s
 // RUN: not %clang -c --target=aarch64 -mcmodel=kernel %s 2>&1 | FileCheck --check-prefix=AARCH64-KERNEL %s
+// RUN: %clang --target=loongarch64 -### -S -mcmodel=normal %s 2>&1 | FileCheck --check-prefix=SMALL %s
+// RUN: %clang --target=loongarch64 -### -S -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=MEDIUM %s
+// RUN: %clang --target=loongarch64 -### -S -mcmodel=extreme %s 2>&1 | FileCheck --check-prefix=LARGE %s
+// RUN: not %clang -c --target=loongarch64 -mcmodel=tiny %s 2>&1 | FileCheck --check-prefix=ERR-LOONGARCH64-TINY %s
+// RUN: not %clang -c --target=loongarch64 -mcmodel=small %s 2>&1 | FileCheck --check-prefix=ERR-LOONGARCH64-SMALL %s
+// RUN: not %clang -c --target=loongarch64 -mcmodel=kernel %s 2>&1 | FileCheck --check-prefix=ERR-LOONGARCH64-KERNEL %s
+// RUN: not %clang -c --target=loongarch64 -mcmodel=large %s 2>&1 | FileCheck --check-prefix=ERR-LOONGARCH64-LARGE %s
+// RUN: not %clang -c --target=loongarch64 -mcmodel=extreme -fplt %s 2>&1 | FileCheck --check-prefix=ERR-LOONGARCH64-PLT-EXTREME %s
 
 // TINY: "-mcmodel=tiny"
 // SMALL: "-mcmodel=small"
@@ -20,3 +28,10 @@
 
 // AARCH64-MEDIUM: error: invalid argument 'medium' to -mcmodel=
 // AARCH64-KERNEL: error: invalid argument 'kernel' to -mcmodel=
+
+// ERR-LOONGARCH64-TINY:   error: invalid argument 'tiny' to -mcmodel=
+// ERR-LOONGARCH64-SMALL:  error: invalid argument 'small' to -mcmodel=
+// ERR-LOONGARCH64-KERNEL: error: invalid argument 'kernel' to -mcmodel=
+// ERR-LOONGARCH64-LARGE:  error: invalid argument 'large' to -mcmodel=
+
+// ERR-LOONGARCH64-PLT-EXTREME: error: invalid argument '-mcmodel=extreme' not allowed with '-fplt'
-- 
2.20.1


From b0e5225dea19a71b0c2f2168c117ac5032c2d18a Mon Sep 17 00:00:00 2001
From: Zhaoxin Yang <yangzhaoxin@loongson.cn>
Date: Tue, 9 Jul 2024 14:13:19 +0800
Subject: [PATCH 2/9] [LoongArch][clang] Add support for option `-msimd=` and
 macro `__loongarch_simd_width`. (#97984)

(cherry picked from commit 626c7ce33f850831949e4e724016ddbff3a34990)
---
 .../clang/Basic/DiagnosticDriverKinds.td      |   2 +
 clang/include/clang/Driver/Options.td         |   3 +
 clang/lib/Basic/Targets/LoongArch.cpp         |   8 +-
 .../lib/Driver/ToolChains/Arch/LoongArch.cpp  |  29 ++++
 clang/test/Driver/loongarch-msimd.c           | 129 ++++++++++++++++++
 clang/test/Preprocessor/init-loongarch.c      |   3 +
 6 files changed, 172 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Driver/loongarch-msimd.c

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 6b68bc458b93..060f96118364 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -757,6 +757,8 @@ def err_drv_loongarch_wrong_fpu_width_for_lasx : Error<
   "wrong fpu width; LASX depends on 64-bit FPU.">;
 def err_drv_loongarch_invalid_simd_option_combination : Error<
   "invalid option combination; LASX depends on LSX.">;
+def err_drv_loongarch_invalid_msimd_EQ : Error<
+  "invalid argument '%0' to -msimd=; must be one of: none, lsx, lasx">;
 
 def err_drv_expand_response_file : Error<
   "failed to expand response file: %0">;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 344c8bd49da7..530bb53ea9b5 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4236,6 +4236,9 @@ def mlasx : Flag<["-"], "mlasx">, Group<m_loongarch_Features_Group>,
   HelpText<"Enable Loongson Advanced SIMD Extension (LASX).">;
 def mno_lasx : Flag<["-"], "mno-lasx">, Group<m_loongarch_Features_Group>,
   HelpText<"Disable Loongson Advanced SIMD Extension (LASX).">;
+def msimd_EQ : Joined<["-"], "msimd=">, Group<m_loongarch_Features_Group>,
+  Flags<[TargetSpecific]>,
+  HelpText<"Select the SIMD extension(s) to be enabled in LoongArch either 'none', 'lsx', 'lasx'.">;
 def mnop_mcount : Flag<["-"], "mnop-mcount">, HelpText<"Generate mcount/__fentry__ calls as nops. To activate they need to be patched in.">,
   Flags<[CC1Option]>, Group<m_Group>,
   MarshallingInfoFlag<CodeGenOpts<"MNopMCount">>;
diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp
index 88537989a051..913404240916 100644
--- a/clang/lib/Basic/Targets/LoongArch.cpp
+++ b/clang/lib/Basic/Targets/LoongArch.cpp
@@ -208,10 +208,14 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts,
     TuneCPU = ArchName;
   Builder.defineMacro("__loongarch_tune", Twine('"') + TuneCPU + Twine('"'));
 
-  if (HasFeatureLSX)
+  if (HasFeatureLASX) {
+    Builder.defineMacro("__loongarch_simd_width", "256");
     Builder.defineMacro("__loongarch_sx", Twine(1));
-  if (HasFeatureLASX)
     Builder.defineMacro("__loongarch_asx", Twine(1));
+  } else if (HasFeatureLSX) {
+    Builder.defineMacro("__loongarch_simd_width", "128");
+    Builder.defineMacro("__loongarch_sx", Twine(1));
+  }
 
   StringRef ABI = getABI();
   if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s")
diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
index 31153a67ad28..2d9c3f810a06 100644
--- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -207,6 +207,35 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
     } else /*-mno-lasx*/
       Features.push_back("-lasx");
   }
+
+  // Select lsx/lasx feature determined by -msimd=.
+  // Option -msimd= has lower priority than -m[no-]lsx and -m[no-]lasx.
+  if (const Arg *A = Args.getLastArg(options::OPT_msimd_EQ)) {
+    StringRef MSIMD = A->getValue();
+    if (MSIMD == "lsx") {
+      // Option -msimd=lsx depends on 64-bit FPU.
+      // -m*-float and -mfpu=none/0/32 conflict with -mlsx.
+      if (llvm::find(Features, "-d") != Features.end())
+        D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LSX*/ 0;
+      // The previous option does not contain feature -lsx.
+      else if (llvm::find(Features, "-lsx") == Features.end())
+        Features.push_back("+lsx");
+    } else if (MSIMD == "lasx") {
+      // Option -msimd=lasx depends on 64-bit FPU and LSX.
+      // -m*-float and -mfpu=none/0/32 conflict with -mlsx.
+      if (llvm::find(Features, "-d") != Features.end())
+        D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LASX*/ 1;
+      else if (llvm::find(Features, "-lsx") != Features.end())
+        D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination);
+      // The previous option does not contain feature -lasx.
+      else if (llvm::find(Features, "-lasx") == Features.end()) {
+        Features.push_back("+lsx");
+        Features.push_back("+lasx");
+      }
+    } else if (MSIMD != "none") {
+      D.Diag(diag::err_drv_loongarch_invalid_msimd_EQ) << MSIMD;
+    }
+  }
 }
 
 std::string loongarch::postProcessTargetCPUString(const std::string &CPU,
diff --git a/clang/test/Driver/loongarch-msimd.c b/clang/test/Driver/loongarch-msimd.c
new file mode 100644
index 000000000000..984f3e8bf2bf
--- /dev/null
+++ b/clang/test/Driver/loongarch-msimd.c
@@ -0,0 +1,129 @@
+/// Test -msimd options.
+
+/// COM: -msimd=none
+// RUN: %clang --target=loongarch64 -mlasx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,LASX
+// RUN: %clang --target=loongarch64 -mlasx -mlsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,LASX
+
+// RUN: %clang --target=loongarch64 -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlsx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -mlsx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -mlsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlsx -msimd=none -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+
+
+/// COM: -msimd=lsx
+// RUN: %clang --target=loongarch64 -mlasx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,LASX
+// RUN: %clang --target=loongarch64 -mlasx -mlsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,LASX
+
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlsx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -mlsx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+
+// RUN: %clang --target=loongarch64 -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -mlsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+
+
+/// COM: -msimd=lasx
+// RUN: %clang --target=loongarch64 -msimd=lasx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,LASX
+// RUN: %clang --target=loongarch64 -mlasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,LASX
+// RUN: %clang --target=loongarch64 -mlasx -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,LASX
+// RUN: %clang --target=loongarch64 -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,LASX
+
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+// RUN: %clang --target=loongarch64 -mno-lasx -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+// RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
+// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
+
+
+// LSX: "-target-feature" "+lsx"
+// LASX: "-target-feature" "+lasx"
+// NOLSX-NOT: "-target-feature" "+lsx"
+// NOLASX-NOT: "-target-feature" "+lasx"
diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c
index e235a7283021..154ad82e0f8c 100644
--- a/clang/test/Preprocessor/init-loongarch.c
+++ b/clang/test/Preprocessor/init-loongarch.c
@@ -817,6 +817,7 @@
 // RUN: %clang --target=loongarch64 -mno-lasx -mlsx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MLSX %s
 // MLSX-NOT: #define __loongarch_asx
+// MLSX: #define __loongarch_simd_width 128
 // MLSX: #define __loongarch_sx 1
 
 // RUN: %clang --target=loongarch64 -mlasx -x c -E -dM %s -o - \
@@ -828,6 +829,7 @@
 // RUN: %clang --target=loongarch64 -mlasx -mlsx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MLASX %s
 // MLASX: #define __loongarch_asx 1
+// MLASX: #define __loongarch_simd_width 256
 // MLASX: #define __loongarch_sx 1
 
 // RUN: %clang --target=loongarch64 -mno-lsx -x c -E -dM %s -o - \
@@ -841,4 +843,5 @@
 // RUN: %clang --target=loongarch64 -mno-lasx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MNO-LSX %s
 // MNO-LSX-NOT: #define __loongarch_asx
+// MNO-LSX-NOT: #define __loongarch_simd_width
 // MNO-LSX-NOT: #define __loongarch_sx
-- 
2.20.1


From b2f8e92e88bf63e54ace9b2f9b2aa77dcf0c50c4 Mon Sep 17 00:00:00 2001
From: Zhaoxin Yang <yangzhaoxin@loongson.cn>
Date: Thu, 11 Jul 2024 17:43:38 +0800
Subject: [PATCH 3/9] [LoongArch][clang] Modify `loongarch-msimd.c` to avoid
 `grep -o`. NFC (#98442)

Address buildbot failure:
https://lab.llvm.org/buildbot/#/builders/64/builds/250/steps/6/logs/FAIL__Clang__loongarch-msimd_c

(cherry picked from commit 74b933c28e777fdc04e50f5f96e4f7a4ad1e79a6)
---
 clang/test/Driver/loongarch-msimd.c | 42 +++--------------------------
 1 file changed, 4 insertions(+), 38 deletions(-)

diff --git a/clang/test/Driver/loongarch-msimd.c b/clang/test/Driver/loongarch-msimd.c
index 984f3e8bf2bf..cd463300c874 100644
--- a/clang/test/Driver/loongarch-msimd.c
+++ b/clang/test/Driver/loongarch-msimd.c
@@ -2,128 +2,94 @@
 
 /// COM: -msimd=none
 // RUN: %clang --target=loongarch64 -mlasx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 // RUN: %clang --target=loongarch64 -mlasx -mlsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 
 // RUN: %clang --target=loongarch64 -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlsx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -mlsx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -mlsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlsx -msimd=none -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 
 
 /// COM: -msimd=lsx
 // RUN: %clang --target=loongarch64 -mlasx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 // RUN: %clang --target=loongarch64 -mlasx -mlsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlsx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -mlsx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -mno-lsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 
 // RUN: %clang --target=loongarch64 -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -mlsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 
 
 /// COM: -msimd=lasx
 // RUN: %clang --target=loongarch64 -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 // RUN: %clang --target=loongarch64 -mlasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 // RUN: %clang --target=loongarch64 -mlasx -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 // RUN: %clang --target=loongarch64 -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
 
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -msimd=lsx -fsyntax-only %s -### 2>&1 | \
-// RUN:   grep -o '"-target-feature" "+[[:alnum:]]\+"' | sort -r | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 
 
-// LSX: "-target-feature" "+lsx"
-// LASX: "-target-feature" "+lasx"
+// NOLSX-NOT: "-target-feature" "+lsx"
+// NOLASX-NOT: "-target-feature" "+lasx"
+// LSX-DAG: "-target-feature" "+lsx"
+// LASX-DAG: "-target-feature" "+lasx"
 // NOLSX-NOT: "-target-feature" "+lsx"
 // NOLASX-NOT: "-target-feature" "+lasx"
-- 
2.20.1


From b5d3aa3ac0dcf98fbb5f8d2d9de295be991c9e8f Mon Sep 17 00:00:00 2001
From: Zhaoxin Yang <yangzhaoxin@loongson.cn>
Date: Tue, 23 Jul 2024 12:06:59 +0800
Subject: [PATCH 4/9] [LoongArch][CodeGen] Implement 128-bit and 256-bit vector
 shuffle. (#100054)

[LoongArch][CodeGen] Implement 128-bit and 256-bit vector shuffle
operations.

In LoongArch, shuffle operations can be divided into two types:
- Single-vector shuffle: Shuffle using only one vector, with the other
vector being `undef` or not selected by mask. This can be expanded to
instructions such as `vreplvei` and `vshuf4i`.
- Two-vector shuffle: Shuflle using two vectors. This can be expanded to
instructions like `vilv[l/h]`, `vpack[ev/od]`, `vpick[ev/od]` and the
basic `vshuf`.

In the future, more optimizations may be added, such as handling 1-bit
vectors and processing single element patterns, etc.

(cherry picked from commit 464ea880cf7710cc8675c83001d7ae020406cf42)
---
 clang/lib/Driver/ToolChains/Arch/LoongArch.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
index 2d9c3f810a06..8b3d2837a4e5 100644
--- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -216,7 +216,7 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
       // Option -msimd=lsx depends on 64-bit FPU.
       // -m*-float and -mfpu=none/0/32 conflict with -mlsx.
       if (llvm::find(Features, "-d") != Features.end())
-        D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LSX*/ 0;
+        D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lsx);
       // The previous option does not contain feature -lsx.
       else if (llvm::find(Features, "-lsx") == Features.end())
         Features.push_back("+lsx");
@@ -224,7 +224,7 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
       // Option -msimd=lasx depends on 64-bit FPU and LSX.
       // -m*-float and -mfpu=none/0/32 conflict with -mlsx.
       if (llvm::find(Features, "-d") != Features.end())
-        D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LASX*/ 1;
+        D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lasx);
       else if (llvm::find(Features, "-lsx") != Features.end())
         D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination);
       // The previous option does not contain feature -lasx.
-- 
2.20.1


From 17f537eeaef8db451c70fc56a921e5ff542f713b Mon Sep 17 00:00:00 2001
From: Ami-zhang <zhanglimin@loongson.cn>
Date: Tue, 23 Jul 2024 14:02:04 +0800
Subject: [PATCH 5/9] [LoongArch] Enable 128-bits vector by default (#100056)

This commit is to enable 128 vector feature by default, in order to be
consistent with gcc.

(cherry picked from commit b4ef0ba244899a64a1b1e6448eca942cfa5eda18)
---
 .../lib/Driver/ToolChains/Arch/LoongArch.cpp  | 76 +++++++++++--------
 .../test/Driver/loongarch-default-features.c  |  2 +-
 clang/test/Driver/loongarch-mlasx.c           |  6 +-
 clang/test/Driver/loongarch-msimd.c           |  4 +-
 clang/test/Driver/loongarch-msingle-float.c   |  4 +-
 clang/test/Driver/loongarch-msoft-float.c     |  4 +-
 clang/test/Preprocessor/init-loongarch.c      |  8 +-
 7 files changed, 60 insertions(+), 44 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
index 8b3d2837a4e5..87d7b30ef5d3 100644
--- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -127,6 +127,11 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
                                            const llvm::Triple &Triple,
                                            const ArgList &Args,
                                            std::vector<StringRef> &Features) {
+  // Enable the `lsx` feature on 64-bit LoongArch by default.
+  if (Triple.isLoongArch64() &&
+      (!Args.hasArgNoClaim(clang::driver::options::OPT_march_EQ)))
+    Features.push_back("+lsx");
+
   std::string ArchName;
   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
     ArchName = A->getValue();
@@ -145,9 +150,11 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
     } else if (A->getOption().matches(options::OPT_msingle_float)) {
       Features.push_back("+f");
       Features.push_back("-d");
+      Features.push_back("-lsx");
     } else /*Soft-float*/ {
       Features.push_back("-f");
       Features.push_back("-d");
+      Features.push_back("-lsx");
     }
   } else if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
     StringRef FPU = A->getValue();
@@ -157,9 +164,11 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
     } else if (FPU == "32") {
       Features.push_back("+f");
       Features.push_back("-d");
+      Features.push_back("-lsx");
     } else if (FPU == "0" || FPU == "none") {
       Features.push_back("-f");
       Features.push_back("-d");
+      Features.push_back("-lsx");
     } else {
       D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
     }
@@ -175,6 +184,42 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
     A->ignoreTargetSpecific();
   if (Arg *A = Args.getLastArgNoClaim(options::OPT_mfpu_EQ))
     A->ignoreTargetSpecific();
+  if (Arg *A = Args.getLastArgNoClaim(options::OPT_msimd_EQ))
+    A->ignoreTargetSpecific();
+
+  // Select lsx/lasx feature determined by -msimd=.
+  // Option -msimd= precedes -m[no-]lsx and -m[no-]lasx.
+  if (const Arg *A = Args.getLastArg(options::OPT_msimd_EQ)) {
+    StringRef MSIMD = A->getValue();
+    if (MSIMD == "lsx") {
+      // Option -msimd=lsx depends on 64-bit FPU.
+      // -m*-float and -mfpu=none/0/32 conflict with -msimd=lsx.
+      if (llvm::find(Features, "-d") != Features.end())
+        D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lsx);
+      else
+        Features.push_back("+lsx");
+    } else if (MSIMD == "lasx") {
+      // Option -msimd=lasx depends on 64-bit FPU and LSX.
+      // -m*-float, -mfpu=none/0/32 and -mno-lsx conflict with -msimd=lasx.
+      if (llvm::find(Features, "-d") != Features.end())
+        D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lasx);
+      else if (llvm::find(Features, "-lsx") != Features.end())
+        D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination);
+
+      // The command options do not contain -mno-lasx.
+      if (!Args.getLastArg(options::OPT_mno_lasx)) {
+        Features.push_back("+lsx");
+        Features.push_back("+lasx");
+      }
+    } else if (MSIMD == "none") {
+      if (llvm::find(Features, "+lsx") != Features.end())
+        Features.push_back("-lsx");
+      if (llvm::find(Features, "+lasx") != Features.end())
+        Features.push_back("-lasx");
+    } else {
+      D.Diag(diag::err_drv_loongarch_invalid_msimd_EQ) << MSIMD;
+    }
+  }
 
   // Select lsx feature determined by -m[no-]lsx.
   if (const Arg *A = Args.getLastArg(options::OPT_mlsx, options::OPT_mno_lsx)) {
@@ -198,8 +243,6 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
     if (A->getOption().matches(options::OPT_mlasx)) {
       if (llvm::find(Features, "-d") != Features.end())
         D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lasx);
-      else if (llvm::find(Features, "-lsx") != Features.end())
-        D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination);
       else { /*-mlasx*/
         Features.push_back("+lsx");
         Features.push_back("+lasx");
@@ -207,35 +250,6 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D,
     } else /*-mno-lasx*/
       Features.push_back("-lasx");
   }
-
-  // Select lsx/lasx feature determined by -msimd=.
-  // Option -msimd= has lower priority than -m[no-]lsx and -m[no-]lasx.
-  if (const Arg *A = Args.getLastArg(options::OPT_msimd_EQ)) {
-    StringRef MSIMD = A->getValue();
-    if (MSIMD == "lsx") {
-      // Option -msimd=lsx depends on 64-bit FPU.
-      // -m*-float and -mfpu=none/0/32 conflict with -mlsx.
-      if (llvm::find(Features, "-d") != Features.end())
-        D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lsx);
-      // The previous option does not contain feature -lsx.
-      else if (llvm::find(Features, "-lsx") == Features.end())
-        Features.push_back("+lsx");
-    } else if (MSIMD == "lasx") {
-      // Option -msimd=lasx depends on 64-bit FPU and LSX.
-      // -m*-float and -mfpu=none/0/32 conflict with -mlsx.
-      if (llvm::find(Features, "-d") != Features.end())
-        D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lasx);
-      else if (llvm::find(Features, "-lsx") != Features.end())
-        D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination);
-      // The previous option does not contain feature -lasx.
-      else if (llvm::find(Features, "-lasx") == Features.end()) {
-        Features.push_back("+lsx");
-        Features.push_back("+lasx");
-      }
-    } else if (MSIMD != "none") {
-      D.Diag(diag::err_drv_loongarch_invalid_msimd_EQ) << MSIMD;
-    }
-  }
 }
 
 std::string loongarch::postProcessTargetCPUString(const std::string &CPU,
diff --git a/clang/test/Driver/loongarch-default-features.c b/clang/test/Driver/loongarch-default-features.c
index 3cdf3ba3d23e..90634bbcf003 100644
--- a/clang/test/Driver/loongarch-default-features.c
+++ b/clang/test/Driver/loongarch-default-features.c
@@ -2,7 +2,7 @@
 // RUN: %clang --target=loongarch64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LA64
 
 // LA32: "target-features"="+32bit"
-// LA64: "target-features"="+64bit,+d,+f,+ual"
+// LA64: "target-features"="+64bit,+d,+f,+lsx,+ual"
 
 int foo(void) {
   return 3;
diff --git a/clang/test/Driver/loongarch-mlasx.c b/clang/test/Driver/loongarch-mlasx.c
index 0b934f125c9e..87634ff5a9a4 100644
--- a/clang/test/Driver/loongarch-mlasx.c
+++ b/clang/test/Driver/loongarch-mlasx.c
@@ -5,7 +5,7 @@
 // RUN: %clang --target=loongarch64 -mno-lasx -fsyntax-only %s -### 2>&1 | \
 // RUN:   FileCheck %s --check-prefix=CC1-NOLASX
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   FileCheck %s --check-prefix=CC1-NOLASX
+// RUN:   FileCheck %s --check-prefix=CC1-LSX
 // RUN: %clang --target=loongarch64 -mno-lasx -mlasx -fsyntax-only %s -### 2>&1 | \
 // RUN:   FileCheck %s --check-prefix=CC1-LASX
 // RUN: %clang --target=loongarch64 -mlsx -mlasx -fsyntax-only %s -### 2>&1 | \
@@ -18,7 +18,7 @@
 // RUN: %clang --target=loongarch64 -mno-lasx -S -emit-llvm %s -o - | \
 // RUN:   FileCheck %s --check-prefix=IR-NOLASX
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -S -emit-llvm %s -o - | \
-// RUN:   FileCheck %s --check-prefix=IR-NOLASX
+// RUN:   FileCheck %s --check-prefix=IR-LSX
 // RUN: %clang --target=loongarch64 -mno-lasx -mlasx -S -emit-llvm %s -o - | \
 // RUN:   FileCheck %s --check-prefix=IR-LASX
 // RUN: %clang --target=loongarch64 -mlsx -mlasx -S -emit-llvm %s -o - | \
@@ -26,9 +26,11 @@
 // RUN: %clang --target=loongarch64 -mlasx -mlsx -S -emit-llvm %s -o - | \
 // RUN:   FileCheck %s --check-prefix=IR-LASX
 
+// CC1-LSX: "-target-feature" "+lsx"
 // CC1-LASX: "-target-feature" "+lsx" "-target-feature" "+lasx"
 // CC1-NOLASX: "-target-feature" "-lasx"
 
+// IR-LSX: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+lsx{{(,.*)?}}"
 // IR-LASX: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+lasx{{(,.*)?}}"
 // IR-NOLASX: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-lasx{{(,.*)?}}"
 
diff --git a/clang/test/Driver/loongarch-msimd.c b/clang/test/Driver/loongarch-msimd.c
index cd463300c874..49d298e1b2e3 100644
--- a/clang/test/Driver/loongarch-msimd.c
+++ b/clang/test/Driver/loongarch-msimd.c
@@ -75,9 +75,9 @@
 // RUN:   FileCheck %s --check-prefixes=LSX,LASX
 
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 // RUN: %clang --target=loongarch64 -mno-lasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
-// RUN:   FileCheck %s --check-prefixes=NOLSX,NOLASX
+// RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
 
 // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \
 // RUN:   FileCheck %s --check-prefixes=LSX,NOLASX
diff --git a/clang/test/Driver/loongarch-msingle-float.c b/clang/test/Driver/loongarch-msingle-float.c
index bd9b3e8a8c01..4eb0865b53a5 100644
--- a/clang/test/Driver/loongarch-msingle-float.c
+++ b/clang/test/Driver/loongarch-msingle-float.c
@@ -11,10 +11,10 @@
 // WARN: warning: ignoring '-mabi=lp64s' as it conflicts with that implied by '-msingle-float' (lp64f)
 // WARN: warning: ignoring '-mfpu=64' as it conflicts with that implied by '-msingle-float' (32)
 
-// CC1: "-target-feature" "+f"{{.*}} "-target-feature" "-d"
+// CC1: "-target-feature" "+f"{{.*}} "-target-feature" "-d" "-target-feature" "-lsx"
 // CC1: "-target-abi" "lp64f"
 
-// IR: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+f,{{(.*,)?}}-d"
+// IR: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+f,{{(.*,)?}}-d,-lsx"
 
 int foo(void) {
   return 3;
diff --git a/clang/test/Driver/loongarch-msoft-float.c b/clang/test/Driver/loongarch-msoft-float.c
index 0e5121ac84b4..ebf27fb00e30 100644
--- a/clang/test/Driver/loongarch-msoft-float.c
+++ b/clang/test/Driver/loongarch-msoft-float.c
@@ -11,10 +11,10 @@
 // WARN: warning: ignoring '-mabi=lp64d' as it conflicts with that implied by '-msoft-float' (lp64s)
 // WARN: warning: ignoring '-mfpu=64' as it conflicts with that implied by '-msoft-float' (0)
 
-// CC1: "-target-feature" "-f"{{.*}} "-target-feature" "-d"
+// CC1: "-target-feature" "-f"{{.*}} "-target-feature" "-d" "-target-feature" "-lsx"
 // CC1: "-target-abi" "lp64s"
 
-// IR: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-d,{{(.*,)?}}-f{{(,.*)?}}"
+// IR: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-d,{{(.*,)?}}-f,-lsx"
 
 int foo(void) {
   return 3;
diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c
index 154ad82e0f8c..635d029ce9d3 100644
--- a/clang/test/Preprocessor/init-loongarch.c
+++ b/clang/test/Preprocessor/init-loongarch.c
@@ -814,6 +814,8 @@
 // RUN:   | FileCheck --match-full-lines --check-prefix=MLSX %s
 // RUN: %clang --target=loongarch64 -mlsx -mno-lasx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MLSX %s
+// RUN: %clang --target=loongarch64 -mno-lasx -x c -E -dM %s -o - \
+// RUN:   | FileCheck --match-full-lines --check-prefix=MLSX %s
 // RUN: %clang --target=loongarch64 -mno-lasx -mlsx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MLSX %s
 // MLSX-NOT: #define __loongarch_asx
@@ -822,12 +824,12 @@
 
 // RUN: %clang --target=loongarch64 -mlasx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MLASX %s
-// RUN: %clang --target=loongarch64 -mno-lasx -mlasx -x c -E -dM %s -o - \
-// RUN:   | FileCheck --match-full-lines --check-prefix=MLASX %s
 // RUN: %clang --target=loongarch64 -mlsx -mlasx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MLASX %s
 // RUN: %clang --target=loongarch64 -mlasx -mlsx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MLASX %s
+// RUN: %clang --target=loongarch64 -mno-lasx -mlasx -x c -E -dM %s -o - \
+// RUN:   | FileCheck --match-full-lines --check-prefix=MLASX %s
 // MLASX: #define __loongarch_asx 1
 // MLASX: #define __loongarch_simd_width 256
 // MLASX: #define __loongarch_sx 1
@@ -840,8 +842,6 @@
 // RUN:   | FileCheck --match-full-lines --check-prefix=MNO-LSX %s
 // RUN: %clang --target=loongarch64 -mno-lasx -mno-lsx -x c -E -dM %s -o - \
 // RUN:   | FileCheck --match-full-lines --check-prefix=MNO-LSX %s
-// RUN: %clang --target=loongarch64 -mno-lasx -x c -E -dM %s -o - \
-// RUN:   | FileCheck --match-full-lines --check-prefix=MNO-LSX %s
 // MNO-LSX-NOT: #define __loongarch_asx
 // MNO-LSX-NOT: #define __loongarch_simd_width
 // MNO-LSX-NOT: #define __loongarch_sx
-- 
2.20.1


From 57eaecf7bdb7a7502580076b365b4f70dde1185d Mon Sep 17 00:00:00 2001
From: Ami-zhang <zhanglimin@loongson.cn>
Date: Tue, 23 Jan 2024 14:24:58 +0800
Subject: [PATCH 6/9] [LoongArch] Add definitions and feature 'frecipe' for FP
 approximation intrinsics/builtins (#78962)

This PR adds definitions and 'frecipe' feature for FP approximation
intrinsics/builtins. In additions, this adds and complements relative
testcases.

(cherry picked from commit fcb8342a219ada8ec641790a4c8a9f969d7d64ee)
---
 .../clang/Basic/BuiltinsLoongArchBase.def     |  5 +++
 .../clang/Basic/BuiltinsLoongArchLASX.def     |  6 +++
 .../clang/Basic/BuiltinsLoongArchLSX.def      |  6 +++
 clang/lib/Headers/larchintrin.h               | 12 +++++
 clang/lib/Headers/lasxintrin.h                | 24 ++++++++++
 clang/lib/Headers/lsxintrin.h                 | 24 ++++++++++
 .../LoongArch/builtin-dbl-approximate.c       | 45 +++++++++++++++++++
 .../LoongArch/builtin-flt-approximate.c       | 45 +++++++++++++++++++
 .../CodeGen/LoongArch/intrinsic-la64-error.c  | 21 +++++++++
 .../lasx/builtin-approximate-alias.c          | 37 +++++++++++++++
 .../LoongArch/lasx/builtin-approximate.c      | 38 ++++++++++++++++
 .../LoongArch/lsx/builtin-approximate-alias.c | 37 +++++++++++++++
 .../LoongArch/lsx/builtin-approximate.c       | 38 ++++++++++++++++
 13 files changed, 338 insertions(+)
 create mode 100644 clang/test/CodeGen/LoongArch/builtin-dbl-approximate.c
 create mode 100644 clang/test/CodeGen/LoongArch/builtin-flt-approximate.c
 create mode 100644 clang/test/CodeGen/LoongArch/lasx/builtin-approximate-alias.c
 create mode 100644 clang/test/CodeGen/LoongArch/lasx/builtin-approximate.c
 create mode 100644 clang/test/CodeGen/LoongArch/lsx/builtin-approximate-alias.c
 create mode 100644 clang/test/CodeGen/LoongArch/lsx/builtin-approximate.c

diff --git a/clang/include/clang/Basic/BuiltinsLoongArchBase.def b/clang/include/clang/Basic/BuiltinsLoongArchBase.def
index cbb239223aae..a5a07c167908 100644
--- a/clang/include/clang/Basic/BuiltinsLoongArchBase.def
+++ b/clang/include/clang/Basic/BuiltinsLoongArchBase.def
@@ -51,3 +51,8 @@ TARGET_BUILTIN(__builtin_loongarch_iocsrwr_d, "vUWiUi", "nc", "64bit")
 
 TARGET_BUILTIN(__builtin_loongarch_lddir_d, "WiWiIUWi", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_ldpte_d, "vWiIUWi", "nc", "64bit")
+
+TARGET_BUILTIN(__builtin_loongarch_frecipe_s, "ff", "nc", "f,frecipe")
+TARGET_BUILTIN(__builtin_loongarch_frecipe_d, "dd", "nc", "d,frecipe")
+TARGET_BUILTIN(__builtin_loongarch_frsqrte_s, "ff", "nc", "f,frecipe")
+TARGET_BUILTIN(__builtin_loongarch_frsqrte_d, "dd", "nc", "d,frecipe")
diff --git a/clang/include/clang/Basic/BuiltinsLoongArchLASX.def b/clang/include/clang/Basic/BuiltinsLoongArchLASX.def
index 3de200f665b6..4cf51cc000f6 100644
--- a/clang/include/clang/Basic/BuiltinsLoongArchLASX.def
+++ b/clang/include/clang/Basic/BuiltinsLoongArchLASX.def
@@ -657,9 +657,15 @@ TARGET_BUILTIN(__builtin_lasx_xvfsqrt_d, "V4dV4d", "nc", "lasx")
 TARGET_BUILTIN(__builtin_lasx_xvfrecip_s, "V8fV8f", "nc", "lasx")
 TARGET_BUILTIN(__builtin_lasx_xvfrecip_d, "V4dV4d", "nc", "lasx")
 
+TARGET_BUILTIN(__builtin_lasx_xvfrecipe_s, "V8fV8f", "nc", "lasx,frecipe")
+TARGET_BUILTIN(__builtin_lasx_xvfrecipe_d, "V4dV4d", "nc", "lasx,frecipe")
+
 TARGET_BUILTIN(__builtin_lasx_xvfrsqrt_s, "V8fV8f", "nc", "lasx")
 TARGET_BUILTIN(__builtin_lasx_xvfrsqrt_d, "V4dV4d", "nc", "lasx")
 
+TARGET_BUILTIN(__builtin_lasx_xvfrsqrte_s, "V8fV8f", "nc", "lasx,frecipe")
+TARGET_BUILTIN(__builtin_lasx_xvfrsqrte_d, "V4dV4d", "nc", "lasx,frecipe")
+
 TARGET_BUILTIN(__builtin_lasx_xvfcvtl_s_h, "V8fV16s", "nc", "lasx")
 TARGET_BUILTIN(__builtin_lasx_xvfcvth_s_h, "V8fV16s", "nc", "lasx")
 TARGET_BUILTIN(__builtin_lasx_xvfcvtl_d_s, "V4dV8f", "nc", "lasx")
diff --git a/clang/include/clang/Basic/BuiltinsLoongArchLSX.def b/clang/include/clang/Basic/BuiltinsLoongArchLSX.def
index 8e6aec886c50..c90f4dc5458f 100644
--- a/clang/include/clang/Basic/BuiltinsLoongArchLSX.def
+++ b/clang/include/clang/Basic/BuiltinsLoongArchLSX.def
@@ -641,9 +641,15 @@ TARGET_BUILTIN(__builtin_lsx_vfsqrt_d, "V2dV2d", "nc", "lsx")
 TARGET_BUILTIN(__builtin_lsx_vfrecip_s, "V4fV4f", "nc", "lsx")
 TARGET_BUILTIN(__builtin_lsx_vfrecip_d, "V2dV2d", "nc", "lsx")
 
+TARGET_BUILTIN(__builtin_lsx_vfrecipe_s, "V4fV4f", "nc", "lsx,frecipe")
+TARGET_BUILTIN(__builtin_lsx_vfrecipe_d, "V2dV2d", "nc", "lsx,frecipe")
+
 TARGET_BUILTIN(__builtin_lsx_vfrsqrt_s, "V4fV4f", "nc", "lsx")
 TARGET_BUILTIN(__builtin_lsx_vfrsqrt_d, "V2dV2d", "nc", "lsx")
 
+TARGET_BUILTIN(__builtin_lsx_vfrsqrte_s, "V4fV4f", "nc", "lsx,frecipe")
+TARGET_BUILTIN(__builtin_lsx_vfrsqrte_d, "V2dV2d", "nc", "lsx,frecipe")
+
 TARGET_BUILTIN(__builtin_lsx_vfcvtl_s_h, "V4fV8s", "nc", "lsx")
 TARGET_BUILTIN(__builtin_lsx_vfcvtl_d_s, "V2dV4f", "nc", "lsx")
 
diff --git a/clang/lib/Headers/larchintrin.h b/clang/lib/Headers/larchintrin.h
index 24dd29ce91ff..f4218295919a 100644
--- a/clang/lib/Headers/larchintrin.h
+++ b/clang/lib/Headers/larchintrin.h
@@ -228,6 +228,18 @@ extern __inline void
   ((void)__builtin_loongarch_ldpte_d((long int)(_1), (_2)))
 #endif
 
+#define __frecipe_s(/*float*/ _1)                                              \
+  (float)__builtin_loongarch_frecipe_s((float)_1)
+
+#define __frecipe_d(/*double*/ _1)                                             \
+  (double)__builtin_loongarch_frecipe_d((double)_1)
+
+#define __frsqrte_s(/*float*/ _1)                                              \
+  (float)__builtin_loongarch_frsqrte_s((float)_1)
+
+#define __frsqrte_d(/*double*/ _1)                                             \
+  (double)__builtin_loongarch_frsqrte_d((double)_1)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/clang/lib/Headers/lasxintrin.h b/clang/lib/Headers/lasxintrin.h
index 6b4d5012a24b..dafc2a2f3e6a 100644
--- a/clang/lib/Headers/lasxintrin.h
+++ b/clang/lib/Headers/lasxintrin.h
@@ -1726,6 +1726,18 @@ extern __inline
   return (__m256d)__builtin_lasx_xvfrecip_d((v4f64)_1);
 }
 
+extern __inline
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256
+    __lasx_xvfrecipe_s(__m256 _1) {
+  return (__m256)__builtin_lasx_xvfrecipe_s((v8f32)_1);
+}
+
+extern __inline
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256d
+    __lasx_xvfrecipe_d(__m256d _1) {
+  return (__m256d)__builtin_lasx_xvfrecipe_d((v4f64)_1);
+}
+
 extern __inline
     __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256
     __lasx_xvfrint_s(__m256 _1) {
@@ -1750,6 +1762,18 @@ extern __inline
   return (__m256d)__builtin_lasx_xvfrsqrt_d((v4f64)_1);
 }
 
+extern __inline
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256
+    __lasx_xvfrsqrte_s(__m256 _1) {
+  return (__m256)__builtin_lasx_xvfrsqrte_s((v8f32)_1);
+}
+
+extern __inline
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256d
+    __lasx_xvfrsqrte_d(__m256d _1) {
+  return (__m256d)__builtin_lasx_xvfrsqrte_d((v4f64)_1);
+}
+
 extern __inline
     __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256
     __lasx_xvflogb_s(__m256 _1) {
diff --git a/clang/lib/Headers/lsxintrin.h b/clang/lib/Headers/lsxintrin.h
index a29bc7757ab5..f347955ce6fb 100644
--- a/clang/lib/Headers/lsxintrin.h
+++ b/clang/lib/Headers/lsxintrin.h
@@ -1776,6 +1776,18 @@ extern __inline
   return (__m128d)__builtin_lsx_vfrecip_d((v2f64)_1);
 }
 
+extern __inline
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128
+    __lsx_vfrecipe_s(__m128 _1) {
+  return (__m128)__builtin_lsx_vfrecipe_s((v4f32)_1);
+}
+
+extern __inline
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128d
+    __lsx_vfrecipe_d(__m128d _1) {
+  return (__m128d)__builtin_lsx_vfrecipe_d((v2f64)_1);
+}
+
 extern __inline
     __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128
     __lsx_vfrint_s(__m128 _1) {
@@ -1800,6 +1812,18 @@ extern __inline
   return (__m128d)__builtin_lsx_vfrsqrt_d((v2f64)_1);
 }
 
+extern __inline
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128
+    __lsx_vfrsqrte_s(__m128 _1) {
+  return (__m128)__builtin_lsx_vfrsqrte_s((v4f32)_1);
+}
+
+extern __inline
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128d
+    __lsx_vfrsqrte_d(__m128d _1) {
+  return (__m128d)__builtin_lsx_vfrsqrte_d((v2f64)_1);
+}
+
 extern __inline
     __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128
     __lsx_vflogb_s(__m128 _1) {
diff --git a/clang/test/CodeGen/LoongArch/builtin-dbl-approximate.c b/clang/test/CodeGen/LoongArch/builtin-dbl-approximate.c
new file mode 100644
index 000000000000..e5fe684346c0
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/builtin-dbl-approximate.c
@@ -0,0 +1,45 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -triple loongarch32 -target-feature +d -target-feature +frecipe -O2 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple loongarch64 -target-feature +d -target-feature +frecipe -O2 -emit-llvm %s -o - | FileCheck %s
+
+#include <larchintrin.h>
+
+// CHECK-LABEL: @frecipe_d
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call double @llvm.loongarch.frecipe.d(double [[A:%.*]])
+// CHECK-NEXT:    ret double [[TMP0]]
+//
+double frecipe_d (double _1)
+{
+  return __builtin_loongarch_frecipe_d (_1);
+}
+
+// CHECK-LABEL: @frsqrte_d
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call double @llvm.loongarch.frsqrte.d(double [[A:%.*]])
+// CHECK-NEXT:    ret double [[TMP0]]
+//
+double frsqrte_d (double _1)
+{
+  return __builtin_loongarch_frsqrte_d (_1);
+}
+
+// CHECK-LABEL: @frecipe_d_alia
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call double @llvm.loongarch.frecipe.d(double [[A:%.*]])
+// CHECK-NEXT:    ret double [[TMP0]]
+//
+double frecipe_d_alia (double _1)
+{
+  return __frecipe_d (_1);
+}
+
+// CHECK-LABEL: @frsqrte_d_alia
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call double @llvm.loongarch.frsqrte.d(double [[A:%.*]])
+// CHECK-NEXT:    ret double [[TMP0]]
+//
+double frsqrte_d_alia (double _1)
+{
+  return __frsqrte_d (_1);
+}
diff --git a/clang/test/CodeGen/LoongArch/builtin-flt-approximate.c b/clang/test/CodeGen/LoongArch/builtin-flt-approximate.c
new file mode 100644
index 000000000000..47bb47084364
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/builtin-flt-approximate.c
@@ -0,0 +1,45 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -triple loongarch32 -target-feature +f -target-feature +frecipe -O2 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple loongarch64 -target-feature +f -target-feature +frecipe -O2 -emit-llvm %s -o - | FileCheck %s
+
+#include <larchintrin.h>
+
+// CHECK-LABEL: @frecipe_s
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call float @llvm.loongarch.frecipe.s(float [[A:%.*]])
+// CHECK-NEXT:    ret float [[TMP0]]
+//
+float frecipe_s (float _1)
+{
+  return __builtin_loongarch_frecipe_s (_1);
+}
+
+// CHECK-LABEL: @frsqrte_s
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call float @llvm.loongarch.frsqrte.s(float [[A:%.*]])
+// CHECK-NEXT:    ret float [[TMP0]]
+//
+float frsqrte_s (float _1)
+{
+  return __builtin_loongarch_frsqrte_s (_1);
+}
+
+// CHECK-LABEL: @frecipe_s_alia
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call float @llvm.loongarch.frecipe.s(float [[A:%.*]])
+// CHECK-NEXT:    ret float [[TMP0]]
+//
+float frecipe_s_alia (float _1)
+{
+  return __frecipe_s (_1);
+}
+
+// CHECK-LABEL: @frsqrte_s_alia
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call float @llvm.loongarch.frsqrte.s(float [[A:%.*]])
+// CHECK-NEXT:    ret float [[TMP0]]
+//
+float frsqrte_s_alia (float _1)
+{
+  return __frsqrte_s (_1);
+}
diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la64-error.c b/clang/test/CodeGen/LoongArch/intrinsic-la64-error.c
index efb3b94175cf..a3242dfd41e9 100644
--- a/clang/test/CodeGen/LoongArch/intrinsic-la64-error.c
+++ b/clang/test/CodeGen/LoongArch/intrinsic-la64-error.c
@@ -1,7 +1,28 @@
 // RUN: %clang_cc1 -triple loongarch64 -emit-llvm -S -verify %s -o /dev/null
+// RUN: not %clang_cc1 -triple loongarch64 -DFEATURE_CHECK -emit-llvm %s -o /dev/null 2>&1 \
+// RUN:   | FileCheck %s
 
 #include <larchintrin.h>
 
+#ifdef FEATURE_CHECK
+void test_feature(unsigned long *v_ul, int *v_i, float a, double b) {
+// CHECK: error: '__builtin_loongarch_cacop_w' needs target feature 32bit
+  __builtin_loongarch_cacop_w(1, v_ul[0], 1024);
+// CHECK: error: '__builtin_loongarch_movfcsr2gr' needs target feature f
+  v_i[0] = __builtin_loongarch_movfcsr2gr(1);
+// CHECK: error: '__builtin_loongarch_movgr2fcsr' needs target feature f
+  __builtin_loongarch_movgr2fcsr(1, v_i[1]);
+// CHECK: error: '__builtin_loongarch_frecipe_s' needs target feature f,frecipe
+  float f1 = __builtin_loongarch_frecipe_s(a);
+// CHECK: error: '__builtin_loongarch_frsqrte_s' needs target feature f,frecipe
+  float f2 = __builtin_loongarch_frsqrte_s(a);
+// CHECK: error: '__builtin_loongarch_frecipe_d' needs target feature d,frecipe
+  double d1 = __builtin_loongarch_frecipe_d(b);
+// CHECK: error: '__builtin_loongarch_frsqrte_d' needs target feature d,frecipe
+  double d2 = __builtin_loongarch_frsqrte_d(b);
+}
+#endif
+
 void csrrd_d(int a) {
   __builtin_loongarch_csrrd_d(16384); // expected-error {{argument value 16384 is outside the valid range [0, 16383]}}
   __builtin_loongarch_csrrd_d(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 16383]}}
diff --git a/clang/test/CodeGen/LoongArch/lasx/builtin-approximate-alias.c b/clang/test/CodeGen/LoongArch/lasx/builtin-approximate-alias.c
new file mode 100644
index 000000000000..b79f93940399
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lasx/builtin-approximate-alias.c
@@ -0,0 +1,37 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple loongarch64 -target-feature +lasx -target-feature +frecipe -O2 -emit-llvm %s -o - | FileCheck %s
+
+#include <lasxintrin.h>
+
+// CHECK-LABEL: @xvfrecipe_s(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[_1:%.*]] = load <8 x float>, ptr [[TMP0:%.*]], align 32, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <8 x float> @llvm.loongarch.lasx.xvfrecipe.s(<8 x float> [[_1]])
+// CHECK-NEXT:    store <8 x float> [[TMP1]], ptr [[AGG_RESULT:%.*]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT:    ret void
+//
+v8f32 xvfrecipe_s(v8f32 _1) { return __lasx_xvfrecipe_s(_1); }
+// CHECK-LABEL: @xvfrecipe_d(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[_1:%.*]] = load <4 x double>, ptr [[TMP0:%.*]], align 32, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <4 x double> @llvm.loongarch.lasx.xvfrecipe.d(<4 x double> [[_1]])
+// CHECK-NEXT:    store <4 x double> [[TMP1]], ptr [[AGG_RESULT:%.*]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT:    ret void
+//
+v4f64 xvfrecipe_d(v4f64 _1) { return __lasx_xvfrecipe_d(_1); }
+// CHECK-LABEL: @xvfrsqrte_s(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[_1:%.*]] = load <8 x float>, ptr [[TMP0:%.*]], align 32, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <8 x float> @llvm.loongarch.lasx.xvfrsqrte.s(<8 x float> [[_1]])
+// CHECK-NEXT:    store <8 x float> [[TMP1]], ptr [[AGG_RESULT:%.*]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT:    ret void
+//
+v8f32 xvfrsqrte_s(v8f32 _1) { return __lasx_xvfrsqrte_s(_1); }
+// CHECK-LABEL: @xvfrsqrte_d(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[_1:%.*]] = load <4 x double>, ptr [[TMP0:%.*]], align 32, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <4 x double> @llvm.loongarch.lasx.xvfrsqrte.d(<4 x double> [[_1]])
+// CHECK-NEXT:    store <4 x double> [[TMP1]], ptr [[AGG_RESULT:%.*]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT:    ret void
+//
+v4f64 xvfrsqrte_d(v4f64 _1) { return __lasx_xvfrsqrte_d(_1); }
diff --git a/clang/test/CodeGen/LoongArch/lasx/builtin-approximate.c b/clang/test/CodeGen/LoongArch/lasx/builtin-approximate.c
new file mode 100644
index 000000000000..63e9ba639ea2
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lasx/builtin-approximate.c
@@ -0,0 +1,38 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple loongarch64 -target-feature +lasx -target-feature +frecipe -O2 -emit-llvm %s -o - | FileCheck %s
+
+typedef float v8f32 __attribute__((vector_size(32), aligned(32)));
+typedef double v4f64 __attribute__((vector_size(32), aligned(32)));
+
+// CHECK-LABEL: @xvfrecipe_s
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[_1:%.*]] = load <8 x float>, ptr [[TMP0:%.*]], align 32, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <8 x float> @llvm.loongarch.lasx.xvfrecipe.s(<8 x float> [[_1]])
+// CHECK-NEXT:    store <8 x float> [[TMP1]], ptr [[AGG_RESULT:%.*]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT:    ret void
+//
+v8f32 xvfrecipe_s(v8f32 _1) { return __builtin_lasx_xvfrecipe_s(_1); }
+// CHECK-LABEL: @xvfrecipe_d
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[_1:%.*]] = load <4 x double>, ptr [[TMP0:%.*]], align 32, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <4 x double> @llvm.loongarch.lasx.xvfrecipe.d(<4 x double> [[_1]])
+// CHECK-NEXT:    store <4 x double> [[TMP1]], ptr [[AGG_RESULT:%.*]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT:    ret void
+//
+v4f64 xvfrecipe_d(v4f64 _1) { return __builtin_lasx_xvfrecipe_d(_1); }
+// CHECK-LABEL: @xvfrsqrte_s
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[_1:%.*]] = load <8 x float>, ptr [[TMP0:%.*]], align 32, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <8 x float> @llvm.loongarch.lasx.xvfrsqrte.s(<8 x float> [[_1]])
+// CHECK-NEXT:    store <8 x float> [[TMP1]], ptr [[AGG_RESULT:%.*]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT:    ret void
+//
+v8f32 xvfrsqrte_s(v8f32 _1) { return __builtin_lasx_xvfrsqrte_s(_1); }
+// CHECK-LABEL: @xvfrsqrte_d
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[_1:%.*]] = load <4 x double>, ptr [[TMP0:%.*]], align 32, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <4 x double> @llvm.loongarch.lasx.xvfrsqrte.d(<4 x double> [[_1]])
+// CHECK-NEXT:    store <4 x double> [[TMP1]], ptr [[AGG_RESULT:%.*]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT:    ret void
+//
+v4f64 xvfrsqrte_d(v4f64 _1) { return __builtin_lasx_xvfrsqrte_d(_1); }
diff --git a/clang/test/CodeGen/LoongArch/lsx/builtin-approximate-alias.c b/clang/test/CodeGen/LoongArch/lsx/builtin-approximate-alias.c
new file mode 100644
index 000000000000..f26f032c878e
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lsx/builtin-approximate-alias.c
@@ -0,0 +1,37 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple loongarch64 -target-feature +lsx -target-feature +frecipe -O2 -emit-llvm %s -o - | FileCheck %s
+
+#include <lsxintrin.h>
+
+// CHECK-LABEL: @vfrecipe_s(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[_1_COERCE:%.*]] to <4 x float>
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <4 x float> @llvm.loongarch.lsx.vfrecipe.s(<4 x float> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to i128
+// CHECK-NEXT:    ret i128 [[TMP2]]
+//
+v4f32 vfrecipe_s(v4f32 _1) { return __lsx_vfrecipe_s(_1); }
+// CHECK-LABEL: @vfrecipe_d(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[_1_COERCE:%.*]] to <2 x double>
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <2 x double> @llvm.loongarch.lsx.vfrecipe.d(<2 x double> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to i128
+// CHECK-NEXT:    ret i128 [[TMP2]]
+//
+v2f64 vfrecipe_d(v2f64 _1) { return __lsx_vfrecipe_d(_1); }
+// CHECK-LABEL: @vfrsqrte_s(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[_1_COERCE:%.*]] to <4 x float>
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <4 x float> @llvm.loongarch.lsx.vfrsqrte.s(<4 x float> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to i128
+// CHECK-NEXT:    ret i128 [[TMP2]]
+//
+v4f32 vfrsqrte_s(v4f32 _1) { return __lsx_vfrsqrte_s(_1); }
+// CHECK-LABEL: @vfrsqrte_d(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[_1_COERCE:%.*]] to <2 x double>
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <2 x double> @llvm.loongarch.lsx.vfrsqrte.d(<2 x double> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to i128
+// CHECK-NEXT:    ret i128 [[TMP2]]
+//
+v2f64 vfrsqrte_d(v2f64 _1) { return __lsx_vfrsqrte_d(_1); }
diff --git a/clang/test/CodeGen/LoongArch/lsx/builtin-approximate.c b/clang/test/CodeGen/LoongArch/lsx/builtin-approximate.c
new file mode 100644
index 000000000000..39fa1663db34
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lsx/builtin-approximate.c
@@ -0,0 +1,38 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple loongarch64 -target-feature +lsx -target-feature +frecipe -O2 -emit-llvm %s -o - | FileCheck %s
+
+typedef float v4f32 __attribute__ ((vector_size(16), aligned(16)));
+typedef double v2f64 __attribute__ ((vector_size(16), aligned(16)));
+
+// CHECK-LABEL: @vfrecipe_s
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[_1_COERCE:%.*]] to <4 x float>
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <4 x float> @llvm.loongarch.lsx.vfrecipe.s(<4 x float> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to i128
+// CHECK-NEXT:    ret i128 [[TMP2]]
+//
+v4f32 vfrecipe_s (v4f32 _1) { return __builtin_lsx_vfrecipe_s (_1); }
+// CHECK-LABEL: @vfrecipe_d
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[_1_COERCE:%.*]] to <2 x double>
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <2 x double> @llvm.loongarch.lsx.vfrecipe.d(<2 x double> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to i128
+// CHECK-NEXT:    ret i128 [[TMP2]]
+//
+v2f64 vfrecipe_d (v2f64 _1) { return __builtin_lsx_vfrecipe_d (_1); }
+// CHECK-LABEL: @vfrsqrte_s
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[_1_COERCE:%.*]] to <4 x float>
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <4 x float> @llvm.loongarch.lsx.vfrsqrte.s(<4 x float> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to i128
+// CHECK-NEXT:    ret i128 [[TMP2]]
+//
+v4f32 vfrsqrte_s (v4f32 _1) { return __builtin_lsx_vfrsqrte_s (_1); }
+// CHECK-LABEL: @vfrsqrte_d
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast i128 [[_1_COERCE:%.*]] to <2 x double>
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <2 x double> @llvm.loongarch.lsx.vfrsqrte.d(<2 x double> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to i128
+// CHECK-NEXT:    ret i128 [[TMP2]]
+//
+v2f64 vfrsqrte_d (v2f64 _1) { return __builtin_lsx_vfrsqrte_d (_1); }
-- 
2.20.1


From 6f9531b069971dc0f5c6b28bd6a6754c1b5fde72 Mon Sep 17 00:00:00 2001
From: Ami-zhang <zhanglimin@loongson.cn>
Date: Tue, 23 Jul 2024 14:03:28 +0800
Subject: [PATCH 7/9] [LoongArch] Support -march=la64v1.0 and -march=la64v1.1
 (#100057)

The newly added strings `la64v1.0` and `la64v1.1` in `-march` are as
described in LoongArch toolchains conventions (see [1]).

The target-cpu/feature attributes are forwarded to compiler when
specifying particular `-march` parameter. The default cpu `loongarch64`
is returned when archname is `la64v1.0` or `la64v1.1`.

In addition, this commit adds `la64v1.0`/`la64v1.1` to
"__loongarch_arch" and adds definition for macro "__loongarch_frecipe".

[1]: https://github.com/loongson/la-toolchain-conventions

(cherry picked from commit 5a1b9896ad5a7dcd25a1cc7a4d3fd44155e4b22d)
---
 clang/lib/Basic/Targets/LoongArch.cpp         | 23 +++++++++++++++-
 clang/lib/Basic/Targets/LoongArch.h           |  2 ++
 .../lib/Driver/ToolChains/Arch/LoongArch.cpp  | 10 +++++--
 clang/test/Driver/loongarch-march.c           | 22 +++++++++++++++
 clang/test/Preprocessor/init-loongarch.c      | 27 ++++++++++++++++---
 5 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp
index 913404240916..5fede3d7cdc4 100644
--- a/clang/lib/Basic/Targets/LoongArch.cpp
+++ b/clang/lib/Basic/Targets/LoongArch.cpp
@@ -200,7 +200,24 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts,
 
   // Define __loongarch_arch.
   StringRef ArchName = getCPU();
-  Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"'));
+  if (ArchName == "loongarch64") {
+    if (HasFeatureLSX) {
+      // TODO: As more features of the V1.1 ISA are supported, a unified "v1.1"
+      // arch feature set will be used to include all sub-features belonging to
+      // the V1.1 ISA version.
+      if (HasFeatureFrecipe)
+        Builder.defineMacro("__loongarch_arch",
+                            Twine('"') + "la64v1.1" + Twine('"'));
+      else
+        Builder.defineMacro("__loongarch_arch",
+                            Twine('"') + "la64v1.0" + Twine('"'));
+    } else {
+      Builder.defineMacro("__loongarch_arch",
+                          Twine('"') + ArchName + Twine('"'));
+    }
+  } else {
+    Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"'));
+  }
 
   // Define __loongarch_tune.
   StringRef TuneCPU = getTargetOpts().TuneCPU;
@@ -216,6 +233,8 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("__loongarch_simd_width", "128");
     Builder.defineMacro("__loongarch_sx", Twine(1));
   }
+  if (HasFeatureFrecipe)
+    Builder.defineMacro("__loongarch_frecipe", Twine(1));
 
   StringRef ABI = getABI();
   if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s")
@@ -289,6 +308,8 @@ bool LoongArchTargetInfo::handleTargetFeatures(
       HasFeatureLSX = true;
     else if (Feature == "+lasx")
       HasFeatureLASX = true;
+    else if (Feature == "+frecipe")
+      HasFeatureFrecipe = true;
   }
   return true;
 }
diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h
index 3313102492cb..4d2965f5b3a3 100644
--- a/clang/lib/Basic/Targets/LoongArch.h
+++ b/clang/lib/Basic/Targets/LoongArch.h
@@ -29,6 +29,7 @@ protected:
   bool HasFeatureF;
   bool HasFeatureLSX;
   bool HasFeatureLASX;
+  bool HasFeatureFrecipe;
 
 public:
   LoongArchTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
@@ -37,6 +38,7 @@ public:
     HasFeatureF = false;
     HasFeatureLSX = false;
     HasFeatureLASX = false;
+    HasFeatureFrecipe = false;
     LongDoubleWidth = 128;
     LongDoubleAlign = 128;
     LongDoubleFormat = &llvm::APFloat::IEEEquad();
diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
index 87d7b30ef5d3..21106c425206 100644
--- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -268,8 +268,14 @@ std::string loongarch::postProcessTargetCPUString(const std::string &CPU,
 std::string loongarch::getLoongArchTargetCPU(const llvm::opt::ArgList &Args,
                                              const llvm::Triple &Triple) {
   std::string CPU;
+  std::string Arch;
   // If we have -march, use that.
-  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
-    CPU = A->getValue();
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    Arch = A->getValue();
+    if (Arch == "la64v1.0" || Arch == "la64v1.1")
+      CPU = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());
+    else
+      CPU = Arch;
+  }
   return postProcessTargetCPUString(CPU, Triple);
 }
diff --git a/clang/test/Driver/loongarch-march.c b/clang/test/Driver/loongarch-march.c
index 9214130cd034..d06da72a755c 100644
--- a/clang/test/Driver/loongarch-march.c
+++ b/clang/test/Driver/loongarch-march.c
@@ -2,10 +2,18 @@
 // RUN:   FileCheck %s --check-prefix=CC1-LOONGARCH64
 // RUN: %clang --target=loongarch64 -march=la464 -fsyntax-only %s -### 2>&1 | \
 // RUN:   FileCheck %s --check-prefix=CC1-LA464
+// RUN: %clang --target=loongarch64 -march=la64v1.0 -fsyntax-only %s -### 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=CC1-LA64V1P0
+// RUN: %clang --target=loongarch64 -march=la64v1.1 -fsyntax-only %s -### 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=CC1-LA64V1P1
 // RUN: %clang --target=loongarch64 -march=loongarch64 -S -emit-llvm %s -o - | \
 // RUN:   FileCheck %s --check-prefix=IR-LOONGARCH64
 // RUN: %clang --target=loongarch64 -march=la464 -S -emit-llvm %s -o - | \
 // RUN:   FileCheck %s --check-prefix=IR-LA464
+// RUN: %clang --target=loongarch64 -march=la64v1.0 -S -emit-llvm %s -o - | \
+// RUN:   FileCheck %s --check-prefix=IR-LA64V1P0
+// RUN: %clang --target=loongarch64 -march=la64v1.1 -S -emit-llvm %s -o - | \
+// RUN:   FileCheck %s --check-prefix=IR-LA64V1P1
 
 // CC1-LOONGARCH64: "-target-cpu" "loongarch64"
 // CC1-LOONGARCH64-NOT: "-target-feature"
@@ -19,8 +27,22 @@
 // CC1-LA464-NOT: "-target-feature"
 // CC1-LA464: "-target-abi" "lp64d"
 
+// CC1-LA64V1P0: "-target-cpu" "loongarch64"
+// CC1-LA64V1P0-NOT: "-target-feature"
+// CC1-LA64V1P0: "-target-feature" "+64bit" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+ual"
+// CC1-LA64V1P0-NOT: "-target-feature"
+// CC1-LA64V1P0: "-target-abi" "lp64d"
+
+// CC1-LA64V1P1: "-target-cpu" "loongarch64"
+// CC1-LA64V1P1-NOT: "-target-feature"
+// CC1-LA64V1P1: "-target-feature" "+64bit" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+ual" "-target-feature" "+frecipe"
+// CC1-LA64V1P1-NOT: "-target-feature"
+// CC1-LA64V1P1: "-target-abi" "lp64d"
+
 // IR-LOONGARCH64: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+f,+ual"
 // IR-LA464: attributes #[[#]] ={{.*}}"target-cpu"="la464" {{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx,+ual"
+// IR-LA64V1P0: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+lsx,+ual"
+// IR-LA64V1P1: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+frecipe,+lsx,+ual"
 
 int foo(void) {
   return 3;
diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c
index 635d029ce9d3..cfa3ddb20f10 100644
--- a/clang/test/Preprocessor/init-loongarch.c
+++ b/clang/test/Preprocessor/init-loongarch.c
@@ -788,24 +788,43 @@
 // LA64-FPU0-LP64S-NOT: #define __loongarch_single_float
 // LA64-FPU0-LP64S: #define __loongarch_soft_float 1
 
-/// Check __loongarch_arch and __loongarch_tune.
+/// Check __loongarch_arch{_tune/_frecipe}.
 
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - | \
-// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 | \
 // RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la464 | \
 // RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la464 -DTUNE=la464 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=loongarch64 | \
-// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=la464 | \
-// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la464 %s
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=la464 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -mtune=la464 | \
 // RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la464 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la464 -mtune=loongarch64 | \
 // RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la464 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 | \
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 -Xclang -target-feature -Xclang -lsx | \
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 -Xclang -target-feature -Xclang +frecipe | \
+// RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lsx | \
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 | \
+// RUN:   FileCheck --match-full-lines  --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 -Xclang -target-feature -Xclang -frecipe | \
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 -Xclang -target-feature -Xclang -lsx | \
+// RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=loongarch64 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +frecipe | \
+// RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=loongarch64 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lsx -Xclang -target-feature -Xclang +frecipe | \
+// RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s
 
 // ARCH-TUNE: #define __loongarch_arch "[[ARCH]]"
+// FRECIPE: #define __loongarch_frecipe 1
 // ARCH-TUNE: #define __loongarch_tune "[[TUNE]]"
 
 // RUN: %clang --target=loongarch64 -mlsx -x c -E -dM %s -o - \
-- 
2.20.1


From 6094875aa6aab1e28a096294783cada0243e95d5 Mon Sep 17 00:00:00 2001
From: Ami-zhang <zhanglimin@loongson.cn>
Date: Tue, 23 Jul 2024 15:14:20 +0800
Subject: [PATCH 8/9] [LoongArch] Support la664 (#100068)

A new ProcessorModel called `la664` is defined in LoongArch.td to
support `-march/-mtune=la664`.

(cherry picked from commit fcec298087dba0c83f6d0bbafd6cd934c42cbf82)
---
 clang/test/Driver/loongarch-march.c      | 11 +++++++++++
 clang/test/Driver/loongarch-mtune.c      |  5 +++++
 clang/test/Preprocessor/init-loongarch.c |  8 ++++++++
 3 files changed, 24 insertions(+)

diff --git a/clang/test/Driver/loongarch-march.c b/clang/test/Driver/loongarch-march.c
index d06da72a755c..2d5b315d962a 100644
--- a/clang/test/Driver/loongarch-march.c
+++ b/clang/test/Driver/loongarch-march.c
@@ -6,6 +6,8 @@
 // RUN:   FileCheck %s --check-prefix=CC1-LA64V1P0
 // RUN: %clang --target=loongarch64 -march=la64v1.1 -fsyntax-only %s -### 2>&1 | \
 // RUN:   FileCheck %s --check-prefix=CC1-LA64V1P1
+// RUN: %clang --target=loongarch64 -march=la664 -fsyntax-only %s -### 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=CC1-LA664
 // RUN: %clang --target=loongarch64 -march=loongarch64 -S -emit-llvm %s -o - | \
 // RUN:   FileCheck %s --check-prefix=IR-LOONGARCH64
 // RUN: %clang --target=loongarch64 -march=la464 -S -emit-llvm %s -o - | \
@@ -14,6 +16,8 @@
 // RUN:   FileCheck %s --check-prefix=IR-LA64V1P0
 // RUN: %clang --target=loongarch64 -march=la64v1.1 -S -emit-llvm %s -o - | \
 // RUN:   FileCheck %s --check-prefix=IR-LA64V1P1
+// RUN: %clang --target=loongarch64 -march=la664 -S -emit-llvm %s -o - | \
+// RUN:   FileCheck %s --check-prefix=IR-LA664
 
 // CC1-LOONGARCH64: "-target-cpu" "loongarch64"
 // CC1-LOONGARCH64-NOT: "-target-feature"
@@ -39,10 +43,17 @@
 // CC1-LA64V1P1-NOT: "-target-feature"
 // CC1-LA64V1P1: "-target-abi" "lp64d"
 
+// CC1-LA664: "-target-cpu" "la664"
+// CC1-LA664-NOT: "-target-feature"
+// CC1-LA664: "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+lasx" "-target-feature" "+ual" "-target-feature" "+frecipe"
+// CC1-LA664-NOT: "-target-feature"
+// CC1-LA664: "-target-abi" "lp64d"
+
 // IR-LOONGARCH64: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+f,+ual"
 // IR-LA464: attributes #[[#]] ={{.*}}"target-cpu"="la464" {{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx,+ual"
 // IR-LA64V1P0: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+lsx,+ual"
 // IR-LA64V1P1: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+frecipe,+lsx,+ual"
+// IR-LA664: attributes #[[#]] ={{.*}}"target-cpu"="la664" {{.*}}"target-features"="+64bit,+d,+f,+frecipe,+lasx,+lsx,+ual"
 
 int foo(void) {
   return 3;
diff --git a/clang/test/Driver/loongarch-mtune.c b/clang/test/Driver/loongarch-mtune.c
index 6f3f39e9bbd8..face12e1a1a8 100644
--- a/clang/test/Driver/loongarch-mtune.c
+++ b/clang/test/Driver/loongarch-mtune.c
@@ -8,6 +8,11 @@
 // RUN: %clang --target=loongarch64 -mtune=la464 -S -emit-llvm %s -o - | \
 // RUN:   FileCheck %s --check-prefix=IRATTR -DCPU=la464
 
+// RUN: %clang --target=loongarch64 -mtune=la664 -fsyntax-only %s -### 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=CC1ARG -DCPU=la664
+// RUN: %clang --target=loongarch64 -mtune=la664 -S -emit-llvm %s -o - | \
+// RUN:   FileCheck %s --check-prefix=IRATTR -DCPU=la664
+
 // RUN: %clang --target=loongarch64 -mtune=invalidcpu -fsyntax-only %s -### 2>&1 | \
 // RUN:   FileCheck %s --check-prefix=CC1ARG -DCPU=invalidcpu
 // RUN: not %clang --target=loongarch64 -mtune=invalidcpu -S -emit-llvm %s -o /dev/null 2>&1 | \
diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c
index cfa3ddb20f10..7ce3d2de8c78 100644
--- a/clang/test/Preprocessor/init-loongarch.c
+++ b/clang/test/Preprocessor/init-loongarch.c
@@ -822,6 +822,14 @@
 // RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=loongarch64 -DTUNE=loongarch64 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lsx -Xclang -target-feature -Xclang +frecipe | \
 // RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la664 | \
+// RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la664 -DTUNE=la664 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=la664 | \
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la664 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -mtune=la664 | \
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la664 %s
+// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la664 -mtune=loongarch64 | \
+// RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la664 -DTUNE=loongarch64 %s
 
 // ARCH-TUNE: #define __loongarch_arch "[[ARCH]]"
 // FRECIPE: #define __loongarch_frecipe 1
-- 
2.20.1


From 18f453f2dba969c1fdcbda562079113de7bbcfca Mon Sep 17 00:00:00 2001
From: Ami-zhang <zhanglimin@loongson.cn>
Date: Tue, 23 Jul 2024 15:20:30 +0800
Subject: [PATCH 9/9] [LoongArch] Fix test issue of init-loongarch.c

(cherry picked from commit d59925c39856f255f4dd4427ccc650f2c2692a24)
---
 clang/test/Preprocessor/init-loongarch.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c
index 7ce3d2de8c78..887b6d6af7e1 100644
--- a/clang/test/Preprocessor/init-loongarch.c
+++ b/clang/test/Preprocessor/init-loongarch.c
@@ -825,7 +825,7 @@
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la664 | \
 // RUN:   FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la664 -DTUNE=la664 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=la664 | \
-// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la664 %s
+// RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=la664 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -mtune=la664 | \
 // RUN:   FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la664 %s
 // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la664 -mtune=loongarch64 | \
-- 
2.20.1

