diff --git a/0002-pkg_an8_llvm_13.0.1-1.0.3.patch b/0002-pkg_an8_llvm_13.0.1-1.0.3.patch new file mode 100644 index 0000000000000000000000000000000000000000..57523c0315b28c192e36ec48323e990e968e3088 --- /dev/null +++ b/0002-pkg_an8_llvm_13.0.1-1.0.3.patch @@ -0,0 +1,3563 @@ +diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h +index 82dfdc270..4646ffddc 100644 +--- a/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h ++++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h +@@ -330,6 +330,43 @@ public: + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); + }; + ++// @brief LoongArch64 support. ++class OrcLoongArch64 { ++public: ++ static constexpr unsigned PointerSize = 8; ++ static constexpr unsigned TrampolineSize = 40; ++ static constexpr unsigned StubSize = 32; ++ static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; ++ static constexpr unsigned ResolverCodeSize = 0x120; ++ ++ /// Write the resolver code into the given memory. The user is ++ /// responsible for allocating the memory and setting permissions. ++ /// ++ /// ReentryFnAddr should be the address of a function whose signature matches ++ /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr ++ /// argument of writeResolverCode will be passed as the second argument to ++ /// the function at ReentryFnAddr. ++ static void writeResolverCode(char *ResolverWorkingMem, ++ JITTargetAddress ResolverTargetAddress, ++ JITTargetAddress ReentryFnAddr, ++ JITTargetAddress ReentryCtxAddr); ++ ++ /// Write the requested number of trampolines into the given memory, ++ /// which must be big enough to hold 1 pointer, plus NumTrampolines ++ /// trampolines. ++ static void writeTrampolines(char *TrampolineBlockWorkingMem, ++ JITTargetAddress TrampolineBlockTargetAddress, ++ JITTargetAddress ResolverFnAddr, ++ unsigned NumTrampolines); ++ /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. ++ /// Stubs will be written as if linked at StubsBlockTargetAddress, with the ++ /// Nth stub using the Nth pointer in memory starting at ++ /// PointersBlockTargetAddress. ++ static void writeIndirectStubsBlock( ++ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, ++ JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); ++}; ++ + } // end namespace orc + } // end namespace llvm + +diff --git a/llvm/include/llvm/Support/Base64.h b/llvm/include/llvm/Support/Base64.h +index 62064a35a..da4ae1688 100644 +--- a/llvm/include/llvm/Support/Base64.h ++++ b/llvm/include/llvm/Support/Base64.h +@@ -13,6 +13,7 @@ + #ifndef LLVM_SUPPORT_BASE64_H + #define LLVM_SUPPORT_BASE64_H + ++#include + #include + + namespace llvm { +diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h +index 44f5a750f..937e0572d 100644 +--- a/llvm/include/llvm/Support/Signals.h ++++ b/llvm/include/llvm/Support/Signals.h +@@ -14,6 +14,7 @@ + #ifndef LLVM_SUPPORT_SIGNALS_H + #define LLVM_SUPPORT_SIGNALS_H + ++#include + #include + + namespace llvm { +diff --git a/llvm/lib/CodeGen/RegisterScavenging.cpp b/llvm/lib/CodeGen/RegisterScavenging.cpp +index e89b0bd8e..e35cf7aa6 100644 +--- a/llvm/lib/CodeGen/RegisterScavenging.cpp ++++ b/llvm/lib/CodeGen/RegisterScavenging.cpp +@@ -424,10 +424,6 @@ findSurvivorBackwards(const MachineRegisterInfo &MRI, + InstrCountDown = InstrLimit; + Pos = I; + } +- if (I->getFlag(MachineInstr::FrameSetup)) { +- Pos = To; +- break; +- } + if (I == MBB.begin()) + break; + } +diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +index 348fad6da..943b20d36 100644 +--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp ++++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +@@ -698,6 +698,9 @@ InstrEmitter::EmitDbgValue(SDDbgValue *SD, + MIB.addMetadata(Var); + MIB.addMetadata(Expr); + AddDbgValueLocationOps(MIB, DbgValDesc, LocationOps, VRBaseMap); ++ // FIXME: Fix rustc build error with lto=thin option on loongarch. ++ if (MF->getTarget().getTargetTriple().isLoongArch()) ++ return nullptr; + return &*MIB; + } + +diff --git a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp +index b9c70b0ae..6140b1715 100644 +--- a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp ++++ b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp +@@ -258,6 +258,9 @@ EPCIndirectionUtils::Create(ExecutorProcessControl &EPC) { + case Triple::mips64el: + return CreateWithABI(EPC); + ++ case Triple::loongarch64: ++ return CreateWithABI(EPC); ++ + case Triple::x86_64: + if (TT.getOS() == Triple::OSType::Win32) + return CreateWithABI(EPC); +diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +index e8dd1bb90..c57a28866 100644 +--- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp ++++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +@@ -147,6 +147,11 @@ createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES, + return CCMgrT::Create(ES, ErrorHandlerAddress); + } + ++ case Triple::loongarch64: { ++ typedef orc::LocalJITCompileCallbackManager CCMgrT; ++ return CCMgrT::Create(ES, ErrorHandlerAddress); ++ } ++ + case Triple::x86_64: { + if (T.getOS() == Triple::OSType::Win32) { + typedef orc::LocalJITCompileCallbackManager CCMgrT; +diff --git a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp +index e1f494415..4dba00f1d 100644 +--- a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp ++++ b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp +@@ -131,6 +131,10 @@ createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES, + case Triple::mips64el: + return LocalLazyCallThroughManager::Create(ES, ErrorHandlerAddr); + ++ case Triple::loongarch64: ++ return LocalLazyCallThroughManager::Create( ++ ES, ErrorHandlerAddr); ++ + case Triple::x86_64: + if (T.getOS() == Triple::OSType::Win32) + return LocalLazyCallThroughManager::Create( +diff --git a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp +index 18b3c5e12..440831d79 100644 +--- a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp ++++ b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp +@@ -906,5 +906,206 @@ void OrcMips64::writeIndirectStubsBlock( + Stub[8 * I + 7] = 0x00000000; // nop + } + } ++ ++void OrcLoongArch64::writeResolverCode(char *ResolverWorkingMem, ++ JITTargetAddress ResolverTargetAddress, ++ JITTargetAddress ReentryFnAddr, ++ JITTargetAddress ReentryCtxAddr) { ++ ++ const uint32_t ResolverCode[] = { ++ // resolver_entry: ++ 0x02fc8063, // 0x0: addi.d $r3,$r3,-224(0xf20) ++ 0x29c00064, // 0x4: st.d $r4,$r3,0 ++ 0x29c02065, // 0x8: st.d $r5,$r3,8(0x8) ++ 0x29c04066, // 0xc: st.d $r6,$r3,16(0x10) ++ 0x29c06067, // 0x10: st.d $r7,$r3,24(0x18) ++ 0x29c08068, // 0x14: st.d $r8,$r3,32(0x20) ++ 0x29c0a069, // 0x18: st.d $r9,$r3,40(0x28) ++ 0x29c0c06a, // 0x1c: st.d $r10,$r3,48(0x30) ++ 0x29c0e06b, // 0x20: st.d $r11,$r3,56(0x38) ++ 0x29c1006c, // 0x24: st.d $r12,$r3,64(0x40) ++ 0x29c1206d, // 0x28: st.d $r13,$r3,72(0x48) ++ 0x29c1406e, // 0x2c: st.d $r14,$r3,80(0x50) ++ 0x29c1606f, // 0x30: st.d $r15,$r3,88(0x58) ++ 0x29c18070, // 0x34: st.d $r16,$r3,96(0x60) ++ 0x29c1a071, // 0x38: st.d $r17,$r3,104(0x68) ++ 0x29c1c072, // 0x3c: st.d $r18,$r3,112(0x70) ++ 0x29c1e073, // 0x40: st.d $r19,$r3,120(0x78) ++ 0x29c20074, // 0x44: st.d $r20,$r3,128(0x80) ++ 0x29c22076, // 0x48: st.d $r22,$r3,136(0x88) ++ 0x29c24077, // 0x4c: st.d $r23,$r3,144(0x90) ++ 0x29c26078, // 0x50: st.d $r24,$r3,152(0x98) ++ 0x29c28079, // 0x54: st.d $r25,$r3,160(0xa0) ++ 0x29c2a07a, // 0x58: st.d $r26,$r3,168(0xa8) ++ 0x29c2c07b, // 0x5c: st.d $r27,$r3,176(0xb0) ++ 0x29c2e07c, // 0x60: st.d $r28,$r3,184(0xb8) ++ 0x29c3007d, // 0x64: st.d $r29,$r3,192(0xc0) ++ 0x29c3207e, // 0x68: st.d $r30,$r3,200(0xc8) ++ 0x29c3407f, // 0x6c: st.d $r31,$r3,208(0xd0) ++ 0x29c36061, // 0x70: st.d $r1,$r3,216(0xd8) ++ // JIT re-entry ctx addr. ++ 0x00000000, // 0x74: lu12i.w $a0,hi(ctx) ++ 0x00000000, // 0x78: ori $a0,$a0,lo(ctx) ++ 0x00000000, // 0x7c: lu32i.d $a0,higher(ctx) ++ 0x00000000, // 0x80: lu52i.d $a0,$a0,highest(ctx) ++ ++ 0x00150025, // 0x84: move $r5,$r1 ++ 0x02ffa0a5, // 0x88: addi.d $r5,$r5,-24(0xfe8) ++ ++ // JIT re-entry fn addr: ++ 0x00000000, // 0x8c: lu12i.w $t0,hi(reentry) ++ 0x00000000, // 0x90: ori $t0,$t0,lo(reentry) ++ 0x00000000, // 0x94: lu32i.d $t0,higher(reentry) ++ 0x00000000, // 0x98: lu52i.d $t0,$t0,highest(reentry) ++ 0x4c0002a1, // 0x9c: jirl $r1,$r21,0 ++ 0x00150095, // 0xa0: move $r21,$r4 ++ 0x28c36061, // 0xa4: ld.d $r1,$r3,216(0xd8) ++ 0x28c3407f, // 0xa8: ld.d $r31,$r3,208(0xd0) ++ 0x28c3207e, // 0xac: ld.d $r30,$r3,200(0xc8) ++ 0x28c3007d, // 0xb0: ld.d $r29,$r3,192(0xc0) ++ 0x28c2e07c, // 0xb4: ld.d $r28,$r3,184(0xb8) ++ 0x28c2c07b, // 0xb8: ld.d $r27,$r3,176(0xb0) ++ 0x28c2a07a, // 0xbc: ld.d $r26,$r3,168(0xa8) ++ 0x28c28079, // 0xc0: ld.d $r25,$r3,160(0xa0) ++ 0x28c26078, // 0xc4: ld.d $r24,$r3,152(0x98) ++ 0x28c24077, // 0xc8: ld.d $r23,$r3,144(0x90) ++ 0x28c22076, // 0xcc: ld.d $r22,$r3,136(0x88) ++ 0x28c20074, // 0xd0: ld.d $r20,$r3,128(0x80) ++ 0x28c1e073, // 0xd4: ld.d $r19,$r3,120(0x78) ++ 0x28c1c072, // 0xd8: ld.d $r18,$r3,112(0x70) ++ 0x28c1a071, // 0xdc: ld.d $r17,$r3,104(0x68) ++ 0x28c18070, // 0xe0: ld.d $r16,$r3,96(0x60) ++ 0x28c1606f, // 0xe4: ld.d $r15,$r3,88(0x58) ++ 0x28c1406e, // 0xe8: ld.d $r14,$r3,80(0x50) ++ 0x28c1206d, // 0xec: ld.d $r13,$r3,72(0x48) ++ 0x28c1006c, // 0xf0: ld.d $r12,$r3,64(0x40) ++ 0x28c0e06b, // 0xf4: ld.d $r11,$r3,56(0x38) ++ 0x28c0c06a, // 0xf8: ld.d $r10,$r3,48(0x30) ++ 0x28c0a069, // 0xfc: ld.d $r9,$r3,40(0x28) ++ 0x28c08068, // 0x100: ld.d $r8,$r3,32(0x20) ++ 0x28c06067, // 0x104: ld.d $r7,$r3,24(0x18) ++ 0x28c04066, // 0x108: ld.d $r6,$r3,16(0x10) ++ 0x28c02065, // 0x10c: ld.d $r5,$r3,8(0x8) ++ 0x28c00064, // 0x110: ld.d $r4,$r3,0 ++ 0x02c38063, // 0x114: addi.d $r3,$r3,224(0xe0) ++ 0x00150281, // 0x118: move $r1,$r20 ++ 0x4c0002a0, // 0x11c: jirl $r0,$r21,0 ++ }; ++ ++ const unsigned ReentryFnAddrOffset = 0x8c; // JIT re-entry fn addr lu12i.w ++ const unsigned ReentryCtxAddrOffset = 0x74; // JIT re-entry ctx addr lu12i.w ++ ++ memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode)); ++ ++ uint32_t ReentryCtxLU12i = 0x14000004 | ((ReentryCtxAddr << 32 >> 44) << 5); ++ uint32_t ReentryCtxORi = 0x03800084 | ((ReentryCtxAddr & 0xFFF) << 10); ++ uint32_t ReentryCtxLU32i = 0x16000004 | ((ReentryCtxAddr << 12 >> 44) << 5); ++ uint32_t ReentryCtxLU52i = 0x03000084 | ((ReentryCtxAddr >> 52) << 10); ++ ++ memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLU12i, ++ sizeof(ReentryCtxLU12i)); ++ memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 4), &ReentryCtxORi, ++ sizeof(ReentryCtxORi)); ++ memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 8), &ReentryCtxLU32i, ++ sizeof(ReentryCtxLU32i)); ++ memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 12), &ReentryCtxLU52i, ++ sizeof(ReentryCtxLU52i)); ++ ++ uint32_t ReentryLU12i = 0x14000015 | ((ReentryFnAddr << 32 >> 44) << 5); ++ uint32_t ReentryORi = 0x038002b5 | ((ReentryFnAddr & 0xFFF) << 10); ++ uint32_t ReentryLU32i = 0x16000015 | ((ReentryFnAddr << 12 >> 44) << 5); ++ uint32_t ReentryLU52i = 0x030002b5 | ((ReentryFnAddr >> 52) << 10); ++ ++ memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryLU12i, ++ sizeof(ReentryLU12i)); ++ memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 4), &ReentryORi, ++ sizeof(ReentryORi)); ++ memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 8), &ReentryLU32i, ++ sizeof(ReentryLU32i)); ++ memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 12), &ReentryLU52i, ++ sizeof(ReentryLU52i)); ++} ++ ++void OrcLoongArch64::writeTrampolines( ++ char *TrampolineBlockWorkingMem, ++ JITTargetAddress TrampolineBlockTargetAddress, ++ JITTargetAddress ResolverFnAddr, unsigned NumTrampolines) { ++ ++ uint32_t *Trampolines = ++ reinterpret_cast(TrampolineBlockWorkingMem); ++ ++ uint64_t HiBits = ((ResolverFnAddr << 32 >> 44) << 5); ++ uint64_t LoBits = ((ResolverFnAddr & 0xFFF) << 10); ++ uint64_t HigherBits = ((ResolverFnAddr << 12 >> 44) << 5); ++ uint64_t HighestBits = ((ResolverFnAddr >> 52) << 10); ++ ++ for (unsigned I = 0; I < NumTrampolines; ++I) { ++ Trampolines[10 * I + 0] = 0x00150034; // move $t8,$ra ++ Trampolines[10 * I + 1] = ++ 0x14000015 | HiBits; // lu12i.w $r21,hi(ResolveAddr) ++ Trampolines[10 * I + 2] = ++ 0x038002b5 | LoBits; // ori $r21,$r21,lo(ResolveAddr) ++ Trampolines[10 * I + 3] = ++ 0x16000015 | HigherBits; // lu32i $r21,higher(ResolveAddr) ++ Trampolines[10 * I + 4] = ++ 0x030002b5 | HighestBits; // lu52i $r21,$r21,highest(ResolveAddr) ++ Trampolines[10 * I + 5] = 0x4c0002a1; // jirl $ra, $r21, 0 ++ } ++} ++ ++void OrcLoongArch64::writeIndirectStubsBlock( ++ char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, ++ JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) { ++ // Stub format is: ++ // ++ // .section __orc_stubs ++ // stub1: ++ // lu12i.w $r21, %abs(ptr1)<<32>>44 ++ // ori $r21, $r21, %abs(ptr1)&0xfff ++ // lu32i.d $r21, %abs(ptr1)<<12>>44 ++ // lu52i.d $r21, $r21, %abs(ptr1)>>52 ++ // ld.d $r21, $r21, 0 ++ // jirl $r0, $r21, 0 ++ // stub2: ++ // lu12i.w $r21, %abs(ptr2)<<32>>44 ++ // ori $r21, $r21, %abs(ptr2)&0xfff ++ // lu32i.d $r21, %abs(ptr2)<<12>>44 ++ // lu52i.d $r21, $r21, %abs(ptr2)>>52 ++ // ld.d $r21, $r21, 0 ++ // jirl $r0, $r21, 0 ++ // ++ // ... ++ // ++ // .section __orc_ptrs ++ // ptr1: ++ // .dword 0x0 ++ // ptr2: ++ // .dword 0x0 ++ // ++ // ... ++ ++ assert(stubAndPointerRangesOk( ++ StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) && ++ "PointersBlock is out of range"); ++ ++ // Populate the stubs page stubs and mark it executable. ++ uint32_t *Stub = reinterpret_cast(StubsBlockWorkingMem); ++ uint64_t PtrAddr = PointersBlockTargetAddress; ++ ++ for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 8) { ++ uint64_t HiBits = ((PtrAddr << 32 >> 44) << 5); ++ uint64_t LoBits = ((PtrAddr & 0xFFF) << 10); ++ uint64_t HigherBits = ((PtrAddr << 12 >> 44) << 5); ++ uint64_t HighestBits = ((PtrAddr >> 52) << 10); ++ Stub[8 * I + 0] = 0x14000015 | HiBits; // lu12i.w $r21, hi(PtrAddr) ++ Stub[8 * I + 1] = 0x038002b5 | LoBits; // ori $r21, $r21, lo(PtrAddr) ++ Stub[8 * I + 2] = 0x16000015 | HigherBits; // lu32i.d $r21, higher(PtrAddr) ++ Stub[8 * I + 3] = ++ 0x030002b5 | HighestBits; // lu52i.d $r21, $r21, highest(PtrAddr) ++ Stub[8 * I + 4] = 0x28c002b5; // ld.d $r21, $r21, 0 ++ Stub[8 * I + 5] = 0x4c0002a0; // jirl $r0, $r21, 0 ++ } ++} ++ + } // End namespace orc. + } // End namespace llvm. +diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +index efe0b9cd6..9cd7e79a6 100644 +--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp ++++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +@@ -606,6 +606,191 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, + } + } + ++void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section, ++ uint64_t Offset, ++ uint64_t Value, uint32_t Type, ++ int64_t Addend) { ++ uint32_t *TargetPtr = ++ reinterpret_cast(Section.getAddressWithOffset(Offset)); ++ uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); ++ uint64_t tmp1, tmp2, tmp3; ++ ++ LLVM_DEBUG(dbgs() << "[XXX] resolveLoongArch64Relocation, LocalAddress: 0x" ++ << format("%llx", Section.getAddressWithOffset(Offset)) ++ << " FinalAddress: 0x" << format("%llx", FinalAddress) ++ << " Value: 0x" << format("%llx", Value) << " Type: 0x" ++ << format("%x", Type) << " Addend: 0x" ++ << format("%llx", Addend) << "\n"); ++ ++ switch (Type) { ++ case ELF::R_LARCH_SOP_PUSH_GPREL: ++ case ELF::R_LARCH_SOP_PUSH_TLS_TPREL: ++ case ELF::R_LARCH_SOP_PUSH_TLS_GOT: ++ case ELF::R_LARCH_SOP_PUSH_TLS_GD: ++ default: ++ llvm_unreachable("Relocation type not implemented yet!"); ++ break; ++ case ELF::R_LARCH_MARK_LA: ++ // mark la ++ MarkLA = true; ++ break; ++ case ELF::R_LARCH_SOP_PUSH_ABSOLUTE: ++ if (MarkLA && !Addend) ++ // push(value) ++ ValuesStack.push_back(Value); ++ else ++ // push(addend) ++ ValuesStack.push_back(Addend); ++ break; ++ case ELF::R_LARCH_SOP_PUSH_PLT_PCREL: ++ case ELF::R_LARCH_SOP_PUSH_PCREL: ++ MarkLA = false; ++ // push(value -pc + addend) ++ ValuesStack.push_back(Value - FinalAddress + Addend); ++ break; ++ case ELF::R_LARCH_SOP_NOT: ++ // pop(tmp1) ++ // push(!tmp1) ++ tmp1 = ValuesStack.pop_back_val(); ++ ValuesStack.push_back(!tmp1); ++ break; ++ case ELF::R_LARCH_SOP_AND: ++ // pop(tmp2) ++ // pop(tmp1) ++ // push(tmp1 & tmp2) ++ tmp2 = ValuesStack.pop_back_val(); ++ tmp1 = ValuesStack.pop_back_val(); ++ ValuesStack.push_back(tmp1 & tmp2); ++ break; ++ case ELF::R_LARCH_SOP_IF_ELSE: ++ // pop(tmp3) ++ // pop(tmp2) ++ // pop(tmp1) ++ // push(tmp1 ? tmp2 : tmp3) ++ tmp3 = ValuesStack.pop_back_val(); ++ tmp2 = ValuesStack.pop_back_val(); ++ tmp1 = ValuesStack.pop_back_val(); ++ ValuesStack.push_back(tmp1 ? tmp2 : tmp3); ++ break; ++ case ELF::R_LARCH_SOP_ADD: ++ // pop(tmp2) ++ // pop(tmp1) ++ // push(tmp1 + tmp2) ++ tmp2 = ValuesStack.pop_back_val(); ++ tmp1 = ValuesStack.pop_back_val(); ++ ValuesStack.push_back(tmp1 + tmp2); ++ break; ++ case ELF::R_LARCH_SOP_SUB: ++ // pop(tmp2) ++ // pop(tmp1) ++ // push(tmp1 - tmp2) ++ tmp2 = ValuesStack.pop_back_val(); ++ tmp1 = ValuesStack.pop_back_val(); ++ ValuesStack.push_back(tmp1 - tmp2); ++ break; ++ case ELF::R_LARCH_SOP_SR: ++ // pop(tmp2) ++ // pop(tmp1) ++ // push(tmp1 >> tmp2) ++ tmp2 = ValuesStack.pop_back_val(); ++ tmp1 = ValuesStack.pop_back_val(); ++ ValuesStack.push_back(tmp1 >> tmp2); ++ break; ++ case ELF::R_LARCH_SOP_SL: ++ // pop(tmp2) ++ // pop(tmp1) ++ // push(tmp1 << tmp2) ++ tmp2 = ValuesStack.pop_back_val(); ++ tmp1 = ValuesStack.pop_back_val(); ++ ValuesStack.push_back(tmp1 << tmp2); ++ break; ++ case ELF::R_LARCH_32: ++ support::ulittle32_t::ref{TargetPtr} = ++ static_cast(Value + Addend); ++ break; ++ case ELF::R_LARCH_64: ++ support::ulittle64_t::ref{TargetPtr} = Value + Addend; ++ break; ++ case ELF::R_LARCH_SOP_POP_32_U_10_12: ++ case ELF::R_LARCH_SOP_POP_32_S_10_12: ++ // pop(tmp1) ++ // get(inst) ++ // inst=(inst & 0xffc003ff)|((tmp1 & 0xfff) << 10) ++ // write(inst) ++ tmp1 = ValuesStack.pop_back_val(); ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} & 0xffc003ff) | ++ static_cast((tmp1 & 0xfff) << 10); ++ break; ++ case ELF::R_LARCH_SOP_POP_32_S_5_20: ++ // pop(tmp1) ++ // get(inst) ++ // inst=(inst & 0xfe00001f)|((tmp1 & 0xfffff) << 5) ++ // write(inst) ++ tmp1 = ValuesStack.pop_back_val(); ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} & 0xfe00001f) | ++ static_cast((tmp1 & 0xfffff) << 5); ++ break; ++ case ELF::R_LARCH_SOP_POP_32_S_10_16_S2: ++ // pop(tmp1) ++ // tmp1 >>=2 ++ // get(inst) ++ // inst=(inst & 0xfc0003ff)|((tmp1 & 0xffff) << 10) ++ // write(inst) ++ tmp1 = ValuesStack.pop_back_val(); ++ tmp1 >>= 2; ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} & 0xfc0003ff) | ++ static_cast((tmp1 & 0xffff) << 10); ++ break; ++ case ELF::R_LARCH_SOP_POP_32_S_0_5_10_16_S2: ++ // pop(tmp1) ++ // tmp1 >>= 2 ++ // get(inst) ++ // inst=(inst & 0xfc0003e0)|((tmp1 & 0xffff) << 10)|((tmp1 & 0x1f0000) >> ++ // 16) write(inst) ++ tmp1 = ValuesStack.pop_back_val(); ++ tmp1 >>= 2; ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} & 0xfc0003e0) | ++ static_cast((tmp1 & 0xffff) << 10) | ++ static_cast((tmp1 & 0x1f0000) >> 16); ++ break; ++ case ELF::R_LARCH_SOP_POP_32_S_0_10_10_16_S2: ++ // pop(tmp1) ++ // tmp1 >>= 2 ++ // get(inst) ++ // inst=(inst & 0xfc000000)|((tmp1 & 0xffff) << 10)|((tmp1 & 0x3ff0000) >> ++ // 16) write(inst) ++ tmp1 = ValuesStack.pop_back_val(); ++ tmp1 >>= 2; ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} & 0xfc000000) | ++ static_cast((tmp1 & 0xffff) << 10) | ++ static_cast((tmp1 & 0x3ff0000) >> 16); ++ break; ++ case ELF::R_LARCH_ADD32: ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} + ++ static_cast(Value + Addend)); ++ break; ++ case ELF::R_LARCH_SUB32: ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} - ++ static_cast(Value + Addend)); ++ break; ++ case ELF::R_LARCH_ADD64: ++ support::ulittle64_t::ref{TargetPtr} = ++ (support::ulittle64_t::ref{TargetPtr} + Value + Addend); ++ break; ++ case ELF::R_LARCH_SUB64: ++ support::ulittle64_t::ref{TargetPtr} = ++ (support::ulittle64_t::ref{TargetPtr} - Value - Addend); ++ break; ++ } ++} ++ + void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) { + if (Arch == Triple::UnknownArch || + !StringRef(Triple::getArchTypePrefix(Arch)).equals("mips")) { +@@ -1022,6 +1207,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, + resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, + (uint32_t)(Addend & 0xffffffffL)); + break; ++ case Triple::loongarch64: ++ resolveLoongArch64Relocation(Section, Offset, Value, Type, Addend); ++ break; + case Triple::ppc: // Fall through. + case Triple::ppcle: + resolvePPC32Relocation(Section, Offset, Value, Type, Addend); +@@ -1336,6 +1524,25 @@ RuntimeDyldELF::processRelocationRef( + } + processSimpleRelocation(SectionID, Offset, RelType, Value); + } ++ } else if (Arch == Triple::loongarch64) { ++ RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(TargetName); ++ if (!TargetName.empty()) { ++ if (Loc == GlobalSymbolTable.end()) { ++ IsSaved = true; ++ SavedSymbol = TargetName; ++ } else { ++ IsSaved = false; ++ } ++ } ++ if (IsSaved == true) { ++ Value.SymbolName = SavedSymbol.data(); ++ processSimpleRelocation(SectionID, Offset, RelType, Value); ++ } else { ++ uint8_t *TargetAddr = getSymbolLocalAddress(TargetName); ++ resolveRelocation(Sections[SectionID], Offset, ++ reinterpret_cast(TargetAddr), RelType, ++ Addend); ++ } + } else if (IsMipsO32ABI) { + uint8_t *Placeholder = reinterpret_cast( + computePlaceholderAddress(SectionID, Offset)); +@@ -1849,6 +2056,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() { + case Triple::x86_64: + case Triple::aarch64: + case Triple::aarch64_be: ++ case Triple::loongarch64: + case Triple::ppc64: + case Triple::ppc64le: + case Triple::systemz: +diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +index 31892b746..24578190f 100644 +--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h ++++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +@@ -48,6 +48,10 @@ class RuntimeDyldELF : public RuntimeDyldImpl { + void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset, + uint32_t Value, uint32_t Type, int32_t Addend); + ++ void resolveLoongArch64Relocation(const SectionEntry &Section, ++ uint64_t Offset, uint64_t Value, ++ uint32_t Type, int64_t Addend); ++ + void resolvePPC32Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend); + +@@ -155,6 +159,12 @@ private: + // EH frame sections with the memory manager. + SmallVector UnregisteredEHFrameSections; + ++ // For loongarch evaluteRelocation ++ SmallVector ValuesStack; ++ bool IsSaved; ++ bool MarkLA; ++ StringRef SavedSymbol; ++ + // Map between GOT relocation value and corresponding GOT offset + std::map GOTOffsetMap; + +diff --git a/llvm/lib/Target/LoongArch/LoongArch.td b/llvm/lib/Target/LoongArch/LoongArch.td +index 100b37a5d..167985f44 100644 +--- a/llvm/lib/Target/LoongArch/LoongArch.td ++++ b/llvm/lib/Target/LoongArch/LoongArch.td +@@ -64,6 +64,9 @@ def FeatureLSX : SubtargetFeature<"lsx", "HasLSX", "true", "Support LSX">; + + def FeatureLASX : SubtargetFeature<"lasx", "HasLASX", "true", "Support LASX", [FeatureLSX]>; + ++def FeatureUnalignedAccess ++ : SubtargetFeature<"unaligned-access", "UnalignedAccess", "true", ++ "Allow all unaligned memory access">; + //===----------------------------------------------------------------------===// + // Register File, Calling Conv, Instruction Descriptions + //===----------------------------------------------------------------------===// +@@ -78,7 +81,8 @@ def LoongArchInstrInfo : InstrInfo; + // LoongArch processors supported. + //===----------------------------------------------------------------------===// + +-def : ProcessorModel<"la464", NoSchedModel, [Feature64Bit]>; ++def : ProcessorModel<"la464", NoSchedModel, ++ [Feature64Bit, FeatureUnalignedAccess]>; + + def LoongArchAsmParser : AsmParser { + let ShouldEmitMatchRegisterName = 0; +diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp +index 3624fdf20..0f33e1db6 100644 +--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp ++++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudo.cpp +@@ -61,6 +61,13 @@ namespace { + bool expandAtomicBinOp(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI, unsigned Size); ++ bool expandXINSERT_BOp(MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ bool expandINSERT_HOp(MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); ++ bool expandXINSERT_FWOp(MachineBasicBlock &BB, ++ MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI); + bool expandAtomicBinOpSubword(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI); +@@ -303,6 +310,1282 @@ bool LoongArchExpandPseudo::expandAtomicCmpSwap(MachineBasicBlock &BB, + return true; + } + ++bool LoongArchExpandPseudo::expandXINSERT_FWOp( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ ++ unsigned isGP64 = 0; ++ switch (I->getOpcode()) { ++ case LoongArch::XINSERT_FW_VIDX64_PSEUDO_POSTRA: ++ isGP64 = 1; ++ break; ++ case LoongArch::XINSERT_FW_VIDX_PSEUDO_POSTRA: ++ break; ++ default: ++ llvm_unreachable("Unknown subword vector pseudo for expansion!"); ++ } ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned SrcVecReg = I->getOperand(1).getReg(); ++ unsigned LaneReg = I->getOperand(2).getReg(); ++ unsigned SrcValReg = I->getOperand(3).getReg(); ++ ++ unsigned Dsttmp = I->getOperand(4).getReg(); ++ unsigned RI = I->getOperand(5).getReg(); ++ unsigned RJ = I->getOperand(6).getReg(); ++ Dsttmp = SrcVecReg; ++ ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *blocks[11]; ++ MachineFunction::iterator It = ++BB.getIterator(); ++ for (int i = 0; i < 11; i++) { ++ blocks[i] = MF->CreateMachineBasicBlock(LLVM_BB); ++ MF->insert(It, blocks[i]); ++ } ++ ++ MachineBasicBlock *mainMBB = blocks[0]; ++ MachineBasicBlock *FirstMBB = blocks[1]; ++ MachineBasicBlock *sinkMBB = blocks[9]; ++ MachineBasicBlock *exitMBB = blocks[10]; ++ ++ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ BB.addSuccessor(mainMBB, BranchProbability::getOne()); ++ for (int i = 1; i < 9; i++) { ++ mainMBB->addSuccessor(blocks[i]); ++ blocks[i]->addSuccessor(sinkMBB); ++ } ++ ++ unsigned ADDI, BLT, ZERO; ++ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; ++ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; ++ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ ++ for (int i = 1; i < 8; i++) { ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(i); ++ BuildMI(mainMBB, DL, TII->get(BLT)) ++ .addReg(LaneReg) ++ .addReg(RI) ++ .addMBB(blocks[i + 1]); ++ } ++ ++ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(FirstMBB); ++ ++ BuildMI(FirstMBB, DL, TII->get(LoongArch::XVINSGR2VR_W), Dsttmp) ++ .addReg(SrcVecReg) ++ .addReg(RJ) ++ .addImm(7); ++ BuildMI(FirstMBB, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ for (int i = 0; i < 7; i++) { ++ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::XVINSGR2VR_W), Dsttmp) ++ .addReg(SrcVecReg) ++ .addReg(RJ) ++ .addImm(i); ++ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ } ++ ++ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::XVORI_B), Dest) ++ .addReg(Dsttmp) ++ .addImm(0); ++ ++ LivePhysRegs LiveRegs; ++ for (int i = 0; i < 11; i++) { ++ computeAndAddLiveIns(LiveRegs, *blocks[i]); ++ } ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandINSERT_HOp( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ ++ unsigned isGP64 = 0; ++ switch (I->getOpcode()) { ++ case LoongArch::INSERT_H_VIDX64_PSEUDO_POSTRA: ++ isGP64 = 1; ++ break; ++ default: ++ llvm_unreachable("Unknown subword vector pseudo for expansion!"); ++ } ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned SrcVecReg = I->getOperand(1).getReg(); ++ unsigned LaneReg = I->getOperand(2).getReg(); ++ unsigned SrcValReg = I->getOperand(3).getReg(); ++ ++ unsigned Dsttmp = I->getOperand(4).getReg(); ++ unsigned RI = I->getOperand(5).getReg(); ++ Dsttmp = SrcVecReg; ++ ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *blocks[11]; ++ MachineFunction::iterator It = ++BB.getIterator(); ++ for (int i = 0; i < 11; i++) { ++ blocks[i] = MF->CreateMachineBasicBlock(LLVM_BB); ++ MF->insert(It, blocks[i]); ++ } ++ ++ MachineBasicBlock *mainMBB = blocks[0]; ++ MachineBasicBlock *FirstMBB = blocks[1]; ++ MachineBasicBlock *sinkMBB = blocks[9]; ++ MachineBasicBlock *exitMBB = blocks[10]; ++ ++ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ BB.addSuccessor(mainMBB, BranchProbability::getOne()); ++ for (int i = 1; i < 9; i++) { ++ mainMBB->addSuccessor(blocks[i]); ++ blocks[i]->addSuccessor(sinkMBB); ++ } ++ ++ unsigned ADDI, BLT, ZERO; ++ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; ++ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; ++ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ ++ for (int i = 1; i < 8; i++) { ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(i); ++ BuildMI(mainMBB, DL, TII->get(BLT)) ++ .addReg(LaneReg) ++ .addReg(RI) ++ .addMBB(blocks[i + 1]); ++ } ++ ++ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(FirstMBB); ++ ++ BuildMI(FirstMBB, DL, TII->get(LoongArch::VINSGR2VR_H), Dsttmp) ++ .addReg(SrcVecReg) ++ .addReg(SrcValReg) ++ .addImm(7); ++ BuildMI(FirstMBB, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ for (int i = 0; i < 7; i++) { ++ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::VINSGR2VR_H), Dsttmp) ++ .addReg(SrcVecReg) ++ .addReg(SrcValReg) ++ .addImm(i); ++ BuildMI(blocks[i + 2], DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ } ++ ++ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::VORI_B), Dest) ++ .addReg(Dsttmp) ++ .addImm(0); ++ ++ LivePhysRegs LiveRegs; ++ for (int i = 0; i < 11; i++) { ++ computeAndAddLiveIns(LiveRegs, *blocks[i]); ++ } ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ ++ return true; ++} ++ ++bool LoongArchExpandPseudo::expandXINSERT_BOp( ++ MachineBasicBlock &BB, MachineBasicBlock::iterator I, ++ MachineBasicBlock::iterator &NMBBI) { ++ ++ MachineFunction *MF = BB.getParent(); ++ ++ DebugLoc DL = I->getDebugLoc(); ++ ++ unsigned isGP64 = 0; ++ switch (I->getOpcode()) { ++ case LoongArch::XINSERT_B_VIDX64_PSEUDO_POSTRA: ++ isGP64 = 1; ++ break; ++ case LoongArch::XINSERT_B_VIDX_PSEUDO_POSTRA: ++ break; ++ default: ++ llvm_unreachable("Unknown subword vector pseudo for expansion!"); ++ } ++ ++ unsigned Dest = I->getOperand(0).getReg(); ++ unsigned SrcVecReg = I->getOperand(1).getReg(); ++ unsigned LaneReg = I->getOperand(2).getReg(); ++ unsigned SrcValReg = I->getOperand(3).getReg(); ++ ++ unsigned R4r = I->getOperand(5).getReg(); ++ unsigned Rib = I->getOperand(6).getReg(); ++ unsigned Ris = I->getOperand(7).getReg(); ++ unsigned R7b1 = I->getOperand(8).getReg(); ++ unsigned R7b2 = I->getOperand(9).getReg(); ++ unsigned R7b3 = I->getOperand(10).getReg(); ++ unsigned R7r80_3 = I->getOperand(11).getReg(); ++ unsigned R7r80l_3 = I->getOperand(12).getReg(); ++ unsigned R7r81_3 = I->getOperand(13).getReg(); ++ unsigned R7r81l_3 = I->getOperand(14).getReg(); ++ unsigned R7r82_3 = I->getOperand(15).getReg(); ++ unsigned R7r82l_3 = I->getOperand(16).getReg(); ++ unsigned RI = I->getOperand(17).getReg(); ++ unsigned tmp_Dst73 = I->getOperand(18).getReg(); ++ unsigned Rimm = I->getOperand(19).getReg(); ++ unsigned R70 = I->getOperand(20).getReg(); ++ tmp_Dst73 = SrcVecReg; ++ ++ const BasicBlock *LLVM_BB = BB.getBasicBlock(); ++ MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SevenMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ZeroMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *OneMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *TwoMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *ThreeMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FourMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *FiveMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB0 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB1 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB2 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *SixMBB3 = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineFunction::iterator It = ++BB.getIterator(); ++ MF->insert(It, mainMBB); ++ MF->insert(It, SevenMBB); ++ MF->insert(It, SevenMBB3); ++ MF->insert(It, SevenMBB0); ++ MF->insert(It, SevenMBB1); ++ MF->insert(It, SevenMBB2); ++ MF->insert(It, ZeroMBB); ++ MF->insert(It, ZeroMBB3); ++ MF->insert(It, ZeroMBB0); ++ MF->insert(It, ZeroMBB1); ++ MF->insert(It, ZeroMBB2); ++ MF->insert(It, OneMBB); ++ MF->insert(It, OneMBB3); ++ MF->insert(It, OneMBB0); ++ MF->insert(It, OneMBB1); ++ MF->insert(It, OneMBB2); ++ MF->insert(It, TwoMBB); ++ MF->insert(It, TwoMBB3); ++ MF->insert(It, TwoMBB0); ++ MF->insert(It, TwoMBB1); ++ MF->insert(It, TwoMBB2); ++ MF->insert(It, ThreeMBB); ++ MF->insert(It, ThreeMBB3); ++ MF->insert(It, ThreeMBB0); ++ MF->insert(It, ThreeMBB1); ++ MF->insert(It, ThreeMBB2); ++ MF->insert(It, FourMBB); ++ MF->insert(It, FourMBB3); ++ MF->insert(It, FourMBB0); ++ MF->insert(It, FourMBB1); ++ MF->insert(It, FourMBB2); ++ MF->insert(It, FiveMBB); ++ MF->insert(It, FiveMBB3); ++ MF->insert(It, FiveMBB0); ++ MF->insert(It, FiveMBB1); ++ MF->insert(It, FiveMBB2); ++ MF->insert(It, SixMBB); ++ MF->insert(It, SixMBB3); ++ MF->insert(It, SixMBB0); ++ MF->insert(It, SixMBB1); ++ MF->insert(It, SixMBB2); ++ MF->insert(It, sinkMBB); ++ MF->insert(It, exitMBB); ++ ++ exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); ++ exitMBB->transferSuccessorsAndUpdatePHIs(&BB); ++ ++ BB.addSuccessor(mainMBB, BranchProbability::getOne()); ++ mainMBB->addSuccessor(SevenMBB); ++ mainMBB->addSuccessor(ZeroMBB); ++ mainMBB->addSuccessor(OneMBB); ++ mainMBB->addSuccessor(TwoMBB); ++ mainMBB->addSuccessor(ThreeMBB); ++ mainMBB->addSuccessor(FourMBB); ++ mainMBB->addSuccessor(FiveMBB); ++ mainMBB->addSuccessor(SixMBB); ++ SevenMBB->addSuccessor(SevenMBB0); ++ SevenMBB->addSuccessor(SevenMBB1); ++ SevenMBB->addSuccessor(SevenMBB2); ++ SevenMBB->addSuccessor(SevenMBB3); ++ SevenMBB0->addSuccessor(sinkMBB); ++ SevenMBB1->addSuccessor(sinkMBB); ++ SevenMBB2->addSuccessor(sinkMBB); ++ SevenMBB3->addSuccessor(sinkMBB); ++ ZeroMBB->addSuccessor(ZeroMBB0); ++ ZeroMBB->addSuccessor(ZeroMBB1); ++ ZeroMBB->addSuccessor(ZeroMBB2); ++ ZeroMBB->addSuccessor(ZeroMBB3); ++ ZeroMBB0->addSuccessor(sinkMBB); ++ ZeroMBB1->addSuccessor(sinkMBB); ++ ZeroMBB2->addSuccessor(sinkMBB); ++ ZeroMBB3->addSuccessor(sinkMBB); ++ OneMBB->addSuccessor(OneMBB0); ++ OneMBB->addSuccessor(OneMBB1); ++ OneMBB->addSuccessor(OneMBB2); ++ OneMBB->addSuccessor(OneMBB3); ++ OneMBB0->addSuccessor(sinkMBB); ++ OneMBB1->addSuccessor(sinkMBB); ++ OneMBB2->addSuccessor(sinkMBB); ++ OneMBB3->addSuccessor(sinkMBB); ++ TwoMBB->addSuccessor(TwoMBB0); ++ TwoMBB->addSuccessor(TwoMBB1); ++ TwoMBB->addSuccessor(TwoMBB2); ++ TwoMBB->addSuccessor(TwoMBB3); ++ TwoMBB0->addSuccessor(sinkMBB); ++ TwoMBB1->addSuccessor(sinkMBB); ++ TwoMBB2->addSuccessor(sinkMBB); ++ TwoMBB3->addSuccessor(sinkMBB); ++ ThreeMBB->addSuccessor(ThreeMBB0); ++ ThreeMBB->addSuccessor(ThreeMBB1); ++ ThreeMBB->addSuccessor(ThreeMBB2); ++ ThreeMBB->addSuccessor(ThreeMBB3); ++ ThreeMBB0->addSuccessor(sinkMBB); ++ ThreeMBB1->addSuccessor(sinkMBB); ++ ThreeMBB2->addSuccessor(sinkMBB); ++ ThreeMBB3->addSuccessor(sinkMBB); ++ FourMBB->addSuccessor(FourMBB0); ++ FourMBB->addSuccessor(FourMBB1); ++ FourMBB->addSuccessor(FourMBB2); ++ FourMBB->addSuccessor(FourMBB3); ++ FourMBB0->addSuccessor(sinkMBB); ++ FourMBB1->addSuccessor(sinkMBB); ++ FourMBB2->addSuccessor(sinkMBB); ++ FourMBB3->addSuccessor(sinkMBB); ++ FiveMBB->addSuccessor(FiveMBB0); ++ FiveMBB->addSuccessor(FiveMBB1); ++ FiveMBB->addSuccessor(FiveMBB2); ++ FiveMBB->addSuccessor(FiveMBB3); ++ FiveMBB0->addSuccessor(sinkMBB); ++ FiveMBB1->addSuccessor(sinkMBB); ++ FiveMBB2->addSuccessor(sinkMBB); ++ FiveMBB3->addSuccessor(sinkMBB); ++ SixMBB->addSuccessor(SixMBB0); ++ SixMBB->addSuccessor(SixMBB1); ++ SixMBB->addSuccessor(SixMBB2); ++ SixMBB->addSuccessor(SixMBB3); ++ SixMBB0->addSuccessor(sinkMBB); ++ SixMBB1->addSuccessor(sinkMBB); ++ SixMBB2->addSuccessor(sinkMBB); ++ SixMBB3->addSuccessor(sinkMBB); ++ ++ unsigned SRLI, ADDI, OR, MOD, BLT, ZERO; ++ SRLI = isGP64 ? LoongArch::SRLI_D : LoongArch::SRLI_W; ++ ADDI = isGP64 ? LoongArch::ADDI_D : LoongArch::ADDI_W; ++ OR = isGP64 ? LoongArch::OR : LoongArch::OR32; ++ MOD = isGP64 ? LoongArch::MOD_DU : LoongArch::MOD_WU; ++ BLT = isGP64 ? LoongArch::BLT : LoongArch::BLT32; ++ ZERO = isGP64 ? LoongArch::ZERO_64 : LoongArch::ZERO; ++ ++ BuildMI(mainMBB, DL, TII->get(SRLI), Rimm).addReg(LaneReg).addImm(2); ++ BuildMI(mainMBB, DL, TII->get(ADDI), R4r).addReg(ZERO).addImm(4); ++ BuildMI(mainMBB, DL, TII->get(OR), Rib).addReg(Rimm).addReg(ZERO); ++ BuildMI(mainMBB, DL, TII->get(MOD), Ris).addReg(Rib).addReg(R4r); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(1); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(ZeroMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(2); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(OneMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(3); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(TwoMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(4); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(ThreeMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(5); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(FourMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(6); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(FiveMBB); ++ BuildMI(mainMBB, DL, TII->get(ADDI), RI).addReg(ZERO).addImm(7); ++ BuildMI(mainMBB, DL, TII->get(BLT)).addReg(Rib).addReg(RI).addMBB(SixMBB); ++ BuildMI(mainMBB, DL, TII->get(LoongArch::B32)).addMBB(SevenMBB); ++ ++ BuildMI(SevenMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(7); ++ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(SevenMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b1) ++ .addMBB(SevenMBB0); ++ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(SevenMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b2) ++ .addMBB(SevenMBB1); ++ BuildMI(SevenMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(SevenMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b3) ++ .addMBB(SevenMBB2); ++ BuildMI(SevenMBB, DL, TII->get(LoongArch::B32)).addMBB(SevenMBB3); ++ ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0x00fff); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(7); ++ BuildMI(SevenMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xff00f); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(7); ++ BuildMI(SevenMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xffff0); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(7); ++ BuildMI(SevenMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xfffff); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(7); ++ BuildMI(SevenMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ZeroMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(0); ++ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(ZeroMBB0); ++ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(ZeroMBB1); ++ BuildMI(ZeroMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(ZeroMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(ZeroMBB2); ++ BuildMI(ZeroMBB, DL, TII->get(LoongArch::B32)).addMBB(ZeroMBB3); ++ ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(0); ++ BuildMI(ZeroMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(0); ++ BuildMI(ZeroMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(0); ++ BuildMI(ZeroMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(0); ++ BuildMI(ZeroMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(OneMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(1); ++ BuildMI(OneMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(OneMBB0); ++ BuildMI(OneMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(OneMBB1); ++ BuildMI(OneMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(OneMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(OneMBB2); ++ BuildMI(OneMBB, DL, TII->get(LoongArch::B32)).addMBB(OneMBB3); ++ ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(1); ++ BuildMI(OneMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(1); ++ BuildMI(OneMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(1); ++ BuildMI(OneMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(1); ++ BuildMI(OneMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(TwoMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(2); ++ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(TwoMBB0); ++ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(TwoMBB1); ++ BuildMI(TwoMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(TwoMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(TwoMBB2); ++ BuildMI(TwoMBB, DL, TII->get(LoongArch::B32)).addMBB(TwoMBB3); ++ ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(2); ++ BuildMI(TwoMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(2); ++ BuildMI(TwoMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(2); ++ BuildMI(TwoMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(2); ++ BuildMI(TwoMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ThreeMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(3); ++ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(ThreeMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b1) ++ .addMBB(ThreeMBB0); ++ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(ThreeMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b2) ++ .addMBB(ThreeMBB1); ++ BuildMI(ThreeMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(ThreeMBB, DL, TII->get(BLT)) ++ .addReg(Ris) ++ .addReg(R7b3) ++ .addMBB(ThreeMBB2); ++ BuildMI(ThreeMBB, DL, TII->get(LoongArch::B32)).addMBB(ThreeMBB3); ++ ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0x00fff); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(3); ++ BuildMI(ThreeMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xff00f); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(3); ++ BuildMI(ThreeMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xffff0); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(3); ++ BuildMI(ThreeMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3) ++ .addImm(0xfffff); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(3); ++ BuildMI(ThreeMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FourMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(4); ++ BuildMI(FourMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(FourMBB0); ++ BuildMI(FourMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(FourMBB1); ++ BuildMI(FourMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(FourMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(FourMBB2); ++ BuildMI(FourMBB, DL, TII->get(LoongArch::B32)).addMBB(FourMBB3); ++ ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(4); ++ BuildMI(FourMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(4); ++ BuildMI(FourMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(4); ++ BuildMI(FourMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(4); ++ BuildMI(FourMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FiveMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(5); ++ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(FiveMBB0); ++ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(FiveMBB1); ++ BuildMI(FiveMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(FiveMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(FiveMBB2); ++ BuildMI(FiveMBB, DL, TII->get(LoongArch::B32)).addMBB(FiveMBB3); ++ ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(5); ++ BuildMI(FiveMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(5); ++ BuildMI(FiveMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(5); ++ BuildMI(FiveMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(5); ++ BuildMI(FiveMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SixMBB, DL, TII->get(LoongArch::XVPICKVE2GR_W), R70) ++ .addReg(SrcVecReg) ++ .addImm(6); ++ BuildMI(SixMBB, DL, TII->get(ADDI), R7b1).addReg(ZERO).addImm(1); ++ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b1).addMBB(SixMBB0); ++ BuildMI(SixMBB, DL, TII->get(ADDI), R7b2).addReg(ZERO).addImm(2); ++ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b2).addMBB(SixMBB1); ++ BuildMI(SixMBB, DL, TII->get(ADDI), R7b3).addReg(ZERO).addImm(3); ++ BuildMI(SixMBB, DL, TII->get(BLT)).addReg(Ris).addReg(R7b3).addMBB(SixMBB2); ++ BuildMI(SixMBB, DL, TII->get(LoongArch::B32)).addMBB(SixMBB3); ++ ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0x00fff); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80_3); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(6); ++ BuildMI(SixMBB3, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(8); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xff00f); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xfff); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(6); ++ BuildMI(SixMBB0, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(16); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xffff0); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0x0ff); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(6); ++ BuildMI(SixMBB1, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::SLLI_W), R7r80_3) ++ .addReg(SrcValReg) ++ .addImm(24); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::SRLI_W), R7r80l_3) ++ .addReg(R7r80_3) ++ .addImm(24); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::LU12I_W), R7r81l_3).addImm(0xfffff); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::ORI32), R7r81_3) ++ .addReg(R7r81l_3) ++ .addImm(0xf00); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::AND32), R7r82l_3) ++ .addReg(R70) ++ .addReg(R7r81_3); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::OR32), R7r82_3) ++ .addReg(R7r82l_3) ++ .addReg(R7r80l_3); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::XVINSGR2VR_W), tmp_Dst73) ++ .addReg(SrcVecReg) ++ .addReg(R7r82_3) ++ .addImm(6); ++ BuildMI(SixMBB2, DL, TII->get(LoongArch::B32)).addMBB(sinkMBB); ++ ++ sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); ++ ++ BuildMI(sinkMBB, DL, TII->get(LoongArch::XVORI_B), Dest) ++ .addReg(tmp_Dst73) ++ .addImm(0); ++ ++ LivePhysRegs LiveRegs; ++ computeAndAddLiveIns(LiveRegs, *mainMBB); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB0); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB1); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB2); ++ computeAndAddLiveIns(LiveRegs, *SevenMBB3); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB0); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB1); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB2); ++ computeAndAddLiveIns(LiveRegs, *ZeroMBB3); ++ computeAndAddLiveIns(LiveRegs, *OneMBB); ++ computeAndAddLiveIns(LiveRegs, *OneMBB0); ++ computeAndAddLiveIns(LiveRegs, *OneMBB1); ++ computeAndAddLiveIns(LiveRegs, *OneMBB2); ++ computeAndAddLiveIns(LiveRegs, *OneMBB3); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB0); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB1); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB2); ++ computeAndAddLiveIns(LiveRegs, *TwoMBB3); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB0); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB1); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB2); ++ computeAndAddLiveIns(LiveRegs, *ThreeMBB3); ++ computeAndAddLiveIns(LiveRegs, *FourMBB); ++ computeAndAddLiveIns(LiveRegs, *FourMBB0); ++ computeAndAddLiveIns(LiveRegs, *FourMBB1); ++ computeAndAddLiveIns(LiveRegs, *FourMBB2); ++ computeAndAddLiveIns(LiveRegs, *FourMBB3); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB0); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB1); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB2); ++ computeAndAddLiveIns(LiveRegs, *FiveMBB3); ++ computeAndAddLiveIns(LiveRegs, *SixMBB); ++ computeAndAddLiveIns(LiveRegs, *SixMBB0); ++ computeAndAddLiveIns(LiveRegs, *SixMBB1); ++ computeAndAddLiveIns(LiveRegs, *SixMBB2); ++ computeAndAddLiveIns(LiveRegs, *SixMBB3); ++ computeAndAddLiveIns(LiveRegs, *sinkMBB); ++ computeAndAddLiveIns(LiveRegs, *exitMBB); ++ ++ NMBBI = BB.end(); ++ I->eraseFromParent(); ++ ++ return true; ++} ++ + bool LoongArchExpandPseudo::expandAtomicBinOpSubword( + MachineBasicBlock &BB, MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI) { +@@ -695,6 +1978,7 @@ bool LoongArchExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, + bool LoongArchExpandPseudo::expandLoadAddr(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI) { ++ MachineFunction *MF = BB.getParent(); + MachineInstr &MI = *I; + DebugLoc DL = MI.getDebugLoc(); + +@@ -702,6 +1986,7 @@ bool LoongArchExpandPseudo::expandLoadAddr(MachineBasicBlock &BB, + unsigned DestReg = MI.getOperand(0).getReg(); + unsigned TmpReg; + const MachineOperand &MO = MI.getOperand(1); ++ Reloc::Model RM = MF->getTarget().getRelocationModel(); + + MachineInstrBuilder MIB1, MIB2, MIB3, MIB4, MIB5; + unsigned HiFlag, LoFlag, HigherFlag, HighestFlag; +@@ -715,10 +2000,22 @@ bool LoongArchExpandPseudo::expandLoadAddr(MachineBasicBlock &BB, + + switch (Op) { + case LoongArch::LoadAddrLocal: +- // pcaddu12i + addi.d +- LoFlag = LoongArchII::MO_PCREL_LO; +- HiFlag = LoongArchII::MO_PCREL_HI; +- LoOp = LoongArch::ADDI_D_rri; ++ if (RM == Reloc::Static) { // for jit ++ HiFlag = LoongArchII::MO_ABS_HI; ++ LoFlag = LoongArchII::MO_ABS_LO; ++ HigherFlag = LoongArchII::MO_ABS_HIGHER; ++ HighestFlag = LoongArchII::MO_ABS_HIGHEST; ++ // lu12i.w + ori + lu32i.d + lu52i.d ++ HiOp = LoongArch::LU12I_W; ++ LoOp = LoongArch::ORI; ++ HigherOp = LoongArch::LU32I_D; ++ HighestOp = LoongArch::LU52I_D; ++ } else { ++ // pcaddu12i + addi.d ++ LoFlag = LoongArchII::MO_PCREL_LO; ++ HiFlag = LoongArchII::MO_PCREL_HI; ++ LoOp = LoongArch::ADDI_D_rri; ++ } + break; + case LoongArch::LoadAddrLocalRR: + // pcaddu12i + ori + lu32i.d + lu52i.d + add.d +@@ -809,7 +2106,31 @@ bool LoongArchExpandPseudo::expandLoadAddr(MachineBasicBlock &BB, + MIB1 = BuildMI(BB, I, DL, TII->get(HiOp), DestReg); + + switch (Op) { +- case LoongArch::LoadAddrLocal: // la.local rd, symbol ++ case LoongArch::LoadAddrLocal: ++ if (RM == Reloc::Static) { // for jit ++ // la.abs rd, symbol ++ MIB2 = BuildMI(BB, I, DL, TII->get(LoOp), DestReg).addReg(DestReg); ++ MIB3 = BuildMI(BB, I, DL, TII->get(HigherOp), DestReg); ++ MIB4 = BuildMI(BB, I, DL, TII->get(HighestOp), DestReg).addReg(DestReg); ++ if (MO.isJTI()) { ++ MIB1.addJumpTableIndex(MO.getIndex(), HiFlag); ++ MIB2.addJumpTableIndex(MO.getIndex(), LoFlag); ++ MIB3.addJumpTableIndex(MO.getIndex(), HigherFlag); ++ MIB4.addJumpTableIndex(MO.getIndex(), HighestFlag); ++ } else if (MO.isBlockAddress()) { ++ MIB1.addBlockAddress(MO.getBlockAddress(), 0, HiFlag); ++ MIB2.addBlockAddress(MO.getBlockAddress(), 0, LoFlag); ++ MIB3.addBlockAddress(MO.getBlockAddress(), 0, HigherFlag); ++ MIB4.addBlockAddress(MO.getBlockAddress(), 0, HighestFlag); ++ } else { ++ MIB1.addDisp(MO, 0, HiFlag); ++ MIB2.addDisp(MO, 0, LoFlag); ++ MIB3.addDisp(MO, 0, HigherFlag); ++ MIB4.addDisp(MO, 0, HighestFlag); ++ } ++ break; ++ } ++ LLVM_FALLTHROUGH; + case LoongArch::LoadAddrGlobal: // la.global rd, symbol + case LoongArch::LoadAddrGlobal_Alias: // la rd, symbol + case LoongArch::LoadAddrTLS_IE: // la.tls.ie rd, symbol +@@ -905,7 +2226,6 @@ bool LoongArchExpandPseudo::expandLoadAddr(MachineBasicBlock &BB, + bool LoongArchExpandPseudo::expandPseudoTailCall( + MachineBasicBlock &BB, MachineBasicBlock::iterator I) { + +- MachineFunction *MF = BB.getParent(); + MachineInstr &MI = *I; + DebugLoc DL = MI.getDebugLoc(); + +@@ -959,9 +2279,8 @@ bool LoongArchExpandPseudo::expandPseudoCall(MachineBasicBlock &BB, + MIB3 = BuildMI(BB, I, DL, TII->get(LoongArch::LU32I_D), Ra); + MIB4 = BuildMI(BB, I, DL, TII->get(LoongArch::LU52I_D), Ra) + .addReg(Ra); +- MIB5 = BuildMI(BB, I, DL, TII->get(LoongArch::JIRL), Ra) +- .addReg(Ra) +- .addImm(0); ++ MIB5 = ++ BuildMI(BB, I, DL, TII->get(LoongArch::JIRL), Ra).addReg(Ra).addImm(0); + if (MO.isSymbol()) { + MIB1.addExternalSymbol(MO.getSymbolName(), HiFlag); + MIB2.addExternalSymbol(MO.getSymbolName(), LoFlag); +@@ -979,8 +2298,7 @@ bool LoongArchExpandPseudo::expandPseudoCall(MachineBasicBlock &BB, + MachineInstrBuilder MIB2; + + MIB1 = BuildMI(BB, I, DL, TII->get(LoongArch::PCADDU18I), Ra); +- MIB2 = BuildMI(BB, I, DL, TII->get(LoongArch::JIRL_CALL), Ra) +- .addReg(Ra); ++ MIB2 = BuildMI(BB, I, DL, TII->get(LoongArch::JIRL_CALL), Ra).addReg(Ra); + if (MO.isSymbol()) { + MIB1.addExternalSymbol(MO.getSymbolName(), HiFlag); + MIB2.addExternalSymbol(MO.getSymbolName(), LoFlag); +@@ -1081,6 +2399,14 @@ bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB, + case LoongArch::ATOMIC_LOAD_UMIN_I8_POSTRA: + case LoongArch::ATOMIC_LOAD_UMIN_I16_POSTRA: + return expandAtomicBinOpSubword(MBB, MBBI, NMBB); ++ case LoongArch::XINSERT_B_VIDX_PSEUDO_POSTRA: ++ case LoongArch::XINSERT_B_VIDX64_PSEUDO_POSTRA: ++ return expandXINSERT_BOp(MBB, MBBI, NMBB); ++ case LoongArch::INSERT_H_VIDX64_PSEUDO_POSTRA: ++ return expandINSERT_HOp(MBB, MBBI, NMBB); ++ case LoongArch::XINSERT_FW_VIDX_PSEUDO_POSTRA: ++ case LoongArch::XINSERT_FW_VIDX64_PSEUDO_POSTRA: ++ return expandXINSERT_FWOp(MBB, MBBI, NMBB); + case LoongArch::ATOMIC_LOAD_ADD_I32_POSTRA: + case LoongArch::ATOMIC_LOAD_SUB_I32_POSTRA: + case LoongArch::ATOMIC_LOAD_AND_I32_POSTRA: +diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +index 2d06173be..e6c01b69e 100644 +--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp ++++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +@@ -287,7 +287,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const LoongArchTargetMachine &T + setOperationAction(ISD::ConstantPool, MVT::i64, Custom); + setOperationAction(ISD::SELECT, MVT::i64, Custom); + setOperationAction(ISD::LOAD, MVT::i64, Legal); +- setOperationAction(ISD::STORE, MVT::i64, Custom); ++ setOperationAction(ISD::STORE, MVT::i64, Legal); + setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); + setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); +@@ -381,8 +381,6 @@ LoongArchTargetLowering::LoongArchTargetLowering(const LoongArchTargetMachine &T + } + + if (Subtarget.is64Bit()) { +- setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom); +- setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom); + setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom); + setTruncStoreAction(MVT::i64, MVT::i32, Custom); + } +@@ -403,8 +401,6 @@ LoongArchTargetLowering::LoongArchTargetLowering(const LoongArchTargetMachine &T + setTargetDAGCombine(ISD::MUL); + setTargetDAGCombine(ISD::SRL); + setTargetDAGCombine(ISD::SRA); +- setTargetDAGCombine(ISD::SDIV); +- setTargetDAGCombine(ISD::UDIV); + + if (ABI.IsLP32()) { + // These libcalls are not available in 32-bit. +@@ -559,7 +555,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const LoongArchTargetMachine &T + setOperationAction(ISD::UDIVREM, MVT::i32, Custom); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + setOperationAction(ISD::LOAD, MVT::i32, Legal); +- setOperationAction(ISD::STORE, MVT::i32, Custom); ++ setOperationAction(ISD::STORE, MVT::i32, Legal); + + setTargetDAGCombine(ISD::MUL); + +@@ -840,9 +836,11 @@ void LoongArchTargetLowering::addLASXFloatType(MVT::SimpleValueType Ty, + setCondCodeAction(ISD::SETGT, Ty, Expand); + } + +-bool +-LoongArchTargetLowering::allowsMisalignedMemoryAccesses( +- EVT VT, unsigned, Align, MachineMemOperand::Flags, bool *Fast) const { ++bool LoongArchTargetLowering::allowsMisalignedMemoryAccesses( ++ EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, ++ bool *Fast) const { ++ if (!Subtarget.allowUnalignedAccess()) ++ return false; + if (Fast) + *Fast = true; + return true; +@@ -2083,7 +2081,6 @@ static SDValue performZERO_EXTENDCombine(SDNode *N, SelectionDAG &DAG, + assert((N->getOpcode() == ISD::ZERO_EXTEND) && "Need ISD::ZERO_EXTEND"); + + SDLoc DL(N); +- SDValue Top = N->getOperand(0); + + SDValue Res; + if (Res = performExtend(N, DAG, DCI, Subtarget)) +@@ -2123,8 +2120,6 @@ PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { + case ISD::SUB: + case ISD::SHL: + case ISD::SRL: +- case ISD::SDIV: +- case ISD::UDIV: + return performLogicCombine(N, DAG, Subtarget); + } + return SDValue(); +@@ -4244,12 +4239,10 @@ LoongArchTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, + // after fast register allocation, the spills will end up outside of the + // blocks that their values are defined in, causing livein errors. + +- unsigned DestCopy = MRI.createVirtualRegister(MRI.getRegClass(Dest)); + unsigned PtrCopy = MRI.createVirtualRegister(MRI.getRegClass(Ptr)); + unsigned OldValCopy = MRI.createVirtualRegister(MRI.getRegClass(OldVal)); + unsigned NewValCopy = MRI.createVirtualRegister(MRI.getRegClass(NewVal)); + +- BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), DestCopy).addReg(Dest); + BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), PtrCopy).addReg(Ptr); + BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), OldValCopy).addReg(OldVal); + BuildMI(*BB, II, DL, TII->get(LoongArch::COPY), NewValCopy).addReg(NewVal); +@@ -5412,9 +5405,9 @@ SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op, + return DAG.getNode(ISD::BITCAST, SDLoc(Op), Op.getValueType(), Trunc); + } + +-static bool checkUndef(ArrayRef Mask, unsigned Lo, unsigned Hi) { ++static bool checkUndef(ArrayRef Mask, int Lo, int Hi) { + +- for (unsigned i = Lo, end = Hi; i != end; i++, Hi++) ++ for (int i = Lo, end = Hi; i != end; i++, Hi++) + if (!((Mask[i] == -1) || (Mask[i] == Hi))) + return false; + return true; +@@ -5422,17 +5415,16 @@ static bool checkUndef(ArrayRef Mask, unsigned Lo, unsigned Hi) { + + static bool CheckRev(ArrayRef Mask) { + +- unsigned Num = Mask.size() - 1; +- for (unsigned i = 0; i < Mask.size(); i++, Num--) ++ int Num = Mask.size() - 1; ++ for (long unsigned int i = 0; i < Mask.size(); i++, Num--) + if (Mask[i] != Num) + return false; + return true; + } + +-static bool checkHalf(ArrayRef Mask, unsigned Lo, unsigned Hi, +- unsigned base) { ++static bool checkHalf(ArrayRef Mask, int Lo, int Hi, int base) { + +- for (unsigned i = Lo; i < Hi; i++) ++ for (int i = Lo; i < Hi; i++) + if (Mask[i] != (base + i)) + return false; + return true; +@@ -5441,10 +5433,10 @@ static bool checkHalf(ArrayRef Mask, unsigned Lo, unsigned Hi, + static SDValue lowerHalfHalf(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, + ArrayRef Mask, SelectionDAG &DAG) { + +- unsigned Num = VT.getVectorNumElements(); +- unsigned HalfNum = Num / 2; ++ int Num = VT.getVectorNumElements(); ++ int HalfNum = Num / 2; + +- if (Op1->isUndef() || Op2->isUndef() || Mask.size() > Num) ++ if (Op1->isUndef() || Op2->isUndef() || Mask.size() > (long unsigned int)Num) + return SDValue(); + + if (checkHalf(Mask, HalfNum, Num, Num) && checkHalf(Mask, 0, HalfNum, 0)) { +@@ -5456,9 +5448,9 @@ static SDValue lowerHalfHalf(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, + return SDValue(); + } + +-static bool checkHalfUndef(ArrayRef Mask, unsigned Lo, unsigned Hi) { ++static bool checkHalfUndef(ArrayRef Mask, int Lo, int Hi) { + +- for (unsigned i = Lo; i < Hi; i++) ++ for (int i = Lo; i < Hi; i++) + if (Mask[i] != -1) + return false; + return true; +@@ -5469,13 +5461,10 @@ static bool checkHalfUndef(ArrayRef Mask, unsigned Lo, unsigned Hi) { + static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, + ArrayRef Mask, SelectionDAG &DAG) { + +- unsigned Num = VT.getVectorNumElements(); +- unsigned HalfNum = Num / 2; ++ int Num = VT.getVectorNumElements(); ++ int 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()); +@@ -5579,7 +5568,7 @@ static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, + bool useOp1[3] = {true, true, true}; + bool checkdef = true; + +- for (unsigned i = 0; i < Num; i++) { ++ for (int i = 0; i < Num; i++) { + if (def > 2) { + checkdef = false; + break; +@@ -5600,7 +5589,7 @@ static SDValue lowerHalfUndef(const SDLoc &DL, MVT VT, SDValue Op1, SDValue Op2, + if (checkdef) { + SDValue Vector = DAG.getUNDEF(VT); + EVT EltTy = VT.getVectorElementType(); +- SDValue Ext[def]; ++ SDValue Ext[2]; + + if (check1 || check2) { + for (int i = 0; i < def; i++) { +@@ -5643,13 +5632,7 @@ static SDValue lowerHalfUndef_LSX(const SDLoc &DL, EVT ResTy, MVT VT, + SDValue Op1, SDValue Op2, ArrayRef 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()); +@@ -5696,15 +5679,15 @@ static SDValue lowerVECTOR_SHUFFLE_INSVE(const SDLoc &DL, MVT VT, EVT ResTy, + ArrayRef Mask, + SelectionDAG &DAG) { + +- unsigned Num = VT.getVectorNumElements(); ++ int Num = VT.getVectorNumElements(); + if (ResTy == MVT::v16i16 || ResTy == MVT::v32i8) + return SDValue(); + +- unsigned CheckOne = 0; +- unsigned CheckOther = 0; +- unsigned Idx; ++ int CheckOne = 0; ++ int CheckOther = 0; ++ int Idx; + +- for (unsigned i = 0; i < Num; i++) { ++ for (int i = 0; i < Num; i++) { + if ((Mask[i] == i) || (Mask[i] == -1)) { + CheckOther++; + } else if (Mask[i] == Num) { +@@ -5729,7 +5712,7 @@ static SDValue lowerVECTOR_SHUFFLE_XVPICKVE(const SDLoc &DL, MVT VT, EVT ResTy, + ArrayRef Mask, + SelectionDAG &DAG) { + +- unsigned Num = VT.getVectorNumElements(); ++ int Num = VT.getVectorNumElements(); + if (ResTy == MVT::v16i16 || ResTy == MVT::v32i8 || + (!ISD::isBuildVectorAllZeros(Op1.getNode()))) + return SDValue(); +@@ -5739,7 +5722,7 @@ static SDValue lowerVECTOR_SHUFFLE_XVPICKVE(const SDLoc &DL, MVT VT, EVT ResTy, + if ((Mask[0] < Num) || (Mask[0] > (2 * Num - 1))) + CheckV = false; + +- for (unsigned i = 1; i < Num; i++) { ++ for (int i = 1; i < Num; i++) { + if (Mask[i] != 0) { + CheckV = false; + break; +@@ -5762,10 +5745,10 @@ static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, MVT VT, EVT ResTy, + SelectionDAG &DAG) { + + if (VT == MVT::v4i64) { +- unsigned Num = VT.getVectorNumElements(); ++ int Num = VT.getVectorNumElements(); + + bool CheckV = true; +- for (unsigned i = 0; i < Num; i++) { ++ for (int i = 0; i < Num; i++) { + if (Mask[i] != (i * 2)) { + CheckV = false; + break; +@@ -5883,7 +5866,6 @@ bool LoongArchTargetLowering::isEligibleForTailCallOptimization( + const CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF, + unsigned NextStackOffset, const LoongArchFunctionInfo &FI) const { + +- auto &Callee = CLI.Callee; + auto CalleeCC = CLI.CallConv; + auto IsVarArg = CLI.IsVarArg; + auto &Outs = CLI.Outs; +@@ -6925,6 +6907,17 @@ EVT LoongArchTargetLowering::getTypeForExtReturn(LLVMContext &Context, EVT VT, + return VT.bitsLT(MinVT) ? MinVT : VT; + } + ++static const TargetRegisterClass *getRegisterClassForVT(MVT VT, bool Is64Bit) { ++ // Newer llvm versions (>= 12) do not require simple VTs for constraints and ++ // they use MVT::Other for constraints with complex VTs. For more details, ++ // please see https://reviews.llvm.org/D91710. ++ if (VT == MVT::Other || VT.getSizeInBits() <= 32) ++ return &LoongArch::GPR32RegClass; ++ if (VT.getSizeInBits() <= 64) ++ return Is64Bit ? &LoongArch::GPR64RegClass : &LoongArch::GPR32RegClass; ++ return nullptr; ++} ++ + std::pair LoongArchTargetLowering:: + parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { + const TargetRegisterInfo *TRI = +@@ -6959,7 +6952,10 @@ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { + RC = TRI->getRegClass(LoongArch::FCFRRegClassID); + else { // Parse $r0-$r31. + assert(Prefix == "$r"); +- RC = getRegClassFor((VT == MVT::Other) ? MVT::i32 : VT); ++ if ((RC = getRegisterClassForVT(VT, Subtarget.is64Bit())) == nullptr) { ++ // This will generate an error message. ++ return std::make_pair(0U, nullptr); ++ } + } + + assert(Reg < RC->getNumRegs()); +@@ -7015,15 +7011,7 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo * + if (Constraint.size() == 1) { + switch (Constraint[0]) { + case 'r': +- if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) { +- return std::make_pair(0U, &LoongArch::GPR32RegClass); +- } +- if (VT == MVT::i64 && !Subtarget.is64Bit()) +- return std::make_pair(0U, &LoongArch::GPR32RegClass); +- if (VT == MVT::i64 && Subtarget.is64Bit()) +- return std::make_pair(0U, &LoongArch::GPR64RegClass); +- // This will generate an error message +- return std::make_pair(0U, nullptr); ++ return std::make_pair(0U, getRegisterClassForVT(VT, Subtarget.is64Bit())); + case 'f': // FPU or LSX register + if (VT == MVT::v16i8) + return std::make_pair(0U, &LoongArch::LSX128BRegClass); +@@ -8217,3 +8205,7 @@ LoongArchTargetLowering::getRegisterByName(const char *RegName, LLT VT, + } + report_fatal_error("Invalid register name global variable"); + } ++ ++bool LoongArchTargetLowering::hasAndNot(SDValue Y) const { ++ return Y.getValueType().isScalarInteger() && !isa(Y); ++} +diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +index e22c13ef4..f4aeb0a5e 100644 +--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h ++++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +@@ -234,6 +234,8 @@ class TargetRegisterClass; + return false; + } + ++ bool hasAndNot(SDValue Y) const override; ++ + const TargetRegisterClass *getRepRegClassFor(MVT VT) const override; + + void AdjustInstrPostInstrSelection(MachineInstr &MI, +diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +index 0c753b6da..74d5c977d 100644 +--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td ++++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +@@ -784,7 +784,7 @@ class StPtr + ///R2_IMM16 + class FJirl +- : InstForm<(outs), (ins RO:$rd, RO:$rj, opnd:$offs16), ++ : InstForm<(outs RO:$rd), (ins RO:$rj, opnd:$offs16), + !strconcat(opstr, "\t$rd, $rj, $offs16"), + [], FrmJ, opstr>; + +diff --git a/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp +index ef039aaad..8dbf30f21 100644 +--- a/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp ++++ b/llvm/lib/Target/LoongArch/LoongArchModuleISelDAGToDAG.cpp +@@ -45,8 +45,6 @@ namespace { + + bool LoongArchModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { + LLVM_DEBUG(errs() << "In LoongArchModuleDAGToDAGISel::runMachineFunction\n"); +- auto &TPC = getAnalysis(); +- auto &TM = TPC.getTM(); + return false; + } + +diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp +index e7f18b64b..de9b68211 100644 +--- a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp ++++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp +@@ -38,9 +38,9 @@ LoongArchSubtarget::LoongArchSubtarget(const Triple &TT, StringRef CPU, + MaybeAlign StackAlignOverride) + : LoongArchGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), HasLA64(false), + IsSoftFloat(false), IsSingleFloat(false), IsFP64bit(false), HasLSX(false), +- HasLASX(false), StackAlignOverride(StackAlignOverride), TM(TM), +- TargetTriple(TT), TSInfo(), +- InstrInfo(initializeSubtargetDependencies(CPU, FS, TM)), ++ HasLASX(false), UnalignedAccess(false), ++ StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT), ++ TSInfo(), InstrInfo(initializeSubtargetDependencies(CPU, FS, TM)), + FrameLowering(*this), TLInfo(TM, *this) { + + // Check if Architecture and ABI are compatible. +diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.h b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h +index 15bb75b7a..fbf66110d 100644 +--- a/llvm/lib/Target/LoongArch/LoongArchSubtarget.h ++++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h +@@ -61,6 +61,9 @@ class LoongArchSubtarget : public LoongArchGenSubtargetInfo { + /// entry to the function and which must be maintained by every function. + Align stackAlignment; + ++ // Allow unaligned memory accesses. ++ bool UnalignedAccess; ++ + /// The overridden stack alignment. + MaybeAlign StackAlignOverride; + +@@ -104,6 +107,8 @@ public: + bool hasLASX() const { return HasLASX; } + bool useSoftFloat() const { return IsSoftFloat; } + ++ bool allowUnalignedAccess() const { return UnalignedAccess; } ++ + // After compiler-rt is supported in LA, this returns true. + bool isXRaySupported() const override { return false; } + +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp +index 39fc4d778..a74fee3f8 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp +@@ -43,7 +43,8 @@ static std::pair getRelocPairForSize(unsigned Size) { + } + + static bool requiresFixups(MCContext &C, const MCExpr *Value, +- const MCExpr *&LHS, const MCExpr *&RHS) { ++ const MCExpr *&LHS, const MCExpr *&RHS, ++ LoongArchELFStreamer *MCS) { + const auto *MBE = dyn_cast(Value); + if (MBE == nullptr) + return false; +@@ -69,12 +70,18 @@ static bool requiresFixups(MCContext &C, const MCExpr *Value, + MCConstantExpr::create(E.getConstant(), C), C); + RHS = E.getSymB(); + +- return (A.isInSection() ? true : !A.getName().empty()) || ++ bool isCheckInstr = ++ StringSwitch(MCS->getCurrentSectionOnly()->getName()) ++ .Case(".debug_aranges", true) ++ .Default(false); ++ ++ return (A.isInSection() ++ ? (isCheckInstr ? A.getSection().hasInstructions() : true) ++ : !A.getName().empty()) || + (B.isInSection() ? B.getSection().hasInstructions() + : !B.getName().empty()); + } + +- + LoongArchELFStreamer::LoongArchELFStreamer(MCContext &Context, + std::unique_ptr MAB, + std::unique_ptr OW, +@@ -102,7 +109,7 @@ void LoongArchELFStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { + void LoongArchELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc) { + const MCExpr *A, *B; +- if (!requiresFixups(getContext(), Value, A, B)) ++ if (!requiresFixups(getContext(), Value, A, B, this)) + return MCELFStreamer::emitValueImpl(Value, Size, Loc); + + MCStreamer::emitValueImpl(Value, Size, Loc); +diff --git a/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp b/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp +index bf776db26..5d3ec9ea0 100644 +--- a/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp ++++ b/llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp +@@ -28,6 +28,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetInfo() { + X(getTheLoongArch32Target(), "loongarch32", "LoongArch (32-bit)", "LoongArch"); + #endif + RegisterTarget +- A(getTheLoongArch64Target(), "loongarch64", "LoongArch (64-bit)", "LoongArch"); ++ /*HasJIT=*/true> ++ A(getTheLoongArch64Target(), "loongarch64", "LoongArch (64-bit)", ++ "LoongArch"); + } +diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +index 0d4ca0bce..bfce051de 100644 +--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp ++++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +@@ -105,6 +105,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 kRISCV64_ShadowOffset64 = 0xd55550000; + static const uint64_t kFreeBSD_ShadowOffset32 = 1ULL << 30; +@@ -457,6 +458,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 IsRISCV64 = TargetTriple.getArch() == Triple::riscv64; +@@ -520,7 +522,9 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize, + Mapping.Offset = kWindowsShadowOffset64; + } else if (IsMIPS64) + Mapping.Offset = kMIPS64_ShadowOffset64; +- else if (IsIOS) ++ else if (IsLoongArch64) { ++ Mapping.Offset = kLoongArch64_ShadowOffset64; ++ } else if (IsIOS) + Mapping.Offset = kDynamicShadowSentinel; + else if (IsMacOS && IsAArch64) + Mapping.Offset = kDynamicShadowSentinel; +diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +index fd59e213c..797ec4f50 100644 +--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp ++++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +@@ -5450,6 +5450,8 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan, + return new VarArgPowerPC64Helper(Func, Msan, Visitor); + else if (TargetTriple.getArch() == Triple::systemz) + return new VarArgSystemZHelper(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/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll b/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll +new file mode 100644 +index 000000000..94e330673 +--- /dev/null ++++ b/llvm/test/CodeGen/LoongArch/inlineasm/floating-point-in-gpr.ll +@@ -0,0 +1,31 @@ ++; RUN: llc -march=loongarch64 -target-abi=lp64 -o - %s 2>&1 | FileCheck %s ++ ++;; Test that floating-point bits can be stored in GPR. ++ ++define void @reg_float(float %x) { ++; CHECK-LABEL: reg_float: ++; CHECK: movfr2gr.s $r{{[0-9]+}}, $f0 ++ call void asm "", "r"(float %x) ++ ret void ++} ++ ++define void @r10_float(float %x) { ++; CHECK-LABEL: r10_float: ++; CHECK: movfr2gr.s $r10, $f0 ++ call void asm "", "{$r10}"(float %x) ++ ret void ++} ++ ++define void @reg_double(double %x) { ++; CHECK-LABEL: reg_double: ++; CHECK: movfr2gr.d $r{{[0-9]+}}, $f0 ++ call void asm "", "r"(double %x) ++ ret void ++} ++ ++define void @r10_double(double %x) { ++; CHECK-LABEL: r10_double: ++; CHECK: movfr2gr.d $r10, $f0 ++ call void asm "", "{$r10}"(double %x) ++ ret void ++} +diff --git a/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll b/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll +new file mode 100644 +index 000000000..7f58ea2ee +--- /dev/null ++++ b/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers-error.ll +@@ -0,0 +1,8 @@ ++; RUN: not llc -march=loongarch64 %s 2>&1 | FileCheck %s ++ ++define void @test_i128() { ++; CHECK: error: couldn't allocate input reg for constraint '{$r20}' ++start: ++ call void asm "", "{$r20}"(i128 5) ++ ret void ++} +diff --git a/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll b/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll +new file mode 100644 +index 000000000..d18a184ab +--- /dev/null ++++ b/llvm/test/CodeGen/LoongArch/inlineasm/non-native-value-type-registers.ll +@@ -0,0 +1,42 @@ ++; RUN: llc -march=loongarch64 -o - %s 2>&1 | FileCheck %s ++ ++;; Test that non native value types can be parsed. ++ ++define void @test_i1() { ++; CHECK-LABEL: test_i1: ++; CHECK: ori $r6, $zero, 0 ++; CHECK: jr $ra ++start: ++ call void asm "", "{$r6}"(i1 0) ++ ret void ++} ++ ++;; Note: non-simple values like `i3` are only allowed in newer llvm versions (>= 12). ++;; In older llvm versions (<= 11), SelectionDAGBuilder::visitInlineAsm asserts simple ++;; values must be used. For details, please see https://reviews.llvm.org/D91710. ++define void @test_i3() { ++; CHECK-LABEL: test_i3: ++; CHECK: ori $r7, $zero, 0 ++; CHECK: jr $ra ++start: ++ call void asm "", "{$r7}"(i3 0) ++ ret void ++} ++ ++define void @test_i8() { ++; CHECK-LABEL: test_i8: ++; CHECK: ori $r5, $zero, 0 ++; CHECK: jr $ra ++start: ++ call void asm "", "{$r5}"(i8 0) ++ ret void ++} ++ ++define void @test_i16() { ++; CHECK-LABEL: test_i16: ++; CHECK: ori $r20, $zero, 5 ++; CHECK: jr $ra ++start: ++ call void asm "", "{$r20}"(i16 5) ++ ret void ++} +diff --git a/llvm/test/CodeGen/LoongArch/jirl-verify.ll b/llvm/test/CodeGen/LoongArch/jirl-verify.ll +new file mode 100644 +index 000000000..70b588bea +--- /dev/null ++++ b/llvm/test/CodeGen/LoongArch/jirl-verify.ll +@@ -0,0 +1,34 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -verify-machineinstrs -o - %s \ ++; RUN: | FileCheck %s --check-prefix=STATIC ++; RUN: llc -march=loongarch64 -verify-machineinstrs -relocation-model=pic --code-model=large -o - %s \ ++; RUN: | FileCheck %s --check-prefix=LARGE ++ ++define void @test() nounwind { ++; STATIC-LABEL: test: ++; STATIC: # %bb.0: ++; STATIC-NEXT: addi.d $sp, $sp, -16 ++; STATIC-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; STATIC-NEXT: lu12i.w $ra, foo ++; STATIC-NEXT: ori $ra, $ra, foo ++; STATIC-NEXT: lu32i.d $ra, foo ++; STATIC-NEXT: lu52i.d $ra, $ra, foo ++; STATIC-NEXT: jirl $ra, $ra, 0 ++; STATIC-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; STATIC-NEXT: addi.d $sp, $sp, 16 ++; STATIC-NEXT: jr $ra ++; ++; LARGE-LABEL: test: ++; LARGE: # %bb.0: ++; LARGE-NEXT: addi.d $sp, $sp, -16 ++; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ++; LARGE-NEXT: pcaddu18i $ra, foo ++; LARGE-NEXT: jirl $ra, $ra, foo ++; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload ++; LARGE-NEXT: addi.d $sp, $sp, 16 ++; LARGE-NEXT: jr $ra ++ call void @foo() nounwind ++ ret void ++} ++ ++declare void @foo() +diff --git a/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll b/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll +index c7408c0a7..337632491 100644 +--- a/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll ++++ b/llvm/test/CodeGen/LoongArch/lasx/inline-asm.ll +@@ -1,4 +1,3 @@ +-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + ; A basic inline assembly test + + ; RUN: llc -march=loongarch64 -mattr=+lasx < %s | FileCheck %s +@@ -7,99 +6,50 @@ + @v8i32_r = global <8 x i32> zeroinitializer, align 32 + + define void @test1() nounwind { +-; CHECK-LABEL: test1: +-; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: la.pcrel $r4, v4i64_r +-; CHECK-NEXT: # la expanded slot +-; CHECK-NEXT: #APP +-; CHECK-EMPTY: +-; CHECK-NEXT: xvldi $xr0, 1 +-; CHECK-EMPTY: +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: xvst $xr0, $r4, 0 +-; CHECK-NEXT: jr $ra + entry: ++ ; CHECK-LABEL: test1: + %0 = call <4 x i64> asm "xvldi ${0:u}, 1", "=f"() ++ ; CHECK: xvldi $xr{{[1-3]?[0-9]}}, 1 + store <4 x i64> %0, <4 x i64>* @v4i64_r + ret void + } + + define void @test2() nounwind { +-; CHECK-LABEL: test2: +-; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: la.pcrel $r4, v8i32_r +-; CHECK-NEXT: # la expanded slot +-; CHECK-NEXT: xvld $xr0, $r4, 0 +-; CHECK-NEXT: #APP +-; CHECK-EMPTY: +-; CHECK-NEXT: xvaddi.wu $xr0, $xr0, 1 +-; CHECK-EMPTY: +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: xvst $xr0, $r4, 0 +-; CHECK-NEXT: jr $ra + entry: ++ ; CHECK-LABEL: test2: + %0 = load <8 x i32>, <8 x i32>* @v8i32_r + %1 = call <8 x i32> asm "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f"(<8 x i32> %0) ++ ; CHECK: xvaddi.wu $xr{{[1-3]?[0-9]}}, $xr{{[1-3]?[0-9]}}, 1 + store <8 x i32> %1, <8 x i32>* @v8i32_r + ret void + } + + define void @test2_d() nounwind { +-; CHECK-LABEL: test2_d: +-; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: la.pcrel $r4, v4i64_r +-; CHECK-NEXT: # la expanded slot +-; CHECK-NEXT: xvld $xr0, $r4, 0 +-; CHECK-NEXT: #APP +-; CHECK-EMPTY: +-; CHECK-NEXT: xvaddi.wu $xr0, $xr0, 1 +-; CHECK-EMPTY: +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: xvst $xr0, $r4, 0 +-; CHECK-NEXT: jr $ra + entry: ++ ; CHECK-LABEL: test2_d: + %0 = load < 4 x i64>, < 4 x i64>* @v4i64_r + %1 = call < 4 x i64> asm "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f"(< 4 x i64> %0) ++ ; CHECK: xvaddi.wu $xr{{[1-3]?[0-9]}}, $xr{{[1-3]?[0-9]}}, 1 + store < 4 x i64> %1, < 4 x i64>* @v4i64_r + ret void + } + + define void @test3() nounwind { +-; CHECK-LABEL: test3: +-; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: la.pcrel $r4, v8i32_r +-; CHECK-NEXT: # la expanded slot +-; CHECK-NEXT: xvld $xr1, $r4, 0 +-; CHECK-NEXT: #APP +-; CHECK-EMPTY: +-; CHECK-NEXT: xvaddi.wu $xr1, $xr1, 1 +-; CHECK-EMPTY: +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: xvst $xr1, $r4, 0 +-; CHECK-NEXT: jr $ra + entry: ++ ; CHECK-LABEL: test3: + %0 = load <8 x i32>, <8 x i32>* @v8i32_r + %1 = call <8 x i32> asm sideeffect "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f,~{$xr0}"(<8 x i32> %0) ++ ; CHECK: xvaddi.wu $xr{{([1-9]|[1-3][0-9])}}, $xr{{([1-9]|[1-3][0-9])}}, 1 + store <8 x i32> %1, <8 x i32>* @v8i32_r + ret void + } + + define void @test3_d() nounwind { +-; CHECK-LABEL: test3_d: +-; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: la.pcrel $r4, v4i64_r +-; CHECK-NEXT: # la expanded slot +-; CHECK-NEXT: xvld $xr1, $r4, 0 +-; CHECK-NEXT: #APP +-; CHECK-EMPTY: +-; CHECK-NEXT: xvaddi.wu $xr1, $xr1, 1 +-; CHECK-EMPTY: +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: xvst $xr1, $r4, 0 +-; CHECK-NEXT: jr $ra + entry: ++ ; CHECK-LABEL: test3_d: + %0 = load <4 x i64>, <4 x i64>* @v4i64_r + %1 = call <4 x i64> asm sideeffect "xvaddi.wu ${0:u}, ${1:u}, 1", "=f,f,~{$xr0}"(<4 x i64> %0) ++ ; CHECK: xvaddi.wu $xr{{([1-9]|[1-3][0-9])}}, $xr{{([1-9]|[1-3][0-9])}}, 1 + store <4 x i64> %1, <4 x i64>* @v4i64_r + ret void + } +diff --git a/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll b/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll +index a48facf91..37cb6dfc9 100644 +--- a/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll ++++ b/llvm/test/CodeGen/LoongArch/lsx/inline-asm.ll +@@ -1,4 +1,3 @@ +-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + ; A basic inline assembly test + + ; RUN: llc -march=loongarch64 -mattr=+lsx < %s | FileCheck %s +@@ -6,59 +5,30 @@ + @v2i64_r = global <2 x i64> zeroinitializer, align 16 + + define void @test1() nounwind { +-; CHECK-LABEL: test1: +-; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: la.pcrel $r4, v2i64_r +-; CHECK-NEXT: # la expanded slot +-; CHECK-NEXT: #APP +-; CHECK-EMPTY: +-; CHECK-NEXT: vldi $vr0, 1 +-; CHECK-EMPTY: +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: vst $vr0, $r4, 0 +-; CHECK-NEXT: jr $ra + entry: ++ ; CHECK-LABEL: test1: + %0 = call <2 x i64> asm "vldi ${0:w}, 1", "=f"() ++ ; CHECK: vldi $vr{{[1-3]?[0-9]}}, 1 + store <2 x i64> %0, <2 x i64>* @v2i64_r + ret void + } + + define void @test2() nounwind { +-; CHECK-LABEL: test2: +-; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: la.pcrel $r4, v2i64_r +-; CHECK-NEXT: # la expanded slot +-; CHECK-NEXT: vld $vr0, $r4, 0 +-; CHECK-NEXT: #APP +-; CHECK-EMPTY: +-; CHECK-NEXT: vaddi.wu $vr0, $vr0, 1 +-; CHECK-EMPTY: +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: vst $vr0, $r4, 0 +-; CHECK-NEXT: jr $ra + entry: ++ ; CHECK-LABEL: test2: + %0 = load <2 x i64>, <2 x i64>* @v2i64_r + %1 = call <2 x i64> asm "vaddi.wu ${0:w}, ${1:w}, 1", "=f,f"(<2 x i64> %0) ++ ; CHECK: vaddi.wu $vr{{[1-3]?[0-9]}}, $vr{{[1-3]?[0-9]}}, 1 + store <2 x i64> %1, <2 x i64>* @v2i64_r + ret void + } + + define void @test3() nounwind { +-; CHECK-LABEL: test3: +-; CHECK: # %bb.0: # %entry +-; CHECK-NEXT: la.pcrel $r4, v2i64_r +-; CHECK-NEXT: # la expanded slot +-; CHECK-NEXT: vld $vr1, $r4, 0 +-; CHECK-NEXT: #APP +-; CHECK-EMPTY: +-; CHECK-NEXT: vaddi.wu $vr1, $vr1, 1 +-; CHECK-EMPTY: +-; CHECK-NEXT: #NO_APP +-; CHECK-NEXT: vst $vr1, $r4, 0 +-; CHECK-NEXT: jr $ra + entry: ++ ; CHECK-LABEL: test3: + %0 = load <2 x i64>, <2 x i64>* @v2i64_r + %1 = call <2 x i64> asm sideeffect "vaddi.wu ${0:w}, ${1:w}, 1", "=f,f,~{$vr0}"(<2 x i64> %0) ++ ; CHECK: vaddi.wu $vr{{([1-9]|[1-3][0-9])}}, $vr{{([1-9]|[1-3][0-9])}}, 1 + store <2 x i64> %1, <2 x i64>* @v2i64_r + ret void + } +diff --git a/llvm/test/CodeGen/LoongArch/noti32.ll b/llvm/test/CodeGen/LoongArch/noti32.ll +new file mode 100644 +index 000000000..9aa8c4391 +--- /dev/null ++++ b/llvm/test/CodeGen/LoongArch/noti32.ll +@@ -0,0 +1,143 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 < %s | FileCheck %s ++ ++define i8 @nor_i8(i8 %a, i8 %b) nounwind { ++; CHECK-LABEL: nor_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: or $r4, $r4, $r5 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %or = or i8 %a, %b ++ %neg = xor i8 %or, -1 ++ ret i8 %neg ++} ++ ++define i16 @nor_i16(i16 %a, i16 %b) nounwind { ++; CHECK-LABEL: nor_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: or $r4, $r4, $r5 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %or = or i16 %a, %b ++ %neg = xor i16 %or, -1 ++ ret i16 %neg ++} ++ ++define i32 @nor_i32(i32 %a, i32 %b) nounwind { ++; CHECK-LABEL: nor_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: or $r4, $r4, $r5 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %or = or i32 %a, %b ++ %neg = xor i32 %or, -1 ++ ret i32 %neg ++} ++ ++define i8 @nor_zero_i8(i8 %a) nounwind { ++; CHECK-LABEL: nor_zero_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i8 %a, -1 ++ ret i8 %neg ++} ++ ++define i16 @nor_zero_i16(i16 %a) nounwind { ++; CHECK-LABEL: nor_zero_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i16 %a, -1 ++ ret i16 %neg ++} ++ ++define i32 @nor_zero_i32(i32 %a) nounwind { ++; CHECK-LABEL: nor_zero_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: nor $r4, $zero, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i32 %a, -1 ++ ret i32 %neg ++} ++ ++define i8 @orn_i8(i8 %a, i8 %b) nounwind { ++; CHECK-LABEL: orn_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: nor $r5, $zero, $r5 ++; CHECK-NEXT: or $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i8 %b, -1 ++ %or = or i8 %neg, %a ++ ret i8 %or ++} ++ ++define i16 @orn_i16(i16 %a, i16 %b) nounwind { ++; CHECK-LABEL: orn_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: nor $r5, $zero, $r5 ++; CHECK-NEXT: or $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i16 %b, -1 ++ %or = or i16 %neg, %a ++ ret i16 %or ++} ++ ++define i32 @orn_i32(i32 %a, i32 %b) nounwind { ++; CHECK-LABEL: orn_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: nor $r5, $zero, $r5 ++; CHECK-NEXT: or $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %neg = xor i32 %b, -1 ++ %or = or i32 %neg, %a ++ ret i32 %or ++} ++ ++define i8 @andn_i8(i8 %a, i8 %b) nounwind { ++; CHECK-LABEL: andn_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %neg = xor i8 %b, -1 ++ %and = and i8 %neg, %a ++ ret i8 %and ++} ++ ++define i16 @andn_i16(i16 %a, i16 %b) nounwind { ++; CHECK-LABEL: andn_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %neg = xor i16 %b, -1 ++ %and = and i16 %neg, %a ++ ret i16 %and ++} ++ ++define i32 @andn_i32(i32 %a, i32 %b) nounwind { ++; CHECK-LABEL: andn_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %neg = xor i32 %b, -1 ++ %and = and i32 %neg, %a ++ ret i32 %and ++} +diff --git a/llvm/test/CodeGen/LoongArch/select-to-shiftand.ll b/llvm/test/CodeGen/LoongArch/select-to-shiftand.ll +new file mode 100644 +index 000000000..a1b656f86 +--- /dev/null ++++ b/llvm/test/CodeGen/LoongArch/select-to-shiftand.ll +@@ -0,0 +1,147 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -o - %s | FileCheck %s ++ ++define i8 @select_variable_negimm_i8(i8 signext %a, i8 signext %b) { ++; CHECK-LABEL: select_variable_negimm_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: srai.w $r4, $r4, 7 ++; CHECK-NEXT: andn $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %cmp = icmp sgt i8 %a, -1 ++ %sel = select i1 %cmp, i8 %b, i8 0 ++ ret i8 %sel ++} ++ ++define i8 @select_variable_zero_i8(i8 signext %a) { ++; CHECK-LABEL: select_variable_zero_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: srai.w $r5, $r4, 7 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %cmp = icmp sgt i8 %a, 0 ++ %sel = select i1 %cmp, i8 %a, i8 0 ++ ret i8 %sel ++} ++ ++define i8 @select_sub_zero_i8(i8 signext %x, i8 signext %y) { ++; CHECK-LABEL: select_sub_zero_i8: ++; CHECK: # %bb.0: ++; CHECK-NEXT: sub.w $r4, $r4, $r5 ++; CHECK-NEXT: ext.w.b $r5, $r4 ++; CHECK-NEXT: srai.w $r5, $r5, 7 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %sub = sub nsw i8 %x, %y ++ %cmp = icmp sgt i8 %sub, 0 ++ %sel = select i1 %cmp, i8 %sub, i8 0 ++ ret i8 %sel ++} ++ ++define i16 @select_variable_negimm_i16(i16 signext %a, i16 signext %b) { ++; CHECK-LABEL: select_variable_negimm_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: srai.w $r4, $r4, 15 ++; CHECK-NEXT: andn $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %cmp = icmp sgt i16 %a, -1 ++ %sel = select i1 %cmp, i16 %b, i16 0 ++ ret i16 %sel ++} ++ ++define i16 @select_variable_zero_i16(i16 signext %a) { ++; CHECK-LABEL: select_variable_zero_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: srai.w $r5, $r4, 15 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %cmp = icmp sgt i16 %a, 0 ++ %sel = select i1 %cmp, i16 %a, i16 0 ++ ret i16 %sel ++} ++ ++define i16 @select_sub_zero_i16(i16 signext %x, i16 signext %y) { ++; CHECK-LABEL: select_sub_zero_i16: ++; CHECK: # %bb.0: ++; CHECK-NEXT: sub.w $r4, $r4, $r5 ++; CHECK-NEXT: ext.w.h $r5, $r4 ++; CHECK-NEXT: srai.w $r5, $r5, 15 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %sub = sub nsw i16 %x, %y ++ %cmp = icmp sgt i16 %sub, 0 ++ %sel = select i1 %cmp, i16 %sub, i16 0 ++ ret i16 %sel ++} ++ ++define i32 @select_variable_negimm_i32(i32 signext %a, i32 signext %b) { ++; CHECK-LABEL: select_variable_negimm_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: srai.w $r4, $r4, 31 ++; CHECK-NEXT: andn $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %cmp = icmp sgt i32 %a, -1 ++ %sel = select i1 %cmp, i32 %b, i32 0 ++ ret i32 %sel ++} ++ ++define i32 @select_variable_zero_i32(i32 signext %a) { ++; CHECK-LABEL: select_variable_zero_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: slli.w $r4, $r4, 0 ++; CHECK-NEXT: srai.w $r5, $r4, 31 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %cmp = icmp sgt i32 %a, 0 ++ %sel = select i1 %cmp, i32 %a, i32 0 ++ ret i32 %sel ++} ++ ++define i32 @select_sub_zero_i32(i32 signext %x, i32 signext %y) { ++; CHECK-LABEL: select_sub_zero_i32: ++; CHECK: # %bb.0: ++; CHECK-NEXT: sub.w $r4, $r4, $r5 ++; CHECK-NEXT: srai.w $r5, $r4, 31 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %sub = sub nsw i32 %x, %y ++ %cmp = icmp sgt i32 %sub, 0 ++ %sel = select i1 %cmp, i32 %sub, i32 0 ++ ret i32 %sel ++} ++ ++define i64 @select_variable_negimm_i64(i64 signext %a, i64 signext %b) { ++; CHECK-LABEL: select_variable_negimm_i64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: srai.d $r4, $r4, 63 ++; CHECK-NEXT: andn $r4, $r5, $r4 ++; CHECK-NEXT: jr $ra ++ %cmp = icmp sgt i64 %a, -1 ++ %sel = select i1 %cmp, i64 %b, i64 0 ++ ret i64 %sel ++} ++ ++define i64 @select_variable_zero_i64(i64 signext %a) { ++; CHECK-LABEL: select_variable_zero_i64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: srai.d $r5, $r4, 63 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %cmp = icmp sgt i64 %a, 0 ++ %sel = select i1 %cmp, i64 %a, i64 0 ++ ret i64 %sel ++} ++ ++define i64 @select_sub_zero_i64(i64 signext %x, i64 signext %y) { ++; CHECK-LABEL: select_sub_zero_i64: ++; CHECK: # %bb.0: ++; CHECK-NEXT: sub.d $r4, $r4, $r5 ++; CHECK-NEXT: srai.d $r5, $r4, 63 ++; CHECK-NEXT: andn $r4, $r4, $r5 ++; CHECK-NEXT: jr $ra ++ %sub = sub nsw i64 %x, %y ++ %cmp = icmp sgt i64 %sub, 0 ++ %sel = select i1 %cmp, i64 %sub, i64 0 ++ ret i64 %sel ++} +diff --git a/llvm/test/CodeGen/LoongArch/trunc.ll b/llvm/test/CodeGen/LoongArch/trunc.ll +index 0cc8d248a..d1b5a3a14 100644 +--- a/llvm/test/CodeGen/LoongArch/trunc.ll ++++ b/llvm/test/CodeGen/LoongArch/trunc.ll +@@ -76,6 +76,8 @@ entry: + define signext i32 @sdiv(i64 %a, i64 %b) { + ; CHECK-LABEL: sdiv: + ; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 + ; CHECK-NEXT: div.w $r4, $r4, $r5 + ; CHECK-NEXT: bne $r5, $zero, 8 + ; CHECK-NEXT: break 7 +@@ -91,6 +93,8 @@ entry: + define signext i32 @udiv(i64 %a, i64 %b) { + ; CHECK-LABEL: udiv: + ; CHECK: # %bb.0: # %entry ++; CHECK-NEXT: slli.w $r5, $r5, 0 ++; CHECK-NEXT: slli.w $r4, $r4, 0 + ; CHECK-NEXT: div.wu $r4, $r4, $r5 + ; CHECK-NEXT: bne $r5, $zero, 8 + ; CHECK-NEXT: break 7 +diff --git a/llvm/test/CodeGen/LoongArch/unalignment.ll b/llvm/test/CodeGen/LoongArch/unalignment.ll +new file mode 100644 +index 000000000..d468a361f +--- /dev/null ++++ b/llvm/test/CodeGen/LoongArch/unalignment.ll +@@ -0,0 +1,72 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -march=loongarch64 -o - %s | FileCheck -check-prefix=UNALIGNED %s ++; RUN: llc -march=loongarch64 -mattr=+unaligned-access -o - %s | FileCheck -check-prefix=UNALIGNED %s ++; RUN: llc -march=loongarch64 -mattr=-unaligned-access -o - %s | FileCheck -check-prefix=ALIGNED %s ++ ++define i32 @i32_load(i32* %p) { ++; UNALIGNED-LABEL: i32_load: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.w $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++; ++; ALIGNED-LABEL: i32_load: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.hu $r4, $r4, 2 ++; ALIGNED-NEXT: slli.w $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define signext i32 @i32_sextload(i32* %p) { ++; UNALIGNED-LABEL: i32_sextload: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.w $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++; ++; ALIGNED-LABEL: i32_sextload: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.h $r4, $r4, 2 ++; ALIGNED-NEXT: slli.d $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define zeroext i32 @i32_zextload(i32* %p) { ++; UNALIGNED-LABEL: i32_zextload: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.wu $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++; ++; ALIGNED-LABEL: i32_zextload: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.hu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.hu $r4, $r4, 2 ++; ALIGNED-NEXT: slli.d $r4, $r4, 16 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++ %tmp = load i32, i32* %p, align 2 ++ ret i32 %tmp ++} ++ ++define i64 @i64_load(i64* %p) { ++; UNALIGNED-LABEL: i64_load: ++; UNALIGNED: # %bb.0: ++; UNALIGNED-NEXT: ld.d $r4, $r4, 0 ++; UNALIGNED-NEXT: jr $ra ++; ++; ALIGNED-LABEL: i64_load: ++; ALIGNED: # %bb.0: ++; ALIGNED-NEXT: ld.wu $r5, $r4, 0 ++; ALIGNED-NEXT: ld.wu $r4, $r4, 4 ++; ALIGNED-NEXT: slli.d $r4, $r4, 32 ++; ALIGNED-NEXT: or $r4, $r4, $r5 ++; ALIGNED-NEXT: jr $ra ++ %tmp = load i64, i64* %p, align 4 ++ ret i64 %tmp ++} +diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_GOTAndStubsOptimization.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_GOTAndStubsOptimization.s +index 98df053c9..45c078c10 100644 +--- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_GOTAndStubsOptimization.s ++++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_GOTAndStubsOptimization.s +@@ -1,3 +1,4 @@ ++# UNSUPPORTED: loongarch64 + # RUN: rm -rf %t && mkdir -p %t + # RUN: llvm-mc -triple=x86_64-apple-macos10.9 -filetype=obj \ + # RUN: -o %t/helper.o %S/Inputs/MachO_GOTAndStubsOptimizationHelper.s +diff --git a/llvm/test/ExecutionEngine/MCJIT/eh-lg-pic.ll b/llvm/test/ExecutionEngine/MCJIT/eh-lg-pic.ll +index f2d6a54a5..86c7374fb 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/eh-lg-pic.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/eh-lg-pic.ll +@@ -1,4 +1,5 @@ + ; REQUIRES: cxx-shared-library ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -relocation-model=pic -code-model=large %s + ; XFAIL: cygwin, windows-msvc, windows-gnu, mips-, mipsel-, i686, i386, aarch64, arm + declare i8* @__cxa_allocate_exception(i64) +diff --git a/llvm/test/ExecutionEngine/MCJIT/eh.ll b/llvm/test/ExecutionEngine/MCJIT/eh.ll +index ed5ff644d..f419c875f 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/eh.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/eh.ll +@@ -1,4 +1,5 @@ + ; REQUIRES: cxx-shared-library ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit %s + + ; XFAIL: arm, cygwin, windows-msvc, windows-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/lit.local.cfg b/llvm/test/ExecutionEngine/MCJIT/lit.local.cfg +index e2535ef1d..09f1a2ab6 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/lit.local.cfg ++++ b/llvm/test/ExecutionEngine/MCJIT/lit.local.cfg +@@ -1,7 +1,8 @@ + root = config.root + targets = root.targets + if ('X86' in targets) | ('AArch64' in targets) | ('ARM' in targets) | \ +- ('Mips' in targets) | ('PowerPC' in targets) | ('SystemZ' in targets): ++ ('Mips' in targets) | ('PowerPC' in targets) | ('SystemZ' in targets) | \ ++ ('LoongArch' in targets) : + config.unsupported = False + else: + config.unsupported = True +@@ -9,7 +10,7 @@ else: + # FIXME: autoconf and cmake produce different arch names. We should normalize + # them before getting here. + if root.host_arch not in ['i386', 'x86', 'x86_64', 'AMD64', +- 'AArch64', 'ARM', 'Mips', ++ 'AArch64', 'ARM', 'Mips', 'loongarch64', + 'PowerPC', 'ppc64', 'ppc64le', 'SystemZ']: + config.unsupported = True + +diff --git a/llvm/test/ExecutionEngine/MCJIT/multi-module-eh-a.ll b/llvm/test/ExecutionEngine/MCJIT/multi-module-eh-a.ll +index 3709aa441..afd38c007 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/multi-module-eh-a.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/multi-module-eh-a.ll +@@ -1,4 +1,5 @@ + ; REQUIRES: cxx-shared-library ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -extra-module=%p/Inputs/multi-module-eh-b.ll %s + + ; XFAIL: arm, cygwin, windows-msvc, windows-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/cross-module-a.ll b/llvm/test/ExecutionEngine/MCJIT/remote/cross-module-a.ll +index 7a1731e74..d7b7e6972 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/cross-module-a.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/cross-module-a.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -extra-module=%p/Inputs/cross-module-b.ll -disable-lazy-compilation=true -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null + ; XFAIL: windows-gnu,windows-msvc + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/eh.ll b/llvm/test/ExecutionEngine/MCJIT/remote/eh.ll +index be60ec730..cf5ef00bf 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/eh.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/eh.ll +@@ -1,4 +1,5 @@ + ; REQUIRES: cxx-shared-library ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s + ; XFAIL: arm, cygwin, windows-msvc, windows-gnu + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/multi-module-a.ll b/llvm/test/ExecutionEngine/MCJIT/remote/multi-module-a.ll +index 37b74de29..d26936cb2 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/multi-module-a.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/multi-module-a.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -extra-module=%p/Inputs/multi-module-b.ll -extra-module=%p/Inputs/multi-module-c.ll -disable-lazy-compilation=true -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null + ; XFAIL: windows-gnu,windows-msvc + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll b/llvm/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll +index f458ab79f..aefe0b3d1 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null + ; XFAIL: windows-gnu,windows-msvc + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll b/llvm/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll +index b8684a17a..6776e0813 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/stubs-remote.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -disable-lazy-compilation=false -mcjit-remote-process=lli-child-target%exeext %s + ; XFAIL: windows-gnu,windows-msvc + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll b/llvm/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll +index 060b5e132..ed080372e 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/test-common-symbols-remote.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -O0 -disable-lazy-compilation=false -mcjit-remote-process=lli-child-target%exeext %s + ; XFAIL: windows-gnu,windows-msvc + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll b/llvm/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll +index 6e60396e2..a2aee9c94 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null + ; XFAIL: windows-gnu,windows-msvc + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll b/llvm/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll +index b6fae4600..753c6273f 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-remote.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null + ; XFAIL: windows-gnu,windows-msvc + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-sm-pic.ll b/llvm/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-sm-pic.ll +index bfe09fddc..10132670a 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-sm-pic.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/test-global-init-nonzero-sm-pic.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext \ + ; RUN: -relocation-model=pic -code-model=small %s > /dev/null + ; XFAIL: mips-, mipsel-, aarch64, arm, i686, i386, windows-gnu, windows-msvc +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll b/llvm/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll +index 9e76601c9..61a898fe7 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-remote.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -O0 -mcjit-remote-process=lli-child-target%exeext %s + ; XFAIL: windows-gnu,windows-msvc + ; UNSUPPORTED: powerpc64-unknown-linux-gnu +diff --git a/llvm/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-sm-pic.ll b/llvm/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-sm-pic.ll +index 20f232add..1d737b87e 100644 +--- a/llvm/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-sm-pic.ll ++++ b/llvm/test/ExecutionEngine/MCJIT/remote/test-ptr-reloc-sm-pic.ll +@@ -1,3 +1,4 @@ ++; UNSUPPORTED: loongarch64 + ; RUN: %lli -jit-kind=mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext \ + ; RUN: -O0 -relocation-model=pic -code-model=small %s + ; XFAIL: mips-, mipsel-, aarch64, arm, i686, i386, windows-gnu, windows-msvc +diff --git a/llvm/test/ExecutionEngine/frem.ll b/llvm/test/ExecutionEngine/frem.ll +index e4bcda439..390e0f956 100644 +--- a/llvm/test/ExecutionEngine/frem.ll ++++ b/llvm/test/ExecutionEngine/frem.ll +@@ -1,7 +1,6 @@ + ; LLI.exe used to crash on Windows\X86 when certain single precession + ; floating point intrinsics (defined as macros) are used. + ; This unit test guards against the failure. +-; UNSUPPORTED: loongarch + ; + ; RUN: %lli -jit-kind=mcjit %s | FileCheck %s + ; RUN: %lli %s | FileCheck %s +diff --git a/llvm/test/ExecutionEngine/mov64zext32.ll b/llvm/test/ExecutionEngine/mov64zext32.ll +index e30e8d8d3..bba1a1987 100644 +--- a/llvm/test/ExecutionEngine/mov64zext32.ll ++++ b/llvm/test/ExecutionEngine/mov64zext32.ll +@@ -1,4 +1,3 @@ +-; UNSUPPORTED: loongarch + ; RUN: %lli -jit-kind=mcjit %s > /dev/null + ; RUN: %lli %s > /dev/null + +diff --git a/llvm/test/ExecutionEngine/test-interp-vec-arithm_float.ll b/llvm/test/ExecutionEngine/test-interp-vec-arithm_float.ll +index a0f78eb0e..6f784265a 100644 +--- a/llvm/test/ExecutionEngine/test-interp-vec-arithm_float.ll ++++ b/llvm/test/ExecutionEngine/test-interp-vec-arithm_float.ll +@@ -1,4 +1,3 @@ +-; UNSUPPORTED: loongarch + ; RUN: %lli -jit-kind=mcjit %s > /dev/null + ; RUN: %lli %s > /dev/null + +diff --git a/llvm/test/ExecutionEngine/test-interp-vec-arithm_int.ll b/llvm/test/ExecutionEngine/test-interp-vec-arithm_int.ll +index 3e0a0f14e..6896af83c 100644 +--- a/llvm/test/ExecutionEngine/test-interp-vec-arithm_int.ll ++++ b/llvm/test/ExecutionEngine/test-interp-vec-arithm_int.ll +@@ -1,4 +1,3 @@ +-; UNSUPPORTED: loongarch + ; RUN: %lli -jit-kind=mcjit %s > /dev/null + ; RUN: %lli %s > /dev/null + +diff --git a/llvm/test/ExecutionEngine/test-interp-vec-logical.ll b/llvm/test/ExecutionEngine/test-interp-vec-logical.ll +index 49cfa5b15..f654120ea 100644 +--- a/llvm/test/ExecutionEngine/test-interp-vec-logical.ll ++++ b/llvm/test/ExecutionEngine/test-interp-vec-logical.ll +@@ -1,4 +1,3 @@ +-; UNSUPPORTED: loongarch + ; RUN: %lli -jit-kind=mcjit %s > /dev/null + ; RUN: %lli %s > /dev/null + +diff --git a/llvm/test/ExecutionEngine/test-interp-vec-setcond-fp.ll b/llvm/test/ExecutionEngine/test-interp-vec-setcond-fp.ll +index 7765b1ae9..84bdec1cf 100644 +--- a/llvm/test/ExecutionEngine/test-interp-vec-setcond-fp.ll ++++ b/llvm/test/ExecutionEngine/test-interp-vec-setcond-fp.ll +@@ -1,4 +1,3 @@ +-; UNSUPPORTED: loongarch + ; RUN: %lli -jit-kind=mcjit %s > /dev/null + ; RUN: %lli %s > /dev/null + +diff --git a/llvm/test/ExecutionEngine/test-interp-vec-setcond-int.ll b/llvm/test/ExecutionEngine/test-interp-vec-setcond-int.ll +index a81f999c5..5a20fc4f1 100644 +--- a/llvm/test/ExecutionEngine/test-interp-vec-setcond-int.ll ++++ b/llvm/test/ExecutionEngine/test-interp-vec-setcond-int.ll +@@ -1,4 +1,3 @@ +-; UNSUPPORTED: loongarch + ; RUN: %lli -jit-kind=mcjit %s > /dev/null + ; RUN: %lli %s > /dev/null + +diff --git a/llvm/tools/sancov/sancov.cpp b/llvm/tools/sancov/sancov.cpp +index b274310f4..51a178461 100644 +--- a/llvm/tools/sancov/sancov.cpp ++++ b/llvm/tools/sancov/sancov.cpp +@@ -691,7 +691,7 @@ static uint64_t getPreviousInstructionPc(uint64_t PC, + Triple TheTriple) { + if (TheTriple.isARM()) { + return (PC - 3) & (~1); +- } else if (TheTriple.isAArch64()) { ++ } else if (TheTriple.isAArch64() || TheTriple.isLoongArch64()) { + return PC - 4; + } else if (TheTriple.isMIPS()) { + return PC - 8; +diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp +index 9eb2ef5d4..72faccd79 100644 +--- a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp ++++ b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp +@@ -114,8 +114,7 @@ protected: + // TODO: Print error messages in failure logs, use them to audit this list. + // Some architectures may be unsupportable or missing key components, but + // some may just be failing due to bugs in this testcase. +- if (Triple.startswith("armv7") || Triple.startswith("armv8l") || +- Triple.startswith("loongarch")) ++ if (Triple.startswith("armv7") || Triple.startswith("armv8l")) + return false; + llvm::Triple T(Triple); + if (T.isOSAIX() && T.isPPC64()) +diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/targets.gni b/llvm/utils/gn/secondary/llvm/lib/Target/targets.gni +index 3ed8ad488..c0ce54c60 100644 +--- a/llvm/utils/gn/secondary/llvm/lib/Target/targets.gni ++++ b/llvm/utils/gn/secondary/llvm/lib/Target/targets.gni +@@ -64,7 +64,7 @@ foreach(target, llvm_targets_to_build) { + } else if (target == "BPF") { + llvm_build_BPF = true + } else if (target == "LoongArch") { +- llvm_build_BPF = true ++ llvm_build_LoongArch = true + } else if (target == "Mips") { + llvm_build_Mips = true + } else if (target == "PowerPC") { diff --git a/llvm.spec b/llvm.spec index 1c7d022f1e4aab1e2248fe1cd48fc2bfda7f8341..3d6173dedb9bc7d86b4c2843df3feed842236415 100644 --- a/llvm.spec +++ b/llvm.spec @@ -1,4 +1,4 @@ -%define anolis_release .0.2 +%define anolis_release .0.3 # Components enabled if supported by target architecture: %define gold_arches %{ix86} x86_64 %{arm} aarch64 %{power64} %if 0%{?rhel} > 8 || 0%{?fedora} @@ -94,7 +94,10 @@ Source4: lit.fedora.cfg.py Patch0: 0001-cmake-Allow-shared-libraries-to-customize-the-soname.patch %endif Patch2: 0001-XFAIL-missing-abstract-variable.ll-test-on-ppc64le.patch + +# Patches for LoongArch Patch3: 0001-Support-LoongArch.patch +Patch4: 0002-pkg_an8_llvm_13.0.1-1.0.3.patch # RHEL-specific patches. Patch101: 0001-Deactivate-markdown-doc.patch @@ -548,6 +551,9 @@ fi %endif %changelog +* Mon Nov 07 2022 chenli - 13.0.1-1.0.3 +- 13.0.1-1.0.3 Release + * Tue Oct 18 2022 Liwei Ge - 13.0.1-1.0.2 - Disable pandoc