[llvm-branch-commits] [llvm] [LoongArch] Add memory barrier optimization pass (PR #218597)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Sep 9 19:48:57 PDT 2026
https://github.com/heiher updated https://github.com/llvm/llvm-project/pull/218597
>From c1b6f774b5781ca2ced34430866f10a481c54c82 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Mon, 17 Aug 2026 14:04:22 +0800
Subject: [PATCH 1/5] [LoongArch] Add memory barrier optimization pass
Add a machine-level pass to remove redundant DBARs and merge them
with atomic memory operations. The pass uses machine dominator and
post-dominator trees to ensure the transformation is safe across
basic blocks.
---
llvm/lib/Target/LoongArch/CMakeLists.txt | 1 +
llvm/lib/Target/LoongArch/LoongArch.h | 2 +
.../LoongArch/LoongArchMemoryBarrierOpt.cpp | 645 ++++++++++++
.../LoongArch/LoongArchTargetMachine.cpp | 3 +
.../CodeGen/LoongArch/memory-barrier-opt.ll | 987 ++++++++++++++----
llvm/test/CodeGen/LoongArch/opt-pipeline.ll | 3 +
.../llvm/lib/Target/LoongArch/BUILD.gn | 1 +
7 files changed, 1437 insertions(+), 205 deletions(-)
create mode 100644 llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
diff --git a/llvm/lib/Target/LoongArch/CMakeLists.txt b/llvm/lib/Target/LoongArch/CMakeLists.txt
index c856173ca89de..e720afb7aab45 100644
--- a/llvm/lib/Target/LoongArch/CMakeLists.txt
+++ b/llvm/lib/Target/LoongArch/CMakeLists.txt
@@ -25,6 +25,7 @@ add_llvm_target(LoongArchCodeGen
LoongArchISelDAGToDAG.cpp
LoongArchISelLowering.cpp
LoongArchMCInstLower.cpp
+ LoongArchMemoryBarrierOpt.cpp
LoongArchMergeBaseOffset.cpp
LoongArchOptWInstrs.cpp
LoongArchRegisterInfo.cpp
diff --git a/llvm/lib/Target/LoongArch/LoongArch.h b/llvm/lib/Target/LoongArch/LoongArch.h
index e5b3083348792..b5534b535b54b 100644
--- a/llvm/lib/Target/LoongArch/LoongArch.h
+++ b/llvm/lib/Target/LoongArch/LoongArch.h
@@ -37,6 +37,7 @@ FunctionPass *createLoongArchDeadRegisterDefinitionsPass();
FunctionPass *createLoongArchExpandAtomicPseudoPass();
FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM,
CodeGenOptLevel OptLevel);
+FunctionPass *createLoongArchMemoryBarrierOptPass();
FunctionPass *createLoongArchMergeBaseOffsetOptPass();
FunctionPass *createLoongArchOptWInstrsPass();
FunctionPass *createLoongArchPreRAExpandPseudoPass();
@@ -45,6 +46,7 @@ void initializeLoongArchAsmPrinterPass(PassRegistry &);
void initializeLoongArchDAGToDAGISelLegacyPass(PassRegistry &);
void initializeLoongArchDeadRegisterDefinitionsPass(PassRegistry &);
void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &);
+void initializeLoongArchMemoryBarrierOptPass(PassRegistry &);
void initializeLoongArchMergeBaseOffsetOptPass(PassRegistry &);
void initializeLoongArchOptWInstrsPass(PassRegistry &);
void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &);
diff --git a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
new file mode 100644
index 0000000000000..1f29cdc8638c1
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
@@ -0,0 +1,645 @@
+//===---- LoongArchMemoryBarrierOpt.cpp - Memory barrier Optimization -----===//
+//
+// 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 removes or merges redundant memory barrier instructions.
+///
+/// - DBAR x + DBAR y -> DBAR (x & y)
+/// - DBAR x + AMO_DB -> AMO_DB
+/// - DBAR x + AMO -> AMO_DB
+/// - DBAR x + LL -> LL
+/// - AMO_DB + DBAR x -> AMO_DB
+/// - AMO + DBAR x -> AMO_DB
+/// - SC + DBAR x -> SC
+///
+//===----------------------------------------------------------------------===//
+
+#include "LoongArch.h"
+#include "LoongArchInstrInfo.h"
+#include "LoongArchSubtarget.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachinePostDominators.h"
+#include "llvm/InitializePasses.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-memory-barrier-opt"
+#define LOONGARCH_MEMORY_BARRIER_OPT_NAME \
+ "LoongArch Memory Barrier Optimisation pass"
+
+static cl::opt<bool> RequireNoPathBypass(
+ "loongarch-require-no-path-bypass",
+ cl::desc("Optimize only when no paths bypass either memory barrier"),
+ cl::init(true), cl::Hidden);
+
+static cl::opt<bool> DisableInlineAsm(
+ "loongarch-disable-inline-asm-barrier-opt",
+ cl::desc("Disable optimization of memory barriers in InlineAsm"),
+ cl::init(false), cl::Hidden);
+
+static cl::opt<bool> ReplaceEliminatedMBToNop(
+ "loongarch-replace-eliminated-dbar-to-nop",
+ cl::desc("Replace eliminated DBARs with NOPs to preserve code layout"),
+ cl::init(false), cl::Hidden);
+
+namespace {
+
+static std::optional<std::pair<StringRef, StringRef>> parseMB(StringRef Asm) {
+ auto T1 = llvm::getToken(Asm);
+ if (!T1.first.equals_insensitive("dbar"))
+ return std::nullopt;
+ auto T2 = llvm::getToken(T1.second);
+ if (T2.first.empty())
+ return std::nullopt;
+ auto T3 = llvm::getToken(T2.second);
+ if (T3.first.trim().empty() || T3.first.starts_with('#'))
+ return std::pair(T1.first, T2.first);
+ return std::nullopt;
+}
+
+static std::optional<std::pair<StringRef, StringRef>>
+isAsmMB(const MachineInstr &MI) {
+ if (DisableInlineAsm)
+ return std::nullopt;
+ if (!MI.isInlineAsm())
+ return std::nullopt;
+ auto Asm = MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
+ return parseMB(Asm);
+}
+
+static StringRef getAMDB(StringRef Name) {
+ return StringSwitch<StringRef>(Name.lower())
+ .Case("amswap.b", "amswap_db.b")
+ .Case("amswap.h", "amswap_db.h")
+ .Case("amswap.w", "amswap_db.w")
+ .Case("amswap.d", "amswap_db.d")
+ .Case("amswap_db.b", "amswap_db.b")
+ .Case("amswap_db.h", "amswap_db.h")
+ .Case("amswap_db.w", "amswap_db.w")
+ .Case("amswap_db.d", "amswap_db.d")
+ .Case("amadd.b", "amadd_db.b")
+ .Case("amadd.h", "amadd_db.h")
+ .Case("amadd.w", "amadd_db.w")
+ .Case("amadd.d", "amadd_db.d")
+ .Case("amadd_db.b", "amadd_db.b")
+ .Case("amadd_db.h", "amadd_db.h")
+ .Case("amadd_db.w", "amadd_db.w")
+ .Case("amadd_db.d", "amadd_db.d")
+ .Case("amand.w", "amand_db.w")
+ .Case("amand.d", "amand_db.d")
+ .Case("amand_db.w", "amand_db.w")
+ .Case("amand_db.d", "amand_db.d")
+ .Case("amor.w", "amor_db.w")
+ .Case("amor.d", "amor_db.d")
+ .Case("amor_db.w", "amor_db.w")
+ .Case("amor_db.d", "amor_db.d")
+ .Case("amxor.w", "amxor_db.w")
+ .Case("amxor.d", "amxor_db.d")
+ .Case("amxor_db.w", "amxor_db.w")
+ .Case("amxor_db.d", "amxor_db.d")
+ .Case("ammax.w", "ammax_db.w")
+ .Case("ammax.d", "ammax_db.d")
+ .Case("ammax_db.w", "ammax_db.w")
+ .Case("ammax_db.d", "ammax_db.d")
+ .Case("ammin.w", "ammin_db.w")
+ .Case("ammin.d", "ammin_db.d")
+ .Case("ammin_db.w", "ammin_db.w")
+ .Case("ammin_db.d", "ammin_db.d")
+ .Case("ammax.wu", "ammax_db.wu")
+ .Case("ammax.du", "ammax_db.du")
+ .Case("ammax_db.wu", "ammax_db.wu")
+ .Case("ammax_db.du", "ammax_db.du")
+ .Case("ammin.wu", "ammin_db.wu")
+ .Case("ammin.du", "ammin_db.du")
+ .Case("ammin_db.wu", "ammin_db.wu")
+ .Case("ammin_db.du", "ammin_db.du")
+ .Case("amcas.b", "amcas_db.b")
+ .Case("amcas.h", "amcas_db.h")
+ .Case("amcas.w", "amcas_db.w")
+ .Case("amcas.d", "amcas_db.d")
+ .Case("amcas_db.b", "amcas_db.b")
+ .Case("amcas_db.h", "amcas_db.h")
+ .Case("amcas_db.w", "amcas_db.w")
+ .Case("amcas_db.d", "amcas_db.d")
+ .Default({});
+}
+
+static std::optional<std::pair<StringRef, StringRef>> parseAM(StringRef Asm) {
+ auto T1 = llvm::getToken(Asm);
+ auto OpName = getAMDB(T1.first);
+ if (OpName.empty())
+ return std::nullopt;
+ auto T2 = llvm::getToken(T1.second, ",");
+ if (T2.first.empty())
+ return std::nullopt;
+ auto T3 = llvm::getToken(T2.second, ",");
+ if (T3.first.empty())
+ return std::nullopt;
+ auto T4 = llvm::getToken(T3.second, ",");
+ if (T4.first.empty())
+ return std::nullopt;
+ auto T5 = llvm::getToken(T4.second);
+ if (T5.first.trim().empty() || T5.first.starts_with('#')) {
+ StringRef Operands(T2.first.data(),
+ T4.first.data() + T4.first.size() - T2.first.data());
+ return std::pair(OpName, Operands);
+ }
+ return std::nullopt;
+}
+
+static std::optional<std::pair<StringRef, StringRef>>
+isAsmAM(const MachineInstr &MI) {
+ if (DisableInlineAsm)
+ return std::nullopt;
+ if (!MI.isInlineAsm())
+ return std::nullopt;
+ auto Asm = MI.getOperand(InlineAsm::MIOp_AsmString).getSymbolName();
+ return parseAM(Asm);
+}
+
+static bool isMB(const MachineInstr &MI) {
+ return MI.getOpcode() == LoongArch::DBAR;
+}
+
+static bool isLL(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ case LoongArch::LL_W:
+ case LoongArch::LL_D:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool isSC(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ case LoongArch::SC_W:
+ case LoongArch::SC_D:
+ case LoongArch::SC_Q:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static std::optional<unsigned> isAM(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ case LoongArch::AMSWAP_B:
+ case LoongArch::AMSWAP__DB_B:
+ return LoongArch::AMSWAP__DB_B;
+ case LoongArch::AMSWAP_H:
+ case LoongArch::AMSWAP__DB_H:
+ return LoongArch::AMSWAP__DB_H;
+ case LoongArch::AMSWAP_W:
+ case LoongArch::AMSWAP__DB_W:
+ return LoongArch::AMSWAP__DB_W;
+ case LoongArch::AMSWAP_D:
+ case LoongArch::AMSWAP__DB_D:
+ return LoongArch::AMSWAP__DB_D;
+ case LoongArch::AMADD_B:
+ case LoongArch::AMADD__DB_B:
+ return LoongArch::AMADD__DB_B;
+ case LoongArch::AMADD_H:
+ case LoongArch::AMADD__DB_H:
+ return LoongArch::AMADD__DB_H;
+ case LoongArch::AMADD_W:
+ case LoongArch::AMADD__DB_W:
+ return LoongArch::AMADD__DB_W;
+ case LoongArch::AMADD_D:
+ case LoongArch::AMADD__DB_D:
+ return LoongArch::AMADD__DB_D;
+ case LoongArch::AMAND_W:
+ case LoongArch::AMAND__DB_W:
+ return LoongArch::AMAND__DB_W;
+ case LoongArch::AMAND_D:
+ case LoongArch::AMAND__DB_D:
+ return LoongArch::AMAND__DB_D;
+ case LoongArch::AMOR_W:
+ case LoongArch::AMOR__DB_W:
+ return LoongArch::AMOR__DB_W;
+ case LoongArch::AMOR_D:
+ case LoongArch::AMOR__DB_D:
+ return LoongArch::AMOR__DB_D;
+ case LoongArch::AMXOR_W:
+ case LoongArch::AMXOR__DB_W:
+ return LoongArch::AMXOR__DB_W;
+ case LoongArch::AMXOR_D:
+ case LoongArch::AMXOR__DB_D:
+ return LoongArch::AMXOR__DB_D;
+ case LoongArch::AMMAX_W:
+ case LoongArch::AMMAX__DB_W:
+ return LoongArch::AMMAX__DB_W;
+ case LoongArch::AMMAX_D:
+ case LoongArch::AMMAX__DB_D:
+ return LoongArch::AMMAX__DB_D;
+ case LoongArch::AMMIN_W:
+ case LoongArch::AMMIN__DB_W:
+ return LoongArch::AMMIN__DB_W;
+ case LoongArch::AMMIN_D:
+ case LoongArch::AMMIN__DB_D:
+ return LoongArch::AMMIN__DB_D;
+ case LoongArch::AMMAX_WU:
+ case LoongArch::AMMAX__DB_WU:
+ return LoongArch::AMMAX__DB_WU;
+ case LoongArch::AMMAX_DU:
+ case LoongArch::AMMAX__DB_DU:
+ return LoongArch::AMMAX__DB_DU;
+ case LoongArch::AMMIN_WU:
+ case LoongArch::AMMIN__DB_WU:
+ return LoongArch::AMMIN__DB_WU;
+ case LoongArch::AMMIN_DU:
+ case LoongArch::AMMIN__DB_DU:
+ return LoongArch::AMMIN__DB_DU;
+ case LoongArch::AMCAS_B:
+ case LoongArch::AMCAS__DB_B:
+ return LoongArch::AMCAS__DB_B;
+ case LoongArch::AMCAS_H:
+ case LoongArch::AMCAS__DB_H:
+ return LoongArch::AMCAS__DB_H;
+ case LoongArch::AMCAS_W:
+ case LoongArch::AMCAS__DB_W:
+ return LoongArch::AMCAS__DB_W;
+ case LoongArch::AMCAS_D:
+ case LoongArch::AMCAS__DB_D:
+ return LoongArch::AMCAS__DB_D;
+ default:
+ return std::nullopt;
+ }
+}
+
+static bool isSafeToSkip(const MachineInstr &MI) {
+ if (MI.mayLoadOrStore())
+ return false;
+ if (MI.isCall() || MI.isReturn())
+ return false;
+ if (MI.isInlineAsm())
+ return isAsmMB(MI) != std::nullopt;
+ if (MI.hasUnmodeledSideEffects())
+ return isMB(MI);
+ return true;
+}
+
+struct BarrierHint {
+ BarrierHint(unsigned Hint) : Hint(Hint) {}
+
+ bool subsumes(const BarrierHint &O) const { return (Hint & O.Hint) == Hint; }
+
+ BarrierHint merge(const BarrierHint &O) const {
+ return BarrierHint(Hint & O.Hint);
+ }
+
+ static inline bool isValid(unsigned Hint) { return (Hint & ~0x1f) == 0; }
+
+ unsigned Hint;
+};
+
+struct InstBarrier {
+ InstBarrier(MachineInstr &MI)
+ : MI(&MI), Pre(0), Post(0), Data(0), IsMB(false), IsAM(false),
+ IsAsm(false) {
+ if (isMB(MI)) {
+ unsigned Hint = MI.getOperand(0).getImm();
+ if (!BarrierHint::isValid(Hint))
+ return;
+ IsMB = true;
+ Pre = Post = BarrierHint(Hint);
+ } else if (isLL(MI)) {
+ IsAM = true;
+ Pre = BarrierHint(0b10000);
+ Post = BarrierHint(0b11111);
+ } else if (isSC(MI)) {
+ IsAM = true;
+ Pre = BarrierHint(0b11111);
+ Post = BarrierHint(0b10000);
+ } else if (auto R = isAM(MI)) {
+ IsAM = true;
+ OpcAMDB = *R;
+ Pre = Post = BarrierHint(0b10000);
+ } else if (auto R = isAsmMB(MI)) {
+ OpName = (*R).first;
+ Operands = (*R).second;
+ auto B = parseAsmMB(Operands, MI);
+ if (!B || !BarrierHint::isValid((*B).first))
+ return;
+ IsMB = true;
+ IsAsm = true;
+ HintOff = (*B).second;
+ Pre = Post = BarrierHint((*B).first);
+ } else if (auto R = isAsmAM(MI)) {
+ OpName = (*R).first;
+ Operands = (*R).second;
+ IsAM = true;
+ IsAsm = true;
+ Pre = Post = BarrierHint(0b10000);
+ }
+ }
+
+ static std::optional<std::pair<unsigned, unsigned>>
+ parseAsmMB(StringRef Operand, MachineInstr &MI) {
+ unsigned Hint, HintOff = 0;
+ // DBAR N | 0xN
+ if (!Operand.starts_with('$')) {
+ if (Operand.getAsInteger(0, Hint))
+ return std::nullopt;
+ return std::pair(Hint, HintOff);
+ }
+ // DBAR $N
+ unsigned N = 0, Off, AsmDescOp;
+ if (Operand.drop_front().getAsInteger(0, Off))
+ return std::nullopt;
+ AsmDescOp = InlineAsm::MIOp_FirstOperand;
+ while (AsmDescOp != MI.getNumOperands()) {
+ const MachineOperand &MO = MI.getOperand(AsmDescOp);
+ assert(MO.isImm() && "Unexpected operand type!");
+ const InlineAsm::Flag F(MO.getImm());
+ if (N == Off) {
+ assert(F.isImmKind() && "Unexpected flag kind!");
+ HintOff = AsmDescOp + 1;
+ Hint = MI.getOperand(HintOff).getImm();
+ return std::pair(Hint, HintOff);
+ }
+ AsmDescOp += 1 + F.getNumOperandRegisters();
+ ++N;
+ }
+ return std::nullopt;
+ }
+
+ MachineInstr *MI;
+ BarrierHint Pre;
+ BarrierHint Post;
+ StringRef OpName;
+ StringRef Operands;
+ union {
+ unsigned OpcAMDB;
+ unsigned HintOff;
+ unsigned Data;
+ };
+ bool IsMB;
+ bool IsAM;
+ bool IsAsm;
+};
+
+class LoongArchMemoryBarrierOpt : public MachineFunctionPass {
+public:
+ static char ID;
+
+ LoongArchMemoryBarrierOpt() : MachineFunctionPass(ID) {}
+
+ StringRef getPassName() const override {
+ return LOONGARCH_MEMORY_BARRIER_OPT_NAME;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<MachineDominatorTreeWrapperPass>();
+ AU.addPreserved<MachineDominatorTreeWrapperPass>();
+ AU.addRequired<MachinePostDominatorTreeWrapperPass>();
+ AU.addPreserved<MachinePostDominatorTreeWrapperPass>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ bool runOnMachineFunction(MachineFunction &Fn) override;
+
+private:
+ enum : unsigned {
+ CandidateA = 1u << 0,
+ CandidateB = 1u << 1,
+ };
+
+ unsigned resolveBarrierRedundancy(const MachineInstr *A,
+ const MachineInstr *B) const;
+ bool eliminateRedundantBarrier(InstBarrier &IA, InstBarrier &IB) const;
+
+ MachineFunction *MF;
+ const MachineDominatorTree *MDT;
+ const MachinePostDominatorTree *MPDT;
+};
+
+static bool checkAllPathSafe(const MachineBasicBlock *MBBA,
+ const MachineBasicBlock *MBBB, bool IsAToB) {
+ const MachineBasicBlock *Start = IsAToB ? MBBA : MBBB;
+ const MachineBasicBlock *End = IsAToB ? MBBB : MBBA;
+
+ SmallVector<const MachineBasicBlock *, 16> Worklist;
+ DenseSet<const MachineBasicBlock *> Visited;
+
+ Worklist.push_back(Start);
+ Visited.insert(Start);
+
+ while (!Worklist.empty()) {
+ const MachineBasicBlock *BB = Worklist.pop_back_val();
+
+ if (BB == End)
+ continue;
+
+ if (BB != Start) {
+ for (const MachineInstr &MI : *BB) {
+ if (!isSafeToSkip(MI))
+ return false;
+ }
+ }
+
+ if (IsAToB) {
+ for (const MachineBasicBlock *Succ : BB->successors()) {
+ if (Visited.insert(Succ).second)
+ Worklist.push_back(Succ);
+ }
+ } else {
+ for (const MachineBasicBlock *Pred : BB->predecessors()) {
+ if (Visited.insert(Pred).second)
+ Worklist.push_back(Pred);
+ }
+ }
+ }
+
+ return true;
+}
+
+// Returns a bitmask indicating removal candidates: A (bit 1) and B (bit 2).
+unsigned LoongArchMemoryBarrierOpt::resolveBarrierRedundancy(
+ const MachineInstr *A, const MachineInstr *B) const {
+ const MachineBasicBlock *MBBA = A->getParent();
+ const MachineBasicBlock *MBBB = B->getParent();
+
+ if (MBBA == MBBB) {
+ /* A -> B */
+ for (auto It = std::next(A->getIterator()); It != MBBA->end(); ++It) {
+ if (It == B->getIterator())
+ return CandidateA | CandidateB;
+ if (!isSafeToSkip(*It))
+ return 0;
+ }
+ return 0;
+ }
+
+ // Cross-block walk
+ bool ADomB = MDT->dominates(MBBA, MBBB);
+ bool BPostDomA = MPDT->dominates(MBBB, MBBA);
+ unsigned Mask = 0;
+ if (!ADomB && !BPostDomA)
+ return 0;
+
+ /* A -> MBBA->end() */
+ for (auto It = std::next(A->getIterator()); It != MBBA->end(); ++It)
+ if (!isSafeToSkip(*It))
+ return 0;
+ /* B -> MBBB->begin() */
+ for (auto It = MBBB->begin(); It != B->getIterator(); ++It)
+ if (!isSafeToSkip(*It))
+ return 0;
+
+ /* MBBA -> MBBB */
+ if (BPostDomA)
+ if (checkAllPathSafe(MBBA, MBBB, true /*IsAToB*/))
+ Mask |= CandidateA;
+
+ /* MBBB -> MBBA */
+ if (ADomB)
+ if (checkAllPathSafe(MBBA, MBBB, false /*IsAToB*/))
+ Mask |= CandidateB;
+
+ return Mask;
+}
+
+// Update DBAR hint
+static void updateMB(InstBarrier &I, BarrierHint Hint, MachineFunction *MF) {
+ assert(I.IsMB && "Unexpected!");
+ I.Pre = I.Post = Hint;
+ if (!I.IsAsm) {
+ I.MI->getOperand(0).setImm(Hint.Hint);
+ return;
+ }
+ if (I.HintOff) {
+ I.MI->getOperand(I.HintOff).setImm(Hint.Hint);
+ return;
+ }
+ MachineOperand &MO = I.MI->getOperand(InlineAsm::MIOp_AsmString);
+ auto New = I.OpName.str() + " " + llvm::utostr(Hint.Hint);
+ auto Sym = MF->createExternalSymbolName(New);
+ MO = MachineOperand::CreateES(Sym);
+}
+
+// Replace AMO to AMO_DB
+static void replaceAM(InstBarrier &I, MachineFunction *MF) {
+ if (!I.IsAM)
+ return;
+ if (I.OpcAMDB) {
+ auto &ST = MF->getSubtarget<LoongArchSubtarget>();
+ I.MI->setDesc(ST.getInstrInfo()->get(I.OpcAMDB));
+ return;
+ }
+ if (!I.IsAsm)
+ return;
+ MachineOperand &MO = I.MI->getOperand(InlineAsm::MIOp_AsmString);
+ auto New = I.OpName.str() + " " + I.Operands.str();
+ auto Sym = MF->createExternalSymbolName(New);
+ MO = MachineOperand::CreateES(Sym);
+}
+
+bool LoongArchMemoryBarrierOpt::eliminateRedundantBarrier(
+ InstBarrier &IA, InstBarrier &IB) const {
+ MachineInstr *A = IA.MI;
+ MachineInstr *B = IB.MI;
+
+ if (!A || !B)
+ return false; // Already erased
+ if (A == B)
+ return false;
+
+ unsigned Mask = resolveBarrierRedundancy(A, B);
+ if (!Mask)
+ return false;
+
+ auto eraseOrReplaceWithNop = [&](MachineInstr *MI) {
+ if (ReplaceEliminatedMBToNop) {
+ auto &ST = MF->getSubtarget<LoongArchSubtarget>();
+ BuildMI(*MI->getParent(), MI->getIterator(), MI->getDebugLoc(),
+ ST.getInstrInfo()->get(LoongArch::ANDI), LoongArch::R0)
+ .addReg(LoongArch::R0)
+ .addImm(0);
+ }
+ MI->eraseFromParent();
+ };
+
+ // A B
+ // DBAR x + DBAR y -> DBAR (x & y)
+ // DBAR x + AMO_DB -> AMO_DB
+ // DBAR x + AMO -> AMO_DB
+ // DBAR x + LL -> LL
+ if ((Mask & CandidateA) && IA.IsMB) {
+ if (!IB.Pre.subsumes(IA.Post)) {
+ if (!IB.IsMB || (RequireNoPathBypass && !(Mask & CandidateB)))
+ return false;
+ updateMB(IB, IB.Pre.merge(IA.Post), MF);
+ }
+ replaceAM(IB, MF);
+ eraseOrReplaceWithNop(A);
+ IA.MI = nullptr;
+ return true;
+ }
+
+ // A B
+ // DBAR x + DBAR y -> DBAR (x & y)
+ // AMO_DB + DBAR x -> AMO_DB
+ // AMO + DBAR x -> AMO_DB
+ // SC + DBAR x -> SC
+ if ((Mask & CandidateB) && IB.IsMB) {
+ if (!IA.Post.subsumes(IB.Pre)) {
+ if (!IA.IsMB || (RequireNoPathBypass && !(Mask & CandidateA)))
+ return false;
+ updateMB(IA, IA.Post.merge(IB.Pre), MF);
+ }
+ replaceAM(IA, MF);
+ eraseOrReplaceWithNop(B);
+ IB.MI = nullptr;
+ return true;
+ }
+
+ return false;
+}
+
+bool LoongArchMemoryBarrierOpt::runOnMachineFunction(MachineFunction &Fn) {
+ if (skipFunction(Fn.getFunction()))
+ return false;
+
+ MF = &Fn;
+ MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
+ MPDT = &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
+
+ SmallVector<InstBarrier, 32> Sites;
+ bool Changed = false;
+
+ for (MachineBasicBlock &MBB : Fn)
+ for (MachineInstr &MI : MBB) {
+ InstBarrier IB(MI);
+ if (IB.IsMB || IB.IsAM)
+ Sites.push_back(IB);
+ }
+
+ for (size_t a = 0; a < Sites.size(); ++a) {
+ for (size_t b = a + 1; b < Sites.size(); ++b) {
+ InstBarrier &IA = Sites[a];
+ InstBarrier &IB = Sites[b];
+ Changed |= eliminateRedundantBarrier(IA, IB);
+ Changed |= eliminateRedundantBarrier(IB, IA);
+ }
+ }
+
+ return Changed;
+}
+} // namespace
+
+char LoongArchMemoryBarrierOpt::ID = 0;
+INITIALIZE_PASS_BEGIN(LoongArchMemoryBarrierOpt, DEBUG_TYPE,
+ LOONGARCH_MEMORY_BARRIER_OPT_NAME, false, false)
+INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTreeWrapperPass)
+INITIALIZE_PASS_END(LoongArchMemoryBarrierOpt, DEBUG_TYPE,
+ LOONGARCH_MEMORY_BARRIER_OPT_NAME, false, false)
+
+FunctionPass *llvm::createLoongArchMemoryBarrierOptPass() {
+ return new LoongArchMemoryBarrierOpt();
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
index 0bb73a88bd6fd..faaf33a9162bf 100644
--- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
@@ -38,6 +38,7 @@ LLVMInitializeLoongArchTarget() {
RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
auto *PR = PassRegistry::getPassRegistry();
initializeLoongArchDeadRegisterDefinitionsPass(*PR);
+ initializeLoongArchMemoryBarrierOptPass(*PR);
initializeLoongArchMergeBaseOffsetOptPass(*PR);
initializeLoongArchOptWInstrsPass(*PR);
initializeLoongArchPreRAExpandPseudoPass(*PR);
@@ -201,6 +202,8 @@ void LoongArchPassConfig::addPreEmitPass2() {
// avoiding the possibility for other passes to break the requirements for
// forward progress in the LL/SC block.
addPass(createLoongArchExpandAtomicPseudoPass());
+ if (TM->getOptLevel() != CodeGenOptLevel::None)
+ addPass(createLoongArchMemoryBarrierOptPass());
}
void LoongArchPassConfig::addMachineSSAOptimization() {
diff --git a/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll b/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
index fa37dda01c7b1..3382e28c14891 100644
--- a/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
+++ b/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
@@ -1,14 +1,35 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefixes=CHECK,NORMAL
+; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-require-no-path-bypass=false < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK,BYPASS
+; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-disable-inline-asm-barrier-opt=true < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK,NOIASM
+; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-replace-eliminated-dbar-to-nop=true < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK,BTONOP
;; Positive
define void @dbar_acquire_acquire() nounwind {
-; CHECK-LABEL: dbar_acquire_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 20
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 20
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 20
+; BTONOP-NEXT: ret
entry:
fence acquire
fence acquire
@@ -16,11 +37,26 @@ entry:
}
define void @dbar_acquire_release() nounwind {
-; CHECK-LABEL: dbar_acquire_release:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_release:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 16
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_release:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 16
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_release:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 16
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_release:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 16
+; BTONOP-NEXT: ret
entry:
fence acquire
fence release
@@ -28,12 +64,30 @@ entry:
}
define i32 @dbar_acquire_add_acquire(i32 %a) nounwind {
-; CHECK-LABEL: dbar_acquire_add_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: addi.w $a0, $a0, 1
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_add_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: addi.w $a0, $a0, 1
+; NORMAL-NEXT: dbar 20
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_add_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: addi.w $a0, $a0, 1
+; BYPASS-NEXT: dbar 20
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_add_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: addi.w $a0, $a0, 1
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_add_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: addi.w $a0, $a0, 1
+; BTONOP-NEXT: dbar 20
+; BTONOP-NEXT: ret
entry:
fence acquire
%0 = add i32 %a, 1
@@ -42,11 +96,26 @@ entry:
}
define void @dbar_release_acquire() nounwind {
-; CHECK-LABEL: dbar_release_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_release_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 16
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_release_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 16
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_release_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 16
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_release_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 16
+; BTONOP-NEXT: ret
entry:
fence release
fence acquire
@@ -54,12 +123,27 @@ entry:
}
define void @dbar_seq_cst_acq_rel_seq_cst() nounwind {
-; CHECK-LABEL: dbar_seq_cst_acq_rel_seq_cst:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 16
-; CHECK-NEXT: dbar 16
-; CHECK-NEXT: dbar 16
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_seq_cst_acq_rel_seq_cst:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 16
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_seq_cst_acq_rel_seq_cst:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 16
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_seq_cst_acq_rel_seq_cst:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 16
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_seq_cst_acq_rel_seq_cst:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 16
+; BTONOP-NEXT: ret
entry:
fence seq_cst
fence acq_rel
@@ -68,14 +152,31 @@ entry:
}
define void @dbar_acquire_asm_dbar_acquire() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: dbar 22
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 20
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 20
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: dbar 22
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 20
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm "dbar 22", ""()
@@ -84,14 +185,31 @@ entry:
}
define void @dbar_acquire_asm_space_dbar_acquire() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_space_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: dbar 22
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_space_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 20
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_space_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 20
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_space_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: dbar 22
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_space_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 20
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm " dbar 22", ""()
@@ -100,14 +218,31 @@ entry:
}
define void @dbar_acquire_asm_comment_dbar_acquire() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_comment_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: dbar 22 # barrier
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_comment_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 20
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_comment_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 20
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_comment_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: dbar 22 # barrier
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_comment_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 20
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm "dbar 22 # barrier", ""()
@@ -116,14 +251,31 @@ entry:
}
define void @dbar_acquire_asm_arg0_dbar_acquire() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_arg0_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: dbar 16
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_arg0_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 16
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_arg0_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 16
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_arg0_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: dbar 16
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_arg0_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 16
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm sideeffect "dbar $0", "I,I,~{memory}"(i32 16, i32 22)
@@ -132,14 +284,31 @@ entry:
}
define void @dbar_acquire_asm_arg1_dbar_acquire() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_arg1_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: dbar 16
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_arg1_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 16
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_arg1_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 16
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_arg1_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: dbar 16
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_arg1_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 16
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm sideeffect "dbar $1", "I,I,~{memory}"(i32 22, i32 16)
@@ -148,11 +317,26 @@ entry:
}
define void @dbar_completion_acquire() nounwind {
-; CHECK-LABEL: dbar_completion_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 0
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_completion_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 0
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_completion_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 0
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_completion_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 0
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_completion_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 0
+; BTONOP-NEXT: ret
entry:
call void @llvm.loongarch.dbar(i32 0)
fence acquire
@@ -160,11 +344,26 @@ entry:
}
define void @dbar_release_completion() nounwind {
-; CHECK-LABEL: dbar_release_completion:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: dbar 0
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_release_completion:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: dbar 0
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_release_completion:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: dbar 0
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_release_completion:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 0
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_release_completion:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: dbar 0
+; BTONOP-NEXT: ret
entry:
fence release
call void @llvm.loongarch.dbar(i32 0)
@@ -172,12 +371,30 @@ entry:
}
define void @dbar_release_amswap_i8_acquire() nounwind {
-; CHECK-LABEL: dbar_release_amswap_i8_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: addi.w $a0, $zero, -256
-; CHECK-NEXT: amand_db.w $a1, $a0, $zero
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_release_amswap_i8_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: addi.w $a0, $zero, -256
+; NORMAL-NEXT: amand_db.w $a1, $a0, $zero
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_release_amswap_i8_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: addi.w $a0, $zero, -256
+; BYPASS-NEXT: amand_db.w $a1, $a0, $zero
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_release_amswap_i8_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: addi.w $a0, $zero, -256
+; NOIASM-NEXT: amand_db.w $a1, $a0, $zero
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_release_amswap_i8_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: addi.w $a0, $zero, -256
+; BTONOP-NEXT: amand_db.w $a1, $a0, $zero
+; BTONOP-NEXT: ret
entry:
fence release
atomicrmw xchg ptr null, i8 0 acquire
@@ -185,11 +402,26 @@ entry:
}
define void @dbar_release_amswap_i32_acquire() nounwind {
-; CHECK-LABEL: dbar_release_amswap_i32_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: amswap_db.w $a0, $zero, $zero
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_release_amswap_i32_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: amswap_db.w $a0, $zero, $zero
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_release_amswap_i32_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_release_amswap_i32_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: amswap_db.w $a0, $zero, $zero
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_release_amswap_i32_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: amswap_db.w $a0, $zero, $zero
+; BTONOP-NEXT: ret
entry:
fence release
atomicrmw xchg ptr null, i32 0 acquire
@@ -197,11 +429,26 @@ entry:
}
define void @dbar_release_amswap_i32_monotonic() nounwind {
-; CHECK-LABEL: dbar_release_amswap_i32_monotonic:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: amswap.w $a0, $zero, $zero
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_release_amswap_i32_monotonic:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: amswap_db.w $a0, $zero, $zero
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_release_amswap_i32_monotonic:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_release_amswap_i32_monotonic:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: amswap_db.w $a0, $zero, $zero
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_release_amswap_i32_monotonic:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: amswap_db.w $a0, $zero, $zero
+; BTONOP-NEXT: ret
entry:
fence release
atomicrmw xchg ptr null, i32 0 monotonic
@@ -221,12 +468,30 @@ entry:
}
define void @amswap_i8_release_dbar_acquire() nounwind {
-; CHECK-LABEL: amswap_i8_release_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: addi.w $a0, $zero, -256
-; CHECK-NEXT: amand_db.w $a1, $a0, $zero
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: amswap_i8_release_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: addi.w $a0, $zero, -256
+; NORMAL-NEXT: amand_db.w $a1, $a0, $zero
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: amswap_i8_release_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: addi.w $a0, $zero, -256
+; BYPASS-NEXT: amand_db.w $a1, $a0, $zero
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: amswap_i8_release_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: addi.w $a0, $zero, -256
+; NOIASM-NEXT: amand_db.w $a1, $a0, $zero
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: amswap_i8_release_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: addi.w $a0, $zero, -256
+; BTONOP-NEXT: amand_db.w $a1, $a0, $zero
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: ret
entry:
atomicrmw xchg ptr null, i8 0 release
fence acquire
@@ -234,11 +499,26 @@ entry:
}
define void @amswap_i32_release_dbar_acquire() nounwind {
-; CHECK-LABEL: amswap_i32_release_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: amswap_db.w $a0, $zero, $zero
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: amswap_i32_release_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: amswap_db.w $a0, $zero, $zero
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: amswap_i32_release_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: amswap_i32_release_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: amswap_db.w $a0, $zero, $zero
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: amswap_i32_release_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: amswap_db.w $a0, $zero, $zero
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: ret
entry:
atomicrmw xchg ptr null, i32 0 release
fence acquire
@@ -258,13 +538,31 @@ entry:
}
define void @dbar_release_amswap_i8_release_dbar_acquire() nounwind {
-; CHECK-LABEL: dbar_release_amswap_i8_release_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: addi.w $a0, $zero, -256
-; CHECK-NEXT: amand_db.w $a1, $a0, $zero
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_release_amswap_i8_release_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: addi.w $a0, $zero, -256
+; NORMAL-NEXT: amand_db.w $a1, $a0, $zero
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_release_amswap_i8_release_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: addi.w $a0, $zero, -256
+; BYPASS-NEXT: amand_db.w $a1, $a0, $zero
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_release_amswap_i8_release_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: addi.w $a0, $zero, -256
+; NOIASM-NEXT: amand_db.w $a1, $a0, $zero
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_release_amswap_i8_release_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: addi.w $a0, $zero, -256
+; BTONOP-NEXT: amand_db.w $a1, $a0, $zero
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: ret
entry:
fence release
atomicrmw xchg ptr null, i8 0 release
@@ -273,12 +571,27 @@ entry:
}
define void @dbar_acquire_amswap_i32_release_dbar_acquire() nounwind {
-; CHECK-LABEL: dbar_acquire_amswap_i32_release_dbar_acquire:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: amswap_db.w $a0, $zero, $zero
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_amswap_i32_release_dbar_acquire:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: amswap_db.w $a0, $zero, $zero
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_amswap_i32_release_dbar_acquire:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_amswap_i32_release_dbar_acquire:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: amswap_db.w $a0, $zero, $zero
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_amswap_i32_release_dbar_acquire:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: amswap_db.w $a0, $zero, $zero
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: ret
entry:
fence acquire
atomicrmw xchg ptr null, i32 0 release
@@ -301,13 +614,35 @@ entry:
}
define void @dbar_acquire_asm_amswap_i32_release() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_amswap_i32_release:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: amswap_db.w $a0, $a1, $a2
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_amswap_i32_release:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: #APP
+; NORMAL-NEXT: amswap_db.w $a0, $a1, $a2
+; NORMAL-NEXT: #NO_APP
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_amswap_i32_release:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: #APP
+; BYPASS-NEXT: amswap_db.w $a0, $a1, $a2
+; BYPASS-NEXT: #NO_APP
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_amswap_i32_release:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: amswap_db.w $a0, $a1, $a2
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_amswap_i32_release:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: #APP
+; BTONOP-NEXT: amswap_db.w $a0, $a1, $a2
+; BTONOP-NEXT: #NO_APP
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm "amswap_db.w $$r4, $$r5, $$r6", ""()
@@ -315,13 +650,35 @@ entry:
}
define void @dbar_acquire_asm_amswap_i32_monotonic() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_amswap_i32_monotonic:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: amswap.w $a0, $a1, $a2
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_amswap_i32_monotonic:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: #APP
+; NORMAL-NEXT: amswap_db.w $a0, $a1, $a2
+; NORMAL-NEXT: #NO_APP
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_amswap_i32_monotonic:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: #APP
+; BYPASS-NEXT: amswap_db.w $a0, $a1, $a2
+; BYPASS-NEXT: #NO_APP
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_amswap_i32_monotonic:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: amswap.w $a0, $a1, $a2
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_amswap_i32_monotonic:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: #APP
+; BTONOP-NEXT: amswap_db.w $a0, $a1, $a2
+; BTONOP-NEXT: #NO_APP
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm sideeffect "amswap.w $$r4, $$r5, $$r6", ""()
@@ -329,13 +686,35 @@ entry:
}
define void @dbar_acquire_asm_space_amswap_i32_monotonic() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_space_amswap_i32_monotonic:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: amswap.w $a0, $a1, $a2
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_space_amswap_i32_monotonic:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: #APP
+; NORMAL-NEXT: amswap_db.w $a0, $a1, $a2
+; NORMAL-NEXT: #NO_APP
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_space_amswap_i32_monotonic:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: #APP
+; BYPASS-NEXT: amswap_db.w $a0, $a1, $a2
+; BYPASS-NEXT: #NO_APP
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_space_amswap_i32_monotonic:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: amswap.w $a0, $a1, $a2
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_space_amswap_i32_monotonic:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: #APP
+; BTONOP-NEXT: amswap_db.w $a0, $a1, $a2
+; BTONOP-NEXT: #NO_APP
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm sideeffect " amswap.w $$r4, $$r5, $$r6", ""()
@@ -343,13 +722,35 @@ entry:
}
define void @dbar_acquire_asm_comment_amswap_i32_monotonic() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_comment_amswap_i32_monotonic:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: amswap.w $a0, $a1, $a2 # atomic
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_comment_amswap_i32_monotonic:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: #APP
+; NORMAL-NEXT: amswap_db.w $a0, $a1, $a2 # atomic
+; NORMAL-NEXT: #NO_APP
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_comment_amswap_i32_monotonic:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: #APP
+; BYPASS-NEXT: amswap_db.w $a0, $a1, $a2 # atomic
+; BYPASS-NEXT: #NO_APP
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_comment_amswap_i32_monotonic:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: amswap.w $a0, $a1, $a2 # atomic
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_comment_amswap_i32_monotonic:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: #APP
+; BTONOP-NEXT: amswap_db.w $a0, $a1, $a2 # atomic
+; BTONOP-NEXT: #NO_APP
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm sideeffect "amswap.w $$r4, $$r5, $$r6 # atomic", ""()
@@ -357,13 +758,35 @@ entry:
}
define void @dbar_acquire_asm_args_amswap_i32_monotonic() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_args_amswap_i32_monotonic:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: amswap.w $a0, $zero, $zero
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_args_amswap_i32_monotonic:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: #APP
+; NORMAL-NEXT: amswap_db.w $a0, $zero, $zero
+; NORMAL-NEXT: #NO_APP
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_args_amswap_i32_monotonic:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: #APP
+; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
+; BYPASS-NEXT: #NO_APP
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_args_amswap_i32_monotonic:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: amswap.w $a0, $zero, $zero
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_args_amswap_i32_monotonic:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: #APP
+; BTONOP-NEXT: amswap_db.w $a0, $zero, $zero
+; BTONOP-NEXT: #NO_APP
+; BTONOP-NEXT: ret
entry:
fence acquire
call i32 asm sideeffect "amswap.w $0, $1, $2", "=r,r,r,~{memory}"(i32 0, i32 0)
@@ -371,13 +794,35 @@ entry:
}
define void @dbar_acquire_asm_reg_args_amswap_i32_monotonic() nounwind {
-; CHECK-LABEL: dbar_acquire_asm_reg_args_amswap_i32_monotonic:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: #APP
-; CHECK-NEXT: amswap_db.w $ra, $zero, $zero
-; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_asm_reg_args_amswap_i32_monotonic:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: #APP
+; NORMAL-NEXT: amswap_db.w $ra, $zero, $zero
+; NORMAL-NEXT: #NO_APP
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_asm_reg_args_amswap_i32_monotonic:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: #APP
+; BYPASS-NEXT: amswap_db.w $ra, $zero, $zero
+; BYPASS-NEXT: #NO_APP
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_asm_reg_args_amswap_i32_monotonic:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: #APP
+; NOIASM-NEXT: amswap_db.w $ra, $zero, $zero
+; NOIASM-NEXT: #NO_APP
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_asm_reg_args_amswap_i32_monotonic:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: #APP
+; BTONOP-NEXT: amswap_db.w $ra, $zero, $zero
+; BTONOP-NEXT: #NO_APP
+; BTONOP-NEXT: ret
entry:
fence acquire
call void asm sideeffect "amswap_db.w $$r1, $0, $1", "r,r,~{memory}"(i32 0, i32 0)
@@ -385,25 +830,81 @@ entry:
}
define void @dbar_acquire_cmpxchg_i32_dbar_release() nounwind {
-; CHECK-LABEL: dbar_acquire_cmpxchg_i32_dbar_release:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ori $a0, $zero, 1
-; CHECK-NEXT: .LBB28_1: # %entry
-; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ll.w $a1, $zero, 0
-; CHECK-NEXT: bne $a1, $zero, .LBB28_3
-; CHECK-NEXT: # %bb.2: # %entry
-; CHECK-NEXT: # in Loop: Header=BB28_1 Depth=1
-; CHECK-NEXT: move $a2, $a0
-; CHECK-NEXT: sc.w $a2, $zero, 0
-; CHECK-NEXT: beq $a2, $zero, .LBB28_1
-; CHECK-NEXT: b .LBB28_4
-; CHECK-NEXT: .LBB28_3: # %entry
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: .LBB28_4: # %entry
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: ret
+; NORMAL-LABEL: dbar_acquire_cmpxchg_i32_dbar_release:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: ori $a0, $zero, 1
+; NORMAL-NEXT: .LBB28_1: # %entry
+; NORMAL-NEXT: # =>This Inner Loop Header: Depth=1
+; NORMAL-NEXT: ll.w $a1, $zero, 0
+; NORMAL-NEXT: bne $a1, $zero, .LBB28_3
+; NORMAL-NEXT: # %bb.2: # %entry
+; NORMAL-NEXT: # in Loop: Header=BB28_1 Depth=1
+; NORMAL-NEXT: move $a2, $a0
+; NORMAL-NEXT: sc.w $a2, $zero, 0
+; NORMAL-NEXT: beq $a2, $zero, .LBB28_1
+; NORMAL-NEXT: b .LBB28_4
+; NORMAL-NEXT: .LBB28_3: # %entry
+; NORMAL-NEXT: dbar 20
+; NORMAL-NEXT: .LBB28_4: # %entry
+; NORMAL-NEXT: dbar 18
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: dbar_acquire_cmpxchg_i32_dbar_release:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: ori $a0, $zero, 1
+; BYPASS-NEXT: .LBB28_1: # %entry
+; BYPASS-NEXT: # =>This Inner Loop Header: Depth=1
+; BYPASS-NEXT: ll.w $a1, $zero, 0
+; BYPASS-NEXT: bne $a1, $zero, .LBB28_3
+; BYPASS-NEXT: # %bb.2: # %entry
+; BYPASS-NEXT: # in Loop: Header=BB28_1 Depth=1
+; BYPASS-NEXT: move $a2, $a0
+; BYPASS-NEXT: sc.w $a2, $zero, 0
+; BYPASS-NEXT: beq $a2, $zero, .LBB28_1
+; BYPASS-NEXT: b .LBB28_4
+; BYPASS-NEXT: .LBB28_3: # %entry
+; BYPASS-NEXT: .LBB28_4: # %entry
+; BYPASS-NEXT: dbar 16
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: dbar_acquire_cmpxchg_i32_dbar_release:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: ori $a0, $zero, 1
+; NOIASM-NEXT: .LBB28_1: # %entry
+; NOIASM-NEXT: # =>This Inner Loop Header: Depth=1
+; NOIASM-NEXT: ll.w $a1, $zero, 0
+; NOIASM-NEXT: bne $a1, $zero, .LBB28_3
+; NOIASM-NEXT: # %bb.2: # %entry
+; NOIASM-NEXT: # in Loop: Header=BB28_1 Depth=1
+; NOIASM-NEXT: move $a2, $a0
+; NOIASM-NEXT: sc.w $a2, $zero, 0
+; NOIASM-NEXT: beq $a2, $zero, .LBB28_1
+; NOIASM-NEXT: b .LBB28_4
+; NOIASM-NEXT: .LBB28_3: # %entry
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: .LBB28_4: # %entry
+; NOIASM-NEXT: dbar 18
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: dbar_acquire_cmpxchg_i32_dbar_release:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: ori $a0, $zero, 1
+; BTONOP-NEXT: .LBB28_1: # %entry
+; BTONOP-NEXT: # =>This Inner Loop Header: Depth=1
+; BTONOP-NEXT: ll.w $a1, $zero, 0
+; BTONOP-NEXT: bne $a1, $zero, .LBB28_3
+; BTONOP-NEXT: # %bb.2: # %entry
+; BTONOP-NEXT: # in Loop: Header=BB28_1 Depth=1
+; BTONOP-NEXT: move $a2, $a0
+; BTONOP-NEXT: sc.w $a2, $zero, 0
+; BTONOP-NEXT: beq $a2, $zero, .LBB28_1
+; BTONOP-NEXT: b .LBB28_4
+; BTONOP-NEXT: .LBB28_3: # %entry
+; BTONOP-NEXT: dbar 20
+; BTONOP-NEXT: .LBB28_4: # %entry
+; BTONOP-NEXT: dbar 18
+; BTONOP-NEXT: ret
entry:
fence acquire
cmpxchg ptr null, i32 0, i32 1 acquire acquire
@@ -412,17 +913,49 @@ entry:
}
define void @cfg_dominate(i1 %a) {
-; CHECK-LABEL: cfg_dominate:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: andi $a0, $a0, 1
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: beqz $a0, .LBB29_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: ret
-; CHECK-NEXT: .LBB29_2:
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: ret
+; NORMAL-LABEL: cfg_dominate:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: andi $a0, $a0, 1
+; NORMAL-NEXT: dbar 20
+; NORMAL-NEXT: beqz $a0, .LBB29_2
+; NORMAL-NEXT: # %bb.1:
+; NORMAL-NEXT: ret
+; NORMAL-NEXT: .LBB29_2:
+; NORMAL-NEXT: dbar 18
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: cfg_dominate:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: andi $a0, $a0, 1
+; BYPASS-NEXT: dbar 16
+; BYPASS-NEXT: beqz $a0, .LBB29_2
+; BYPASS-NEXT: # %bb.1:
+; BYPASS-NEXT: ret
+; BYPASS-NEXT: .LBB29_2:
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: cfg_dominate:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: andi $a0, $a0, 1
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: beqz $a0, .LBB29_2
+; NOIASM-NEXT: # %bb.1:
+; NOIASM-NEXT: ret
+; NOIASM-NEXT: .LBB29_2:
+; NOIASM-NEXT: dbar 18
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: cfg_dominate:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: andi $a0, $a0, 1
+; BTONOP-NEXT: dbar 20
+; BTONOP-NEXT: beqz $a0, .LBB29_2
+; BTONOP-NEXT: # %bb.1:
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: ret
+; BTONOP-NEXT: .LBB29_2:
+; BTONOP-NEXT: dbar 18
+; BTONOP-NEXT: ret
entry:
fence acquire
br i1 %a, label %2, label %3
@@ -435,21 +968,65 @@ entry:
}
define void @cfg_postdominate(i1 %a, i1 %b, i1 %c) {
-; CHECK-LABEL: cfg_postdominate:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: andi $a0, $a0, 1
-; CHECK-NEXT: beqz $a0, .LBB30_2
-; CHECK-NEXT: .LBB30_1:
-; CHECK-NEXT: andi $a0, $a1, 1
-; CHECK-NEXT: dbar 20
-; CHECK-NEXT: beqz $a0, .LBB30_3
-; CHECK-NEXT: .LBB30_2:
-; CHECK-NEXT: andi $a0, $a2, 1
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: bnez $a0, .LBB30_1
-; CHECK-NEXT: .LBB30_3:
-; CHECK-NEXT: dbar 18
-; CHECK-NEXT: ret
+; NORMAL-LABEL: cfg_postdominate:
+; NORMAL: # %bb.0: # %entry
+; NORMAL-NEXT: andi $a0, $a0, 1
+; NORMAL-NEXT: beqz $a0, .LBB30_2
+; NORMAL-NEXT: .LBB30_1:
+; NORMAL-NEXT: andi $a0, $a1, 1
+; NORMAL-NEXT: dbar 20
+; NORMAL-NEXT: beqz $a0, .LBB30_3
+; NORMAL-NEXT: .LBB30_2:
+; NORMAL-NEXT: andi $a0, $a2, 1
+; NORMAL-NEXT: bnez $a0, .LBB30_1
+; NORMAL-NEXT: .LBB30_3:
+; NORMAL-NEXT: dbar 18
+; NORMAL-NEXT: ret
+;
+; BYPASS-LABEL: cfg_postdominate:
+; BYPASS: # %bb.0: # %entry
+; BYPASS-NEXT: andi $a0, $a0, 1
+; BYPASS-NEXT: beqz $a0, .LBB30_2
+; BYPASS-NEXT: .LBB30_1:
+; BYPASS-NEXT: andi $a0, $a1, 1
+; BYPASS-NEXT: beqz $a0, .LBB30_3
+; BYPASS-NEXT: .LBB30_2:
+; BYPASS-NEXT: andi $a0, $a2, 1
+; BYPASS-NEXT: bnez $a0, .LBB30_1
+; BYPASS-NEXT: .LBB30_3:
+; BYPASS-NEXT: dbar 16
+; BYPASS-NEXT: ret
+;
+; NOIASM-LABEL: cfg_postdominate:
+; NOIASM: # %bb.0: # %entry
+; NOIASM-NEXT: andi $a0, $a0, 1
+; NOIASM-NEXT: beqz $a0, .LBB30_2
+; NOIASM-NEXT: .LBB30_1:
+; NOIASM-NEXT: andi $a0, $a1, 1
+; NOIASM-NEXT: dbar 20
+; NOIASM-NEXT: beqz $a0, .LBB30_3
+; NOIASM-NEXT: .LBB30_2:
+; NOIASM-NEXT: andi $a0, $a2, 1
+; NOIASM-NEXT: bnez $a0, .LBB30_1
+; NOIASM-NEXT: .LBB30_3:
+; NOIASM-NEXT: dbar 18
+; NOIASM-NEXT: ret
+;
+; BTONOP-LABEL: cfg_postdominate:
+; BTONOP: # %bb.0: # %entry
+; BTONOP-NEXT: andi $a0, $a0, 1
+; BTONOP-NEXT: beqz $a0, .LBB30_2
+; BTONOP-NEXT: .LBB30_1:
+; BTONOP-NEXT: andi $a0, $a1, 1
+; BTONOP-NEXT: dbar 20
+; BTONOP-NEXT: beqz $a0, .LBB30_3
+; BTONOP-NEXT: .LBB30_2:
+; BTONOP-NEXT: andi $a0, $a2, 1
+; BTONOP-NEXT: nop
+; BTONOP-NEXT: bnez $a0, .LBB30_1
+; BTONOP-NEXT: .LBB30_3:
+; BTONOP-NEXT: dbar 18
+; BTONOP-NEXT: ret
entry:
br i1 %a, label %2, label %3
2:
diff --git a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
index 4a77cccb99a2e..d3bd7dfc24b4b 100644
--- a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
+++ b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
@@ -180,6 +180,9 @@
; LAXX-NEXT: Stack Frame Layout Analysis
; LAXX-NEXT: LoongArch pseudo instruction expansion pass
; LAXX-NEXT: LoongArch atomic pseudo instruction expansion pass
+; LAXX-NEXT: MachineDominator Tree Construction
+; LAXX-NEXT: MachinePostDominator Tree Construction
+; LAXX-NEXT: LoongArch Memory Barrier Optimisation pass
; LAXX-NEXT: Lazy Machine Block Frequency Analysis
; LAXX-NEXT: Machine Optimization Remark Emitter
; LAXX-NEXT: LoongArch Assembly Printer
diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn
index 810811f7d147c..bec44b7c1d140 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn
@@ -49,6 +49,7 @@ static_library("LLVMLoongArchCodeGen") {
"LoongArchISelLowering.cpp",
"LoongArchInstrInfo.cpp",
"LoongArchMCInstLower.cpp",
+ "LoongArchMemoryBarrierOpt.cpp",
"LoongArchMergeBaseOffset.cpp",
"LoongArchOptWInstrs.cpp",
"LoongArchRegisterInfo.cpp",
>From db862f3d5da183dab469086b3ff9ca9fc3ba0a2e Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Thu, 27 Aug 2026 16:10:44 +0800
Subject: [PATCH 2/5] Refactor LoongArch AMO handling with macros
---
.../LoongArch/LoongArchMemoryBarrierOpt.cpp | 171 ++++--------------
1 file changed, 39 insertions(+), 132 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
index 1f29cdc8638c1..28be20ff42a2f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
@@ -48,6 +48,34 @@ static cl::opt<bool> ReplaceEliminatedMBToNop(
namespace {
+#define AMO_CASES \
+ CASE(AMSWAP, B) \
+ CASE(AMSWAP, H) \
+ CASE(AMSWAP, W) \
+ CASE(AMSWAP, D) \
+ CASE(AMADD, B) \
+ CASE(AMADD, H) \
+ CASE(AMADD, W) \
+ CASE(AMADD, D) \
+ CASE(AMAND, W) \
+ CASE(AMAND, D) \
+ CASE(AMOR, W) \
+ CASE(AMOR, D) \
+ CASE(AMXOR, W) \
+ CASE(AMXOR, D) \
+ CASE(AMMAX, W) \
+ CASE(AMMAX, D) \
+ CASE(AMMAX, WU) \
+ CASE(AMMAX, DU) \
+ CASE(AMMIN, W) \
+ CASE(AMMIN, D) \
+ CASE(AMMIN, WU) \
+ CASE(AMMIN, DU) \
+ CASE(AMCAS, B) \
+ CASE(AMCAS, H) \
+ CASE(AMCAS, W) \
+ CASE(AMCAS, D)
+
static std::optional<std::pair<StringRef, StringRef>> parseMB(StringRef Asm) {
auto T1 = llvm::getToken(Asm);
if (!T1.first.equals_insensitive("dbar"))
@@ -72,60 +100,11 @@ isAsmMB(const MachineInstr &MI) {
}
static StringRef getAMDB(StringRef Name) {
- return StringSwitch<StringRef>(Name.lower())
- .Case("amswap.b", "amswap_db.b")
- .Case("amswap.h", "amswap_db.h")
- .Case("amswap.w", "amswap_db.w")
- .Case("amswap.d", "amswap_db.d")
- .Case("amswap_db.b", "amswap_db.b")
- .Case("amswap_db.h", "amswap_db.h")
- .Case("amswap_db.w", "amswap_db.w")
- .Case("amswap_db.d", "amswap_db.d")
- .Case("amadd.b", "amadd_db.b")
- .Case("amadd.h", "amadd_db.h")
- .Case("amadd.w", "amadd_db.w")
- .Case("amadd.d", "amadd_db.d")
- .Case("amadd_db.b", "amadd_db.b")
- .Case("amadd_db.h", "amadd_db.h")
- .Case("amadd_db.w", "amadd_db.w")
- .Case("amadd_db.d", "amadd_db.d")
- .Case("amand.w", "amand_db.w")
- .Case("amand.d", "amand_db.d")
- .Case("amand_db.w", "amand_db.w")
- .Case("amand_db.d", "amand_db.d")
- .Case("amor.w", "amor_db.w")
- .Case("amor.d", "amor_db.d")
- .Case("amor_db.w", "amor_db.w")
- .Case("amor_db.d", "amor_db.d")
- .Case("amxor.w", "amxor_db.w")
- .Case("amxor.d", "amxor_db.d")
- .Case("amxor_db.w", "amxor_db.w")
- .Case("amxor_db.d", "amxor_db.d")
- .Case("ammax.w", "ammax_db.w")
- .Case("ammax.d", "ammax_db.d")
- .Case("ammax_db.w", "ammax_db.w")
- .Case("ammax_db.d", "ammax_db.d")
- .Case("ammin.w", "ammin_db.w")
- .Case("ammin.d", "ammin_db.d")
- .Case("ammin_db.w", "ammin_db.w")
- .Case("ammin_db.d", "ammin_db.d")
- .Case("ammax.wu", "ammax_db.wu")
- .Case("ammax.du", "ammax_db.du")
- .Case("ammax_db.wu", "ammax_db.wu")
- .Case("ammax_db.du", "ammax_db.du")
- .Case("ammin.wu", "ammin_db.wu")
- .Case("ammin.du", "ammin_db.du")
- .Case("ammin_db.wu", "ammin_db.wu")
- .Case("ammin_db.du", "ammin_db.du")
- .Case("amcas.b", "amcas_db.b")
- .Case("amcas.h", "amcas_db.h")
- .Case("amcas.w", "amcas_db.w")
- .Case("amcas.d", "amcas_db.d")
- .Case("amcas_db.b", "amcas_db.b")
- .Case("amcas_db.h", "amcas_db.h")
- .Case("amcas_db.w", "amcas_db.w")
- .Case("amcas_db.d", "amcas_db.d")
- .Default({});
+#define CASE(Name, Suffix) \
+ .Case(#Name "." #Suffix, #Name "_DB." #Suffix) \
+ .Case(#Name "_DB." #Suffix, #Name "_DB." #Suffix)
+ return StringSwitch<StringRef>(Name.upper()) AMO_CASES.Default({});
+#undef CASE
}
static std::optional<std::pair<StringRef, StringRef>> parseAM(StringRef Asm) {
@@ -187,88 +166,16 @@ static bool isSC(const MachineInstr &MI) {
}
static std::optional<unsigned> isAM(const MachineInstr &MI) {
+#define CASE(Name, Suffix) \
+ case LoongArch::Name##_##Suffix: \
+ case LoongArch::Name##__DB_##Suffix: \
+ return LoongArch::Name##__DB_##Suffix;
switch (MI.getOpcode()) {
- case LoongArch::AMSWAP_B:
- case LoongArch::AMSWAP__DB_B:
- return LoongArch::AMSWAP__DB_B;
- case LoongArch::AMSWAP_H:
- case LoongArch::AMSWAP__DB_H:
- return LoongArch::AMSWAP__DB_H;
- case LoongArch::AMSWAP_W:
- case LoongArch::AMSWAP__DB_W:
- return LoongArch::AMSWAP__DB_W;
- case LoongArch::AMSWAP_D:
- case LoongArch::AMSWAP__DB_D:
- return LoongArch::AMSWAP__DB_D;
- case LoongArch::AMADD_B:
- case LoongArch::AMADD__DB_B:
- return LoongArch::AMADD__DB_B;
- case LoongArch::AMADD_H:
- case LoongArch::AMADD__DB_H:
- return LoongArch::AMADD__DB_H;
- case LoongArch::AMADD_W:
- case LoongArch::AMADD__DB_W:
- return LoongArch::AMADD__DB_W;
- case LoongArch::AMADD_D:
- case LoongArch::AMADD__DB_D:
- return LoongArch::AMADD__DB_D;
- case LoongArch::AMAND_W:
- case LoongArch::AMAND__DB_W:
- return LoongArch::AMAND__DB_W;
- case LoongArch::AMAND_D:
- case LoongArch::AMAND__DB_D:
- return LoongArch::AMAND__DB_D;
- case LoongArch::AMOR_W:
- case LoongArch::AMOR__DB_W:
- return LoongArch::AMOR__DB_W;
- case LoongArch::AMOR_D:
- case LoongArch::AMOR__DB_D:
- return LoongArch::AMOR__DB_D;
- case LoongArch::AMXOR_W:
- case LoongArch::AMXOR__DB_W:
- return LoongArch::AMXOR__DB_W;
- case LoongArch::AMXOR_D:
- case LoongArch::AMXOR__DB_D:
- return LoongArch::AMXOR__DB_D;
- case LoongArch::AMMAX_W:
- case LoongArch::AMMAX__DB_W:
- return LoongArch::AMMAX__DB_W;
- case LoongArch::AMMAX_D:
- case LoongArch::AMMAX__DB_D:
- return LoongArch::AMMAX__DB_D;
- case LoongArch::AMMIN_W:
- case LoongArch::AMMIN__DB_W:
- return LoongArch::AMMIN__DB_W;
- case LoongArch::AMMIN_D:
- case LoongArch::AMMIN__DB_D:
- return LoongArch::AMMIN__DB_D;
- case LoongArch::AMMAX_WU:
- case LoongArch::AMMAX__DB_WU:
- return LoongArch::AMMAX__DB_WU;
- case LoongArch::AMMAX_DU:
- case LoongArch::AMMAX__DB_DU:
- return LoongArch::AMMAX__DB_DU;
- case LoongArch::AMMIN_WU:
- case LoongArch::AMMIN__DB_WU:
- return LoongArch::AMMIN__DB_WU;
- case LoongArch::AMMIN_DU:
- case LoongArch::AMMIN__DB_DU:
- return LoongArch::AMMIN__DB_DU;
- case LoongArch::AMCAS_B:
- case LoongArch::AMCAS__DB_B:
- return LoongArch::AMCAS__DB_B;
- case LoongArch::AMCAS_H:
- case LoongArch::AMCAS__DB_H:
- return LoongArch::AMCAS__DB_H;
- case LoongArch::AMCAS_W:
- case LoongArch::AMCAS__DB_W:
- return LoongArch::AMCAS__DB_W;
- case LoongArch::AMCAS_D:
- case LoongArch::AMCAS__DB_D:
- return LoongArch::AMCAS__DB_D;
+ AMO_CASES
default:
return std::nullopt;
}
+#undef CASE
}
static bool isSafeToSkip(const MachineInstr &MI) {
>From f3ea2a9aa5ca7fdca207dab53cc4e0fd1f71ce64 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Tue, 1 Sep 2026 12:08:56 +0800
Subject: [PATCH 3/5] Add an option to merge AMOs with DBARs into AMO_DB
---
.../LoongArch/LoongArchMemoryBarrierOpt.cpp | 10 +-
.../CodeGen/LoongArch/memory-barrier-opt.ll | 193 ++++++++++++++++++
2 files changed, 202 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
index 28be20ff42a2f..61c5f91e2514d 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
@@ -36,6 +36,11 @@ static cl::opt<bool> RequireNoPathBypass(
cl::desc("Optimize only when no paths bypass either memory barrier"),
cl::init(true), cl::Hidden);
+static cl::opt<bool> MergeAMOWithMB(
+ "loongarch-merge-amo-with-dbar",
+ cl::desc("Merge AMOs with DBARs into AMO_DB during optimization"),
+ cl::init(true), cl::Hidden);
+
static cl::opt<bool> DisableInlineAsm(
"loongarch-disable-inline-asm-barrier-opt",
cl::desc("Disable optimization of memory barriers in InlineAsm"),
@@ -101,7 +106,7 @@ isAsmMB(const MachineInstr &MI) {
static StringRef getAMDB(StringRef Name) {
#define CASE(Name, Suffix) \
- .Case(#Name "." #Suffix, #Name "_DB." #Suffix) \
+ .Case(#Name "." #Suffix, MergeAMOWithMB ? #Name "_DB." #Suffix : "") \
.Case(#Name "_DB." #Suffix, #Name "_DB." #Suffix)
return StringSwitch<StringRef>(Name.upper()) AMO_CASES.Default({});
#undef CASE
@@ -168,6 +173,9 @@ static bool isSC(const MachineInstr &MI) {
static std::optional<unsigned> isAM(const MachineInstr &MI) {
#define CASE(Name, Suffix) \
case LoongArch::Name##_##Suffix: \
+ if (!MergeAMOWithMB) \
+ return std::nullopt; \
+ [[fallthrough]]; \
case LoongArch::Name##__DB_##Suffix: \
return LoongArch::Name##__DB_##Suffix;
switch (MI.getOpcode()) {
diff --git a/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll b/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
index 3382e28c14891..33b6bc42a80f3 100644
--- a/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
+++ b/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
@@ -2,6 +2,8 @@
; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefixes=CHECK,NORMAL
; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-require-no-path-bypass=false < %s \
; RUN: | FileCheck %s --check-prefixes=CHECK,BYPASS
+; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-merge-amo-with-dbar=false < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK,NOMAMO
; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-disable-inline-asm-barrier-opt=true < %s \
; RUN: | FileCheck %s --check-prefixes=CHECK,NOIASM
; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-replace-eliminated-dbar-to-nop=true < %s \
@@ -20,6 +22,11 @@ define void @dbar_acquire_acquire() nounwind {
; BYPASS-NEXT: dbar 20
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -47,6 +54,11 @@ define void @dbar_acquire_release() nounwind {
; BYPASS-NEXT: dbar 16
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_release:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 16
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_release:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 16
@@ -76,6 +88,12 @@ define i32 @dbar_acquire_add_acquire(i32 %a) nounwind {
; BYPASS-NEXT: dbar 20
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_add_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: addi.w $a0, $a0, 1
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_add_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: addi.w $a0, $a0, 1
@@ -106,6 +124,11 @@ define void @dbar_release_acquire() nounwind {
; BYPASS-NEXT: dbar 16
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_release_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 16
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_release_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 16
@@ -133,6 +156,11 @@ define void @dbar_seq_cst_acq_rel_seq_cst() nounwind {
; BYPASS-NEXT: dbar 16
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_seq_cst_acq_rel_seq_cst:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 16
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_seq_cst_acq_rel_seq_cst:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 16
@@ -162,6 +190,11 @@ define void @dbar_acquire_asm_dbar_acquire() nounwind {
; BYPASS-NEXT: dbar 20
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -195,6 +228,11 @@ define void @dbar_acquire_asm_space_dbar_acquire() nounwind {
; BYPASS-NEXT: dbar 20
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_space_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_space_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -228,6 +266,11 @@ define void @dbar_acquire_asm_comment_dbar_acquire() nounwind {
; BYPASS-NEXT: dbar 20
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_comment_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_comment_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -261,6 +304,11 @@ define void @dbar_acquire_asm_arg0_dbar_acquire() nounwind {
; BYPASS-NEXT: dbar 16
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_arg0_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 16
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_arg0_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -294,6 +342,11 @@ define void @dbar_acquire_asm_arg1_dbar_acquire() nounwind {
; BYPASS-NEXT: dbar 16
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_arg1_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 16
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_arg1_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -327,6 +380,11 @@ define void @dbar_completion_acquire() nounwind {
; BYPASS-NEXT: dbar 0
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_completion_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 0
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_completion_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 0
@@ -354,6 +412,11 @@ define void @dbar_release_completion() nounwind {
; BYPASS-NEXT: dbar 0
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_release_completion:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 0
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_release_completion:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 0
@@ -383,6 +446,12 @@ define void @dbar_release_amswap_i8_acquire() nounwind {
; BYPASS-NEXT: amand_db.w $a1, $a0, $zero
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_release_amswap_i8_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: addi.w $a0, $zero, -256
+; NOMAMO-NEXT: amand_db.w $a1, $a0, $zero
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_release_amswap_i8_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: addi.w $a0, $zero, -256
@@ -412,6 +481,11 @@ define void @dbar_release_amswap_i32_acquire() nounwind {
; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_release_amswap_i32_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: amswap_db.w $a0, $zero, $zero
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_release_amswap_i32_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: amswap_db.w $a0, $zero, $zero
@@ -439,6 +513,12 @@ define void @dbar_release_amswap_i32_monotonic() nounwind {
; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_release_amswap_i32_monotonic:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 18
+; NOMAMO-NEXT: amswap.w $a0, $zero, $zero
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_release_amswap_i32_monotonic:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: amswap_db.w $a0, $zero, $zero
@@ -480,6 +560,12 @@ define void @amswap_i8_release_dbar_acquire() nounwind {
; BYPASS-NEXT: amand_db.w $a1, $a0, $zero
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: amswap_i8_release_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: addi.w $a0, $zero, -256
+; NOMAMO-NEXT: amand_db.w $a1, $a0, $zero
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: amswap_i8_release_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: addi.w $a0, $zero, -256
@@ -509,6 +595,11 @@ define void @amswap_i32_release_dbar_acquire() nounwind {
; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: amswap_i32_release_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: amswap_db.w $a0, $zero, $zero
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: amswap_i32_release_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: amswap_db.w $a0, $zero, $zero
@@ -550,6 +641,12 @@ define void @dbar_release_amswap_i8_release_dbar_acquire() nounwind {
; BYPASS-NEXT: amand_db.w $a1, $a0, $zero
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_release_amswap_i8_release_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: addi.w $a0, $zero, -256
+; NOMAMO-NEXT: amand_db.w $a1, $a0, $zero
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_release_amswap_i8_release_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: addi.w $a0, $zero, -256
@@ -581,6 +678,11 @@ define void @dbar_acquire_amswap_i32_release_dbar_acquire() nounwind {
; BYPASS-NEXT: amswap_db.w $a0, $zero, $zero
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_amswap_i32_release_dbar_acquire:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: amswap_db.w $a0, $zero, $zero
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_amswap_i32_release_dbar_acquire:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: amswap_db.w $a0, $zero, $zero
@@ -628,6 +730,13 @@ define void @dbar_acquire_asm_amswap_i32_release() nounwind {
; BYPASS-NEXT: #NO_APP
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_amswap_i32_release:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: #APP
+; NOMAMO-NEXT: amswap_db.w $a0, $a1, $a2
+; NOMAMO-NEXT: #NO_APP
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_amswap_i32_release:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -664,6 +773,14 @@ define void @dbar_acquire_asm_amswap_i32_monotonic() nounwind {
; BYPASS-NEXT: #NO_APP
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_amswap_i32_monotonic:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: #APP
+; NOMAMO-NEXT: amswap.w $a0, $a1, $a2
+; NOMAMO-NEXT: #NO_APP
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_amswap_i32_monotonic:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -700,6 +817,14 @@ define void @dbar_acquire_asm_space_amswap_i32_monotonic() nounwind {
; BYPASS-NEXT: #NO_APP
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_space_amswap_i32_monotonic:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: #APP
+; NOMAMO-NEXT: amswap.w $a0, $a1, $a2
+; NOMAMO-NEXT: #NO_APP
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_space_amswap_i32_monotonic:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -736,6 +861,14 @@ define void @dbar_acquire_asm_comment_amswap_i32_monotonic() nounwind {
; BYPASS-NEXT: #NO_APP
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_comment_amswap_i32_monotonic:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: #APP
+; NOMAMO-NEXT: amswap.w $a0, $a1, $a2 # atomic
+; NOMAMO-NEXT: #NO_APP
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_comment_amswap_i32_monotonic:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -772,6 +905,14 @@ define void @dbar_acquire_asm_args_amswap_i32_monotonic() nounwind {
; BYPASS-NEXT: #NO_APP
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_args_amswap_i32_monotonic:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: #APP
+; NOMAMO-NEXT: amswap.w $a0, $zero, $zero
+; NOMAMO-NEXT: #NO_APP
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_args_amswap_i32_monotonic:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -808,6 +949,13 @@ define void @dbar_acquire_asm_reg_args_amswap_i32_monotonic() nounwind {
; BYPASS-NEXT: #NO_APP
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_asm_reg_args_amswap_i32_monotonic:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: #APP
+; NOMAMO-NEXT: amswap_db.w $ra, $zero, $zero
+; NOMAMO-NEXT: #NO_APP
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_asm_reg_args_amswap_i32_monotonic:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: dbar 20
@@ -867,6 +1015,25 @@ define void @dbar_acquire_cmpxchg_i32_dbar_release() nounwind {
; BYPASS-NEXT: dbar 16
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: dbar_acquire_cmpxchg_i32_dbar_release:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: ori $a0, $zero, 1
+; NOMAMO-NEXT: .LBB28_1: # %entry
+; NOMAMO-NEXT: # =>This Inner Loop Header: Depth=1
+; NOMAMO-NEXT: ll.w $a1, $zero, 0
+; NOMAMO-NEXT: bne $a1, $zero, .LBB28_3
+; NOMAMO-NEXT: # %bb.2: # %entry
+; NOMAMO-NEXT: # in Loop: Header=BB28_1 Depth=1
+; NOMAMO-NEXT: move $a2, $a0
+; NOMAMO-NEXT: sc.w $a2, $zero, 0
+; NOMAMO-NEXT: beq $a2, $zero, .LBB28_1
+; NOMAMO-NEXT: b .LBB28_4
+; NOMAMO-NEXT: .LBB28_3: # %entry
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: .LBB28_4: # %entry
+; NOMAMO-NEXT: dbar 18
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: dbar_acquire_cmpxchg_i32_dbar_release:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: ori $a0, $zero, 1
@@ -934,6 +1101,17 @@ define void @cfg_dominate(i1 %a) {
; BYPASS-NEXT: .LBB29_2:
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: cfg_dominate:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: andi $a0, $a0, 1
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: beqz $a0, .LBB29_2
+; NOMAMO-NEXT: # %bb.1:
+; NOMAMO-NEXT: ret
+; NOMAMO-NEXT: .LBB29_2:
+; NOMAMO-NEXT: dbar 18
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: cfg_dominate:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: andi $a0, $a0, 1
@@ -997,6 +1175,21 @@ define void @cfg_postdominate(i1 %a, i1 %b, i1 %c) {
; BYPASS-NEXT: dbar 16
; BYPASS-NEXT: ret
;
+; NOMAMO-LABEL: cfg_postdominate:
+; NOMAMO: # %bb.0: # %entry
+; NOMAMO-NEXT: andi $a0, $a0, 1
+; NOMAMO-NEXT: beqz $a0, .LBB30_2
+; NOMAMO-NEXT: .LBB30_1:
+; NOMAMO-NEXT: andi $a0, $a1, 1
+; NOMAMO-NEXT: dbar 20
+; NOMAMO-NEXT: beqz $a0, .LBB30_3
+; NOMAMO-NEXT: .LBB30_2:
+; NOMAMO-NEXT: andi $a0, $a2, 1
+; NOMAMO-NEXT: bnez $a0, .LBB30_1
+; NOMAMO-NEXT: .LBB30_3:
+; NOMAMO-NEXT: dbar 18
+; NOMAMO-NEXT: ret
+;
; NOIASM-LABEL: cfg_postdominate:
; NOIASM: # %bb.0: # %entry
; NOIASM-NEXT: andi $a0, $a0, 1
>From 46e5b0173885dc560a8e2e6bd8fbf1ba094c5df3 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Wed, 9 Sep 2026 21:53:24 +0800
Subject: [PATCH 4/5] Fix assertion failure
---
llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
index 61c5f91e2514d..c93629453058d 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
@@ -272,7 +272,8 @@ struct InstBarrier {
assert(MO.isImm() && "Unexpected operand type!");
const InlineAsm::Flag F(MO.getImm());
if (N == Off) {
- assert(F.isImmKind() && "Unexpected flag kind!");
+ if (!F.isImmKind())
+ return std::nullopt;
HintOff = AsmDescOp + 1;
Hint = MI.getOperand(HintOff).getImm();
return std::pair(Hint, HintOff);
>From eeead2388fe721033fd6e5c47c08009163208205 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Thu, 10 Sep 2026 10:48:17 +0800
Subject: [PATCH 5/5] Address wanglei's comments
---
.../Target/LoongArch/LoongArchMemoryBarrierOpt.cpp | 6 ++----
llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll | 11 ++++++-----
2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
index c93629453058d..d05f223da1a82 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMemoryBarrierOpt.cpp
@@ -434,8 +434,7 @@ static void updateMB(InstBarrier &I, BarrierHint Hint, MachineFunction *MF) {
}
MachineOperand &MO = I.MI->getOperand(InlineAsm::MIOp_AsmString);
auto New = I.OpName.str() + " " + llvm::utostr(Hint.Hint);
- auto Sym = MF->createExternalSymbolName(New);
- MO = MachineOperand::CreateES(Sym);
+ MO.ChangeToES(MF->createExternalSymbolName(New), MO.getTargetFlags());
}
// Replace AMO to AMO_DB
@@ -451,8 +450,7 @@ static void replaceAM(InstBarrier &I, MachineFunction *MF) {
return;
MachineOperand &MO = I.MI->getOperand(InlineAsm::MIOp_AsmString);
auto New = I.OpName.str() + " " + I.Operands.str();
- auto Sym = MF->createExternalSymbolName(New);
- MO = MachineOperand::CreateES(Sym);
+ MO.ChangeToES(MF->createExternalSymbolName(New), MO.getTargetFlags());
}
bool LoongArchMemoryBarrierOpt::eliminateRedundantBarrier(
diff --git a/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll b/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
index 33b6bc42a80f3..cf3041b1094c0 100644
--- a/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
+++ b/llvm/test/CodeGen/LoongArch/memory-barrier-opt.ll
@@ -1,12 +1,13 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefixes=CHECK,NORMAL
-; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-require-no-path-bypass=false < %s \
+; RUN: llc --mtriple=loongarch64 -mattr=+d -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK,NORMAL
+; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-require-no-path-bypass=false -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefixes=CHECK,BYPASS
-; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-merge-amo-with-dbar=false < %s \
+; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-merge-amo-with-dbar=false -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefixes=CHECK,NOMAMO
-; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-disable-inline-asm-barrier-opt=true < %s \
+; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-disable-inline-asm-barrier-opt=true -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefixes=CHECK,NOIASM
-; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-replace-eliminated-dbar-to-nop=true < %s \
+; RUN: llc --mtriple=loongarch64 -mattr=+d --loongarch-replace-eliminated-dbar-to-nop=true -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefixes=CHECK,BTONOP
;; Positive
More information about the llvm-branch-commits
mailing list