From 17d277b7346b6cfcd236e5c12a34f25cf7c72a73 Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Tue, 28 Nov 2017 18:57:02 +0000 Subject: [PATCH] [mir] Print/Parse both MOLoad and MOStore when they occur together. Summary: They're not always mutually exclusive. read-modify-write atomics are both at the same time. One example of this is the SWP instructions on AArch64. Another example is GlobalISel's G_ATOMICRMW_* generic instructions which will be added in a later patch. Reviewers: arphaman, aemerson Reviewed By: aemerson Subscribers: aemerson, javed.absar, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D40157 llvm-svn: 319202 --- llvm/lib/CodeGen/MIRParser/MIParser.cpp | 12 +++++++++++- llvm/lib/CodeGen/MIRPrinter.cpp | 12 +++++++----- llvm/test/CodeGen/MIR/AArch64/swp.mir | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 llvm/test/CodeGen/MIR/AArch64/swp.mir diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 10dbaf7..9b5539a 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -2280,6 +2280,12 @@ bool MIParser::parseMachineMemoryOperand(MachineMemOperand *&Dest) { Flags |= MachineMemOperand::MOStore; lex(); + // Optional 'store' for operands that both load and store. + if (Token.is(MIToken::Identifier) && Token.stringValue() == "store") { + Flags |= MachineMemOperand::MOStore; + lex(); + } + // Optional synchronization scope. SyncScope::ID SSID; if (parseOptionalScope(MF.getFunction()->getContext(), SSID)) @@ -2302,7 +2308,11 @@ bool MIParser::parseMachineMemoryOperand(MachineMemOperand *&Dest) { MachinePointerInfo Ptr = MachinePointerInfo(); if (Token.is(MIToken::Identifier)) { - const char *Word = Flags & MachineMemOperand::MOLoad ? "from" : "into"; + const char *Word = + ((Flags & MachineMemOperand::MOLoad) && + (Flags & MachineMemOperand::MOStore)) + ? "on" + : Flags & MachineMemOperand::MOLoad ? "from" : "into"; if (Token.stringValue() != Word) return error(Twine("expected '") + Word + "'"); lex(); diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 02b0b7e..989e042 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -1110,12 +1110,12 @@ void MIPrinter::print(const LLVMContext &Context, const TargetInstrInfo &TII, if (Op.getFlags() & MachineMemOperand::MOTargetFlag3) OS << '"' << getTargetMMOFlagName(TII, MachineMemOperand::MOTargetFlag3) << "\" "; + + assert((Op.isLoad() || Op.isStore()) && "machine memory operand must be a load or store (or both)"); if (Op.isLoad()) OS << "load "; - else { - assert(Op.isStore() && "Non load machine operand must be a store"); + if (Op.isStore()) OS << "store "; - } printSyncScope(Context, Op.getSyncScopeID()); @@ -1126,10 +1126,12 @@ void MIPrinter::print(const LLVMContext &Context, const TargetInstrInfo &TII, OS << Op.getSize(); if (const Value *Val = Op.getValue()) { - OS << (Op.isLoad() ? " from " : " into "); + OS << ((Op.isLoad() && Op.isStore()) ? " on " + : Op.isLoad() ? " from " : " into "); printIRValueReference(*Val); } else if (const PseudoSourceValue *PVal = Op.getPseudoValue()) { - OS << (Op.isLoad() ? " from " : " into "); + OS << ((Op.isLoad() && Op.isStore()) ? " on " + : Op.isLoad() ? " from " : " into "); assert(PVal && "Expected a pseudo source value"); switch (PVal->kind()) { case PseudoSourceValue::Stack: diff --git a/llvm/test/CodeGen/MIR/AArch64/swp.mir b/llvm/test/CodeGen/MIR/AArch64/swp.mir new file mode 100644 index 0000000..4a31ab4 --- /dev/null +++ b/llvm/test/CodeGen/MIR/AArch64/swp.mir @@ -0,0 +1,33 @@ +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass none -o - %s | FileCheck %s + +--- | + define i32 @swp(i32* %addr) #0 { + entry: + %0 = atomicrmw xchg i32* %addr, i32 1 monotonic + ret i32 %0 + } + + attributes #0 = { "target-features"="+lse" } +... +--- +name: swp +alignment: 2 +tracksRegLiveness: true +registers: + - { id: 0, class: gpr64common } + - { id: 1, class: gpr32 } + - { id: 2, class: gpr32 } +liveins: + - { reg: '%x0', virtual-reg: '%0' } +body: | + bb.0.entry: + liveins: %x0 + + ; CHECK-LABEL: swp + ; CHECK: {{[0-9]+}}:gpr32 = SWPW killed %1, %0 :: (volatile load store monotonic 4 on %ir.addr) + %0:gpr64common = COPY %x0 + %1:gpr32 = MOVi32imm 1 + %2:gpr32 = SWPW killed %1, %0 :: (volatile load store monotonic 4 on %ir.addr) + %w0 = COPY %2 + RET_ReallyLR implicit %w0 +... -- 2.7.4