Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandAtomicPseudoInsts.cpp
35269 views
//==- LoongArchExpandAtomicPseudoInsts.cpp - Expand atomic pseudo instrs. -===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a pass that expands atomic pseudo instructions into9// target instructions. This pass should be run at the last possible moment,10// avoiding the possibility for other passes to break the requirements for11// forward progress in the LL/SC block.12//13//===----------------------------------------------------------------------===//1415#include "LoongArch.h"16#include "LoongArchInstrInfo.h"17#include "LoongArchTargetMachine.h"1819#include "llvm/CodeGen/LivePhysRegs.h"20#include "llvm/CodeGen/MachineFunctionPass.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"2223using namespace llvm;2425#define LoongArch_EXPAND_ATOMIC_PSEUDO_NAME \26"LoongArch atomic pseudo instruction expansion pass"2728namespace {2930class LoongArchExpandAtomicPseudo : public MachineFunctionPass {31public:32const LoongArchInstrInfo *TII;33static char ID;3435LoongArchExpandAtomicPseudo() : MachineFunctionPass(ID) {36initializeLoongArchExpandAtomicPseudoPass(*PassRegistry::getPassRegistry());37}3839bool runOnMachineFunction(MachineFunction &MF) override;4041StringRef getPassName() const override {42return LoongArch_EXPAND_ATOMIC_PSEUDO_NAME;43}4445private:46bool expandMBB(MachineBasicBlock &MBB);47bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,48MachineBasicBlock::iterator &NextMBBI);49bool expandAtomicBinOp(MachineBasicBlock &MBB,50MachineBasicBlock::iterator MBBI, AtomicRMWInst::BinOp,51bool IsMasked, int Width,52MachineBasicBlock::iterator &NextMBBI);53bool expandAtomicMinMaxOp(MachineBasicBlock &MBB,54MachineBasicBlock::iterator MBBI,55AtomicRMWInst::BinOp, bool IsMasked, int Width,56MachineBasicBlock::iterator &NextMBBI);57bool expandAtomicCmpXchg(MachineBasicBlock &MBB,58MachineBasicBlock::iterator MBBI, bool IsMasked,59int Width, MachineBasicBlock::iterator &NextMBBI);60};6162char LoongArchExpandAtomicPseudo::ID = 0;6364bool LoongArchExpandAtomicPseudo::runOnMachineFunction(MachineFunction &MF) {65TII =66static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());67bool Modified = false;68for (auto &MBB : MF)69Modified |= expandMBB(MBB);70return Modified;71}7273bool LoongArchExpandAtomicPseudo::expandMBB(MachineBasicBlock &MBB) {74bool Modified = false;7576MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();77while (MBBI != E) {78MachineBasicBlock::iterator NMBBI = std::next(MBBI);79Modified |= expandMI(MBB, MBBI, NMBBI);80MBBI = NMBBI;81}8283return Modified;84}8586bool LoongArchExpandAtomicPseudo::expandMI(87MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,88MachineBasicBlock::iterator &NextMBBI) {89switch (MBBI->getOpcode()) {90case LoongArch::PseudoMaskedAtomicSwap32:91return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, true, 32,92NextMBBI);93case LoongArch::PseudoAtomicSwap32:94return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, false, 32,95NextMBBI);96case LoongArch::PseudoMaskedAtomicLoadAdd32:97return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, true, 32, NextMBBI);98case LoongArch::PseudoMaskedAtomicLoadSub32:99return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, true, 32, NextMBBI);100case LoongArch::PseudoAtomicLoadNand32:101return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 32,102NextMBBI);103case LoongArch::PseudoAtomicLoadNand64:104return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 64,105NextMBBI);106case LoongArch::PseudoMaskedAtomicLoadNand32:107return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, true, 32,108NextMBBI);109case LoongArch::PseudoAtomicLoadAdd32:110return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, false, 32,111NextMBBI);112case LoongArch::PseudoAtomicLoadSub32:113return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, false, 32,114NextMBBI);115case LoongArch::PseudoAtomicLoadAnd32:116return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::And, false, 32,117NextMBBI);118case LoongArch::PseudoAtomicLoadOr32:119return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Or, false, 32, NextMBBI);120case LoongArch::PseudoAtomicLoadXor32:121return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xor, false, 32,122NextMBBI);123case LoongArch::PseudoMaskedAtomicLoadUMax32:124return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMax, true, 32,125NextMBBI);126case LoongArch::PseudoMaskedAtomicLoadUMin32:127return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMin, true, 32,128NextMBBI);129case LoongArch::PseudoCmpXchg32:130return expandAtomicCmpXchg(MBB, MBBI, false, 32, NextMBBI);131case LoongArch::PseudoCmpXchg64:132return expandAtomicCmpXchg(MBB, MBBI, false, 64, NextMBBI);133case LoongArch::PseudoMaskedCmpXchg32:134return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI);135case LoongArch::PseudoMaskedAtomicLoadMax32:136return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Max, true, 32,137NextMBBI);138case LoongArch::PseudoMaskedAtomicLoadMin32:139return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Min, true, 32,140NextMBBI);141}142return false;143}144145static void doAtomicBinOpExpansion(const LoongArchInstrInfo *TII,146MachineInstr &MI, DebugLoc DL,147MachineBasicBlock *ThisMBB,148MachineBasicBlock *LoopMBB,149MachineBasicBlock *DoneMBB,150AtomicRMWInst::BinOp BinOp, int Width) {151Register DestReg = MI.getOperand(0).getReg();152Register ScratchReg = MI.getOperand(1).getReg();153Register AddrReg = MI.getOperand(2).getReg();154Register IncrReg = MI.getOperand(3).getReg();155156// .loop:157// ll.[w|d] dest, (addr)158// binop scratch, dest, val159// sc.[w|d] scratch, scratch, (addr)160// beqz scratch, loop161BuildMI(LoopMBB, DL,162TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)163.addReg(AddrReg)164.addImm(0);165switch (BinOp) {166default:167llvm_unreachable("Unexpected AtomicRMW BinOp");168case AtomicRMWInst::Xchg:169BuildMI(LoopMBB, DL, TII->get(LoongArch::OR), ScratchReg)170.addReg(IncrReg)171.addReg(LoongArch::R0);172break;173case AtomicRMWInst::Nand:174BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)175.addReg(DestReg)176.addReg(IncrReg);177BuildMI(LoopMBB, DL, TII->get(LoongArch::NOR), ScratchReg)178.addReg(ScratchReg)179.addReg(LoongArch::R0);180break;181case AtomicRMWInst::Add:182BuildMI(LoopMBB, DL, TII->get(LoongArch::ADD_W), ScratchReg)183.addReg(DestReg)184.addReg(IncrReg);185break;186case AtomicRMWInst::Sub:187BuildMI(LoopMBB, DL, TII->get(LoongArch::SUB_W), ScratchReg)188.addReg(DestReg)189.addReg(IncrReg);190break;191case AtomicRMWInst::And:192BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)193.addReg(DestReg)194.addReg(IncrReg);195break;196case AtomicRMWInst::Or:197BuildMI(LoopMBB, DL, TII->get(LoongArch::OR), ScratchReg)198.addReg(DestReg)199.addReg(IncrReg);200break;201case AtomicRMWInst::Xor:202BuildMI(LoopMBB, DL, TII->get(LoongArch::XOR), ScratchReg)203.addReg(DestReg)204.addReg(IncrReg);205break;206}207BuildMI(LoopMBB, DL,208TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D), ScratchReg)209.addReg(ScratchReg)210.addReg(AddrReg)211.addImm(0);212BuildMI(LoopMBB, DL, TII->get(LoongArch::BEQZ))213.addReg(ScratchReg)214.addMBB(LoopMBB);215}216217static void insertMaskedMerge(const LoongArchInstrInfo *TII, DebugLoc DL,218MachineBasicBlock *MBB, Register DestReg,219Register OldValReg, Register NewValReg,220Register MaskReg, Register ScratchReg) {221assert(OldValReg != ScratchReg && "OldValReg and ScratchReg must be unique");222assert(OldValReg != MaskReg && "OldValReg and MaskReg must be unique");223assert(ScratchReg != MaskReg && "ScratchReg and MaskReg must be unique");224225// res = oldval ^ ((oldval ^ newval) & masktargetdata);226BuildMI(MBB, DL, TII->get(LoongArch::XOR), ScratchReg)227.addReg(OldValReg)228.addReg(NewValReg);229BuildMI(MBB, DL, TII->get(LoongArch::AND), ScratchReg)230.addReg(ScratchReg)231.addReg(MaskReg);232BuildMI(MBB, DL, TII->get(LoongArch::XOR), DestReg)233.addReg(OldValReg)234.addReg(ScratchReg);235}236237static void doMaskedAtomicBinOpExpansion(238const LoongArchInstrInfo *TII, MachineInstr &MI, DebugLoc DL,239MachineBasicBlock *ThisMBB, MachineBasicBlock *LoopMBB,240MachineBasicBlock *DoneMBB, AtomicRMWInst::BinOp BinOp, int Width) {241assert(Width == 32 && "Should never need to expand masked 64-bit operations");242Register DestReg = MI.getOperand(0).getReg();243Register ScratchReg = MI.getOperand(1).getReg();244Register AddrReg = MI.getOperand(2).getReg();245Register IncrReg = MI.getOperand(3).getReg();246Register MaskReg = MI.getOperand(4).getReg();247248// .loop:249// ll.w destreg, (alignedaddr)250// binop scratch, destreg, incr251// xor scratch, destreg, scratch252// and scratch, scratch, masktargetdata253// xor scratch, destreg, scratch254// sc.w scratch, scratch, (alignedaddr)255// beqz scratch, loop256BuildMI(LoopMBB, DL, TII->get(LoongArch::LL_W), DestReg)257.addReg(AddrReg)258.addImm(0);259switch (BinOp) {260default:261llvm_unreachable("Unexpected AtomicRMW BinOp");262case AtomicRMWInst::Xchg:263BuildMI(LoopMBB, DL, TII->get(LoongArch::ADDI_W), ScratchReg)264.addReg(IncrReg)265.addImm(0);266break;267case AtomicRMWInst::Add:268BuildMI(LoopMBB, DL, TII->get(LoongArch::ADD_W), ScratchReg)269.addReg(DestReg)270.addReg(IncrReg);271break;272case AtomicRMWInst::Sub:273BuildMI(LoopMBB, DL, TII->get(LoongArch::SUB_W), ScratchReg)274.addReg(DestReg)275.addReg(IncrReg);276break;277case AtomicRMWInst::Nand:278BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)279.addReg(DestReg)280.addReg(IncrReg);281BuildMI(LoopMBB, DL, TII->get(LoongArch::NOR), ScratchReg)282.addReg(ScratchReg)283.addReg(LoongArch::R0);284// TODO: support other AtomicRMWInst.285}286287insertMaskedMerge(TII, DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg,288ScratchReg);289290BuildMI(LoopMBB, DL, TII->get(LoongArch::SC_W), ScratchReg)291.addReg(ScratchReg)292.addReg(AddrReg)293.addImm(0);294BuildMI(LoopMBB, DL, TII->get(LoongArch::BEQZ))295.addReg(ScratchReg)296.addMBB(LoopMBB);297}298299bool LoongArchExpandAtomicPseudo::expandAtomicBinOp(300MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,301AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,302MachineBasicBlock::iterator &NextMBBI) {303MachineInstr &MI = *MBBI;304DebugLoc DL = MI.getDebugLoc();305306MachineFunction *MF = MBB.getParent();307auto LoopMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());308auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());309310// Insert new MBBs.311MF->insert(++MBB.getIterator(), LoopMBB);312MF->insert(++LoopMBB->getIterator(), DoneMBB);313314// Set up successors and transfer remaining instructions to DoneMBB.315LoopMBB->addSuccessor(LoopMBB);316LoopMBB->addSuccessor(DoneMBB);317DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());318DoneMBB->transferSuccessors(&MBB);319MBB.addSuccessor(LoopMBB);320321if (IsMasked)322doMaskedAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp,323Width);324else325doAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp, Width);326327NextMBBI = MBB.end();328MI.eraseFromParent();329330LivePhysRegs LiveRegs;331computeAndAddLiveIns(LiveRegs, *LoopMBB);332computeAndAddLiveIns(LiveRegs, *DoneMBB);333334return true;335}336337static void insertSext(const LoongArchInstrInfo *TII, DebugLoc DL,338MachineBasicBlock *MBB, Register ValReg,339Register ShamtReg) {340BuildMI(MBB, DL, TII->get(LoongArch::SLL_W), ValReg)341.addReg(ValReg)342.addReg(ShamtReg);343BuildMI(MBB, DL, TII->get(LoongArch::SRA_W), ValReg)344.addReg(ValReg)345.addReg(ShamtReg);346}347348bool LoongArchExpandAtomicPseudo::expandAtomicMinMaxOp(349MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,350AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,351MachineBasicBlock::iterator &NextMBBI) {352assert(IsMasked == true &&353"Should only need to expand masked atomic max/min");354assert(Width == 32 && "Should never need to expand masked 64-bit operations");355356MachineInstr &MI = *MBBI;357DebugLoc DL = MI.getDebugLoc();358MachineFunction *MF = MBB.getParent();359auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());360auto LoopIfBodyMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());361auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());362auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());363364// Insert new MBBs.365MF->insert(++MBB.getIterator(), LoopHeadMBB);366MF->insert(++LoopHeadMBB->getIterator(), LoopIfBodyMBB);367MF->insert(++LoopIfBodyMBB->getIterator(), LoopTailMBB);368MF->insert(++LoopTailMBB->getIterator(), DoneMBB);369370// Set up successors and transfer remaining instructions to DoneMBB.371LoopHeadMBB->addSuccessor(LoopIfBodyMBB);372LoopHeadMBB->addSuccessor(LoopTailMBB);373LoopIfBodyMBB->addSuccessor(LoopTailMBB);374LoopTailMBB->addSuccessor(LoopHeadMBB);375LoopTailMBB->addSuccessor(DoneMBB);376DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());377DoneMBB->transferSuccessors(&MBB);378MBB.addSuccessor(LoopHeadMBB);379380Register DestReg = MI.getOperand(0).getReg();381Register Scratch1Reg = MI.getOperand(1).getReg();382Register Scratch2Reg = MI.getOperand(2).getReg();383Register AddrReg = MI.getOperand(3).getReg();384Register IncrReg = MI.getOperand(4).getReg();385Register MaskReg = MI.getOperand(5).getReg();386387//388// .loophead:389// ll.w destreg, (alignedaddr)390// and scratch2, destreg, mask391// move scratch1, destreg392BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::LL_W), DestReg)393.addReg(AddrReg)394.addImm(0);395BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::AND), Scratch2Reg)396.addReg(DestReg)397.addReg(MaskReg);398BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::OR), Scratch1Reg)399.addReg(DestReg)400.addReg(LoongArch::R0);401402switch (BinOp) {403default:404llvm_unreachable("Unexpected AtomicRMW BinOp");405// bgeu scratch2, incr, .looptail406case AtomicRMWInst::UMax:407BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGEU))408.addReg(Scratch2Reg)409.addReg(IncrReg)410.addMBB(LoopTailMBB);411break;412// bgeu incr, scratch2, .looptail413case AtomicRMWInst::UMin:414BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGEU))415.addReg(IncrReg)416.addReg(Scratch2Reg)417.addMBB(LoopTailMBB);418break;419case AtomicRMWInst::Max:420insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());421// bge scratch2, incr, .looptail422BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGE))423.addReg(Scratch2Reg)424.addReg(IncrReg)425.addMBB(LoopTailMBB);426break;427case AtomicRMWInst::Min:428insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());429// bge incr, scratch2, .looptail430BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGE))431.addReg(IncrReg)432.addReg(Scratch2Reg)433.addMBB(LoopTailMBB);434break;435// TODO: support other AtomicRMWInst.436}437438// .loopifbody:439// xor scratch1, destreg, incr440// and scratch1, scratch1, mask441// xor scratch1, destreg, scratch1442insertMaskedMerge(TII, DL, LoopIfBodyMBB, Scratch1Reg, DestReg, IncrReg,443MaskReg, Scratch1Reg);444445// .looptail:446// sc.w scratch1, scratch1, (addr)447// beqz scratch1, loop448BuildMI(LoopTailMBB, DL, TII->get(LoongArch::SC_W), Scratch1Reg)449.addReg(Scratch1Reg)450.addReg(AddrReg)451.addImm(0);452BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))453.addReg(Scratch1Reg)454.addMBB(LoopHeadMBB);455456NextMBBI = MBB.end();457MI.eraseFromParent();458459LivePhysRegs LiveRegs;460computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);461computeAndAddLiveIns(LiveRegs, *LoopIfBodyMBB);462computeAndAddLiveIns(LiveRegs, *LoopTailMBB);463computeAndAddLiveIns(LiveRegs, *DoneMBB);464465return true;466}467468bool LoongArchExpandAtomicPseudo::expandAtomicCmpXchg(469MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsMasked,470int Width, MachineBasicBlock::iterator &NextMBBI) {471MachineInstr &MI = *MBBI;472DebugLoc DL = MI.getDebugLoc();473MachineFunction *MF = MBB.getParent();474auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());475auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());476auto TailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());477auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());478479// Insert new MBBs.480MF->insert(++MBB.getIterator(), LoopHeadMBB);481MF->insert(++LoopHeadMBB->getIterator(), LoopTailMBB);482MF->insert(++LoopTailMBB->getIterator(), TailMBB);483MF->insert(++TailMBB->getIterator(), DoneMBB);484485// Set up successors and transfer remaining instructions to DoneMBB.486LoopHeadMBB->addSuccessor(LoopTailMBB);487LoopHeadMBB->addSuccessor(TailMBB);488LoopTailMBB->addSuccessor(DoneMBB);489LoopTailMBB->addSuccessor(LoopHeadMBB);490TailMBB->addSuccessor(DoneMBB);491DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());492DoneMBB->transferSuccessors(&MBB);493MBB.addSuccessor(LoopHeadMBB);494495Register DestReg = MI.getOperand(0).getReg();496Register ScratchReg = MI.getOperand(1).getReg();497Register AddrReg = MI.getOperand(2).getReg();498Register CmpValReg = MI.getOperand(3).getReg();499Register NewValReg = MI.getOperand(4).getReg();500501if (!IsMasked) {502// .loophead:503// ll.[w|d] dest, (addr)504// bne dest, cmpval, tail505BuildMI(LoopHeadMBB, DL,506TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)507.addReg(AddrReg)508.addImm(0);509BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BNE))510.addReg(DestReg)511.addReg(CmpValReg)512.addMBB(TailMBB);513// .looptail:514// move scratch, newval515// sc.[w|d] scratch, scratch, (addr)516// beqz scratch, loophead517// b done518BuildMI(LoopTailMBB, DL, TII->get(LoongArch::OR), ScratchReg)519.addReg(NewValReg)520.addReg(LoongArch::R0);521BuildMI(LoopTailMBB, DL,522TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D),523ScratchReg)524.addReg(ScratchReg)525.addReg(AddrReg)526.addImm(0);527BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))528.addReg(ScratchReg)529.addMBB(LoopHeadMBB);530BuildMI(LoopTailMBB, DL, TII->get(LoongArch::B)).addMBB(DoneMBB);531} else {532// .loophead:533// ll.[w|d] dest, (addr)534// and scratch, dest, mask535// bne scratch, cmpval, tail536Register MaskReg = MI.getOperand(5).getReg();537BuildMI(LoopHeadMBB, DL,538TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)539.addReg(AddrReg)540.addImm(0);541BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::AND), ScratchReg)542.addReg(DestReg)543.addReg(MaskReg);544BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BNE))545.addReg(ScratchReg)546.addReg(CmpValReg)547.addMBB(TailMBB);548549// .looptail:550// andn scratch, dest, mask551// or scratch, scratch, newval552// sc.[w|d] scratch, scratch, (addr)553// beqz scratch, loophead554// b done555BuildMI(LoopTailMBB, DL, TII->get(LoongArch::ANDN), ScratchReg)556.addReg(DestReg)557.addReg(MaskReg);558BuildMI(LoopTailMBB, DL, TII->get(LoongArch::OR), ScratchReg)559.addReg(ScratchReg)560.addReg(NewValReg);561BuildMI(LoopTailMBB, DL,562TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D),563ScratchReg)564.addReg(ScratchReg)565.addReg(AddrReg)566.addImm(0);567BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))568.addReg(ScratchReg)569.addMBB(LoopHeadMBB);570BuildMI(LoopTailMBB, DL, TII->get(LoongArch::B)).addMBB(DoneMBB);571}572573AtomicOrdering FailureOrdering =574static_cast<AtomicOrdering>(MI.getOperand(IsMasked ? 6 : 5).getImm());575int hint;576577switch (FailureOrdering) {578case AtomicOrdering::Acquire:579case AtomicOrdering::AcquireRelease:580case AtomicOrdering::SequentiallyConsistent:581// acquire582hint = 0b10100;583break;584default:585hint = 0x700;586}587588// .tail:589// dbar 0x700 | acquire590BuildMI(TailMBB, DL, TII->get(LoongArch::DBAR)).addImm(hint);591592NextMBBI = MBB.end();593MI.eraseFromParent();594595LivePhysRegs LiveRegs;596computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);597computeAndAddLiveIns(LiveRegs, *LoopTailMBB);598computeAndAddLiveIns(LiveRegs, *TailMBB);599computeAndAddLiveIns(LiveRegs, *DoneMBB);600601return true;602}603604} // end namespace605606INITIALIZE_PASS(LoongArchExpandAtomicPseudo, "loongarch-expand-atomic-pseudo",607LoongArch_EXPAND_ATOMIC_PSEUDO_NAME, false, false)608609namespace llvm {610611FunctionPass *createLoongArchExpandAtomicPseudoPass() {612return new LoongArchExpandAtomicPseudo();613}614615} // end namespace llvm616617618