llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
25.95k stars 10.58k forks source link

[LoongArch] Optimize *W Instructions at MI level #90463

Closed heiher closed 1 week ago

heiher commented 2 weeks ago

Referring to RISC-V, adding an MI level pass to optimize *W instructions for LoongArch.

First it removes unneeded sext(addi.w rd, rs, 0) instructions. Either because the sign extended bits aren't consumed or because the input was already sign extended by an earlier instruction.

Then:

  1. Unless explicit disabled or the target prefers instructions with W suffix, it removes the -w suffix from opw instructions whenever all users are dependent only on the lower word of the result of the instruction. The cases handled are:

    • addi.w because it helps reduce test differences between LA32 and LA64 w/o being a pessimization.
  2. Or if explicit enabled or the target prefers instructions with W suffix, it adds the W suffix to the instruction whenever all users are dependent only on the lower word of the result of the instruction. The cases handled are:

    • add.d/addi.d/sub.d/mul.d.
    • slli.d with imm < 32.
    • ld.d/ld.wu.
llvmbot commented 2 weeks ago

@llvm/pr-subscribers-backend-loongarch

Author: hev (heiher)

Changes Referring to RISC-V, adding an MI level pass to optimize *W instructions for LoongArch. First it removes unneeded sext(addi.w rd, rs, 0) instructions. Either because the sign extended bits aren't consumed or because the input was already sign extended by an earlier instruction. Then: 1. Unless explicit disabled or the target prefers instructions with W suffix, it removes the -w suffix from opw instructions whenever all users are dependent only on the lower word of the result of the instruction. The cases handled are: * addi.w because it helps reduce test differences between LA32 and LA64 w/o being a pessimization. 2. Or if explicit enabled or the target prefers instructions with W suffix, it adds the W suffix to the instruction whenever all users are dependent only on the lower word of the result of the instruction. The cases handled are: * add.d/addi.d/sub.d/mul.d. * slli.d with imm < 32. * ld.d/ld.wu. --- Patch is 142.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/90463.diff 19 Files Affected: - (modified) llvm/lib/Target/LoongArch/CMakeLists.txt (+1) - (modified) llvm/lib/Target/LoongArch/LoongArch.h (+2) - (modified) llvm/lib/Target/LoongArch/LoongArch.td (+3) - (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+17-1) - (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp (+6) - (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.h (+3) - (modified) llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h (+9) - (added) llvm/lib/Target/LoongArch/LoongArchOptWInstrs.cpp (+815) - (modified) llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp (+10) - (modified) llvm/test/CodeGen/LoongArch/atomicrmw-uinc-udec-wrap.ll (+121-121) - (modified) llvm/test/CodeGen/LoongArch/gep-imm.ll (+3-5) - (modified) llvm/test/CodeGen/LoongArch/ir-instruction/add.ll (+6-6) - (modified) llvm/test/CodeGen/LoongArch/ir-instruction/atomic-cmpxchg.ll (+50-96) - (modified) llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-fp.ll (-40) - (modified) llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-minmax.ll (-80) - (modified) llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw.ll (-80) - (modified) llvm/test/CodeGen/LoongArch/preferred-alignments.ll (+3-3) - (modified) llvm/test/CodeGen/LoongArch/sextw-removal.ll (+554-32) - (modified) llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn (+1) ``````````diff diff --git a/llvm/lib/Target/LoongArch/CMakeLists.txt b/llvm/lib/Target/LoongArch/CMakeLists.txt index 5fb8b60be6c660..5085e23f82a7b6 100644 --- a/llvm/lib/Target/LoongArch/CMakeLists.txt +++ b/llvm/lib/Target/LoongArch/CMakeLists.txt @@ -23,6 +23,7 @@ add_llvm_target(LoongArchCodeGen LoongArchISelDAGToDAG.cpp LoongArchISelLowering.cpp LoongArchMCInstLower.cpp + LoongArchOptWInstrs.cpp LoongArchRegisterInfo.cpp LoongArchSubtarget.cpp LoongArchTargetMachine.cpp diff --git a/llvm/lib/Target/LoongArch/LoongArch.h b/llvm/lib/Target/LoongArch/LoongArch.h index 09ca089c91151b..2109176d499820 100644 --- a/llvm/lib/Target/LoongArch/LoongArch.h +++ b/llvm/lib/Target/LoongArch/LoongArch.h @@ -35,10 +35,12 @@ bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, FunctionPass *createLoongArchExpandAtomicPseudoPass(); FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM); +FunctionPass *createLoongArchOptWInstrsPass(); FunctionPass *createLoongArchPreRAExpandPseudoPass(); FunctionPass *createLoongArchExpandPseudoPass(); void initializeLoongArchDAGToDAGISelPass(PassRegistry &); void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &); +void initializeLoongArchOptWInstrsPass(PassRegistry &); void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &); void initializeLoongArchExpandPseudoPass(PassRegistry &); } // end namespace llvm diff --git a/llvm/lib/Target/LoongArch/LoongArch.td b/llvm/lib/Target/LoongArch/LoongArch.td index c2a669931d78fe..8a628157c6018d 100644 --- a/llvm/lib/Target/LoongArch/LoongArch.td +++ b/llvm/lib/Target/LoongArch/LoongArch.td @@ -117,6 +117,9 @@ def FeatureFrecipe "Support frecipe.{s/d} and frsqrte.{s/d} instructions.">; def HasFrecipe : Predicate<"Subtarget->hasFrecipe()">; +def TunePreferWInst + : SubtargetFeature<"prefer-w-inst", "PreferWInst", "true", + "Prefer instructions with W suffix">; //===----------------------------------------------------------------------===// // Registers, instruction descriptions ... diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 285d5c2a63b2da..c59385b3d8125c 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -3746,6 +3746,7 @@ static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL, + const ISD::InputArg &In, const LoongArchTargetLowering &TLI) { MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); @@ -3756,6 +3757,21 @@ static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain, RegInfo.addLiveIn(VA.getLocReg(), VReg); Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT); + // If input is sign extended from 32 bits, note it for the OptW pass. + if (In.isOrigArg()) { + Argument *OrigArg = MF.getFunction().getArg(In.getOrigArgIndex()); + if (OrigArg->getType()->isIntegerTy()) { + unsigned BitWidth = OrigArg->getType()->getIntegerBitWidth(); + // An input zero extended from i31 can also be considered sign extended. + if ((BitWidth <= 32 && In.Flags.isSExt()) || + (BitWidth < 32 && In.Flags.isZExt())) { + LoongArchMachineFunctionInfo *LAFI = + MF.getInfo(); + LAFI->addSExt32Register(VReg); + } + } + } + return convertLocVTToValVT(DAG, Val, VA, DL); } @@ -3887,7 +3903,7 @@ SDValue LoongArchTargetLowering::LowerFormalArguments( CCValAssign &VA = ArgLocs[i]; SDValue ArgValue; if (VA.isRegLoc()) - ArgValue = unpackFromRegLoc(DAG, Chain, VA, DL, *this); + ArgValue = unpackFromRegLoc(DAG, Chain, VA, DL, Ins[i], *this); else ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL); if (VA.getLocInfo() == CCValAssign::Indirect) { diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp index 6576100d3b3218..a0be29a2f744fd 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -534,3 +534,9 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { {MO_GD_PC_HI, "loongarch-gd-pc-hi"}}; return ArrayRef(TargetFlags); } + +// Returns true if this is the sext.w pattern, addi.w rd, rs, 0. +bool LoongArch::isSEXT_W(const MachineInstr &MI) { + return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() && + MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0; +} diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h index 4b145d0baa4171..3b80f55bc84fc5 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h @@ -90,6 +90,9 @@ class LoongArchInstrInfo : public LoongArchGenInstrInfo { namespace LoongArch { +// Returns true if this is the sext.w pattern, addi.w rd, rs, 0. +bool isSEXT_W(const MachineInstr &MI); + // Mask assignments for floating-point. static constexpr unsigned FClassMaskSignalingNaN = 0x001; static constexpr unsigned FClassMaskQuietNaN = 0x002; diff --git a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h index 0d819154a89c9e..a7366a5dba0412 100644 --- a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h +++ b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h @@ -36,6 +36,9 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo { /// insertIndirectBranch. int BranchRelaxationSpillFrameIndex = -1; + /// Registers that have been sign extended from i32. + SmallVector SExt32Registers; + public: LoongArchMachineFunctionInfo(const Function &F, const TargetSubtargetInfo *STI) {} @@ -62,6 +65,12 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo { void setBranchRelaxationSpillFrameIndex(int Index) { BranchRelaxationSpillFrameIndex = Index; } + + void addSExt32Register(Register Reg) { SExt32Registers.push_back(Reg); } + + bool isSExt32Register(Register Reg) const { + return is_contained(SExt32Registers, Reg); + } }; } // end namespace llvm diff --git a/llvm/lib/Target/LoongArch/LoongArchOptWInstrs.cpp b/llvm/lib/Target/LoongArch/LoongArchOptWInstrs.cpp new file mode 100644 index 00000000000000..677ba11c17d516 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchOptWInstrs.cpp @@ -0,0 +1,815 @@ +//===- LoongArchOptWInstrs.cpp - MI W instruction optimizations ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// +// +// This pass does some optimizations for *W instructions at the MI level. +// +// First it removes unneeded sext(addi.w rd, rs, 0) instructions. Either +// because the sign extended bits aren't consumed or because the input was +// already sign extended by an earlier instruction. +// +// Then: +// 1. Unless explicit disabled or the target prefers instructions with W suffix, +// it removes the -w suffix from opw instructions whenever all users are +// dependent only on the lower word of the result of the instruction. +// The cases handled are: +// * addi.w because it helps reduce test differences between LA32 and LA64 +// w/o being a pessimization. +// +// 2. Or if explicit enabled or the target prefers instructions with W suffix, +// it adds the W suffix to the instruction whenever all users are dependent +// only on the lower word of the result of the instruction. +// The cases handled are: +// * add.d/addi.d/sub.d/mul.d. +// * slli.d with imm < 32. +// * ld.d/ld.wu. +//===---------------------------------------------------------------------===// + +#include "LoongArch.h" +#include "LoongArchMachineFunctionInfo.h" +#include "LoongArchSubtarget.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/TargetInstrInfo.h" + +using namespace llvm; + +#define DEBUG_TYPE "loongarch-opt-w-instrs" +#define LOONGARCH_OPT_W_INSTRS_NAME "LoongArch Optimize W Instructions" + +STATISTIC(NumRemovedSExtW, "Number of removed sign-extensions"); +STATISTIC(NumTransformedToWInstrs, + "Number of instructions transformed to W-ops"); + +static cl::opt DisableSExtWRemoval("loongarch-disable-sextw-removal", + cl::desc("Disable removal of sext.w"), + cl::init(false), cl::Hidden); +static cl::opt DisableStripWSuffix("loongarch-disable-strip-w-suffix", + cl::desc("Disable strip W suffix"), + cl::init(false), cl::Hidden); + +namespace { + +class LoongArchOptWInstrs : public MachineFunctionPass { +public: + static char ID; + + LoongArchOptWInstrs() : MachineFunctionPass(ID) {} + + bool runOnMachineFunction(MachineFunction &MF) override; + bool removeSExtWInstrs(MachineFunction &MF, const LoongArchInstrInfo &TII, + const LoongArchSubtarget &ST, + MachineRegisterInfo &MRI); + bool stripWSuffixes(MachineFunction &MF, const LoongArchInstrInfo &TII, + const LoongArchSubtarget &ST, MachineRegisterInfo &MRI); + bool appendWSuffixes(MachineFunction &MF, const LoongArchInstrInfo &TII, + const LoongArchSubtarget &ST, MachineRegisterInfo &MRI); + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + StringRef getPassName() const override { return LOONGARCH_OPT_W_INSTRS_NAME; } +}; + +} // end anonymous namespace + +char LoongArchOptWInstrs::ID = 0; +INITIALIZE_PASS(LoongArchOptWInstrs, DEBUG_TYPE, LOONGARCH_OPT_W_INSTRS_NAME, + false, false) + +FunctionPass *llvm::createLoongArchOptWInstrsPass() { + return new LoongArchOptWInstrs(); +} + +// Checks if all users only demand the lower \p OrigBits of the original +// instruction's result. +// TODO: handle multiple interdependent transformations +static bool hasAllNBitUsers(const MachineInstr &OrigMI, + const LoongArchSubtarget &ST, + const MachineRegisterInfo &MRI, unsigned OrigBits) { + + SmallSet, 4> Visited; + SmallVector, 4> Worklist; + + Worklist.push_back(std::make_pair(&OrigMI, OrigBits)); + + while (!Worklist.empty()) { + auto P = Worklist.pop_back_val(); + const MachineInstr *MI = P.first; + unsigned Bits = P.second; + + if (!Visited.insert(P).second) + continue; + + // Only handle instructions with one def. + if (MI->getNumExplicitDefs() != 1) + return false; + + Register DestReg = MI->getOperand(0).getReg(); + if (!DestReg.isVirtual()) + return false; + + for (auto &UserOp : MRI.use_nodbg_operands(DestReg)) { + const MachineInstr *UserMI = UserOp.getParent(); + unsigned OpIdx = UserOp.getOperandNo(); + + switch (UserMI->getOpcode()) { + default: + // TODO: Add vector + return false; + + case LoongArch::ADD_W: + case LoongArch::ADDI_W: + case LoongArch::SUB_W: + case LoongArch::ALSL_W: + case LoongArch::ALSL_WU: + case LoongArch::MUL_W: + case LoongArch::MULH_W: + case LoongArch::MULH_WU: + case LoongArch::MULW_D_W: + case LoongArch::MULW_D_WU: + // TODO: {DIV,MOD}.{W,WU} consumes the upper 32 bits before LA664+. + // case LoongArch::DIV_W: + // case LoongArch::DIV_WU: + // case LoongArch::MOD_W: + // case LoongArch::MOD_WU: + case LoongArch::SLL_W: + case LoongArch::SLLI_W: + case LoongArch::SRL_W: + case LoongArch::SRLI_W: + case LoongArch::SRA_W: + case LoongArch::SRAI_W: + case LoongArch::ROTR_W: + case LoongArch::ROTRI_W: + case LoongArch::CLO_W: + case LoongArch::CLZ_W: + case LoongArch::CTO_W: + case LoongArch::CTZ_W: + case LoongArch::BYTEPICK_W: + case LoongArch::REVB_2H: + case LoongArch::BITREV_4B: + case LoongArch::BITREV_W: + case LoongArch::BSTRINS_W: + case LoongArch::BSTRPICK_W: + case LoongArch::CRC_W_W_W: + case LoongArch::CRCC_W_W_W: + case LoongArch::MOVGR2FCSR: + case LoongArch::MOVGR2FRH_W: + case LoongArch::MOVGR2FR_W_64: + if (Bits >= 32) + break; + return false; + case LoongArch::MOVGR2CF: + if (Bits >= 1) + break; + return false; + case LoongArch::EXT_W_B: + if (Bits >= 8) + break; + return false; + case LoongArch::EXT_W_H: + if (Bits >= 16) + break; + return false; + + case LoongArch::SRLI_D: { + // If we are shifting right by less than Bits, and users don't demand + // any bits that were shifted into [Bits-1:0], then we can consider this + // as an N-Bit user. + unsigned ShAmt = UserMI->getOperand(2).getImm(); + if (Bits > ShAmt) { + Worklist.push_back(std::make_pair(UserMI, Bits - ShAmt)); + break; + } + return false; + } + + // these overwrite higher input bits, otherwise the lower word of output + // depends only on the lower word of input. So check their uses read W. + case LoongArch::SLLI_D: + if (Bits >= (ST.getGRLen() - UserMI->getOperand(2).getImm())) + break; + Worklist.push_back(std::make_pair(UserMI, Bits)); + break; + case LoongArch::ANDI: { + uint64_t Imm = UserMI->getOperand(2).getImm(); + if (Bits >= (unsigned)llvm::bit_width(Imm)) + break; + Worklist.push_back(std::make_pair(UserMI, Bits)); + break; + } + case LoongArch::ORI: { + uint64_t Imm = UserMI->getOperand(2).getImm(); + if (Bits >= (unsigned)llvm::bit_width(~Imm)) + break; + Worklist.push_back(std::make_pair(UserMI, Bits)); + break; + } + + case LoongArch::SLL_D: + // Operand 2 is the shift amount which uses log2(grlen) bits. + if (OpIdx == 2) { + if (Bits >= Log2_32(ST.getGRLen())) + break; + return false; + } + Worklist.push_back(std::make_pair(UserMI, Bits)); + break; + + case LoongArch::SRA_D: + case LoongArch::SRL_D: + case LoongArch::ROTR_D: + // Operand 2 is the shift amount which uses 6 bits. + if (OpIdx == 2 && Bits >= Log2_32(ST.getGRLen())) + break; + return false; + + case LoongArch::ST_B: + case LoongArch::STX_B: + case LoongArch::STGT_B: + case LoongArch::STLE_B: + case LoongArch::IOCSRWR_B: + // The first argument is the value to store. + if (OpIdx == 0 && Bits >= 8) + break; + return false; + case LoongArch::ST_H: + case LoongArch::STX_H: + case LoongArch::STGT_H: + case LoongArch::STLE_H: + case LoongArch::IOCSRWR_H: + // The first argument is the value to store. + if (OpIdx == 0 && Bits >= 16) + break; + return false; + case LoongArch::ST_W: + case LoongArch::STX_W: + case LoongArch::SCREL_W: + case LoongArch::STPTR_W: + case LoongArch::STGT_W: + case LoongArch::STLE_W: + case LoongArch::IOCSRWR_W: + // The first argument is the value to store. + if (OpIdx == 0 && Bits >= 32) + break; + return false; + + case LoongArch::CRC_W_B_W: + case LoongArch::CRCC_W_B_W: + if ((OpIdx == 1 && Bits >= 8) || (OpIdx == 2 && Bits >= 32)) + break; + return false; + case LoongArch::CRC_W_H_W: + case LoongArch::CRCC_W_H_W: + if ((OpIdx == 1 && Bits >= 16) || (OpIdx == 2 && Bits >= 32)) + break; + return false; + case LoongArch::CRC_W_D_W: + case LoongArch::CRCC_W_D_W: + if (OpIdx == 2 && Bits >= 32) + break; + return false; + + // For these, lower word of output in these operations, depends only on + // the lower word of input. So, we check all uses only read lower word. + case LoongArch::COPY: + case LoongArch::PHI: + case LoongArch::ADD_D: + case LoongArch::ADDI_D: + case LoongArch::SUB_D: + case LoongArch::MUL_D: + case LoongArch::AND: + case LoongArch::OR: + case LoongArch::NOR: + case LoongArch::XOR: + case LoongArch::XORI: + case LoongArch::ANDN: + case LoongArch::ORN: + Worklist.push_back(std::make_pair(UserMI, Bits)); + break; + + case LoongArch::MASKNEZ: + case LoongArch::MASKEQZ: + if (OpIdx != 1) + return false; + Worklist.push_back(std::make_pair(UserMI, Bits)); + break; + } + } + } + + return true; +} + +static bool hasAllWUsers(const MachineInstr &OrigMI, + const LoongArchSubtarget &ST, + const MachineRegisterInfo &MRI) { + return hasAllNBitUsers(OrigMI, ST, MRI, 32); +} + +// This function returns true if the machine instruction always outputs a value +// where bits 63:32 match bit 31. +static bool isSignExtendingOpW(const MachineInstr &MI, + const MachineRegisterInfo &MRI, unsigned OpNo) { + switch (MI.getOpcode()) { + // Normal cases + case LoongArch::ADD_W: + case LoongArch::SUB_W: + case LoongArch::ADDI_W: + case LoongArch::ALSL_W: + case LoongArch::LU12I_W: + case LoongArch::SLT: + case LoongArch::SLTU: + case LoongArch::SLTI: + case LoongArch::SLTUI: + case LoongArch::ANDI: + case LoongArch::MUL_W: + case LoongArch::MULH_W: + case LoongArch::MULH_WU: + case LoongArch::DIV_W: + case LoongArch::MOD_W: + case LoongArch::DIV_WU: + case LoongArch::MOD_WU: + case LoongArch::SLL_W: + case LoongArch::SRL_W: + case LoongArch::SRA_W: + case LoongArch::ROTR_W: + case LoongArch::SLLI_W: + case LoongArch::SRLI_W: + case LoongArch::SRAI_W: + case LoongArch::ROTRI_W: + case LoongArch::EXT_W_B: + case LoongArch::EXT_W_H: + case LoongArch::CLO_W: + case LoongArch::CLZ_W: + case LoongArch::CTO_W: + case LoongArch::CTZ_W: + case LoongArch::BYTEPICK_W: + case LoongArch::REVB_2H: + case LoongArch::BITREV_4B: + case LoongArch::BITREV_W: + case LoongArch::BSTRINS_W: + case LoongArch::BSTRPICK_W: + case LoongArch::LD_B: + case LoongArch::LD_H: + case LoongArch::LD_W: + case LoongArch::LD_BU: + case LoongArch::LD_HU: + case LoongArch::LL_W: + case LoongArch::LLACQ_W: + case LoongArch::RDTIMEL_W: + case LoongArch::RDTIMEH_W: + case LoongArch::CPUCFG: + case LoongArch::LDX_B: + case LoongArch::LDX_H: + case LoongArch::LDX_W: + case LoongArch::LDX_BU: + case LoongArch::LDX_HU: + case LoongArch::LDPTR_W: + case LoongArch::LDGT_B: + case LoongArch::LDGT_H: + case LoongArch::LDGT_W: + case LoongArch::LDLE_B: + case LoongArch::LDLE_H: + case LoongArch::LDLE_W: + case LoongArch::AMSWAP_B: + case LoongArch::AMSWAP_H: + case LoongArch::AMSWAP_W: + case LoongArch::AMADD_B: + case LoongArch::AMADD_H: + case LoongArch::AMADD_W: + case LoongArch::AMAND_W: + case LoongArch::AMOR_W: + case LoongArch::AMXOR_W: + case LoongArch::AMMAX_W: + case LoongArch::AMMIN_W: + case LoongArch::AMMAX_WU: + case LoongArch::AMMIN_WU: + case LoongArch::AMSWAP__DB_B: + case LoongArch::AMSWAP__DB_H: + case LoongArch::AMSWAP__DB_W: + case LoongArch::AMADD__DB_B: + case LoongArch::AMADD__DB_H: + case LoongArch::AMADD__DB_W: + case LoongArch::AMAND__DB_W: + case LoongArch::AMOR__DB_W: + case LoongArch::AMXOR__DB_W: + case LoongArch::AMMAX__DB_W: + case LoongArch::AMMIN__DB_W: + case LoongArch::AMMAX__DB_WU: + case LoongArch::AMMIN__DB_WU: + case LoongArch::AMCAS... [truncated] ``````````