From f5ebe810b5197dbb268db890c5bfec016f447101 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Tue, 11 Aug 2026 17:47:01 +0800 Subject: [MIR] Parse one-ordering compare-exchange MMOs --- backend/lib/CodeGen/MachineMemOperand.cpp | 7 +-- backend/lib/MIR/MIParser.cpp | 78 +++++++++++++++---------------- 2 files changed, 42 insertions(+), 43 deletions(-) (limited to 'backend/lib') diff --git a/backend/lib/CodeGen/MachineMemOperand.cpp b/backend/lib/CodeGen/MachineMemOperand.cpp index 5f126fd..cb90e61 100644 --- a/backend/lib/CodeGen/MachineMemOperand.cpp +++ b/backend/lib/CodeGen/MachineMemOperand.cpp @@ -37,13 +37,15 @@ namespace { } [[nodiscard]] bool isValidCompareExchangeFailureOrdering(AtomicOrdering Ordering) noexcept { - return Ordering == AtomicOrdering::Monotonic || Ordering == AtomicOrdering::Acquire || - Ordering == AtomicOrdering::SequentiallyConsistent; + return Ordering == AtomicOrdering::NotAtomic || Ordering == AtomicOrdering::Monotonic || + Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::SequentiallyConsistent; } [[nodiscard]] bool isFailureOrderingNoStrongerThanSuccess(AtomicOrdering Failure, AtomicOrdering Success) noexcept { switch (Failure) { + case AtomicOrdering::NotAtomic: + return true; case AtomicOrdering::Monotonic: return isValidAtomicReadModifyWriteOrdering(Success); case AtomicOrdering::Acquire: @@ -51,7 +53,6 @@ namespace { Success == AtomicOrdering::SequentiallyConsistent; case AtomicOrdering::SequentiallyConsistent: return Success == AtomicOrdering::SequentiallyConsistent; - case AtomicOrdering::NotAtomic: case AtomicOrdering::Unordered: case AtomicOrdering::Release: case AtomicOrdering::AcquireRelease: diff --git a/backend/lib/MIR/MIParser.cpp b/backend/lib/MIR/MIParser.cpp index 01ecbf5..f634119 100644 --- a/backend/lib/MIR/MIParser.cpp +++ b/backend/lib/MIR/MIParser.cpp @@ -2,6 +2,7 @@ #include "rcc/MIR/MIParser.h" +#include "rcc/CodeGen/GenericOpcodes.h" #include "rcc/CodeGen/InlineAsm.h" #include "rcc/CodeGen/InstructionDescriptor.h" #include "rcc/CodeGen/MachineBasicBlock.h" @@ -406,7 +407,7 @@ private: [[nodiscard]] bool parseCFIUnsigned(std::uint32_t &Result); [[nodiscard]] bool parseCFIOperand(ParsedOperand &Result); [[nodiscard]] bool parseMemoryBase(MemoryBase &Result, std::int64_t &Offset); - [[nodiscard]] bool parseMemoryOperand(const MachineMemOperand *&Result); + [[nodiscard]] bool parseMemoryOperand(const MachineMemOperand *&Result, Opcode InstructionOpcode); [[nodiscard]] bool parsePredicateOperand(ParsedOperand &Result, bool IsFloating); [[nodiscard]] bool parseShuffleMaskOperand(ParsedOperand &Result); [[nodiscard]] bool parseDebugInstrRefOperand(ParsedOperand &Result); @@ -585,8 +586,7 @@ bool MIParser::Impl::parseScalarLowLevelType(const MIToken &TypeToken, LLT &Resu std::uint64_t Value = 0; if (!parseUnsignedDigits(Digits, Value)) - return fail(TypeToken, - "expected integers after 's'/'i'/'f'/'bf'/'p' type identifier"); + return fail(TypeToken, "expected integers after 's'/'i'/'f'/'bf'/'p' type identifier"); Expected Created = makeUnexpected(ErrorCode::ParseError, "invalid low-level type"); switch (Kind) { @@ -642,15 +642,13 @@ bool MIParser::Impl::parseScalarLowLevelType(const MIToken &TypeToken, LLT &Resu bool MIParser::Impl::parseLowLevelType(LLT &Result) { const MIToken Begin = token(); const auto HasScalarPrefix = [](std::string_view Spelling) { - return Spelling.starts_with('s') || Spelling.starts_with('i') || - Spelling.starts_with('f') || Spelling.starts_with("bf") || - Spelling.starts_with('p'); + return Spelling.starts_with('s') || Spelling.starts_with('i') || Spelling.starts_with('f') || + Spelling.starts_with("bf") || Spelling.starts_with('p'); }; if (at(MITokenKind::Identifier)) { if (!HasScalarPrefix(token().stringValue())) { - return fail(Begin, - "expected tN, pA, , , , or " - " for GlobalISel type, where t = {'s', 'i', 'f', 'bf'}"); + return fail(Begin, "expected tN, pA, , , , or " + " for GlobalISel type, where t = {'s', 'i', 'f', 'bf'}"); } if (parseScalarLowLevelType(token(), Result)) return true; @@ -658,9 +656,8 @@ bool MIParser::Impl::parseLowLevelType(LLT &Result) { return false; } if (!consume(MITokenKind::Less)) { - return fail(Begin, - "expected tN, pA, , , , or " - " for GlobalISel type, where t = {'s', 'i', 'f', 'bf'}"); + return fail(Begin, "expected tN, pA, , , , or " + " for GlobalISel type, where t = {'s', 'i', 'f', 'bf'}"); } bool Scalable = false; @@ -668,20 +665,17 @@ bool MIParser::Impl::parseLowLevelType(LLT &Result) { Scalable = true; advance(); if (!at(MITokenKind::Identifier) || token().stringValue() != "x") { - return fail( - "expected , where t = {'s', 'i', 'f', 'bf', 'p'}"); + return fail("expected , where t = {'s', 'i', 'f', 'bf', 'p'}"); } advance(); } const auto VectorError = [this, &Begin, Scalable] { if (Scalable) { - return fail(Begin, - "expected for vector type, where t = " - "{'s', 'i', 'f', 'bf', 'p'}"); + return fail(Begin, "expected for vector type, where t = " + "{'s', 'i', 'f', 'bf', 'p'}"); } - return fail(Begin, - "expected for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}"); + return fail(Begin, "expected for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}"); }; std::uint64_t ElementCount = 0; @@ -846,13 +840,12 @@ bool MIParser::Impl::parseBlockDefinition(bool Create, std::uint32_t &ID) { if (Blocks.size() >= Options.MaximumBlocks) return fail(Label, "machine basic block count exceeds parser limit"); if (Blocks.contains(ID)) - return fail(Label, - "redefinition of machine basic block with id #" + std::to_string(ID)); + return fail(Label, "redefinition of machine basic block with id #" + std::to_string(ID)); if (!Label.stringValue().empty() && Context.HasIRBlock && !Context.HasIRBlock(Label.stringValue())) { return fail(Label, "basic block '" + std::string(Label.stringValue()) + - "' is not defined in the function '" + - std::string(Function.name()) + "'"); + "' is not defined in the function '" + std::string(Function.name()) + + "'"); } auto Created = Function.createBasicBlock(); if (!Created) @@ -1783,7 +1776,8 @@ bool MIParser::Impl::parseMemoryBase(MemoryBase &Result, std::int64_t &Offset) { return parseOptionalOffset(Offset); } -bool MIParser::Impl::parseMemoryOperand(const MachineMemOperand *&Result) { +bool MIParser::Impl::parseMemoryOperand(const MachineMemOperand *&Result, + Opcode InstructionOpcode) { const MIToken Begin = token(); if (expect(MITokenKind::LeftParen, "'(' before a machine memory operand")) return true; @@ -1870,11 +1864,16 @@ bool MIParser::Impl::parseMemoryOperand(const MachineMemOperand *&Result) { } const bool IsLoad = Description.Accesses.has(MemoryAccessFlag::Load); const bool IsStore = Description.Accesses.has(MemoryAccessFlag::Store); - if (OrderingCount == 1) - Description.AtomicKind = IsLoad && IsStore - ? AtomicOperation::ReadModifyWrite - : (IsLoad ? AtomicOperation::Load : AtomicOperation::Store); - else if (OrderingCount == 2) + if (OrderingCount == 1) { + if (InstructionOpcode == opcode(GenericOpcode::G_ATOMIC_CMPXCHG) || + InstructionOpcode == opcode(GenericOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS)) { + Description.AtomicKind = AtomicOperation::CompareExchange; + } else { + Description.AtomicKind = IsLoad && IsStore + ? AtomicOperation::ReadModifyWrite + : (IsLoad ? AtomicOperation::Load : AtomicOperation::Store); + } + } else if (OrderingCount == 2) Description.AtomicKind = AtomicOperation::CompareExchange; std::uint64_t MinimumBytes = 0; @@ -2608,16 +2607,15 @@ bool MIParser::Impl::parseInstruction(MachineBasicBlock &Block, bool InBundle, if (Operands.size() >= Options.MaximumOperandsPerInstruction) return fail("instruction operand count exceeds parser limit"); ParsedOperand Operand{MachineOperand::immediate(0), std::nullopt, {}}; - const bool IsInlineAsmExtraInfo = - IsInlineAsm && Operands.size() == InlineAsmExtraInfoOperandIndex && - at(MITokenKind::Identifier); - const bool IsInlineAsmOperandFlag = - IsInlineAsm && Operands.size() >= InlineAsmFirstConstraintOperandIndex && - at(MITokenKind::Identifier); - if (IsInlineAsmExtraInfo - ? parseInlineAsmExtraInfoOperand(Operand) - : (IsInlineAsmOperandFlag ? parseInlineAsmOperandFlag(Operand) - : parseOperand(false, Operand))) + const bool IsInlineAsmExtraInfo = IsInlineAsm && + Operands.size() == InlineAsmExtraInfoOperandIndex && + at(MITokenKind::Identifier); + const bool IsInlineAsmOperandFlag = IsInlineAsm && + Operands.size() >= InlineAsmFirstConstraintOperandIndex && + at(MITokenKind::Identifier); + if (IsInlineAsmExtraInfo ? parseInlineAsmExtraInfoOperand(Operand) + : (IsInlineAsmOperandFlag ? parseInlineAsmOperandFlag(Operand) + : parseOperand(false, Operand))) return true; Operands.push_back(std::move(Operand)); if (token().isNewlineOrEnd() || at(MITokenKind::DoubleColon) || at(MITokenKind::LeftBrace) || @@ -2708,7 +2706,7 @@ bool MIParser::Impl::parseInstruction(MachineBasicBlock &Block, bool InBundle, if (MemOperands.size() >= Options.MaximumMemoryOperandsPerInstruction) return fail("machine memory operand count exceeds parser limit"); const MachineMemOperand *MemOperand = nullptr; - if (parseMemoryOperand(MemOperand)) + if (parseMemoryOperand(MemOperand, Descriptor->InstructionOpcode)) return true; MemOperands.push_back(MemOperand); if (token().isNewlineOrEnd() || at(MITokenKind::LeftBrace)) -- cgit v1.2.3