diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 3918eeb11720..b5b2a7c16453 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -531,6 +531,8 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
     return false;
   case llvm::Triple::riscv32:
   case llvm::Triple::riscv64:
+  case llvm::Triple::loongarch64:
+  case llvm::Triple::loongarch32:
     return !areOptimizationsEnabled(Args);
   default:
     break;
@@ -544,8 +546,6 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
       Triple.isOSHurd()) {
     switch (Triple.getArch()) {
     // Don't use a frame pointer on linux if optimizing for certain targets.
-    case llvm::Triple::loongarch64:
-    case llvm::Triple::loongarch32:
     case llvm::Triple::mips64:
     case llvm::Triple::mips64el:
     case llvm::Triple::mips:
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index ed7e821198d8..fdb8fc719af6 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -1029,6 +1029,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
                          getTriple().getArch() == llvm::Triple::thumb ||
                          getTriple().getArch() == llvm::Triple::armeb ||
                          getTriple().getArch() == llvm::Triple::thumbeb;
+  const bool IsLoongArch64 = getTriple().getArch() == llvm::Triple::loongarch64;
   SanitizerMask Res = ToolChain::getSupportedSanitizers();
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::Fuzzer;
@@ -1037,20 +1038,20 @@ SanitizerMask Linux::getSupportedSanitizers() const {
   Res |= SanitizerKind::Memory;
   Res |= SanitizerKind::Vptr;
   Res |= SanitizerKind::SafeStack;
-  if (IsX86_64 || IsMIPS64 || IsAArch64)
+  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsLoongArch64)
     Res |= SanitizerKind::DataFlow;
-  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64)
+  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 || IsLoongArch64)
     Res |= SanitizerKind::Leak;
-  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
+  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsLoongArch64)
     Res |= SanitizerKind::Thread;
   if (IsX86_64)
     Res |= SanitizerKind::KernelMemory;
-  if (IsX86_64 || IsMIPS64)
+  if (IsX86_64 || IsMIPS64 || IsLoongArch64)
     Res |= SanitizerKind::Efficiency;
   if (IsX86 || IsX86_64)
     Res |= SanitizerKind::Function;
   if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch ||
-      IsPowerPC64)
+      IsPowerPC64 || IsLoongArch64)
     Res |= SanitizerKind::Scudo;
   if (IsX86_64 || IsAArch64) {
     Res |= SanitizerKind::HWAddress;
diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index aa360a3ef36e..a00a0e69c0d2 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -155,6 +155,7 @@ endif()
 if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*")
   set(ANDROID 1)
 endif()
+
 pythonize_bool(ANDROID)
 
 set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake
index aeabf17653f5..aefcc454f0cd 100644
--- a/compiler-rt/cmake/base-config-ix.cmake
+++ b/compiler-rt/cmake/base-config-ix.cmake
@@ -220,6 +220,8 @@ macro(test_targets)
       test_target_arch(wasm32 "" "--target=wasm32-unknown-unknown")
     elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "wasm64")
       test_target_arch(wasm64 "" "--target=wasm64-unknown-unknown")
+    elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "loongarch64")
+      test_target_arch(loongarch64 "" "")
     endif()
     set(COMPILER_RT_OS_SUFFIX "")
   endif()
diff --git a/compiler-rt/cmake/builtin-config-ix.cmake b/compiler-rt/cmake/builtin-config-ix.cmake
index c4d0940f9f87..55fdd60b8290 100644
--- a/compiler-rt/cmake/builtin-config-ix.cmake
+++ b/compiler-rt/cmake/builtin-config-ix.cmake
@@ -35,6 +35,7 @@ set(RISCV32 riscv32)
 set(RISCV64 riscv64)
 set(WASM32 wasm32)
 set(WASM64 wasm64)
+set(LOONGARCH64 loongarch64)
 
 if(APPLE)
   set(ARM64 arm64)
@@ -43,7 +44,7 @@ if(APPLE)
 endif()
 
 set(ALL_BUILTIN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
-    ${HEXAGON} ${MIPS32} ${MIPS64} ${PPC64} ${RISCV32} ${RISCV64} ${WASM32} ${WASM64})
+  ${HEXAGON} ${MIPS32} ${MIPS64} ${PPC64} ${RISCV32} ${RISCV64} ${WASM32} ${WASM64} ${LOONGARCH64})
 
 include(CompilerRTUtils)
 include(CompilerRTDarwinUtils)
diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index 5b9433877178..265cd908534b 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -216,6 +216,7 @@ set(RISCV64 riscv64)
 set(S390X s390x)
 set(WASM32 wasm32)
 set(WASM64 wasm64)
+set(LOONGARCH64 loongarch64)
 
 if(APPLE)
   set(ARM64 arm64)
@@ -224,32 +225,32 @@ if(APPLE)
 endif()
 
 set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64}
-    ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X})
+    ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${LOONGARCH64})
 set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
-    ${MIPS32} ${MIPS64} ${PPC64} ${S390X})
-set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
-set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64})
+    ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${LOONGARCH64})
+set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${LOONGARCH64})
+set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64} ${LOONGARCH64})
 
 if(APPLE)
   set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64})
 else()
-  set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64})
+  set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64} ${LOONGARCH64})
 endif()
-set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
+set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${LOONGARCH64})
 set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64})
 set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC64}
-    ${MIPS32} ${MIPS64} ${S390X})
-set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
+    ${MIPS32} ${MIPS64} ${S390X} ${LOONGARCH64})
+set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${LOONGARCH64})
 set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
-    ${MIPS32} ${MIPS64} ${PPC64} ${S390X})
-set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64})
-set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64})
-set(ALL_ESAN_SUPPORTED_ARCH ${X86_64} ${MIPS64})
-set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64})
+    ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${LOONGARCH64})
+set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64} ${LOONGARCH64})
+set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64} ${LOONGARCH64})
+set(ALL_ESAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${LOONGARCH64})
+set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64} ${LOONGARCH64})
 if(APPLE)
 set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
 else()
-set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le)
+set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le ${LOONGARCH64})
 endif()
 set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${X86_64} ${ARM64})
 
@@ -318,13 +319,13 @@ if(APPLE)
 
   # We're setting the flag manually for each target OS
   set(CMAKE_OSX_DEPLOYMENT_TARGET "")
-  
+
   set(DARWIN_COMMON_CFLAGS -stdlib=libc++)
   set(DARWIN_COMMON_LINK_FLAGS
     -stdlib=libc++
     -lc++
     -lc++abi)
-  
+
   check_linker_flag("-fapplication-extension" COMPILER_RT_HAS_APP_EXTENSION)
   if(COMPILER_RT_HAS_APP_EXTENSION)
     list(APPEND DARWIN_COMMON_LINK_FLAGS "-fapplication-extension")
@@ -345,7 +346,7 @@ if(APPLE)
   # Figure out which arches to use for each OS
   darwin_get_toolchain_supported_archs(toolchain_arches)
   message(STATUS "Toolchain supported arches: ${toolchain_arches}")
-  
+
   if(NOT MACOSX_VERSION_MIN_FLAG)
     darwin_test_archs(osx
       DARWIN_osx_ARCHS
diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h
index f3696da62b30..4e9e6a0da7e3 100644
--- a/compiler-rt/lib/asan/asan_mapping.h
+++ b/compiler-rt/lib/asan/asan_mapping.h
@@ -161,6 +161,8 @@ static const u64 kIosSimShadowOffset64 = kDefaultShadowOffset64;
 static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
 static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;
 static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37;
+static const u64 kLoongArch32_ShadowOffset32 = 0x0aaa0000;
+static const u64 kLoongArch64_ShadowOffset64 = 1ULL << 37;
 static const u64 kPPC64_ShadowOffset64 = 1ULL << 44;
 static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52;
 static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30;  // 0x40000000
@@ -187,6 +189,8 @@ static const u64 kMyriadCacheBitMask32 = 0x40000000ULL;
 #    define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
 #  elif defined(__mips__)
 #    define SHADOW_OFFSET kMIPS32_ShadowOffset32
+#  elif defined(__loongarch__)
+#    define SHADOW_OFFSET kLoongArch32_ShadowOffset32
 #  elif SANITIZER_FREEBSD
 #    define SHADOW_OFFSET kFreeBSD_ShadowOffset32
 #  elif SANITIZER_NETBSD
@@ -225,6 +229,8 @@ static const u64 kMyriadCacheBitMask32 = 0x40000000ULL;
 #   define SHADOW_OFFSET kDefaultShadowOffset64
 #  elif defined(__mips64)
 #   define SHADOW_OFFSET kMIPS64_ShadowOffset64
+#  elif defined(__loongarch64)
+#   define SHADOW_OFFSET kLoongArch64_ShadowOffset64
 #  elif SANITIZER_WINDOWS64
 #   define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
 #  else
diff --git a/compiler-rt/lib/asan/tests/asan_test.cc b/compiler-rt/lib/asan/tests/asan_test.cc
index 464e99f614d5..c8c948322277 100644
--- a/compiler-rt/lib/asan/tests/asan_test.cc
+++ b/compiler-rt/lib/asan/tests/asan_test.cc
@@ -624,7 +624,8 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {
 
 #if !defined(__ANDROID__) && !defined(__arm__) && \
     !defined(__aarch64__) && !defined(__mips__) && \
-    !defined(__mips64) && !defined(__s390__)
+    !defined(__mips64) && !defined(__s390__) && \
+    !defined(__loongarch__)
 NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
   // create three red zones for these two stack objects.
   int a;
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 77947417bfed..21af7cc5bd3e 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -501,6 +501,7 @@ set(mips64_SOURCES ${GENERIC_TF_SOURCES}
                    ${mips_SOURCES})
 set(mips64el_SOURCES ${GENERIC_TF_SOURCES}
                      ${mips_SOURCES})
+set(loongarch64_SOURCES ${GENERIC_TF_SOURCES} ${GENERIC_SOURCES})
 
 set(powerpc64_SOURCES
   ppc/divtc3.c
diff --git a/compiler-rt/lib/dfsan/dfsan_platform.h b/compiler-rt/lib/dfsan/dfsan_platform.h
index 98284bafd4ff..acaf38c56d10 100644
--- a/compiler-rt/lib/dfsan/dfsan_platform.h
+++ b/compiler-rt/lib/dfsan/dfsan_platform.h
@@ -31,6 +31,13 @@ struct Mapping {
   static const uptr kAppAddr = 0xF000008000;
   static const uptr kShadowMask = ~0xF000000000;
 };
+#elif defined(__loongarch64)
+struct Mapping {
+  static const uptr kShadowAddr = 0x10000;
+  static const uptr kUnionTableAddr = 0x2000000000;
+  static const uptr kAppAddr = 0xF000008000;
+  static const uptr kShadowMask = ~0xF000000000;
+};
 #elif defined(__aarch64__)
 struct Mapping39 {
   static const uptr kShadowAddr = 0x10000;
diff --git a/compiler-rt/lib/esan/esan_linux.cpp b/compiler-rt/lib/esan/esan_linux.cpp
index 014205ce01eb..c605d4192ec9 100644
--- a/compiler-rt/lib/esan/esan_linux.cpp
+++ b/compiler-rt/lib/esan/esan_linux.cpp
@@ -25,7 +25,8 @@
 namespace __esan {
 
 void verifyAddressSpace() {
-#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_MIPS64)
+#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_MIPS64 \
+    || SANITIZER_LOONGARCH64)
   // The kernel determines its mmap base from the stack size limit.
   // Our Linux 64-bit shadow mapping assumes the stack limit is less than a
   // terabyte, which keeps the mmap region above 0x7e00'.
diff --git a/compiler-rt/lib/esan/esan_shadow.h b/compiler-rt/lib/esan/esan_shadow.h
index b76a9ccbd9e4..f7f66bc19907 100644
--- a/compiler-rt/lib/esan/esan_shadow.h
+++ b/compiler-rt/lib/esan/esan_shadow.h
@@ -142,6 +142,13 @@ static const struct ApplicationRegion AppRegions[] = {
 // [0x00000020'00000000, 0x00000021'00000000)
 // [0x00000015'00000000, 0x00000015'ffffffff]
 
+static const struct ApplicationRegion AppRegions[] = {
+  {0x0100000000u, 0x0200000000u, false},
+  {0xaa00000000u, 0xab00000000u, false},
+  {0xff00000000u, 0xffffffffffu, false},
+};
+#elif SANITIZER_LINUX && SANITIZER_LOONGARCH
+
 static const struct ApplicationRegion AppRegions[] = {
   {0x0100000000u, 0x0200000000u, false},
   {0xaa00000000u, 0xab00000000u, false},
diff --git a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
index 80b33105bb22..087371069e50 100644
--- a/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp
@@ -151,7 +151,7 @@ inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
   // so we return (pc-2) in that case in order to be safe.
   // For A32 mode we return (pc-4) because all instructions are 32 bit long.
   return (PC - 3) & (~1);
-#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
+#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__) || defined(__loongarch__)
   // PCs are always 4 byte aligned.
   return PC - 4;
 #elif defined(__sparc__) || defined(__mips__)
@@ -167,7 +167,7 @@ inline ALWAYS_INLINE uintptr_t GetNextInstructionPc(uintptr_t PC) {
 #if defined(__mips__)
   return PC + 8;
 #elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \
-    defined(__aarch64__)
+    defined(__aarch64__) || defined(__loongarch__)
   return PC + 4;
 #else
   return PC + 1;
diff --git a/compiler-rt/lib/interception/tests/CMakeLists.txt b/compiler-rt/lib/interception/tests/CMakeLists.txt
index 1da0a455bf33..d1a5f42baac6 100644
--- a/compiler-rt/lib/interception/tests/CMakeLists.txt
+++ b/compiler-rt/lib/interception/tests/CMakeLists.txt
@@ -1,6 +1,6 @@
 include(CompilerRTCompile)
 
-filter_available_targets(INTERCEPTION_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el)
+filter_available_targets(INTERCEPTION_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el loongarch64)
 
 set(INTERCEPTION_UNITTESTS
   interception_linux_test.cc
diff --git a/compiler-rt/lib/lsan/lsan.h b/compiler-rt/lib/lsan/lsan.h
index 6baee81d00cd..6804c9648522 100644
--- a/compiler-rt/lib/lsan/lsan.h
+++ b/compiler-rt/lib/lsan/lsan.h
@@ -54,7 +54,8 @@ void GetStackTrace(__sanitizer::BufferedStackTrace *stack,
     stack_top = t->stack_end();
     stack_bottom = t->stack_begin();
   }
-  if (!SANITIZER_MIPS || IsValidFrame(bp, stack_top, stack_bottom)) {
+  if ( (!SANITIZER_MIPS && !SANITIZER_LOONGARCH)
+    || IsValidFrame(bp, stack_top, stack_bottom)) {
     stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast);
   }
 }
diff --git a/compiler-rt/lib/lsan/lsan_allocator.cc b/compiler-rt/lib/lsan/lsan_allocator.cc
index 1b338bd5973e..428fe0ddae39 100644
--- a/compiler-rt/lib/lsan/lsan_allocator.cc
+++ b/compiler-rt/lib/lsan/lsan_allocator.cc
@@ -29,7 +29,7 @@ extern "C" void *memset(void *ptr, int value, uptr num);
 namespace __lsan {
 #if defined(__i386__) || defined(__arm__)
 static const uptr kMaxAllowedMallocSize = 1UL << 30;
-#elif defined(__mips64) || defined(__aarch64__)
+#elif defined(__mips64) || defined(__aarch64__) || defined(__loongarch64)
 static const uptr kMaxAllowedMallocSize = 4UL << 30;
 #else
 static const uptr kMaxAllowedMallocSize = 8UL << 30;
diff --git a/compiler-rt/lib/lsan/lsan_allocator.h b/compiler-rt/lib/lsan/lsan_allocator.h
index 4c4e02fc0902..d362cbf1401a 100644
--- a/compiler-rt/lib/lsan/lsan_allocator.h
+++ b/compiler-rt/lib/lsan/lsan_allocator.h
@@ -51,7 +51,7 @@ struct ChunkMetadata {
 };
 
 #if defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \
-    defined(__arm__)
+    defined(__arm__)  || defined(__loongarch64)
 static const uptr kRegionSizeLog = 20;
 static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
 template <typename AddressSpaceView>
diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc
index eaa5cadc8ffb..51733db5bdb4 100644
--- a/compiler-rt/lib/lsan/lsan_common.cc
+++ b/compiler-rt/lib/lsan/lsan_common.cc
@@ -139,6 +139,8 @@ static inline bool CanBeAHeapPointer(uptr p) {
   return ((p >> 47) == 0);
 #elif defined(__mips64)
   return ((p >> 40) == 0);
+#elif defined(__loongarch64)
+  return ((p >> 40) == 0);
 #elif defined(__aarch64__)
   unsigned runtimeVMA =
     (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h
index 1d1e1e462435..23ed67e29333 100644
--- a/compiler-rt/lib/lsan/lsan_common.h
+++ b/compiler-rt/lib/lsan/lsan_common.h
@@ -33,7 +33,7 @@
 #if (SANITIZER_LINUX && !SANITIZER_ANDROID || SANITIZER_MAC) && \
     (SANITIZER_WORDSIZE == 64) &&                               \
     (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) || \
-     defined(__powerpc64__))
+     defined(__powerpc64__) || defined(__loongarch64))
 #define CAN_SANITIZE_LEAKS 1
 #elif defined(__i386__) && \
     (SANITIZER_LINUX && !SANITIZER_ANDROID || SANITIZER_MAC)
diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h
index 4c2e9f9e24a0..c19b28dee768 100644
--- a/compiler-rt/lib/msan/msan.h
+++ b/compiler-rt/lib/msan/msan.h
@@ -64,6 +64,30 @@ const MappingDesc kMemoryLayout[] = {
 #define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x8000000000ULL)
 #define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x2000000000ULL)
 
+#elif SANITIZER_LINUX && defined(__loongarch64)
+
+// LOONGARCH64 maps:
+// - 0x0000000000-0x0200000000: Program own segments
+// - 0xa200000000-0xc000000000: PIE program segments
+// - 0xe200000000-0xffffffffff: libraries segments.
+const MappingDesc kMemoryLayout[] = {
+    {0x000000000000ULL, 0x000200000000ULL, MappingDesc::APP, "app-1"},
+    {0x000200000000ULL, 0x002200000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x002200000000ULL, 0x004000000000ULL, MappingDesc::SHADOW, "shadow-2"},
+    {0x004000000000ULL, 0x004200000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x004200000000ULL, 0x006000000000ULL, MappingDesc::ORIGIN, "origin-2"},
+    {0x006000000000ULL, 0x006200000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x006200000000ULL, 0x008000000000ULL, MappingDesc::SHADOW, "shadow-3"},
+    {0x008000000000ULL, 0x008200000000ULL, MappingDesc::SHADOW, "shadow-1"},
+    {0x008200000000ULL, 0x00a000000000ULL, MappingDesc::ORIGIN, "origin-3"},
+    {0x00a000000000ULL, 0x00a200000000ULL, MappingDesc::ORIGIN, "origin-1"},
+    {0x00a200000000ULL, 0x00c000000000ULL, MappingDesc::APP, "app-2"},
+    {0x00c000000000ULL, 0x00e200000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x00e200000000ULL, 0x00ffffffffffULL, MappingDesc::APP, "app-3"}};
+
+#define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x8000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x2000000000ULL)
+
 #elif SANITIZER_LINUX && defined(__aarch64__)
 
 // The mapping describes both 39-bits, 42-bits, and 48-bits VMA.  AArch64
diff --git a/compiler-rt/lib/msan/msan_allocator.cc b/compiler-rt/lib/msan/msan_allocator.cc
index 053ab0280397..f3b7fe59f64e 100644
--- a/compiler-rt/lib/msan/msan_allocator.cc
+++ b/compiler-rt/lib/msan/msan_allocator.cc
@@ -45,7 +45,7 @@ struct MsanMapUnmapCallback {
   }
 };
 
-#if defined(__mips64)
+#if defined(__mips64) || defined(__loongarch64)
   static const uptr kMaxAllowedMallocSize = 2UL << 30;
   static const uptr kRegionSizeLog = 20;
   static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc
index 497f943a8a0e..3c03c4093869 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cc
+++ b/compiler-rt/lib/msan/msan_interceptors.cc
@@ -1679,7 +1679,7 @@ void InitializeInterceptors() {
   INTERCEPT_FUNCTION(dlerror);
   INTERCEPT_FUNCTION(dl_iterate_phdr);
   INTERCEPT_FUNCTION(getrusage);
-#if defined(__mips__)
+#if defined(__mips__) || defined(__loongarch__)
   INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
 #else
   INTERCEPT_FUNCTION(pthread_create);
diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc
index 19f46abdc574..5c1ba7fb9507 100644
--- a/compiler-rt/lib/msan/tests/msan_test.cc
+++ b/compiler-rt/lib/msan/tests/msan_test.cc
@@ -3146,6 +3146,8 @@ static void GetPathToLoadable(char *buf, size_t sz) {
   static const char basename[] = "libmsan_loadable.mips64.so";
 #elif defined(__mips64)
   static const char basename[] = "libmsan_loadable.mips64el.so";
+#elif defined(__loongarch64)
+  static const char basename[] = "libmsan_loadable.loongarch64.so";
 #elif defined(__aarch64__)
   static const char basename[] = "libmsan_loadable.aarch64.so";
 #elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt
index f7bf4b009720..7e2d2adbbf56 100644
--- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt
+++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt
@@ -46,6 +46,8 @@ if(UNIX AND NOT APPLE AND NOT OS_NAME MATCHES "SunOS")
     sanitizer_linux_x86_64.S)
   list(APPEND SANITIZER_SOURCES_NOTERMINATION
     sanitizer_linux_mips64.S)
+  list(APPEND SANITIZER_SOURCES_NOTERMINATION
+    sanitizer_linux_loongarch64.S)
 endif()
 
 set(SANITIZER_SOURCES
@@ -214,6 +216,8 @@ if (LLVM_ENABLE_PEDANTIC AND UNIX AND NOT APPLE)
     PROPERTIES COMPILE_FLAGS "-w")
   set_source_files_properties(sanitizer_linux_mips64.S
     PROPERTIES COMPILE_FLAGS "-w")
+  set_source_files_properties(sanitizer_linux_loongarch64.S
+    PROPERTIES COMPILE_FLAGS "-pedantic")
 endif ()
 
 if(APPLE)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
index 48795674c54c..85c804dfb85e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
@@ -14,6 +14,10 @@
 
 #include "sanitizer_platform.h"
 
+#if defined(__loongarch__)
+#define __ARCH_WANT_RENAMEAT 1
+#endif
+
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
     SANITIZER_OPENBSD || SANITIZER_SOLARIS
 
@@ -129,7 +133,7 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
 #endif
 
-#if defined(__x86_64__) || SANITIZER_MIPS64
+#if defined(__x86_64__) || SANITIZER_MIPS64 || SANITIZER_LOONGARCH64
 extern "C" {
 extern void internal_sigreturn();
 }
@@ -337,7 +341,7 @@ uptr internal_lstat(const char *path, void *buf) {
   return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
                           AT_SYMLINK_NOFOLLOW);
 #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
-# if SANITIZER_MIPS64
+#if SANITIZER_MIPS64
   // For mips64, lstat syscall fills buffer in the format of kernel_stat
   struct kernel_stat kbuf;
   int res = internal_syscall(SYSCALL(lstat), path, &kbuf);
@@ -346,7 +350,7 @@ uptr internal_lstat(const char *path, void *buf) {
 # else
   return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
 # endif
-#else
+# else
   struct stat64 buf64;
   int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
   stat64_to_stat(&buf64, (struct stat *)buf);
@@ -842,7 +846,8 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
 // Invokes sigaction via a raw syscall with a restorer, but does not support
 // all platforms yet.
 // We disable for Go simply because we have not yet added to buildgo.sh.
-#if (defined(__x86_64__) || SANITIZER_MIPS64) && !SANITIZER_GO
+#if (defined(__x86_64__) || SANITIZER_MIPS64 || SANITIZER_LOONGARCH64) && \
+    !SANITIZER_GO
 int internal_sigaction_syscall(int signum, const void *act, void *oldact) {
   if (act == nullptr)
     return internal_sigaction_norestorer(signum, act, oldact);
@@ -954,8 +959,14 @@ ThreadLister::Result ThreadLister::ListThreads(
         // See proc_task_readdir implementation in Linux.
         result = Incomplete;
       }
-      if (entry->d_ino && *entry->d_name >= '0' && *entry->d_name <= '9')
-        threads->push_back(internal_atoll(entry->d_name));
+      // In Loongarch64, there are something wrong with internal_getdents
+      // the first character of buffer.data is always wrong
+      char *d_name_ptr = entry->d_name;
+      if (*d_name_ptr < '0' || *d_name_ptr > '9') {
+        ++d_name_ptr;
+      }
+      if (entry->d_ino && *d_name_ptr >= '0' && *d_name_ptr <= '9')
+        threads->push_back(internal_atoll(d_name_ptr));
     }
 
     // Now we are going to detect short-read or early EOF. In such cases Linux
@@ -1053,6 +1064,8 @@ uptr GetMaxVirtualAddress() {
   return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;
 # elif defined(__mips64)
   return (1ULL << 40) - 1;  // 0x000000ffffffffffUL;
+# elif defined(__loongarch64)
+  return (1ULL << 40) - 1;  // 0x000000ffffffffffUL;
 # elif defined(__s390x__)
   return (1ULL << 53) - 1;  // 0x001fffffffffffffUL;
 # else
@@ -1084,7 +1097,7 @@ uptr GetPageSize() {
 #elif SANITIZER_USE_GETAUXVAL
   return getauxval(AT_PAGESZ);
 #elif SANITIZER_FREEBSD || SANITIZER_NETBSD
-// Use sysctl as sysconf can trigger interceptors internally.
+  // Use sysctl as sysconf can trigger interceptors internally.
   int pz = 0;
   uptr pzl = sizeof(pz);
   int mib[2] = {CTL_HW, HW_PAGESIZE};
@@ -1342,6 +1355,61 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                        : "memory", "$29" );
   return res;
 }
+#elif defined(__loongarch__) && SANITIZER_LINUX
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+                    int *parent_tidptr, void *newtls, int *child_tidptr) {
+  long long res;
+  if (!fn || !child_stack)
+    return -EINVAL;
+  CHECK_EQ(0, (uptr)child_stack % 16);
+  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
+  ((unsigned long long *)child_stack)[0] = (uptr)fn;
+  ((unsigned long long *)child_stack)[1] = (uptr)arg;
+
+  register int   __flags         __asm__("r4") = flags;
+  register void *__child_stack   __asm__("r5") = child_stack;
+  register int  *__parent_tidptr __asm__("r6") = parent_tidptr;
+  register void *__newtls        __asm__("r7") = newtls;
+  register int  *__child_tidptr  __asm__("r8") = child_tidptr;
+
+  __asm__ __volatile__(
+      /* $a0 = syscall($a7 = SYSCALL(clone),
+       *               $a0 = flags,
+       *               $a1 = child_stack,
+       *               $a2 = parent_tidptr,
+       *               $a3 = new_tls,
+       *               $a4 = child_tyidptr)
+       */
+
+      /* Do the system call */
+      "addi.d $a7, $r0, %1\n"
+      "syscall 0\n"
+
+      "move %0, $a0"
+      : "=r"(res)
+      : "i"(__NR_clone),
+      "r"(__flags), "r"(__child_stack), "r"(__parent_tidptr), "r"(__newtls), "r"(__child_tidptr)
+      :"memory" );
+      if (res != 0) {
+        return res;
+      }
+    __asm__ __volatile__ (
+         /* In the child, now. Call "fn(arg)". */
+      "ld.d $a6, $sp, 0\n"
+      "ld.d $a0, $sp, 8\n"
+
+      "jirl $r1, $a6, 0\n"
+
+      /* Call _exit($v0) */
+      "addi.d $a7, $r0, %1\n"
+      "syscall 0\n"
+
+      "move %0, $a0"
+      : "=r"(res)
+      : "i"(__NR_exit)
+      :"r1", "memory");
+  return res;
+}
 #elif defined(__aarch64__)
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                     int *parent_tidptr, void *newtls, int *child_tidptr) {
@@ -1393,6 +1461,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                        : "x30", "memory");
   return res;
 }
+
 #elif defined(__powerpc64__)
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                    int *parent_tidptr, void *newtls, int *child_tidptr) {
@@ -1837,6 +1906,30 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
 #endif
   }
   return SignalContext::UNKNOWN;
+#elif defined(__loongarch__)
+  uint32_t *exception_source;
+  uint32_t faulty_instruction;
+  uint32_t op_code;
+
+  exception_source = (uint32_t *)ucontext->uc_mcontext.__pc;
+  faulty_instruction = (uint32_t)(*exception_source);
+
+  op_code = (faulty_instruction >> 22) & 0x3ff;
+  switch (op_code) {
+    case 0xa0: //ld.b
+    case 0xa1: //ld.h
+    case 0xa2: //ld.w
+    case 0xa3: //ld.d
+      return SignalContext::READ;
+    case 0xa4:
+    case 0xa5:
+    case 0xa6:
+      return SignalContext::WRITE;
+    case 0xa8:
+    case 0xa9:
+      return SignalContext::READ;
+  }
+  return SignalContext::UNKNOWN;
 #elif defined(__arm__)
   static const uptr FSR_WRITE = 1U << 11;
   uptr fsr = ucontext->uc_mcontext.error_code;
@@ -1896,7 +1989,7 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
   *pc = ucontext->sc_rip;
   *bp = ucontext->sc_rbp;
   *sp = ucontext->sc_rsp;
-# else
+#else
   ucontext_t *ucontext = (ucontext_t*)context;
   *pc = ucontext->uc_mcontext.gregs[REG_RIP];
   *bp = ucontext->uc_mcontext.gregs[REG_RBP];
@@ -1967,6 +2060,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
   *pc = ucontext->uc_mcontext.pc;
   *bp = ucontext->uc_mcontext.gregs[30];
   *sp = ucontext->uc_mcontext.gregs[29];
+#elif defined(__loongarch__)
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.__pc;
+  *bp = ucontext->uc_mcontext.__gregs[30];
+  *sp = ucontext->uc_mcontext.__gregs[3];
 #elif defined(__s390__)
   ucontext_t *ucontext = (ucontext_t*)context;
 # if defined(__s390x__)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h
index c309e33f81b1..3e3b77fbb61a 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h
@@ -59,14 +59,15 @@ uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
 // (like the process-wide error reporting SEGV handler) must use
 // internal_sigaction instead.
 int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
-#if (defined(__x86_64__) || SANITIZER_MIPS64) && !SANITIZER_GO
+#if (defined(__x86_64__) || SANITIZER_MIPS64 || SANITIZER_LOONGARCH64) \
+    && !SANITIZER_GO
 // Uses a raw system call to avoid interceptors.
 int internal_sigaction_syscall(int signum, const void *act, void *oldact);
 #endif
 void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
 #if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) \
   || defined(__powerpc64__) || defined(__s390__) || defined(__i386__) \
-  || defined(__arm__)
+  || defined(__arm__) || defined(__loongarch__)
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                     int *parent_tidptr, void *newtls, int *child_tidptr);
 #endif
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc
index 6ce47ec620dc..4626dfa7cdb8 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -265,7 +265,7 @@ void InitTlsSize() { }
 
 #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) ||          \
      defined(__aarch64__) || defined(__powerpc64__) || defined(__s390__) ||    \
-     defined(__arm__)) &&                                                      \
+     defined(__arm__) || defined(__loongarch__)) && \
     SANITIZER_LINUX && !SANITIZER_ANDROID
 // sizeof(struct pthread) from glibc.
 static atomic_uintptr_t thread_descriptor_size;
@@ -305,6 +305,8 @@ uptr ThreadDescriptorSize() {
 #elif defined(__mips__)
   // TODO(sagarthakur): add more values as per different glibc versions.
   val = FIRST_32_SECOND_64(1152, 1776);
+#elif defined(__loongarch64)
+  val = 1776;
 #elif defined(__aarch64__)
   // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
   val = 1776;
@@ -325,12 +327,14 @@ uptr ThreadSelfOffset() {
   return kThreadSelfOffset;
 }
 
-#if defined(__mips__) || defined(__powerpc64__)
+#if defined(__mips__) || defined(__powerpc64__) || defined(__loongarch__)
 // TlsPreTcbSize includes size of struct pthread_descr and size of tcb
 // head structure. It lies before the static tls blocks.
 static uptr TlsPreTcbSize() {
 # if defined(__mips__)
   const uptr kTcbHead = 16; // sizeof (tcbhead_t)
+# elif defined(__loongarch__)
+  const uptr kTcbHead = 16; // sizeof (tcbhead_t)
 # elif defined(__powerpc64__)
   const uptr kTcbHead = 88; // sizeof (tcbhead_t)
 # endif
@@ -359,6 +363,10 @@ uptr ThreadSelf() {
                 rdhwr %0,$29;\
                 .set pop" : "=r" (thread_pointer));
   descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize();
+# elif defined(__loongarch__)
+  uptr thread_pointer;
+  asm("or %0,$r2,$r0" : "=r" (thread_pointer));
+  descr_addr = thread_pointer - TlsPreTcbSize();
 # elif defined(__aarch64__) || defined(__arm__)
   descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
                                       ThreadDescriptorSize();
@@ -438,7 +446,7 @@ static void GetTls(uptr *addr, uptr *size) {
   *addr -= *size;
   *addr += ThreadDescriptorSize();
 # elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) \
-    || defined(__arm__)
+    || defined(__arm__) || defined(__loongarch__)
   *addr = ThreadSelf();
   *size = GetTlsSize();
 # else
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_loongarch64.S b/compiler-rt/lib/sanitizer_common/sanitizer_linux_loongarch64.S
new file mode 100644
index 000000000000..245816e60546
--- /dev/null
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_loongarch64.S
@@ -0,0 +1,22 @@
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+
+// Avoid being marked as needing an executable stack:
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+// Further contents are loongarch64 only:
+#if defined(__linux__) && defined(__loongarch64)
+
+.section .text
+.globl internal_sigreturn
+.type internal_sigreturn, @function
+internal_sigreturn:
+
+        li.d $r11,139 // #139 is for SYS_rt_sigreturn
+        syscall 0
+
+.size internal_sigreturn, .-internal_sigreturn
+
+#endif // defined(__linux__) && defined(__loongarch64)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
index 82bb1af7746b..42b2936d1e90 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
@@ -222,7 +222,7 @@
 #ifndef SANITIZER_CAN_USE_ALLOCATOR64
 # if (SANITIZER_ANDROID && defined(__aarch64__)) || SANITIZER_FUCHSIA
 #  define SANITIZER_CAN_USE_ALLOCATOR64 1
-# elif defined(__mips64) || defined(__aarch64__)
+# elif defined(__mips64) || defined(__aarch64__) || defined(__loongarch64)
 #  define SANITIZER_CAN_USE_ALLOCATOR64 0
 # else
 #  define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
@@ -232,7 +232,7 @@
 // The range of addresses which can be returned my mmap.
 // FIXME: this value should be different on different platforms.  Larger values
 // will still work but will consume more memory for TwoLevelByteMap.
-#if defined(__mips__)
+#if defined(__mips__) || defined(__loongarch__)
 # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
 #elif defined(__aarch64__)
 # if SANITIZER_MAC
@@ -249,7 +249,7 @@
 // the upstream linux community for all new ports. Other ports may still
 // use legacy syscalls.
 #ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
-# if defined(__aarch64__) && SANITIZER_LINUX
+# if (defined(__aarch64__) || defined(__loongarch64)) && SANITIZER_LINUX
 # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
 # else
 # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
@@ -275,6 +275,21 @@
 # define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12)
 #endif
 
+#if defined(__loongarch__)
+# define SANITIZER_LOONGARCH 1
+# if defined(__loongarch64)
+# define SANITIZER_LOONGARCH32 0
+# define SANITIZER_LOONGARCH64 1
+# else
+# define SANITIZER_LOONGARCH32 1
+# define SANITIZER_LOONGARCH64 0
+# endif
+#else
+# define SANITIZER_LOONGARCH 0
+# define SANITIZER_LOONGARCH32 0
+# define SANITIZER_LOONGARCH64 0
+#endif
+
 /// \macro MSC_PREREQ
 /// \brief Is the compiler MSVC of at least the specified version?
 /// The common \param version values to check for are:
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 4d146651b78d..0dfbff48261e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -477,8 +477,8 @@
   (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \
   SI_NOT_RTEMS)
 #define SANITIZER_INTERCEPT_CFREE \
-  (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \
-  SI_NOT_RTEMS)
+  (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && \
+  !SANITIZER_LOONGARCH && SI_NOT_FUCHSIA && SI_NOT_RTEMS)
 #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS)
 #define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_OPENBSD)
 #define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc
index 46e3b181304e..8300501c6f54 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc
@@ -66,7 +66,7 @@ namespace __sanitizer {
 
 #if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\
                             && !defined(__mips__) && !defined(__s390__)\
-                            && !defined(__sparc__)
+                            && !defined(__sparc__) && !defined(__loongarch__)
 COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
 #endif
 
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
index ecc69bcea79b..63cc69ceab46 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -226,10 +226,11 @@ namespace __sanitizer {
   // has been removed from glibc 2.28.
 #if defined(__aarch64__) || defined(__s390x__) || defined (__mips64) \
   || defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) \
-  || defined(__x86_64__)
+  || defined(__x86_64__) || defined(__loongarch64)
 #define SIZEOF_STRUCT_USTAT 32
 #elif defined(__arm__) || defined(__i386__) || defined(__mips__) \
-  || defined(__powerpc__) || defined(__s390__) || defined(__sparc__)
+  || defined(__powerpc__) || defined(__s390__) || defined(__sparc__) \
+  || defined(__loongarch__)
 #define SIZEOF_STRUCT_USTAT 20
 #else
 #error Unknown size of struct ustat
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index de69852d35a6..260993f7c696 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -84,6 +84,9 @@ namespace __sanitizer {
                  SANITIZER_ANDROID ? FIRST_32_SECOND_64(104, 128) :
                                      FIRST_32_SECOND_64(160, 216);
   const unsigned struct_kernel_stat64_sz = 104;
+#elif defined(__loongarch__)
+    const unsigned struct_kernel_stat_sz = 128;
+    const unsigned struct_kernel_stat64_sz = 128;
 #elif defined(__s390__) && !defined(__s390x__)
   const unsigned struct_kernel_stat_sz = 64;
   const unsigned struct_kernel_stat64_sz = 104;
@@ -655,7 +658,7 @@ namespace __sanitizer {
   };
 #endif // !SANITIZER_ANDROID
 
-#if defined(__mips__)
+#if defined(__mips__) || defined(__loongarch__)
   struct __sanitizer_kernel_sigset_t {
     uptr sig[2];
   };
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc
index 21976b6b1531..8712bd5a68ba 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc
@@ -21,7 +21,7 @@ uptr StackTrace::GetNextInstructionPc(uptr pc) {
 #if defined(__mips__)
   return pc + 8;
 #elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \
-    defined(__aarch64__)
+    defined(__aarch64__) || defined(__loongarch__)
   return pc + 4;
 #else
   return pc + 1;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h
index 450a40a9069f..f30386f60ac3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h
@@ -19,7 +19,8 @@ namespace __sanitizer {
 
 static const u32 kStackTraceMax = 256;
 
-#if defined(__sparc__) || (SANITIZER_LINUX && defined(__mips__))
+#if defined(__sparc__) || (SANITIZER_LINUX && defined(__mips__)) || \
+(SANITIZER_LINUX && defined(__loongarch__))
 # define SANITIZER_CAN_FAST_UNWIND 0
 #elif SANITIZER_WINDOWS
 # define SANITIZER_CAN_FAST_UNWIND 0
@@ -79,7 +80,8 @@ uptr StackTrace::GetPreviousInstructionPc(uptr pc) {
   // so we return (pc-2) in that case in order to be safe.
   // For A32 mode we return (pc-4) because all instructions are 32 bit long.
   return (pc - 3) & (~1);
-#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
+#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__) \
+|| defined(__loongarch__)
   // PCs are always 4 byte aligned.
   return pc - 4;
 #elif defined(__sparc__) || defined(__mips__)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
index fe4fe86daedf..0afbc6551dc8 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -17,13 +17,17 @@
 #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) || \
                         defined(__aarch64__) || defined(__powerpc64__) || \
                         defined(__s390__) || defined(__i386__) || \
-                        defined(__arm__))
+                        defined(__arm__) || defined(__loongarch__))
 
 #include "sanitizer_stoptheworld.h"
 
 #include "sanitizer_platform_limits_posix.h"
 #include "sanitizer_atomic.h"
 
+#if defined(__loongarch__)
+#include <sys/ucontext.h>
+#endif
+
 #include <errno.h>
 #include <sched.h> // for CLONE_* definitions
 #include <stddef.h>
@@ -37,7 +41,7 @@
 # include <asm/ptrace.h>
 #endif
 #include <sys/user.h>  // for user_regs_struct
-#if SANITIZER_ANDROID && SANITIZER_MIPS
+#if (SANITIZER_ANDROID && SANITIZER_MIPS) || SANITIZER_LOONGARCH
 # include <asm/reg.h>  // for mips SP register in sys/user.h
 #endif
 #include <sys/wait.h> // for signal-related stuff
@@ -492,8 +496,14 @@ typedef pt_regs regs_struct;
 
 #elif defined(__mips__)
 typedef struct user regs_struct;
+#elif defined(__loongarch__)
+typedef struct user_regs_struct regs_struct;
+#define ARCH_IOVEC_FOR_GETREGSET
+
 # if SANITIZER_ANDROID
 #  define REG_SP regs[EF_R29]
+# elif SANITIZER_LOONGARCH
+  #define REG_SP gpr[3]
 # else
 #  define REG_SP regs[EF_REG29]
 # endif
diff --git a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
index 21ffe2528c25..0fdd2aa19a8d 100644
--- a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
+++ b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
@@ -3,7 +3,7 @@ include(CompilerRTCompile)
 clang_compiler_add_cxx_check()
 
 # FIXME: use SANITIZER_COMMON_SUPPORTED_ARCH here
-filter_available_targets(SANITIZER_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el)
+filter_available_targets(SANITIZER_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el loongarch64)
 if(APPLE)
   darwin_filter_host_archs(SANITIZER_UNITTEST_SUPPORTED_ARCH SANITIZER_UNITTEST_SUPPORTED_ARCH)
 endif()
diff --git a/compiler-rt/lib/tsan/CMakeLists.txt b/compiler-rt/lib/tsan/CMakeLists.txt
index e1da319ccc87..2be97a829317 100644
--- a/compiler-rt/lib/tsan/CMakeLists.txt
+++ b/compiler-rt/lib/tsan/CMakeLists.txt
@@ -103,7 +103,7 @@ set(TSAN_RUNTIME_LIBRARIES)
 add_compiler_rt_component(tsan)
 
 if(APPLE)
-  add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S rtl/tsan_rtl_aarch64.S)
+  add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S rtl/tsan_rtl_aarch64.S/tsan_rtl_loongarch64.S)
 
   set(TSAN_LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS})
 
@@ -180,6 +180,8 @@ else()
 	VERBATIM)
     elseif(arch MATCHES "mips64|mips64le")
       add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_mips64.S)
+    elseif(arch MATCHES "loongarch64")
+	  add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_loongarch64.S)
     else()
       set(TSAN_ASM_SOURCES)
     endif()
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
index 9e49dfe5d582..4f9fefe308c8 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
@@ -74,7 +74,8 @@ struct ucontext_t {
 };
 #endif
 
-#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1
+#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 \
+    || defined(__loongarch__)
 #define PTHREAD_ABI_BASE  "GLIBC_2.3.2"
 #elif defined(__aarch64__) || SANITIZER_PPC64V2
 #define PTHREAD_ABI_BASE  "GLIBC_2.17"
@@ -525,6 +526,8 @@ static void LongJmp(ThreadState *thr, uptr *env) {
   uptr mangled_sp = env[13];
 # elif defined(__mips64)
   uptr mangled_sp = env[1];
+#elif defined(__loongarch64)
+  uptr mangled_sp = env[2];
 # else
   uptr mangled_sp = env[6];
 # endif
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h
index 8303c241809b..8c6a3e2390b5 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h
@@ -114,6 +114,45 @@ struct Mapping {
   static const uptr kVdsoBeg       = 0xfffff00000ull;
 };
 
+#define TSAN_MID_APP_RANGE 1
+#elif defined(__loongarch64)
+/*
+ * TODO same as mips64 and need to change in the future
+C/C++ on linux/loongarch64 (40-bit VMA)
+0000 0000 00 - 0100 0000 00: -                                           (4 GB)
+0100 0000 00 - 0200 0000 00: main binary                                 (4 GB)
+0200 0000 00 - 2000 0000 00: -                                         (120 GB)
+2000 0000 00 - 4000 0000 00: shadow                                    (128 GB)
+4000 0000 00 - 5000 0000 00: metainfo (memory blocks and sync objects)  (64 GB)
+5000 0000 00 - aa00 0000 00: -                                         (360 GB)
+aa00 0000 00 - ab00 0000 00: main binary (PIE)                           (4 GB)
+ab00 0000 00 - b000 0000 00: -                                          (20 GB)
+b000 0000 00 - b200 0000 00: traces                                      (8 GB)
+b200 0000 00 - fe00 0000 00: -                                         (304 GB)
+fe00 0000 00 - ff00 0000 00: heap                                        (4 GB)
+ff00 0000 00 - ff80 0000 00: -                                           (2 GB)
+ff80 0000 00 - ffff ffff ff: modules and main thread stack              (<2 GB)
+*/
+struct Mapping {
+  static const uptr kMetaShadowBeg = 0x4000000000ull;
+  static const uptr kMetaShadowEnd = 0x5000000000ull;
+  static const uptr kTraceMemBeg   = 0xb000000000ull;
+  static const uptr kTraceMemEnd   = 0xb200000000ull;
+  static const uptr kShadowBeg     = 0x2000000000ull;
+  static const uptr kShadowEnd     = 0x4000000000ull;
+  static const uptr kHeapMemBeg    = 0xfe00000000ull;
+  static const uptr kHeapMemEnd    = 0xff00000000ull;
+  static const uptr kLoAppMemBeg   = 0x0100000000ull;
+  static const uptr kLoAppMemEnd   = 0x0200000000ull;
+  static const uptr kMidAppMemBeg  = 0xaa00000000ull;
+  static const uptr kMidAppMemEnd  = 0xab00000000ull;
+  static const uptr kHiAppMemBeg   = 0xff80000000ull;
+  static const uptr kHiAppMemEnd   = 0xffffffffffull;
+  static const uptr kAppMemMsk     = 0xf800000000ull;
+  static const uptr kAppMemXor     = 0x0800000000ull;
+  static const uptr kVdsoBeg       = 0xfffff00000ull;
+};
+
 #define TSAN_MID_APP_RANGE 1
 #elif defined(__aarch64__) && defined(__APPLE__)
 /*
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc
index c38dcc7f2c1c..7a8982eb16e4 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc
@@ -70,6 +70,9 @@ void InitializeShadowMemory() {
 #elif defined(__mips64)
   const uptr kMadviseRangeBeg  = 0xff00000000ull;
   const uptr kMadviseRangeSize = 0x0100000000ull;
+#elif defined(__loongarch64)
+  const uptr kMadviseRangeBeg  = 0xff00000000ull;
+  const uptr kMadviseRangeSize = 0x0100000000ull;
 #elif defined(__aarch64__) && defined(__APPLE__)
   uptr kMadviseRangeBeg = LoAppMemBeg();
   uptr kMadviseRangeSize = LoAppMemEnd() - LoAppMemBeg();
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
index f038e9682d89..c81a8549eef6 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
@@ -226,7 +226,7 @@ static void StartBackgroundThread() {
   ctx->background_thread = internal_start_thread(&BackgroundThread, 0);
 }
 
-#ifndef __mips__
+#if !(defined(__mips__) || defined(__loongarch__))
 static void StopBackgroundThread() {
   atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed);
   internal_join_thread(ctx->background_thread);
@@ -421,7 +421,7 @@ void MaybeSpawnBackgroundThread() {
   // On MIPS, TSan initialization is run before
   // __pthread_initialize_minimal_internal() is finished, so we can not spawn
   // new threads.
-#if !SANITIZER_GO && !defined(__mips__)
+#if !SANITIZER_GO && !(defined(__mips__) || defined(__loongarch__))
   static atomic_uint32_t bg_thread = {};
   if (atomic_load(&bg_thread, memory_order_relaxed) == 0 &&
       atomic_exchange(&bg_thread, 1, memory_order_relaxed) == 0) {
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
index 3410be294502..4f86cc47896a 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -55,7 +55,8 @@ namespace __tsan {
 
 #if !SANITIZER_GO
 struct MapUnmapCallback;
-#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__)
+#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) \
+    || defined(__loongarch64)
 static const uptr kAllocatorRegionSizeLog = 20;
 static const uptr kAllocatorNumRegions =
     SANITIZER_MMAP_RANGE_SIZE >> kAllocatorRegionSizeLog;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S b/compiler-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S
new file mode 100644
index 000000000000..9331e8afa94a
--- /dev/null
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S
@@ -0,0 +1,156 @@
+.section .text
+
+.hidden __tsan_setjmp
+.comm _ZN14__interception11real_setjmpE,8,8
+.globl setjmp
+.type setjmp, @function
+setjmp:
+
+  # save env parameters
+  addi.d $r3,$r3,-24
+  st.d $r1,$r3,16
+  st.d $r22,$r3,8
+
+  # save jmp_buf
+  st.d $r4,$r3,0
+
+  # obtain $sp
+  add.d $r4,$r0,$r3
+
+  # call tsan interceptor
+  addi.d $r5,$r4,24
+  bl __tsan_setjmp
+
+  # restore jmp_buf
+  ld.d $r4,$r3,0
+
+  # load libc setjmp to r20
+  la $r20,_ZN14__interception11real_setjmpE
+  # restore env parameters
+  ld.d $r22,$r3,8
+  ld.d $r1,$r3,16
+  addi.d $r3,$r3,24
+
+  # tail jump to libc setjmp
+  ld.d $r20,$r20,0
+  jr $r20
+
+.size setjmp, .-setjmp
+
+.hidden __tsan_setjmp
+.globl _setjmp
+.comm _ZN14__interception12real__setjmpE,8,8
+.type _setjmp, @function
+_setjmp:
+
+  # Save env parameters
+  addi.d $r3,$r3,-24
+  st.d $r1,$r3,16
+  st.d $r22,$r3,8
+
+  # save jmp_buf
+  st.d $r4,$r3,0
+
+  # obtain $sp
+  add.d $r4,$r0,$r3
+
+  # call tsan interceptor
+  addi.d $r5,$r4,24
+  bl __tsan_setjmp
+
+  # restore jmp_buf
+  ld.d $r4,$r3,0
+
+  # load libc _setjmp to r20
+  la $r20,_ZN14__interception12real__setjmpE
+
+  # restore env parameters
+  ld.d $r22,$r3,8
+  ld.d $r1,$r3,16
+  addi.d $r3,$r3,24
+
+  # tail jump to libc _setjmp
+  ld.d $r20,$r20,0
+  jr $r20
+
+.size _setjmp, .-_setjmp
+
+.hidden __tsan_setjmp
+.globl sigsetjmp
+.comm _ZN14__interception14real_sigsetjmpE,8,8
+.type sigsetjmp, @function
+sigsetjmp:
+
+  # Save env parameters
+  addi.d $r3,$r3,-32
+  st.d $r1,$r3,24
+  st.d $r22,$r3,16
+
+  # save jmp_buf and savesig
+  st.d $r4,$r3,0
+  st.d $r5,$r3,8
+
+  # obtain $sp
+  add.d $r4,$r0,$r3
+
+  # call tsan interceptor
+  addi.d $r5,$r4,32
+  bl __tsan_setjmp
+
+  # restore jmp_buf and savesig
+  ld.d $r4,$r3,0
+  ld.d $r5,$r3,8
+
+  # load libc sigsetjmp to r20
+  la $r20,_ZN14__interception14real_sigsetjmpE
+
+  # restore env parameters
+  ld.d $r22,$r3,16
+  ld.d $r1,$r3,24
+  addi.d $r3,$r3,32
+
+  # tail jump to libc sigsetjmp
+  ld.d $r20,$r20,0
+  jr $r20
+
+.size sigsetjmp, .-sigsetjmp
+
+.hidden __tsan_setjmp
+.comm _ZN14__interception16real___sigsetjmpE,8,8
+.globl __sigsetjmp
+.type __sigsetjmp, @function
+__sigsetjmp:
+
+  # Save env parameters
+  addi.d $sp,$sp,-32
+  st.d $r1,$r3,24
+  st.d $r22,$r3,16
+
+  # save jmp_buf and savesig
+  st.d $r4,$r3,0
+  st.d $r5,$r3,8
+
+  # obtain $sp
+  add.d $r4,$r0,$r3
+
+  # call tsan interceptor
+  addi.d $r5,$r4,32
+  bl __tsan_setjmp
+
+  # restore jmp_buf and savesig
+  ld.d $r4,$r3,0
+  ld.d $r5,$r3,8
+
+  # load libc __sigsetjmp in r20
+  la $r20,_ZN14__interception16real___sigsetjmpE
+
+  # restore env parameters
+  ld.d $r22,$r3,16
+  ld.d $r1,$r3,24
+  addi.d $r3,$r3,32
+
+  # tail jump to libc __sigsetjmp
+  ld.d $r20,$r20,0
+  jr $r20
+
+.size __sigsetjmp, .-__sigsetjmp
diff --git a/compiler-rt/lib/xray/tests/CMakeLists.txt b/compiler-rt/lib/xray/tests/CMakeLists.txt
index 145852904549..151193d3dc1c 100644
--- a/compiler-rt/lib/xray/tests/CMakeLists.txt
+++ b/compiler-rt/lib/xray/tests/CMakeLists.txt
@@ -63,6 +63,7 @@ if (NOT APPLE)
       ${LLVM_TESTINGSUPPORT_LDFLAGS} XRAY_UNITTEST_LINK_FLAGS)
     append_list_if(COMPILER_RT_HAS_LLVMTESTINGSUPPORT
       ${LLVM_TESTINGSUPPORT_LIBLIST} XRAY_UNITTEST_LINK_FLAGS)
+    list(APPEND XRAY_UNITTEST_LINK_FLAGS -lLLVMXRay -lLLVMSupport -lLLVMDemangle -lLLVMTestingSupport)
   else()
     # We add the library directories one at a time in our CFLAGS.
     foreach (DIR ${LLVM_LIBRARY_DIR})
diff --git a/compiler-rt/lib/xray/xray_interface.cc b/compiler-rt/lib/xray/xray_interface.cc
index 6f7b6615b2c0..a3ba376bc42a 100644
--- a/compiler-rt/lib/xray/xray_interface.cc
+++ b/compiler-rt/lib/xray/xray_interface.cc
@@ -51,6 +51,8 @@ static const int16_t cSledLength = 28;
 static const int16_t cSledLength = 48;
 #elif SANITIZER_MIPS64
 static const int16_t cSledLength = 64;
+#elif SANITIZER_LOONGARCH64
+static const int16_t cSledLength = 64;
 #elif defined(__powerpc64__)
 static const int16_t cSledLength = 8;
 #else
diff --git a/compiler-rt/lib/xray/xray_tsc.h b/compiler-rt/lib/xray/xray_tsc.h
index 180d6df188c1..1fb428c86579 100644
--- a/compiler-rt/lib/xray/xray_tsc.h
+++ b/compiler-rt/lib/xray/xray_tsc.h
@@ -43,7 +43,7 @@ inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
 #include "xray_x86_64.inc"
 #elif defined(__powerpc64__)
 #include "xray_powerpc64.inc"
-#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__)
+#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || defined(__loongarch__)
 // Emulated TSC.
 // There is no instruction like RDTSCP in user mode on ARM. ARM's CP15 does
 //   not have a constant frequency like TSC on x86(_64), it may go faster
diff --git a/compiler-rt/test/asan/CMakeLists.txt b/compiler-rt/test/asan/CMakeLists.txt
index 6c22ef3b10ef..ffce702d31d8 100644
--- a/compiler-rt/test/asan/CMakeLists.txt
+++ b/compiler-rt/test/asan/CMakeLists.txt
@@ -18,7 +18,7 @@ if (SHADOW_MAPPING_UNRELIABLE)
 endif()
 
 macro(get_bits_for_arch arch bits)
-  if (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|arm64|mips64|mips64el|s390x")
+  if (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|arm64|mips64|mips64el|s390x|loongarch64")
     set(${bits} 64)
   elseif (${arch} MATCHES "i386|arm|mips|mipsel")
     set(${bits} 32)
diff --git a/compiler-rt/test/asan/TestCases/Linux/ptrace.cc b/compiler-rt/test/asan/TestCases/Linux/ptrace.cc
index bd3d2d27e1de..3c7cc9b00359 100644
--- a/compiler-rt/test/asan/TestCases/Linux/ptrace.cc
+++ b/compiler-rt/test/asan/TestCases/Linux/ptrace.cc
@@ -1,6 +1,7 @@
 // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
 // XFAIL: android
 // XFAIL: mips
+// XFAIL: loongarch
 //
 // RUN: %clangxx_asan -O0 %s -o %t && %run %t
 // RUN: %clangxx_asan -DPOSITIVE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
diff --git a/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c b/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c
index b1379703ed86..d6c4fb18819b 100644
--- a/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c
+++ b/compiler-rt/test/asan/TestCases/Linux/segv_read_write.c
@@ -1,7 +1,7 @@
 // RUN: %clangxx_asan -std=c++11 -O0 %s -o %t
 // RUN: not %run %t       2>&1 | FileCheck %s --check-prefix=READ
 // RUN: not %run %t write 2>&1 | FileCheck %s --check-prefix=WRITE
-// UNSUPPORTED: powerpc64,mips,s390
+// UNSUPPORTED: powerpc64,mips,s390,loongarch
 
 #include <sys/mman.h>
 
diff --git a/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c b/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c
index 8e86bba4adb1..3f145e68f761 100644
--- a/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c
+++ b/compiler-rt/test/esan/TestCases/mmap-shadow-conflict.c
@@ -6,7 +6,7 @@
 #include <stdio.h>
 
 int main(int argc, char **argv) {
-#if defined(__mips64)
+#if defined(__mips64) || defined(__loongarch64)
   void *Map = mmap((void *)0x0000001600000000ULL, 0x1000, PROT_READ,
                    MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
 #else
@@ -17,7 +17,7 @@ int main(int argc, char **argv) {
     fprintf(stderr, "map failed\n");
   else
     fprintf(stderr, "mapped %p\n", Map);
-#if defined(__mips64)
+#if defined(__mips64) || defined(__loongarch64)
   Map = mmap((void *)0x0000001600000000ULL, 0x1000, PROT_READ,
                    MAP_ANON|MAP_PRIVATE, -1, 0);
 #else
@@ -35,6 +35,10 @@ int main(int argc, char **argv) {
   // mips64-NEXT: Shadow #0: [1140000000-1180000000) (1GB)
   // mips64-NEXT: Shadow #1: [1380000000-13c0000000) (1GB)
   // mips64-NEXT: Shadow #2: [14c0000000-1500000000) (1GB)
+  // loongarch64:      Shadow scale=2 offset=0x004400000000
+  // loongarch64-NEXT: Shadow #0: [1140000000-1180000000) (1GB)
+  // loongarch64-NEXT: Shadow #1: [1380000000-13c0000000) (1GB)
+  // loongarch64-NEXT: Shadow #2: [14c0000000-1500000000) (1GB)
   // CHECK-NEXT: mmap conflict: {{.*}}
   // CHECK-NEXT: map failed
   // CHECK-NEXT: mmap conflict: {{.*}}
diff --git a/compiler-rt/test/esan/lit.cfg b/compiler-rt/test/esan/lit.cfg
index 1bb34ee0865a..8c7bd82b5078 100644
--- a/compiler-rt/test/esan/lit.cfg
+++ b/compiler-rt/test/esan/lit.cfg
@@ -39,5 +39,5 @@ config.substitutions.append(('%env_esan_opts=',
 # Default test suffixes.
 config.suffixes = ['.c', '.cpp']
 
-if config.host_os not in ['Linux', 'FreeBSD'] or config.target_arch not in ['x86_64', 'mips64'] :
+if config.host_os not in ['Linux', 'FreeBSD'] or config.target_arch not in ['x86_64', 'mips64', 'loongarch64'] :
   config.unsupported = True
diff --git a/compiler-rt/test/lsan/lit.common.cfg b/compiler-rt/test/lsan/lit.common.cfg
index a5df951e2e04..eedd8b263f72 100644
--- a/compiler-rt/test/lsan/lit.common.cfg
+++ b/compiler-rt/test/lsan/lit.common.cfg
@@ -68,7 +68,7 @@ config.substitutions.append( ("%clang_lsan ", build_invocation(clang_lsan_cflags
 config.substitutions.append( ("%clangxx_lsan ", build_invocation(clang_lsan_cxxflags)) )
 
 # LeakSanitizer tests are currently supported on x86-64 Linux, PowerPC64 Linux, arm Linux, mips64 Linux, and x86_64 Darwin.
-supported_linux = config.host_os is 'Linux' and config.host_arch in ['x86_64', 'ppc64', 'ppc64le', 'mips64', 'arm', 'armhf', 'armv7l']
+supported_linux = config.host_os is 'Linux' and config.host_arch in ['x86_64', 'ppc64', 'ppc64le', 'mips64', 'arm', 'armhf', 'armv7l', 'loongarch64']
 supported_darwin = config.host_os is 'Darwin' and config.target_arch is 'x86_64'
 if not (supported_linux or supported_darwin):
   config.unsupported = True
diff --git a/compiler-rt/test/msan/allocator_mapping.cc b/compiler-rt/test/msan/allocator_mapping.cc
index 533128f9a0f4..e1c73ae233b9 100644
--- a/compiler-rt/test/msan/allocator_mapping.cc
+++ b/compiler-rt/test/msan/allocator_mapping.cc
@@ -8,7 +8,7 @@
 // This test only makes sense for the 64-bit allocator. The 32-bit allocator
 // does not have a fixed mapping. Exclude platforms that use the 32-bit
 // allocator.
-// UNSUPPORTED: target-is-mips64,target-is-mips64el,aarch64
+// UNSUPPORTED: target-is-mips64,target-is-mips64el,aarch64,loongarch64
 
 #include <assert.h>
 #include <stdio.h>
diff --git a/compiler-rt/test/msan/lit.cfg b/compiler-rt/test/msan/lit.cfg
index e08673d5cfea..a2a1f02df478 100644
--- a/compiler-rt/test/msan/lit.cfg
+++ b/compiler-rt/test/msan/lit.cfg
@@ -41,7 +41,7 @@ if config.host_os not in ['Linux', 'NetBSD', 'FreeBSD']:
 # For mips64, mips64el we have forced store_context_size to 1 because these
 # archs use slow unwinder which is not async signal safe. Therefore we only
 # check the first frame since store_context size is 1.
-if config.host_arch in ['mips64', 'mips64el']:
+if config.host_arch in ['mips64', 'mips64el', 'loongarch64']:
   config.substitutions.append( ('CHECK-%short-stack', 'CHECK-SHORT-STACK'))
 else:
   config.substitutions.append( ('CHECK-%short-stack', 'CHECK-FULL-STACK'))
diff --git a/compiler-rt/test/msan/mmap.cc b/compiler-rt/test/msan/mmap.cc
index d83423735211..ea84e211eeb1 100644
--- a/compiler-rt/test/msan/mmap.cc
+++ b/compiler-rt/test/msan/mmap.cc
@@ -18,7 +18,7 @@ bool AddrIsApp(void *p) {
   return (addr >= 0x000000000000ULL && addr < 0x010000000000ULL) ||
          (addr >= 0x510000000000ULL && addr < 0x600000000000ULL) ||
          (addr >= 0x700000000000ULL && addr < 0x800000000000ULL);
-#elif defined(__mips64)
+#elif defined(__mips64) || defined(__loongarch64)
   return (addr >= 0x0000000000ULL && addr <= 0x0200000000ULL) ||
          (addr >= 0xa200000000ULL && addr <= 0xc000000000ULL) ||
          addr >= 0xe200000000ULL;
@@ -57,7 +57,7 @@ bool AddrIsApp(void *p) {
 
 int main() {
   // Large enough to quickly exhaust the entire address space.
-#if defined(__mips64) || defined(__aarch64__)
+#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch64)
   const size_t kMapSize = 0x100000000ULL;
 #else
   const size_t kMapSize = 0x1000000000ULL;
diff --git a/compiler-rt/test/msan/mmap_below_shadow.cc b/compiler-rt/test/msan/mmap_below_shadow.cc
index 806b19da8ca6..ff306a1eed34 100644
--- a/compiler-rt/test/msan/mmap_below_shadow.cc
+++ b/compiler-rt/test/msan/mmap_below_shadow.cc
@@ -21,7 +21,7 @@ int main(void) {
 #elif defined(__x86_64__)
   uintptr_t hint = 0x4f0000000000ULL;
   const uintptr_t app_start = 0x600000000000ULL;
-#elif defined (__mips64)
+#elif defined (__mips64) || defined(__loongarch64)
   uintptr_t hint = 0x4f00000000ULL;
   const uintptr_t app_start = 0x6000000000ULL;
 #elif defined (__powerpc64__)
diff --git a/compiler-rt/test/msan/strlen_of_shadow.cc b/compiler-rt/test/msan/strlen_of_shadow.cc
index 718cc08dc1fd..5768dd777c82 100644
--- a/compiler-rt/test/msan/strlen_of_shadow.cc
+++ b/compiler-rt/test/msan/strlen_of_shadow.cc
@@ -15,7 +15,7 @@
 const char *mem_to_shadow(const char *p) {
 #if defined(__x86_64__)
   return (char *)((uintptr_t)p ^ 0x500000000000ULL);
-#elif defined (__mips64)
+#elif defined (__mips64) || defined(__loongarch64)
   return (char *)((uintptr_t)p ^ 0x8000000000ULL);
 #elif defined(__powerpc64__)
 #define LINEARIZE_MEM(mem) \
diff --git a/compiler-rt/test/msan/vararg.cc b/compiler-rt/test/msan/vararg.cc
index e1a7b1266165..2b7e28d1c25b 100644
--- a/compiler-rt/test/msan/vararg.cc
+++ b/compiler-rt/test/msan/vararg.cc
@@ -20,6 +20,7 @@
 // XFAIL: aarch64
 // XFAIL: mips
 // XFAIL: powerpc64
+// XFAIL: loongarch64
 
 #include <stdarg.h>
 #include <string.h>
diff --git a/compiler-rt/test/msan/vector_select.cc b/compiler-rt/test/msan/vector_select.cc
index 0cf116497801..b24410e086f6 100644
--- a/compiler-rt/test/msan/vector_select.cc
+++ b/compiler-rt/test/msan/vector_select.cc
@@ -11,7 +11,7 @@ __m128d select(bool b, __m128d c, __m128d d)
 {
   return b ? c : d;
 }
-#elif defined (__mips64) || defined (__powerpc64__)
+#elif defined (__mips64) || defined (__powerpc64__) || defined(__loongarch64)
 typedef double __w64d __attribute__ ((vector_size(16)));
 
 __w64d select(bool b, __w64d c, __w64d d)
diff --git a/compiler-rt/test/msan/wcsncpy.cc b/compiler-rt/test/msan/wcsncpy.cc
index 6471371de980..fc2526c370d9 100644
--- a/compiler-rt/test/msan/wcsncpy.cc
+++ b/compiler-rt/test/msan/wcsncpy.cc
@@ -2,6 +2,7 @@
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
 
 // XFAIL: mips
+// XFAIL: loongarch
 
 #include <assert.h>
 #include <wchar.h>
diff --git a/compiler-rt/test/sanitizer_common/print_address.h b/compiler-rt/test/sanitizer_common/print_address.h
index db2e8341a9d2..3cc3e245d636 100644
--- a/compiler-rt/test/sanitizer_common/print_address.h
+++ b/compiler-rt/test/sanitizer_common/print_address.h
@@ -7,7 +7,8 @@ void print_address(const char *str, int n, ...) {
   va_start(ap, n);
   while (n--) {
     void *p = va_arg(ap, void *);
-#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
+#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) \
+    || defined(__loongarch__)
     // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not
     // match to the format used in the diagnotic message.
     fprintf(stderr, "0x%012lx ", (unsigned long) p);
diff --git a/compiler-rt/test/tsan/map32bit.cc b/compiler-rt/test/tsan/map32bit.cc
index 8aef27bc1900..eb0a1247dae2 100644
--- a/compiler-rt/test/tsan/map32bit.cc
+++ b/compiler-rt/test/tsan/map32bit.cc
@@ -11,6 +11,7 @@
 // XFAIL: mips
 // XFAIL: aarch64
 // XFAIL: powerpc64
+// XFAIL: loongarch64
 
 // MAP_32BIT doesn't exist on OS X and NetBSD.
 // UNSUPPORTED: darwin,netbsd
diff --git a/compiler-rt/test/tsan/mmap_large.cc b/compiler-rt/test/tsan/mmap_large.cc
index c8d258e804d7..10ae9a0ea3d0 100644
--- a/compiler-rt/test/tsan/mmap_large.cc
+++ b/compiler-rt/test/tsan/mmap_large.cc
@@ -19,6 +19,8 @@ int main() {
   const size_t kLog2Size = 39;
 #elif defined(__mips64) || defined(__aarch64__)
   const size_t kLog2Size = 32;
+#elif defined(__loongarch64)
+  const size_t kLog2Size = 32;
 #elif defined(__powerpc64__)
   const size_t kLog2Size = 39;
 #endif
diff --git a/compiler-rt/test/tsan/test.h b/compiler-rt/test/tsan/test.h
index 595590b58ce2..f00f37410bb9 100644
--- a/compiler-rt/test/tsan/test.h
+++ b/compiler-rt/test/tsan/test.h
@@ -61,6 +61,8 @@ unsigned long long monotonic_clock_ns() {
 const int kPCInc = 4;
 #elif defined(__sparc__) || defined(__mips__)
 const int kPCInc = 8;
+#elif defined(__loongarch__)
+const int kPCInc = 4;
 #else
 const int kPCInc = 1;
 #endif
diff --git a/compiler-rt/test/xray/TestCases/Posix/arg1-arg0-logging.cc b/compiler-rt/test/xray/TestCases/Posix/arg1-arg0-logging.cc
index 757f81a8babb..a531622864ee 100644
--- a/compiler-rt/test/xray/TestCases/Posix/arg1-arg0-logging.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/arg1-arg0-logging.cc
@@ -6,7 +6,7 @@
 // RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg0-arg1-logging-" %run %t
 //
 // TODO: Support these in ARM and PPC
-// XFAIL: arm || aarch64 || mips
+// XFAIL: arm || aarch64 || mips || loongarch
 // UNSUPPORTED: powerpc64le
 
 #include "xray/xray_interface.h"
diff --git a/compiler-rt/test/xray/TestCases/Posix/arg1-logger.cc b/compiler-rt/test/xray/TestCases/Posix/arg1-logger.cc
index a6ca0a495250..5e8c86ae5705 100644
--- a/compiler-rt/test/xray/TestCases/Posix/arg1-logger.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/arg1-logger.cc
@@ -11,7 +11,7 @@
 // RUN: rm -f arg1-logger-*
 //
 // At the time of writing, the ARM trampolines weren't written yet.
-// XFAIL: arm || aarch64 || mips
+// XFAIL: arm || aarch64 || mips || loongarch
 // See the mailing list discussion of r296998.
 // UNSUPPORTED: powerpc64le
 
diff --git a/compiler-rt/test/xray/TestCases/Posix/arg1-logging-implicit-this.cc b/compiler-rt/test/xray/TestCases/Posix/arg1-logging-implicit-this.cc
index d8dd62247bff..26129a830742 100644
--- a/compiler-rt/test/xray/TestCases/Posix/arg1-logging-implicit-this.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/arg1-logging-implicit-this.cc
@@ -4,7 +4,7 @@
 // RUN: rm -f log-args-this-*
 // RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=log-args-this-" %run %t
 //
-// XFAIL: FreeBSD || arm || aarch64 || mips
+// XFAIL: FreeBSD || arm || aarch64 || mips || loongarch
 // UNSUPPORTED: powerpc64le
 #include "xray/xray_interface.h"
 #include <cassert>
diff --git a/compiler-rt/test/xray/TestCases/Posix/argv0-log-file-name.cc b/compiler-rt/test/xray/TestCases/Posix/argv0-log-file-name.cc
index a2cb11b4d0d9..dd1bcd6d1b72 100644
--- a/compiler-rt/test/xray/TestCases/Posix/argv0-log-file-name.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/argv0-log-file-name.cc
@@ -7,6 +7,7 @@
 // RUN: rm xray-log.argv0-log-file-name.* xray.log.file.name
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include <cstdio>
 #include <libgen.h>
diff --git a/compiler-rt/test/xray/TestCases/Posix/coverage-sample.cc b/compiler-rt/test/xray/TestCases/Posix/coverage-sample.cc
index 62c13ba3d42a..d83480269ec5 100644
--- a/compiler-rt/test/xray/TestCases/Posix/coverage-sample.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/coverage-sample.cc
@@ -4,6 +4,7 @@
 // RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t | FileCheck %s
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include "xray/xray_interface.h"
 
diff --git a/compiler-rt/test/xray/TestCases/Posix/fixedsize-logging.cc b/compiler-rt/test/xray/TestCases/Posix/fixedsize-logging.cc
index a2a41ce60d6e..f4c7b5c90f10 100644
--- a/compiler-rt/test/xray/TestCases/Posix/fixedsize-logging.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/fixedsize-logging.cc
@@ -8,6 +8,7 @@
 // RUN: rm fixedsize-logging-*
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include <cstdio>
 
diff --git a/compiler-rt/test/xray/TestCases/Posix/func-id-utils.cc b/compiler-rt/test/xray/TestCases/Posix/func-id-utils.cc
index 412753666019..432afa3d6190 100644
--- a/compiler-rt/test/xray/TestCases/Posix/func-id-utils.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/func-id-utils.cc
@@ -5,6 +5,7 @@
 // RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include "xray/xray_interface.h"
 #include <algorithm>
diff --git a/compiler-rt/test/xray/TestCases/Posix/logging-modes.cc b/compiler-rt/test/xray/TestCases/Posix/logging-modes.cc
index f839ba5e5f50..2302995c0faa 100644
--- a/compiler-rt/test/xray/TestCases/Posix/logging-modes.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/logging-modes.cc
@@ -5,6 +5,7 @@
 // RUN: %run %t | FileCheck %s
 //
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include "xray/xray_interface.h"
 #include "xray/xray_log_interface.h"
diff --git a/compiler-rt/test/xray/TestCases/Posix/optional-inmemory-log.cc b/compiler-rt/test/xray/TestCases/Posix/optional-inmemory-log.cc
index feaaa4124750..5fca96d2c8cb 100644
--- a/compiler-rt/test/xray/TestCases/Posix/optional-inmemory-log.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/optional-inmemory-log.cc
@@ -9,6 +9,7 @@
 // RUN: rm -f optional-inmemory-log.xray-*
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include <cstdio>
 
diff --git a/compiler-rt/test/xray/TestCases/Posix/patching-unpatching.cc b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching.cc
index a7ea58f6dc69..686681567a70 100644
--- a/compiler-rt/test/xray/TestCases/Posix/patching-unpatching.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching.cc
@@ -5,6 +5,7 @@
 // RUN: XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include "xray/xray_interface.h"
 
diff --git a/compiler-rt/test/xray/TestCases/Posix/pic_test.cc b/compiler-rt/test/xray/TestCases/Posix/pic_test.cc
index 93e1a6a47d3c..e13b4d1699d2 100644
--- a/compiler-rt/test/xray/TestCases/Posix/pic_test.cc
+++ b/compiler-rt/test/xray/TestCases/Posix/pic_test.cc
@@ -10,6 +10,7 @@
 // RUN: rm -f pic-test-logging-*
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include <cstdio>
 
diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp
index 10ea2d68545a..3d2796b16ae9 100644
--- a/lib/Support/Host.cpp
+++ b/lib/Support/Host.cpp
@@ -1462,6 +1462,36 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
 
   return true;
 }
+#elif defined(__linux__) && defined(__loongarch__)
+bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
+  std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
+  if (!P)
+    return false;
+
+  SmallVector<StringRef, 32> Lines;
+  P->getBuffer().split(Lines, "\n");
+
+  SmallVector<StringRef, 32> CPUFeatures;
+
+  // Look for the CPU features.
+  for (unsigned I = 0, E = Lines.size(); I != E; ++I)
+    if (Lines[I].startswith("features")) {
+      Lines[I].split(CPUFeatures, ' ');
+      break;
+    }
+
+  for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
+    StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
+                                   .Case("lsx", "lsx")
+                                   .Case("lasx", "lasx")
+                                   .Default("");
+
+    if (LLVMFeatureStr != "")
+      Features[LLVMFeatureStr] = true;
+  }
+
+  return true;
+}
 #else
 bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
 #endif
diff --git a/lib/Target/LoongArch/LoongArch32InstrInfo.td b/lib/Target/LoongArch/LoongArch32InstrInfo.td
index 08457d21c826..bd648d309f25 100644
--- a/lib/Target/LoongArch/LoongArch32InstrInfo.td
+++ b/lib/Target/LoongArch/LoongArch32InstrInfo.td
@@ -215,15 +215,15 @@ let usesCustomInserter = 1 in {
                    R3MI<0b01001000>;
     def LDX_BU32 : LDX_FT_LA<"ldx.bu", GPR32Opnd, extloadi8>,
                    R3MI<0b01000000>;
-    def STX_W32 : SDX_FT_LA<"stx.w", GPR32Opnd, store>,
+    def STX_W32 : STX_FT_LA<"stx.w", GPR32Opnd, store>,
                   R3MI<0b00110000>;
     def LDX_H32 : LDX_FT_LA<"ldx.h", GPR32Opnd, sextloadi16>,
                   R3MI<0b00001000>;
     def LDX_B32 : LDX_FT_LA<"ldx.b", GPR32Opnd, sextloadi8>,
                   R3MI<0b00000000>;
-    def STX_B32 : SDX_FT_LA<"stx.b", GPR32Opnd, truncstorei8>,
+    def STX_B32 : STX_FT_LA<"stx.b", GPR32Opnd, truncstorei8>,
                   R3MI<0b00100000>;
-    def STX_H32 : SDX_FT_LA<"stx.h", GPR32Opnd, truncstorei16>,
+    def STX_H32 : STX_FT_LA<"stx.h", GPR32Opnd, truncstorei16>,
                   R3MI<0b00101000>;
   }
 }
diff --git a/lib/Target/LoongArch/LoongArchISelLowering.cpp b/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 1ac0cd1237f6..7cfda999176e 100644
--- a/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -187,6 +187,10 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case LoongArchISD::VBROADCAST:        return "LoongArchISD::VBROADCAST";
   case LoongArchISD::VABSD:             return "LoongArchISD::VABSD";
   case LoongArchISD::UVABSD:            return "LoongArchISD::UVABSD";
+  case LoongArchISD::XVPICKVE:          return "LoongArchISD::XVPICKVE";
+  case LoongArchISD::XVPERMI:           return "LoongArchISD::XVPERMI";
+  case LoongArchISD::XVSHUF4I:          return "LoongArchISD::XVSHUF4I";
+  case LoongArchISD::REVBD:             return "LoongArchISD::REVBD";
   }
   return nullptr;
 }
@@ -632,6 +636,8 @@ addLSXIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
   setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom);
   setOperationAction(ISD::VSELECT, Ty, Legal);
   setOperationAction(ISD::XOR, Ty, Legal);
+  setOperationAction(ISD::MULHS, Ty, Legal);
+  setOperationAction(ISD::MULHU, Ty, Legal);
 
   if (Ty == MVT::v4i32 || Ty == MVT::v2i64) {
     setOperationAction(ISD::SINT_TO_FP, Ty, Custom);
@@ -692,6 +698,8 @@ addLASXIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
   setOperationAction(ISD::VSELECT, Ty, Legal);
   setOperationAction(ISD::XOR, Ty, Legal);
   setOperationAction(ISD::INSERT_SUBVECTOR, Ty, Legal);
+  setOperationAction(ISD::MULHS, Ty, Legal);
+  setOperationAction(ISD::MULHU, Ty, Legal);
 
   if (Ty == MVT::v8i32 || Ty == MVT::v4i64) {
     setOperationAction(ISD::SINT_TO_FP, Ty, Custom);
@@ -4848,6 +4856,15 @@ static bool checkUndef(ArrayRef<int> Mask, unsigned Lo, unsigned Hi) {
   return true;
 }
 
+static bool CheckRev(ArrayRef<int> Mask) {
+
+  unsigned Num = Mask.size() - 1;
+  for (unsigned i = 0; i < Mask.size(); i++, Num--)
+    if (Mask[i] != Num)
+      return false;
+  return true;
+}
+
 //Lowering vectors with half undef data,
 //use EXTRACT_SUBVECTOR and INSERT_SUBVECTOR instead of VECTOR_SHUFFLE
 static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2,
@@ -4856,10 +4873,49 @@ static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2,
   unsigned Num = VT.getVectorNumElements();
   unsigned HalfNum = Num / 2;
   MVT HalfVT = MVT::getVectorVT(VT.getVectorElementType(), HalfNum);
+  MVT VT1 = Op1.getSimpleValueType();
+  MVT VT2 = Op2.getSimpleValueType();
+  unsigned Num1 = VT1.getVectorNumElements();
+  unsigned Num2 = VT2.getVectorNumElements();
+  SDValue Op;
+
+  bool check1 = Op1->isUndef() && (!Op2->isUndef());
+  bool check2 = Op2->isUndef() && (!Op1->isUndef());
+
+  if ((check1 || check2) && (VT1 == VT)) {
+    if (check1) {
+      Op = DAG.getNode(ISD::BITCAST, DL, MVT::v4i64, Op2);
+    } else if (check2) {
+      Op = DAG.getNode(ISD::BITCAST, DL, MVT::v4i64, Op1);
+    }
+
+    if (VT == MVT::v32i8 && CheckRev(Mask)) {
+      SDValue Vector;
+      SDValue Rev[4];
+      SDValue Ext[4];
+      for (int i = 0; i < 4; i++) {
+        Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Op,
+                             DAG.getConstant(i, DL, MVT::i32));
+        Rev[i] = DAG.getNode(LoongArchISD::REVBD, DL, MVT::i64, Ext[i]);
+      }
+
+      Vector =
+          DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, DAG.getUNDEF(VT),
+                      Rev[3], DAG.getConstant(3, DL, MVT::i32));
+      Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector,
+                           Rev[2], DAG.getConstant(2, DL, MVT::i32));
+      Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector,
+                           Rev[1], DAG.getConstant(1, DL, MVT::i32));
+      Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v4i64, Vector,
+                           Rev[0], DAG.getConstant(0, DL, MVT::i32));
+
+      return Vector;
+    }
+  }
 
   bool Lo = true;
   for (unsigned i = 0; i < HalfNum; ++i) {
-    if (Mask[i] != -1){
+    if (Mask[i] != -1) {
       Lo = false;
       break;
     }
@@ -4867,15 +4923,12 @@ static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2,
 
   bool Hi = true;
   for (unsigned i = HalfNum; i < Num; ++i) {
-    if (Mask[i] != -1){
+    if (Mask[i] != -1) {
       Hi = false;
       break;
     }
   }
 
-  if (!Lo && !Hi)
-    return SDValue();
-
   if (Hi && checkUndef(Mask, 0, HalfNum)) {
     SDValue High = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, Op1,
                                DAG.getConstant(HalfNum, DL, MVT::i32));
@@ -4889,9 +4942,219 @@ static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2,
     return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getUNDEF(VT), Low,
                        DAG.getConstant(HalfNum, DL, MVT::i32));
   }
+
+  if ((VT == MVT::v8i32) || (VT == MVT::v4i64)) {
+    int def = 0;
+    int j = 0;
+    int ext[3];
+    int ins[3];
+    bool useOp1[3] = {true, true, true};
+    bool checkdef = true;
+
+    for (unsigned i = 0; i < Num; i++) {
+      if (def > 2) {
+        checkdef = false;
+        break;
+      }
+      if (Mask[i] != -1) {
+        def++;
+        ins[j] = i;
+        if (Mask[i] >= Num) {
+          ext[j] = Mask[i] - Num;
+          useOp1[j] = false;
+        } else {
+          ext[j] = Mask[i];
+        }
+        j++;
+      }
+    }
+
+    if (checkdef) {
+      SDValue Vector = DAG.getUNDEF(VT);
+      EVT EltTy = VT.getVectorElementType();
+      SDValue Ext[def];
+
+      if (check1 || check2) {
+        for (int i = 0; i < def; i++) {
+          if (check1) {
+            Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op2,
+                                 DAG.getConstant(ext[i], DL, MVT::i32));
+            Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i],
+                                 DAG.getConstant(ins[i], DL, MVT::i32));
+          } else if (check2) {
+            Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op1,
+                                 DAG.getConstant(ext[i], DL, MVT::i32));
+            Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i],
+                                 DAG.getConstant(ins[i], DL, MVT::i32));
+          }
+        }
+        return Vector;
+      } else {
+        for (int i = 0; i < def; i++) {
+          if (!useOp1[i]) {
+            Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op2,
+                                 DAG.getConstant(ext[i], DL, MVT::i32));
+            Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i],
+                                 DAG.getConstant(ins[i], DL, MVT::i32));
+          } else {
+            Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltTy, Op1,
+                                 DAG.getConstant(ext[i], DL, MVT::i32));
+            Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vector, Ext[i],
+                                 DAG.getConstant(ins[i], DL, MVT::i32));
+          }
+        }
+        return Vector;
+      }
+    }
+  }
+
+  return SDValue();
+}
+
+static SDValue lowerHalfUndef_LSX(const SDLoc &DL, EVT ResTy, MVT VT,
+                                  SDValue Op1, SDValue Op2, ArrayRef<int> Mask,
+                                  SelectionDAG &DAG) {
+
+  unsigned Num = VT.getVectorNumElements();
+  unsigned HalfNum = Num / 2;
+  MVT HalfVT = MVT::getVectorVT(VT.getVectorElementType(), HalfNum);
+  MVT VT1 = Op1.getSimpleValueType();
+  MVT VT2 = Op2.getSimpleValueType();
+  unsigned Num1 = VT1.getVectorNumElements();
+  unsigned Num2 = VT2.getVectorNumElements();
+
+  bool check1 = Op1->isUndef() && (!Op2->isUndef());
+  bool check2 = Op2->isUndef() && (!Op1->isUndef());
+
+  if ((check1 || check2) && (VT1 == VT)) {
+    SDValue Op;
+
+    if (VT == MVT::v16i8 && CheckRev(Mask)) {
+
+      if (check1) {
+        Op = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, Op2);
+      } else if (check2) {
+        Op = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, Op1);
+      }
+
+      SDValue Vector;
+      SDValue Rev[2];
+      SDValue Ext[2];
+      for (int i = 0; i < 2; i++) {
+        Ext[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Op,
+                             DAG.getConstant(i, DL, MVT::i32));
+        Rev[i] = DAG.getNode(LoongArchISD::REVBD, DL, MVT::i64, Ext[i]);
+      }
+
+      Vector =
+          DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v2i64, DAG.getUNDEF(VT),
+                      Rev[1], DAG.getConstant(1, DL, MVT::i32));
+      Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::v2i64, Vector,
+                           Rev[0], DAG.getConstant(0, DL, MVT::i32));
+
+      return Vector;
+    }
+  }
+
   return SDValue();
 }
 
+// Use SDNode of LoongArchINSVE instead of
+// a series of EXTRACT_VECTOR_ELT and INSERT_VECTOR_ELT
+static SDValue lowerVECTOR_SHUFFLE_INSVE(const SDLoc &DL, MVT VT, EVT ResTy,
+                                         SDValue Op1, SDValue Op2,
+                                         ArrayRef<int> Mask,
+                                         SelectionDAG &DAG) {
+
+  unsigned Num = VT.getVectorNumElements();
+  if (ResTy == MVT::v16i16 || ResTy == MVT::v32i8)
+    return SDValue();
+
+  unsigned CheckOne = 0;
+  unsigned CheckOther = 0;
+  unsigned Idx;
+
+  for (unsigned i = 0; i < Num; i++) {
+    if ((Mask[i] == i) || (Mask[i] == -1)) {
+      CheckOther++;
+    } else if (Mask[i] == Num) {
+      CheckOne++;
+      Idx = i;
+    } else
+      return SDValue();
+  }
+
+  if ((CheckOne != 1) || (CheckOther != (Num - 1)))
+    return SDValue();
+  else {
+    return DAG.getNode(LoongArchISD::INSVE, DL, ResTy, Op1, Op2,
+                       DAG.getConstant(Idx, DL, MVT::i32));
+  }
+
+  return SDValue();
+}
+
+
+static SDValue lowerVECTOR_SHUFFLE_XVPICKVE(const SDLoc &DL, MVT VT, EVT ResTy,
+                                            SDValue Op1, SDValue Op2,
+                                            ArrayRef<int> Mask,
+                                            SelectionDAG &DAG) {
+
+  unsigned Num = VT.getVectorNumElements();
+  if (ResTy == MVT::v16i16 || ResTy == MVT::v32i8 ||
+      (!ISD::isBuildVectorAllZeros(Op1.getNode())))
+    return SDValue();
+
+  bool CheckV = true;
+
+  if ((Mask[0] < Num) || (Mask[0] > (2 * Num - 1)))
+    CheckV = false;
+
+  for (unsigned i = 1; i < Num; i++) {
+    if (Mask[i] != 0) {
+      CheckV = false;
+      break;
+    }
+  }
+
+  if (!CheckV)
+    return SDValue();
+  else {
+    return DAG.getNode(LoongArchISD::XVPICKVE, DL, ResTy, Op1, Op2,
+                       DAG.getConstant(Mask[0] - Num, DL, MVT::i32));
+  }
+
+  return SDValue();
+}
+
+static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, MVT VT, EVT ResTy,
+                                          SDValue Op1, SDValue Op2,
+                                          ArrayRef<int> Mask,
+                                          SelectionDAG &DAG) {
+
+  if (VT == MVT::v4i64) {
+    unsigned Num = VT.getVectorNumElements();
+
+    bool CheckV = true;
+    for (unsigned i = 0; i < Num; i++) {
+      if (Mask[i] != (i * 2)){
+        CheckV = false;
+        break;
+      }
+    }
+
+    if (!CheckV)
+      return SDValue();
+    else {
+      SDValue Res = DAG.getNode(LoongArchISD::XVSHUF4I, DL, ResTy, Op2, Op1,
+                                DAG.getConstant(0, DL, MVT::i32));
+      return DAG.getNode(LoongArchISD::XVPERMI, DL, ResTy, Res,
+                         DAG.getConstant(0xD8, DL, MVT::i32));
+    }
+  } else
+    return SDValue();
+}
+
 // Lower VECTOR_SHUFFLE into one of a number of instructions depending on the
 // indices in the shuffle.
 SDValue LoongArchTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
@@ -4904,7 +5167,6 @@ SDValue LoongArchTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
   MVT VT = Op.getSimpleValueType();
   SDLoc DL(Op);
 
-
   if (ResTy.is128BitVector()) {
 
     int ResTyNumElts = ResTy.getVectorNumElements();
@@ -4913,9 +5175,9 @@ SDValue LoongArchTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
     for (int i = 0; i < ResTyNumElts; ++i)
       Indices.push_back(Node->getMaskElt(i));
 
+    SDValue Result;
     if (isVECTOR_SHUFFLE_VREPLVEI(Op, ResTy, Indices, DAG))
       return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
-    SDValue Result;
     if ((Result = lowerVECTOR_SHUFFLE_VPACKEV(Op, ResTy, Indices, DAG)))
       return Result;
     if ((Result = lowerVECTOR_SHUFFLE_VPACKOD(Op, ResTy, Indices, DAG)))
@@ -4930,9 +5192,10 @@ SDValue LoongArchTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
       return Result;
     if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG)))
       return Result;
+    if ((Result = lowerHalfUndef_LSX(DL, ResTy, VT, Op1, Op2, Mask, DAG)))
+      return Result;
     return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
-  }
-  else if(ResTy.is256BitVector()){
+  } else if (ResTy.is256BitVector()) {
     int ResTyNumElts = ResTy.getVectorNumElements();
     SmallVector<int, 32> Indices;
 
@@ -4958,6 +5221,15 @@ SDValue LoongArchTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
       return Result;
     if ((Result = lowerVECTOR_SHUFFLE_XSHF(Op, ResTy, Indices, DAG)))
       return Result;
+    if ((Result =
+             lowerVECTOR_SHUFFLE_INSVE(DL, VT, ResTy, Op1, Op2, Mask, DAG)))
+      return Result;
+    if ((Result =
+             lowerVECTOR_SHUFFLE_XVPICKVE(DL, VT, ResTy, Op1, Op2, Mask, DAG)))
+      return Result;
+    if ((Result =
+             lowerVECTOR_SHUFFLE_XVSHUF(DL, VT, ResTy, Op1, Op2, Mask, DAG)))
+      return Result;
   }
 
   return SDValue();
diff --git a/lib/Target/LoongArch/LoongArchISelLowering.h b/lib/Target/LoongArch/LoongArchISelLowering.h
index 4b1dbecdcd7e..2054a5ce29e6 100644
--- a/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -126,6 +126,10 @@ class TargetRegisterClass;
 
       VROR,
       VRORI,
+      XVPICKVE,
+      XVPERMI,
+      XVSHUF4I,
+      REVBD,
 
       // Extended vector element extraction
       VEXTRACT_SEXT_ELT,
diff --git a/lib/Target/LoongArch/LoongArchInstrInfo.td b/lib/Target/LoongArch/LoongArchInstrInfo.td
index b5409463a0a0..2820b326c6fd 100644
--- a/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -18,6 +18,9 @@ def SDT_Bstrins : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisSameAs<0, 1>,
                                    SDTCisVT<2, i32>, SDTCisSameAs<2, 3>,
                                    SDTCisSameAs<0, 4>]>;
 
+def SDT_REVBD : SDTypeProfile<1, 1, [SDTCisInt<0>]>;
+def LoongArchREVBD :  SDNode<"LoongArchISD::REVBD", SDT_REVBD>;
+
 def LoongArchBstrpick :  SDNode<"LoongArchISD::BSTRPICK", SDT_Bstrpick>;
 
 def LoongArchBstrins :  SDNode<"LoongArchISD::BSTRINS", SDT_Bstrins>;
@@ -256,6 +259,12 @@ def uimm8_64 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 256; }]> {
   let ParserMatchClass = UImm8Operand;
 }
 
+def uimm8_32 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
+  let PrintMethod = "printUImm<8>";
+  let ParserMatchClass = UImm8Operand;
+}
+
+
 // Transformation Function - get the higher 20 bits.
 def HI20 : SDNodeXForm<imm, [{
   return getImm(N, (N->getZExtValue() >> 12) & 0xFFFFF);
@@ -1024,7 +1033,7 @@ def CTZ_D : Int_Reg2<"ctz.d", GPR64Opnd, cttz>, R2I<0b01011>;
 
 def REVB_4H : Int_Reg2<"revb.4h", GPR64Opnd>, R2I<0b01101>; //[]
 def REVB_2W : Int_Reg2<"revb.2w", GPR64Opnd>, R2I<0b01110>;
-def REVB_D  : Int_Reg2<"revb.d", GPR64Opnd>, R2I<0b01111>;
+def REVB_D  : Int_Reg2<"revb.d", GPR64Opnd, LoongArchREVBD>, R2I<0b01111>;
 def REVH_2W : Int_Reg2<"revh.2w", GPR64Opnd>, R2I<0b10000>;
 def REVH_D  : Int_Reg2<"revh.d", GPR64Opnd>, R2I<0b10001>; //[]
 
@@ -1187,6 +1196,18 @@ class SCBase<string opstr, RegisterOperand RO, DAGOperand MO = mem> :
   let Constraints = "$rd = $dst";
 }
 
+class STGT_LE<string opstr, RegisterOperand RO,
+                 SDPatternOperator OpNode = null_frag> :
+  InstForm<(outs), (ins RO:$rd, RO:$rj, RO:$rk),
+           !strconcat(opstr, "\t$rd, $rj, $rk"),
+           [], FrmI, opstr>;
+
+class Float_STGT_LE<string opstr, RegisterOperand RD, RegisterOperand RS,
+                      SDPatternOperator OpNode= null_frag>
+    : InstForm<(outs), (ins RD:$fd, RS:$rj, RS:$rk),
+          !strconcat(opstr, "\t$fd, $rj, $rk"),
+          [], FrmR, opstr>;
+
 def LL_D : LLBase<"ll.d", GPR64Opnd, mem_simm14_lsl2>, LL_SC<0b010>;
 def SC_D : SCBase<"sc.d", GPR64Opnd, mem_simm14_lsl2>, LL_SC<0b011>;
 
@@ -1254,14 +1275,14 @@ def LDLE_B : Int_Reg3<"ldle.b", GPR64Opnd>, R3MI<0b11110100>;
 def LDLE_H : Int_Reg3<"ldle.h", GPR64Opnd>, R3MI<0b11110101>;
 def LDLE_W : Int_Reg3<"ldle.w", GPR64Opnd>, R3MI<0b11110110>;
 def LDLE_D : Int_Reg3<"ldle.d", GPR64Opnd>, R3MI<0b11110111>;
-def STGT_B : Int_Reg3<"stgt.b", GPR64Opnd>, R3MI<0b11111000>;
-def STGT_H : Int_Reg3<"stgt.h", GPR64Opnd>, R3MI<0b11111001>;
-def STGT_W : Int_Reg3<"stgt.w", GPR64Opnd>, R3MI<0b11111010>;
-def STGT_D : Int_Reg3<"stgt.d", GPR64Opnd>, R3MI<0b11111011>;
-def STLE_B : Int_Reg3<"stle.b", GPR64Opnd>, R3MI<0b11111100>;
-def STLE_H : Int_Reg3<"stle.h", GPR64Opnd>, R3MI<0b11111101>;
-def STLE_W : Int_Reg3<"stle.w", GPR64Opnd>, R3MI<0b11111110>;
-def STLE_D : Int_Reg3<"stle.d", GPR64Opnd>, R3MI<0b11111111>;
+def STGT_B : STGT_LE<"stgt.b", GPR64Opnd>, R3MI<0b11111000>;
+def STGT_H : STGT_LE<"stgt.h", GPR64Opnd>, R3MI<0b11111001>;
+def STGT_W : STGT_LE<"stgt.w", GPR64Opnd>, R3MI<0b11111010>;
+def STGT_D : STGT_LE<"stgt.d", GPR64Opnd>, R3MI<0b11111011>;
+def STLE_B : STGT_LE<"stle.b", GPR64Opnd>, R3MI<0b11111100>;
+def STLE_H : STGT_LE<"stle.h", GPR64Opnd>, R3MI<0b11111101>;
+def STLE_W : STGT_LE<"stle.w", GPR64Opnd>, R3MI<0b11111110>;
+def STLE_D : STGT_LE<"stle.d", GPR64Opnd>, R3MI<0b11111111>;
 
 let isCodeGenOnly = 1 in {
 def PRELD  : Preld<"preld", mem, GPR64Opnd>, PRELD_FM;
@@ -1505,7 +1526,7 @@ class LDX_FT_LA<string opstr, RegisterOperand DRC,
   let mayLoad = 1;
 }
 
-class SDX_FT_LA<string opstr, RegisterOperand DRC,
+class STX_FT_LA<string opstr, RegisterOperand DRC,
                  SDPatternOperator OpNode = null_frag> :
   InstForm<(outs), (ins DRC:$rd, PtrRC:$rj, PtrRC:$rk),
            !strconcat(opstr, "\t$rd, $rj, $rk"),
@@ -1525,13 +1546,13 @@ def LDX_W : LDX_FT_LA<"ldx.w", GPR64Opnd, sextloadi32>,
             R3MI<0b00010000>;
 def LDX_D : LDX_FT_LA<"ldx.d", GPR64Opnd, load>,
             R3MI<0b00011000>;
-def STX_B : SDX_FT_LA<"stx.b", GPR64Opnd, truncstorei8>,
+def STX_B : STX_FT_LA<"stx.b", GPR64Opnd, truncstorei8>,
             R3MI<0b00100000>;
-def STX_H : SDX_FT_LA<"stx.h", GPR64Opnd, truncstorei16>,
+def STX_H : STX_FT_LA<"stx.h", GPR64Opnd, truncstorei16>,
             R3MI<0b00101000>;
-def STX_W : SDX_FT_LA<"stx.w", GPR64Opnd, truncstorei32>,
+def STX_W : STX_FT_LA<"stx.w", GPR64Opnd, truncstorei32>,
             R3MI<0b00110000>;
-def STX_D : SDX_FT_LA<"stx.d", GPR64Opnd, store>,
+def STX_D : STX_FT_LA<"stx.d", GPR64Opnd, store>,
             R3MI<0b00111000>;
 def LDX_BU : LDX_FT_LA<"ldx.bu", GPR64Opnd, extloadi8>,
              R3MI<0b01000000>;
diff --git a/lib/Target/LoongArch/LoongArchInstrInfoF.td b/lib/Target/LoongArch/LoongArchInstrInfoF.td
index 64cc911e9cee..9c064a820933 100644
--- a/lib/Target/LoongArch/LoongArchInstrInfoF.td
+++ b/lib/Target/LoongArch/LoongArchInstrInfoF.td
@@ -473,10 +473,10 @@ def FLDGT_S : Float_Int_Reg3<"fldgt.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101000>;
 def FLDGT_D : Float_Int_Reg3<"fldgt.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101001>;
 def FLDLE_S : Float_Int_Reg3<"fldle.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101010>;
 def FLDLE_D : Float_Int_Reg3<"fldle.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101011>;
-def FSTGT_S : Float_Int_Reg3<"fstgt.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101100>;
-def FSTGT_D : Float_Int_Reg3<"fstgt.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101101>;
-def FSTLE_S : Float_Int_Reg3<"fstle.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101110>;
-def FSTLE_D : Float_Int_Reg3<"fstle.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101111>;
+def FSTGT_S : Float_STGT_LE<"fstgt.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101100>;
+def FSTGT_D : Float_STGT_LE<"fstgt.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101101>;
+def FSTLE_S : Float_STGT_LE<"fstle.s", FGR32Opnd, GPR64Opnd>, R3MF<0b11101110>;
+def FSTLE_D : Float_STGT_LE<"fstle.d", FGR64Opnd, GPR64Opnd>, R3MF<0b11101111>;
 
 let isPseudo = 1, isCodeGenOnly = 1 in {
   def PseudoFFINT_S_W : Float_CVT<"", FGR32Opnd, GPR32Opnd>;
diff --git a/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index d253c0a6b5e6..999bd441644a 100644
--- a/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -29,6 +29,19 @@ def SDT_XVINSERT : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
                                         SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>;
 def SDT_XGETSIGN : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVec<0>, SDTCisSameAs<0, 1>]>;
 
+def SDT_INSVE : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
+                                     SDTCisSameAs<1, 2>,
+                                     SDTCisVT<3, i32>]>;
+
+def SDT_XVPICKVE : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
+                                        SDTCisSameAs<1, 2>,
+                                        SDTCisVT<3, i32>]>;
+
+def SDT_XVSHUF4I : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisInt<0>,
+                                        SDTCisSameAs<0, 1>,
+                                        SDTCisSameAs<0, 2>,
+                                        SDTCisVT<3, i32>]>;
+
 def LoongArchLASXFMADDSUB : SDNode<"LoongArchISD::FMADDSUB", SDT_FMADDSUB>;
 def LoongArchLASXFMSUBADD : SDNode<"LoongArchISD::FMSUBADD", SDT_FMADDSUB>;
 
@@ -45,6 +58,10 @@ def LoongArchXVPERMI : SDNode<"LoongArchISD::XVPERMI", SDT_XVPERMI>;
 def LoongArchXVBROADCAST : SDNode<"LoongArchISD::XVBROADCAST", SDT_XVBROADCAST>;
 def LoongArchXVINSERT : SDNode<"LoongArchISD::XVINSERT", SDT_XVINSERT>;
 
+def LoongArchINSVE : SDNode<"LoongArchISD::INSVE", SDT_INSVE>;
+
+def LoongArchXVSHUF4I : SDNode<"LoongArchISD::XVSHUF4I", SDT_XVSHUF4I>;
+
 def LoongArchXVVREPLVE : SDNode<"LoongArchISD::XVVREPLVE",
                    SDTypeProfile<1, 2, [SDTCisVec<0>,SDTCisInt<0>,
                             SDTCisSameAs<0, 1>, SDTCisVT<2, i32>]>>;
@@ -54,12 +71,11 @@ def LoongArchMemcpy : SDNode<"LoongArchISD::Memcpy",
                  [SDNPHasChain]>;
 
 def LoongArchXGETSIGN : SDNode<"LoongArchISD::XGETSIGN", SDT_XGETSIGN>;
+
+def LoongArchXVPICKVE : SDNode<"LoongArchISD::XVPICKVE", SDT_INSVE>;
+
 def ssetcc : SDNode<"LoongArchISD::SSETCC", SDTSetCC>;
 
-def insve_v8i32 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-        		  (v8i32 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-def insve_v4i64 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-			  (v4i64 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
 
 def xvextractelt_v32i8  : PatFrag<(ops node:$v1, node:$idx),
                                   (LoongArchXVEXTRACTELT node:$v1, node:$idx)>;
@@ -258,17 +274,6 @@ def mxvsplati64_uimm8 : SplatComplexPattern<vsplat_uimm8, v4i64, 1,
                                          [build_vector, bitconvert]>;
 
 
-
-def mxinsve_v32i8 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-    (v32i8 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-def mxinsve_v16i16 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-    (v16i16 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-def mxinsve_v8i32 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-    (v8i32 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-def mxinsve_v4i64 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-    (v4i64 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-
-
 def mxvbset_b : PatFrag<(ops node:$xk, node:$xa),
                       (or node:$xk, (shl vsplat_imm_eq_1, 
                                          node:$xa))>;
@@ -1318,6 +1323,17 @@ class LASX_2R_3R_U8_DESC_BASE<string instr_asm,
   string Constraints = "$xd = $xd_in";
 }
 
+class LASX_2R_3R_U8_SELECT<string instr_asm,
+                           SDPatternOperator OpNode,
+                           RegisterOperand ROXD,
+                           RegisterOperand ROXS> {
+  dag OutOperandList = (outs ROXD:$xd);
+  dag InOperandList = (ins ROXD:$xd_in, ROXS:$xj, vsplat_uimm8:$ui8);
+  string AsmString = !strconcat(instr_asm, "\t$xd, $xj, $ui8");
+  list<dag> Pattern = [(set ROXD:$xd, (OpNode  ROXD:$xd_in, mxvsplati8_uimm8:$ui8, ROXS:$xj))];
+  string Constraints = "$xd = $xd_in";
+}
+
 class LASX_I8_O4_SHF_DESC_BASE<string instr_asm,
                            SDPatternOperator OpNode,
                            RegisterOperand ROXD,
@@ -1390,6 +1406,24 @@ class LASX_2R_3R_U8_DESC_BASE_NN<string instr_asm,
 }
 
 
+class LASX_VLDX_LA<string instr_asm, ValueType VT,
+                   SDPatternOperator OpNode = null_frag,
+                   RegisterOperand ROXD>{
+  dag OutOperandList = (outs ROXD:$xd);
+  dag InOperandList = (ins PtrRC:$rj, PtrRC:$rk);
+  string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $rk");
+  list<dag> Pattern = [(set (VT ROXD:$xd), (OpNode (add iPTR:$rj, iPTR:$rk)))];
+}
+
+
+class LASX_VSTX_LA<string instr_asm, ValueType VT,
+                   SDPatternOperator OpNode = null_frag,
+                   RegisterOperand ROXD>{
+  dag OutOperandList = (outs);
+  dag InOperandList = (ins ROXD:$xd, PtrRC:$rj, PtrRC:$rk);
+  string AsmString = !strconcat(instr_asm, "\t$xd, $rj, $rk");
+  list<dag> Pattern = [(OpNode (VT ROXD:$xd), (add iPTR:$rj, iPTR:$rk))];
+}
 
 
 //encoding
@@ -5141,6 +5175,41 @@ def XVPERMI_QW : LASX_I8_U<0b01110111111011>,
 
 def XVPERMI_QD : LASX_I8_U<0b01110111111011>,
                  LASX_2R_3R_U8_DESC_BASE_NN<"xvpermi.q", LASX256DOpnd, LASX256DOpnd>;
+
+
+def XVBITSELI_B_N : LASX_I8_U<0b01110111110001>,
+                    LASX_2R_3R_U8_SELECT<"xvbitseli.b", vselect, LASX256BOpnd, LASX256BOpnd>;
+
+
+let mayLoad = 1, canFoldAsLoad = 1 in {
+def XVLDX_B : LASX_3R_2GP<0b00111000010010000>,
+              LASX_VLDX_LA<"xvldx", v32i8, load, LASX256BOpnd>;
+
+def XVLDX_H : LASX_3R_2GP<0b00111000010010000>,
+              LASX_VLDX_LA<"xvldx", v16i16, load, LASX256HOpnd>;
+
+def XVLDX_W : LASX_3R_2GP<0b00111000010010000>,
+              LASX_VLDX_LA<"xvldx", v8i32, load, LASX256WOpnd>;
+
+def XVLDX_D : LASX_3R_2GP<0b00111000010010000>,
+              LASX_VLDX_LA<"xvldx", v4i64, load, LASX256DOpnd>;
+}
+
+
+let mayStore = 1 in{
+def XVSTX_B : LASX_3R_2GP<0b00111000010011000>,
+              LASX_VSTX_LA<"xvstx", v32i8, store, LASX256BOpnd>;
+
+def XVSTX_H : LASX_3R_2GP<0b00111000010011000>,
+              LASX_VSTX_LA<"xvstx", v16i16, store, LASX256HOpnd>;
+
+def XVSTX_W : LASX_3R_2GP<0b00111000010011000>,
+              LASX_VSTX_LA<"xvstx", v8i32, store, LASX256WOpnd>;
+
+def XVSTX_D : LASX_3R_2GP<0b00111000010011000>,
+              LASX_VSTX_LA<"xvstx", v4i64, store, LASX256DOpnd>;
+}
+
 }
 
 
@@ -5632,3 +5701,337 @@ def : Pat<(sra
               ),
           (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)))),
           (XVAVG_D  (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>;
+
+
+
+def : Pat<(srl
+               (v32i8 (add LASX256B:$a, LASX256B:$b)),
+               (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (XVAVG_BU  (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>;
+
+def : Pat<(srl
+               (v16i16 (add LASX256H:$a, LASX256H:$b)),
+               (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                     (i32 1),(i32 1),(i32 1),(i32 1),
+                                     (i32 1),(i32 1),(i32 1),(i32 1),
+                                     (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (XVAVG_HU  (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>;
+
+def : Pat<(srl
+               (v8i32 (add LASX256W:$a, LASX256W:$b)),
+               (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (XVAVG_WU  (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>;
+
+def : Pat<(srl
+               (v4i64 (add LASX256D:$a, LASX256D:$b)),
+               (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1))
+                           )
+            ),
+          (XVAVG_DU  (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>;
+
+
+
+def : Pat<(sra
+            (v32i8 (add
+                    (v32i8 (add (v32i8 (
+                    build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                 (i32 1),(i32 1),(i32 1),(i32 1),
+                                 (i32 1),(i32 1),(i32 1),(i32 1),
+                                 (i32 1),(i32 1),(i32 1),(i32 1),
+                                 (i32 1),(i32 1),(i32 1),(i32 1),
+                                 (i32 1),(i32 1),(i32 1),(i32 1),
+                                 (i32 1),(i32 1),(i32 1),(i32 1),
+                                 (i32 1),(i32 1),(i32 1),(i32 1)
+                    )),
+                    (v32i8 (add LASX256B:$a, LASX256B:$b))
+                    )),
+                    (v32i8 (srl
+                           (v32i8 ( add (v32i8(
+                             build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                          (i32 1),(i32 1),(i32 1),(i32 1),
+                                          (i32 1),(i32 1),(i32 1),(i32 1),
+                                          (i32 1),(i32 1),(i32 1),(i32 1),
+                                          (i32 1),(i32 1),(i32 1),(i32 1),
+                                          (i32 1),(i32 1),(i32 1),(i32 1),
+                                          (i32 1),(i32 1),(i32 1),(i32 1),
+                                          (i32 1),(i32 1),(i32 1),(i32 1)
+                           )),
+                           (v32i8 (add LASX256B:$a, LASX256B:$b))
+                           )),
+                           (v32i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7))
+                           )
+                       )
+                 )
+                 )
+            ),
+          (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1)
+          ))),
+          (XVAVGR_B  (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>;
+
+
+def : Pat<(sra
+            (v16i16 (add
+                    (v16i16 (add (v16i16 (
+                       build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1)
+                    )),
+                    (v16i16 (add LASX256H:$a, LASX256H:$b))
+                    )),
+                    (v16i16 (srl
+                       (v16i16 (add (v16i16 (
+                          build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                       (i32 1),(i32 1),(i32 1),(i32 1),
+                                       (i32 1),(i32 1),(i32 1),(i32 1),
+                                       (i32 1),(i32 1),(i32 1),(i32 1)
+                       )),
+                       (v16i16 (add LASX256H:$a, LASX256H:$b))
+                       )),
+                           (v16i16 (build_vector
+                                (i32 15),(i32 15),(i32 15),(i32 15),
+                                (i32 15),(i32 15),(i32 15),(i32 15),
+                                (i32 15),(i32 15),(i32 15),(i32 15),
+                                (i32 15),(i32 15),(i32 15),(i32 15))
+                           )
+                       )
+                 )
+                 )
+            ),
+          (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                (i32 1),(i32 1),(i32 1),(i32 1),
+                                (i32 1),(i32 1),(i32 1),(i32 1),
+                                (i32 1),(i32 1),(i32 1),(i32 1)
+          ))),
+          (XVAVGR_H  (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>;
+
+
+def : Pat<(sra
+            (v8i32 (add
+                      (v8i32 (add (v8i32 (
+                         build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                      (i32 1),(i32 1),(i32 1),(i32 1)
+                      )),
+                      (v8i32 (add LASX256W:$a, LASX256W:$b))
+                      )),
+                    (v8i32 (srl
+                        (v8i32 (add (v8i32 (
+                           build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                        (i32 1),(i32 1),(i32 1),(i32 1)
+                        )),
+                        (v8i32 (add LASX256W:$a, LASX256W:$b))
+                        )),
+                           (v8i32 (build_vector
+                                   (i32 31),(i32 31),(i32 31),(i32 31),
+                                   (i32 31),(i32 31),(i32 31),(i32 31)
+                                   )
+                           )
+                       )
+                 )
+                 )
+            ),
+          (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1)))),
+          (XVAVGR_W  (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>;
+
+def : Pat<(sra
+              (v4i64 (add
+                         (v4i64 (add (v4i64 (
+                            build_vector (i64 1),(i64 1),(i64 1),(i64 1)
+                         )),
+                         (v4i64 (add LASX256D:$a, LASX256D:$b))
+                         )),
+                      (v4i64 (srl
+                         (v4i64 (add (v4i64 (
+                            build_vector (i64 1),(i64 1),(i64 1),(i64 1)
+                         )),
+                         (v4i64 (add LASX256D:$a, LASX256D:$b))
+                         )),
+                                (v4i64 (build_vector
+                                    (i64 63),(i64 63),(i64 63),(i64 63)))
+                            )
+                      )
+                      )
+              ),
+          (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1)))),
+          (XVAVGR_D  (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>;
+
+
+
+def : Pat<(srl
+                (v32i8 (add (v32i8 (
+                build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                             (i32 1),(i32 1),(i32 1),(i32 1),
+                             (i32 1),(i32 1),(i32 1),(i32 1),
+                             (i32 1),(i32 1),(i32 1),(i32 1),
+                             (i32 1),(i32 1),(i32 1),(i32 1),
+                             (i32 1),(i32 1),(i32 1),(i32 1),
+                             (i32 1),(i32 1),(i32 1),(i32 1),
+                             (i32 1),(i32 1),(i32 1),(i32 1)
+                )),
+                (v32i8 (add LASX256B:$a, LASX256B:$b))
+                )),
+               (v32i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (XVAVGR_BU  (v32i8 LASX256B:$a), (v32i8 LASX256B:$b))>;
+
+def : Pat<(srl
+               (v16i16 (add (v16i16 (
+                  build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1)
+               )),
+               (v16i16 (add LASX256H:$a, LASX256H:$b))
+               )),
+               (v16i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                     (i32 1),(i32 1),(i32 1),(i32 1),
+                                     (i32 1),(i32 1),(i32 1),(i32 1),
+                                     (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (XVAVGR_HU  (v16i16 LASX256H:$a), (v16i16 LASX256H:$b))>;
+
+def : Pat<(srl
+               (v8i32 (add (v8i32 (
+                  build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1)
+               )),
+               (v8i32 (add LASX256W:$a, LASX256W:$b))
+               )),
+               (v8i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (XVAVGR_WU  (v8i32 LASX256W:$a), (v8i32 LASX256W:$b))>;
+
+def : Pat<(srl
+               (v4i64 (add (v4i64 (
+                  build_vector (i64 1),(i64 1),(i64 1),(i64 1)
+               )),
+               (v4i64 (add LASX256D:$a, LASX256D:$b))
+               )),
+               (v4i64 (build_vector (i64 1),(i64 1),(i64 1),(i64 1))
+                           )
+            ),
+          (XVAVGR_DU  (v4i64 LASX256D:$a), (v4i64 LASX256D:$b))>;
+
+
+def : Pat<(mulhs LASX256D:$a, LASX256D:$b),
+          (XVMUH_D LASX256D:$a, LASX256D:$b)>;
+
+def : Pat<(mulhs LASX256W:$a, LASX256W:$b),
+          (XVMUH_W LASX256W:$a, LASX256W:$b)>;
+
+def : Pat<(mulhs LASX256H:$a, LASX256H:$b),
+          (XVMUH_H LASX256H:$a, LASX256H:$b)>;
+
+def : Pat<(mulhs LASX256B:$a, LASX256B:$b),
+          (XVMUH_B LASX256B:$a, LASX256B:$b)>;
+
+
+def : Pat<(mulhu LASX256D:$a, LASX256D:$b),
+          (XVMUH_DU LASX256D:$a, LASX256D:$b)>;
+
+def : Pat<(mulhu LASX256W:$a, LASX256W:$b),
+          (XVMUH_WU LASX256W:$a, LASX256W:$b)>;
+
+def : Pat<(mulhu LASX256H:$a, LASX256H:$b),
+          (XVMUH_HU LASX256H:$a, LASX256H:$b)>;
+
+def : Pat<(mulhu LASX256B:$a, LASX256B:$b),
+          (XVMUH_BU LASX256B:$a, LASX256B:$b)>;
+
+
+def : Pat<(LoongArchINSVE  (v8i32 LASX256W:$a), (v8i32 LASX256W:$b), uimm3:$ui3),
+          (XVINSVE0_W  LASX256W:$a, LASX256W:$b, uimm3:$ui3)>;
+
+def : Pat<(LoongArchINSVE  (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm2:$ui2),
+          (XVINSVE0_D  LASX256D:$a, LASX256D:$b, uimm2:$ui2)>;
+
+
+def : Pat<(LoongArchXVPICKVE  (v8i32 (bitconvert (v32i8 (build_vector
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0)
+                              )))), (v8i32 LASX256W:$b), uimm3:$ui3),
+          (XVPICKVE_W  (v8i32 (IMPLICIT_DEF)), LASX256W:$b, uimm3:$ui3)>;
+
+def : Pat<(LoongArchXVPICKVE  (v4i64 (bitconvert (v32i8 (build_vector
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0)
+                              )))), (v4i64 LASX256D:$b), uimm2:$ui2),
+          (XVPICKVE_D  (v4i64 (IMPLICIT_DEF)), LASX256D:$b, uimm2:$ui2)>;
+
+
+def : Pat<(LoongArchXVPICKVE  (v8i32 (build_vector
+                              (i32 0),(i32 0),(i32 0),(i32 0),
+                              (i32 0),(i32 0),(i32 0),(i32 0)
+                              )), (v8i32 LASX256W:$b), uimm3:$ui3),
+          (XVPICKVE_W  (v8i32 (IMPLICIT_DEF)), LASX256W:$b, uimm3:$ui3)>;
+
+def : Pat<(LoongArchXVPICKVE  (v4i64 (build_vector
+                              (i64 0),(i64 0),(i64 0),(i64 0)
+                              )), (v4i64 LASX256D:$b), uimm2:$ui2),
+          (XVPICKVE_D  (v4i64 (IMPLICIT_DEF)), LASX256D:$b, uimm2:$ui2)>;
+
+
+def : Pat<(LoongArchXVPICKVE  (v8i32 LASX256W:$a), (v8i32 LASX256W:$b), uimm3:$ui3),
+          (XVPICKVE_W  LASX256W:$a, LASX256W:$b, uimm3:$ui3)>;
+
+def : Pat<(LoongArchXVPICKVE  (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm2:$ui2),
+          (XVPICKVE_D  LASX256D:$a, LASX256D:$b, uimm2:$ui2)>;
+
+
+def : Pat<(LoongArchXVSHUF4I  (v4i64 LASX256D:$a), (v4i64 LASX256D:$b), uimm8_32:$ui8),
+          (XVSHUF4I_D  LASX256D:$a, LASX256D:$b, uimm8_32:$ui8)>;
+
+def : Pat<(LoongArchXVPERMI  (v4i64 LASX256D:$a), uimm8_32:$ui8),
+          (XVPERMI_D  LASX256D:$a, uimm8_32:$ui8)>;
diff --git a/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
index 3c2affece969..e4c71fcb9203 100644
--- a/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
+++ b/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
@@ -27,9 +27,6 @@ def SDT_SHF : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>,
                                    SDTCisVT<1, i32>, SDTCisSameAs<0, 2>]>;
 def SDT_ILV : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>,
                                    SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>]>;
-def SDT_INSVE : SDTypeProfile<1, 4, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
-                                     SDTCisVT<2, i32>, SDTCisSameAs<0, 3>,
-                                     SDTCisVT<4, i32>]>;
 def SDTVABSD : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
                                     SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>;
 
@@ -50,7 +47,6 @@ def LoongArchVILVH  : SDNode<"LoongArchISD::VILVH",  SDT_ILV>;
 def LoongArchVILVL  : SDNode<"LoongArchISD::VILVL",  SDT_ILV>;
 def LoongArchVPICKEV : SDNode<"LoongArchISD::VPICKEV", SDT_ILV>;
 def LoongArchVPICKOD : SDNode<"LoongArchISD::VPICKOD", SDT_ILV>;
-def LoongArchINSVE : SDNode<"LoongArchISD::INSVE", SDT_INSVE>;
 def LoongArchFMS   : SDNode<"LoongArchISD::FMS", SDTFPTernaryOp>;
 def LoongArchVABSD : SDNode<"LoongArchISD::VABSD", SDTVABSD>;
 def LoongArchUVABSD : SDNode<"LoongArchISD::UVABSD", SDTVABSD>;
@@ -514,15 +510,6 @@ def vinsert_v4i32 : PatFrag<(ops node:$vec, node:$val, node:$idx),
 def vinsert_v2i64 : PatFrag<(ops node:$vec, node:$val, node:$idx),
     (v2i64 (vector_insert node:$vec, node:$val, node:$idx))>;
 
-def insve_v16i8 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-    (v16i8 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-def insve_v8i16 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-    (v8i16 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-def insve_v4i32 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-    (v4i32 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-def insve_v2i64 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
-    (v2i64 (LoongArchINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
-
 class vfsetcc_type<ValueType ResTy, ValueType OpTy, CondCode CC> :
   PatFrag<(ops node:$lhs, node:$rhs),
           (ResTy (vfsetcc (OpTy node:$lhs), (OpTy node:$rhs), CC))>;
@@ -1689,6 +1676,16 @@ class LSX_2R_3R_U8_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
   string Constraints = "$vd = $vd_in";
 }
 
+class LSX_2R_3R_SELECT<string instr_asm, SDPatternOperator OpNode,
+                       RegisterOperand ROVD,
+                       RegisterOperand ROVS> {
+  dag OutOperandList = (outs ROVD:$vd);
+  dag InOperandList = (ins ROVD:$vd_in, ROVS:$vj, vsplat_uimm8:$ui8);
+  string AsmString = !strconcat(instr_asm, "\t$vd, $vj, $ui8");
+  list<dag> Pattern = [(set ROVD:$vd, (OpNode  ROVD:$vd_in, vsplati8_uimm8:$ui8, ROVS:$vj))];
+  string Constraints = "$vd = $vd_in";
+}
+
 class LSX_2R_U8_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
                            RegisterOperand ROVD,
                            RegisterOperand ROVS> {
@@ -1728,6 +1725,25 @@ class LSX_BIT_U8_VREPLVE_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
 }
 
 
+class LSX_VLDX_LA<string instr_asm, ValueType VT,
+                  SDPatternOperator OpNode = null_frag,
+                  RegisterOperand ROVD>{
+  dag OutOperandList = (outs ROVD:$vd);
+  dag InOperandList = (ins PtrRC:$rj, PtrRC:$rk);
+  string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $rk");
+  list<dag> Pattern = [(set (VT ROVD:$vd), (OpNode (add iPTR:$rj, iPTR:$rk)))];
+}
+
+
+class LSX_VSTX_LA<string instr_asm, ValueType VT,
+                  SDPatternOperator OpNode = null_frag,
+                  RegisterOperand ROVD>{
+  dag OutOperandList = (outs);
+  dag InOperandList = (ins ROVD:$vd, PtrRC:$rj, PtrRC:$rk);
+  string AsmString = !strconcat(instr_asm, "\t$vd, $rj, $rk");
+  list<dag> Pattern = [(OpNode (VT ROVD:$vd), (add iPTR:$rj, iPTR:$rk))];
+}
+
 
 class LSXPat<dag pattern, dag result, list<Predicate> pred = [HasLSX]> :
   Pat<pattern, result>, Requires<pred>;
@@ -5046,6 +5062,41 @@ def VFTINTRZ_L_D_N : LSX_2R<0b0111001010011110010011>,
 
 def VBITCLR_D_N : LSX_3R<0b01110001000011011>,
                   LSX_3R_DESC_BASE<"vbitclr.d", vbitclr_d, LSX128DOpnd>;
+
+
+def VBITSELI_B_N : LSX_I8_U<0b01110011110001>,
+                   LSX_2R_3R_SELECT<"vbitseli.b", vselect, LSX128BOpnd, LSX128BOpnd>;
+
+
+let mayLoad = 1, canFoldAsLoad = 1 in {
+def VLDX_B : LSX_3R_2GP<0b00111000010000000>,
+             LSX_VLDX_LA<"vldx", v16i8, load, LSX128BOpnd>;
+
+def VLDX_H : LSX_3R_2GP<0b00111000010000000>,
+             LSX_VLDX_LA<"vldx", v8i16, load, LSX128HOpnd>;
+
+def VLDX_W : LSX_3R_2GP<0b00111000010000000>,
+             LSX_VLDX_LA<"vldx", v4i32, load, LSX128WOpnd>;
+
+def VLDX_D : LSX_3R_2GP<0b00111000010000000>,
+             LSX_VLDX_LA<"vldx", v2i64, load, LSX128DOpnd>;
+}
+
+
+let mayStore = 1 in{
+def VSTX_B : LSX_3R_2GP<0b00111000010001000>,
+             LSX_VSTX_LA<"vstx", v16i8, store, LSX128BOpnd>;
+
+def VSTX_H : LSX_3R_2GP<0b00111000010001000>,
+             LSX_VSTX_LA<"vstx", v8i16, store, LSX128HOpnd>;
+
+def VSTX_W : LSX_3R_2GP<0b00111000010001000>,
+             LSX_VSTX_LA<"vstx", v4i32, store, LSX128WOpnd>;
+
+def VSTX_D : LSX_3R_2GP<0b00111000010001000>,
+             LSX_VSTX_LA<"vstx", v2i64, store, LSX128DOpnd>;
+}
+
 }
 
 
@@ -5305,3 +5356,226 @@ def : Pat<(sra
               ),
           (v2i64 (build_vector (i64 1),(i64 1)))),
           (VAVG_D  (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>;
+
+
+
+def : Pat<(srl
+               (v16i8 (add LSX128B:$a, LSX128B:$b)),
+               (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (VAVG_BU  (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>;
+
+def : Pat<(srl
+               (v8i16 (add LSX128H:$a, LSX128H:$b)),
+               (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (VAVG_HU  (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>;
+
+def : Pat<(srl
+               (v4i32 (add LSX128W:$a, LSX128W:$b)),
+               (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (VAVG_WU  (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>;
+
+def : Pat<(srl
+               (v2i64 (add LSX128D:$a, LSX128D:$b)),
+               (v2i64 (build_vector (i64 1),(i64 1))
+                           )
+            ),
+          (VAVG_DU  (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>;
+
+
+
+
+def : Pat<(sra
+            (v16i8 (add
+                    (v16i8 (add (v16i8 (
+                    build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1)
+                    )),
+                    (v16i8 (add LSX128B:$a, LSX128B:$b))
+                    )),
+                    (v16i8 (srl
+                           (v16i8 ( add (v16i8(
+                             build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                        (i32 1),(i32 1),(i32 1),(i32 1),
+                                        (i32 1),(i32 1),(i32 1),(i32 1),
+                                        (i32 1),(i32 1),(i32 1),(i32 1)
+                           )),
+                           (v16i8 (add LSX128B:$a, LSX128B:$b))
+                           )),
+                           (v16i8 (build_vector (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7),
+                                                (i32 7),(i32 7),(i32 7),(i32 7))
+                           )
+                       )
+                 )
+                 )
+            ),
+          (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1)
+          ))),
+          (VAVGR_B  (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>;
+
+def : Pat<(sra
+            (v8i16 (add
+                    (v8i16 (add (v8i16 (
+                       build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1)
+                    )),
+                    (v8i16 (add LSX128H:$a, LSX128H:$b))
+                    )),
+                    (v8i16 (srl
+                       (v8i16 (add (v8i16 (
+                          build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                       (i32 1),(i32 1),(i32 1),(i32 1)
+                       )),
+                       (v8i16 (add LSX128H:$a, LSX128H:$b))
+                       )),
+                           (v8i16 (build_vector (i32 15),(i32 15),(i32 15),(i32 15),
+                                                (i32 15),(i32 15),(i32 15),(i32 15))
+                           )
+                       )
+                 )
+                 )
+            ),
+          (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1)
+          ))),
+          (VAVGR_H  (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>;
+
+def : Pat<(sra
+            (v4i32 (add
+                      (v4i32 (add (v4i32 (
+                         build_vector (i32 1),(i32 1),(i32 1),(i32 1)
+                      )),
+                      (v4i32 (add LSX128W:$a, LSX128W:$b))
+                      )),
+                    (v4i32 (srl
+                        (v4i32 (add (v4i32 (
+                           build_vector (i32 1),(i32 1),(i32 1),(i32 1)
+                        )),
+                        (v4i32 (add LSX128W:$a, LSX128W:$b))
+                        )),
+                           (v4i32 (build_vector (i32 31),(i32 31),(i32 31),(i32 31))
+                           )
+                       )
+                 )
+                 )
+            ),
+          (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1)))),
+          (VAVGR_W  (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>;
+
+def : Pat<(sra
+              (v2i64 (add
+                         (v2i64 (add (v2i64 (
+                            build_vector (i64 1),(i64 1)
+                         )),
+                         (v2i64 (add LSX128D:$a, LSX128D:$b))
+                         )),
+                      (v2i64 (srl
+                         (v2i64 (add (v2i64 (
+                            build_vector (i64 1),(i64 1)
+                         )),
+                         (v2i64 (add LSX128D:$a, LSX128D:$b))
+                         )),
+                                (v2i64 (build_vector (i64 63),(i64 63)))
+                            )
+                      )
+                      )
+              ),
+          (v2i64 (build_vector (i64 1),(i64 1)))),
+          (VAVGR_D  (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>;
+
+
+
+
+def : Pat<(srl
+               (v16i8 (add (v16i8 (
+               build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                          (i32 1),(i32 1),(i32 1),(i32 1),
+                          (i32 1),(i32 1),(i32 1),(i32 1),
+                          (i32 1),(i32 1),(i32 1),(i32 1)
+               )),
+               (v16i8 (add LSX128B:$a, LSX128B:$b))
+               )),
+               (v16i8 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (VAVGR_BU  (v16i8 LSX128B:$a), (v16i8 LSX128B:$b))>;
+
+def : Pat<(srl
+               (v8i16 (add (v8i16 (
+                  build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                               (i32 1),(i32 1),(i32 1),(i32 1)
+               )),
+               (v8i16 (add LSX128H:$a, LSX128H:$b))
+               )),
+               (v8i16 (build_vector (i32 1),(i32 1),(i32 1),(i32 1),
+                                    (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (VAVGR_HU  (v8i16 LSX128H:$a), (v8i16 LSX128H:$b))>;
+
+def : Pat<(srl
+               (v4i32 (add (v4i32 (
+                  build_vector (i32 1),(i32 1),(i32 1),(i32 1)
+               )),
+               (v4i32 (add LSX128W:$a, LSX128W:$b))
+               )),
+               (v4i32 (build_vector (i32 1),(i32 1),(i32 1),(i32 1))
+                           )
+            ),
+          (VAVGR_WU  (v4i32 LSX128W:$a), (v4i32 LSX128W:$b))>;
+
+def : Pat<(srl
+               (v2i64 (add (v2i64 (
+                  build_vector (i64 1),(i64 1)
+               )),
+               (v2i64 (add LSX128D:$a, LSX128D:$b))
+               )),
+               (v2i64 (build_vector (i64 1),(i64 1))
+                           )
+            ),
+          (VAVGR_DU  (v2i64 LSX128D:$a), (v2i64 LSX128D:$b))>;
+
+
+def : Pat<(mulhs LSX128D:$a, LSX128D:$b),
+          (VMUH_D LSX128D:$a, LSX128D:$b)>;
+
+def : Pat<(mulhs LSX128W:$a, LSX128W:$b),
+          (VMUH_W LSX128W:$a, LSX128W:$b)>;
+
+def : Pat<(mulhs LSX128H:$a, LSX128H:$b),
+          (VMUH_H LSX128H:$a, LSX128H:$b)>;
+
+def : Pat<(mulhs LSX128B:$a, LSX128B:$b),
+          (VMUH_B LSX128B:$a, LSX128B:$b)>;
+
+
+def : Pat<(mulhu LSX128D:$a, LSX128D:$b),
+          (VMUH_DU LSX128D:$a, LSX128D:$b)>;
+
+def : Pat<(mulhu LSX128W:$a, LSX128W:$b),
+          (VMUH_WU LSX128W:$a, LSX128W:$b)>;
+
+def : Pat<(mulhu LSX128H:$a, LSX128H:$b),
+          (VMUH_HU LSX128H:$a, LSX128H:$b)>;
+
+def : Pat<(mulhu LSX128B:$a, LSX128B:$b),
+          (VMUH_BU LSX128B:$a, LSX128B:$b)>;
diff --git a/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp b/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp
index 088c789fd791..d570af5e66c7 100644
--- a/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp
+++ b/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp
@@ -1,8 +1,9 @@
 //===-- LoongArchTargetTransformInfo.cpp - LoongArch specific TTI pass ----------------===//
 //
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 /// \file
diff --git a/lib/Target/LoongArch/LoongArchTargetTransformInfo.h b/lib/Target/LoongArch/LoongArchTargetTransformInfo.h
index df58a15f6e0d..f7f3e738836f 100644
--- a/lib/Target/LoongArch/LoongArchTargetTransformInfo.h
+++ b/lib/Target/LoongArch/LoongArchTargetTransformInfo.h
@@ -1,8 +1,9 @@
 //===-- LoongArchTargetTransformInfo.h - LoongArch specific TTI -------------*- C++ -*-===//
 //
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 // \file
diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index f1558c75cb90..b64cf8186953 100644
--- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -104,6 +104,7 @@ static const uint64_t kPPC64_ShadowOffset64 = 1ULL << 44;
 static const uint64_t kSystemZ_ShadowOffset64 = 1ULL << 52;
 static const uint64_t kMIPS32_ShadowOffset32 = 0x0aaa0000;
 static const uint64_t kMIPS64_ShadowOffset64 = 1ULL << 37;
+static const uint64_t kLoongArch64_ShadowOffset64 = 1ULL << 37;
 static const uint64_t kAArch64_ShadowOffset64 = 1ULL << 36;
 static const uint64_t kFreeBSD_ShadowOffset32 = 1ULL << 30;
 static const uint64_t kFreeBSD_ShadowOffset64 = 1ULL << 46;
@@ -503,6 +504,7 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize,
   bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64;
   bool IsMIPS32 = TargetTriple.isMIPS32();
   bool IsMIPS64 = TargetTriple.isMIPS64();
+  bool IsLoongArch64 = TargetTriple.isLoongArch64();
   bool IsArmOrThumb = TargetTriple.isARM() || TargetTriple.isThumb();
   bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64;
   bool IsWindows = TargetTriple.isOSWindows();
@@ -565,6 +567,9 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize,
       Mapping.Offset = kWindowsShadowOffset64;
     } else if (IsMIPS64)
       Mapping.Offset = kMIPS64_ShadowOffset64;
+      else if (IsLoongArch64) {
+      Mapping.Offset = kLoongArch64_ShadowOffset64;
+     }
     else if (IsIOS)
       // If we're targeting iOS and x86, the binary is built for iOS simulator.
       // We are using dynamic shadow offset on the 64-bit devices.
diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index 4c3c6c9added..3ec54e0a318d 100644
--- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -542,6 +542,7 @@ bool DataFlowSanitizer::doInitialization(Module &M) {
   bool IsMIPS64 = TargetTriple.isMIPS64();
   bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64 ||
                    TargetTriple.getArch() == Triple::aarch64_be;
+  bool IsLoongArch64 = TargetTriple.getArch() == Triple::loongarch64;
 
   const DataLayout &DL = M.getDataLayout();
 
@@ -556,6 +557,11 @@ bool DataFlowSanitizer::doInitialization(Module &M) {
     ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x700000000000LL);
   else if (IsMIPS64)
     ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0xF000000000LL);
+  // FIXME: '~0xF000000000LL' may be taken from the value of mips64's kShadowMask
+  // in the compiler-rt/lib/dfsan/dfsan_platform.h file. I'm not sure it is OK for
+  // loongarch64.
+  else if (IsLoongArch64)
+    ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0xF000000000LL);
   // AArch64 supports multiple VMAs and the shadow mask is set at runtime.
   else if (IsAArch64)
     DFSanRuntimeShadowMask = true;
diff --git a/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp b/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
index db438e78ded9..ac079154e458 100644
--- a/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
+++ b/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
@@ -522,7 +522,7 @@ void EfficiencySanitizer::createDestructor(Module &M, Constant *ToolInfoArg) {
 bool EfficiencySanitizer::initOnModule(Module &M) {
 
   Triple TargetTriple(M.getTargetTriple());
-  if (TargetTriple.isMIPS64())
+  if (TargetTriple.isMIPS64() || TargetTriple.isLoongArch64())
     ShadowParams = ShadowParams40;
   else
     ShadowParams = ShadowParams47;
diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 6cd361c7d6e1..212d87c114b3 100644
--- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -4605,6 +4605,8 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
   else if (TargetTriple.getArch() == Triple::ppc64 ||
            TargetTriple.getArch() == Triple::ppc64le)
     return new VarArgPowerPC64Helper(Func, Msan, Visitor);
+  else if(TargetTriple.getArch() == Triple::loongarch64)
+    return new VarArgLoongArch64Helper(Func, Msan, Visitor);
   else
     return new VarArgNoOpHelper(Func, Msan, Visitor);
 }
diff --git a/utils/UpdateTestChecks/asm.py b/utils/UpdateTestChecks/asm.py
index 923efd5bbef4..4998ab3cb3b4 100644
--- a/utils/UpdateTestChecks/asm.py
+++ b/utils/UpdateTestChecks/asm.py
@@ -50,6 +50,12 @@ ASM_FUNCTION_MIPS_RE = re.compile(
                                               # .Lfunc_end0: (mips64 - NewABI)
     flags=(re.M | re.S))
 
+ASM_FUNCTION_LOONGARCH_RE = re.compile(
+    r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?' # f: (name of func)
+    r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'                    # (body of the function)
+    r'.Lfunc_end[0-9]+:\n',                                # .Lfunc_end[0-9]:
+    flags=(re.M | re.S))
+
 ASM_FUNCTION_PPC_RE = re.compile(
     r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n'
     r'.*?'
@@ -169,6 +175,16 @@ def scrub_asm_mips(asm, args):
   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
   return asm
 
+def scrub_asm_loongarch(asm, args):
+  # Scrub runs of whitespace out of the assembly, but leave the leading
+  # whitespace in place.
+  asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
+  # Expand the tabs used for indentation.
+  asm = string.expandtabs(asm, 2)
+  # Strip trailing whitespace.
+  asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
+  return asm
+
 def scrub_asm_riscv(asm, args):
   # Scrub runs of whitespace out of the assembly, but leave the leading
   # whitespace in place.
@@ -231,6 +247,7 @@ def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, pre
       'armv7eb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
       'armv7eb': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
       'mips': (scrub_asm_mips, ASM_FUNCTION_MIPS_RE),
+      'loongarch64': (scrub_asm_loongarch, ASM_FUNCTION_LOONGARCH_RE),
       'powerpc64': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE),
       'powerpc64le': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE),
       'riscv32': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
