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
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319202
91177308-0d34-0410-b5e6-
96231b3b80d8
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))
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();
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());
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:
--- /dev/null
+# 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
+...