Optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO( const MachineBasicBlock::iterator &MI) const { assert(MI->getNumMemOperands() > 0); SyncScope::ID SSID = SyncScope::SingleThread; AtomicOrdering Ordering = AtomicOrdering::NotAtomic; AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic; SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::NONE; bool IsNonTemporal = true; // Validator should check whether or not MMOs cover the entire set of // locations accessed by the memory instruction. for (const auto &MMO : MI->memoperands()) { IsNonTemporal &= MMO->isNonTemporal(); InstrAddrSpace |= toSIAtomicAddrSpace(MMO->getPointerInfo().getAddrSpace()); AtomicOrdering OpOrdering = MMO->getOrdering(); if (OpOrdering != AtomicOrdering::NotAtomic) { const auto &IsSyncScopeInclusion = MMI->isSyncScopeInclusion(SSID, MMO->getSyncScopeID()); if (!IsSyncScopeInclusion) { reportUnsupported(MI, "Unsupported non-inclusive atomic synchronization scope"); return None; } SSID = IsSyncScopeInclusion.getValue() ? SSID : MMO->getSyncScopeID(); Ordering = isStrongerThan(Ordering, OpOrdering) ? Ordering : MMO->getOrdering(); assert(MMO->getFailureOrdering() != AtomicOrdering::Release && MMO->getFailureOrdering() != AtomicOrdering::AcquireRelease); FailureOrdering = isStrongerThan(FailureOrdering, MMO->getFailureOrdering()) ? FailureOrdering : MMO->getFailureOrdering(); } } SIAtomicScope Scope = SIAtomicScope::NONE; SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE; bool IsCrossAddressSpaceOrdering = false; if (Ordering != AtomicOrdering::NotAtomic) { auto ScopeOrNone = toSIAtomicScope(SSID, InstrAddrSpace); if (!ScopeOrNone) { reportUnsupported(MI, "Unsupported atomic synchronization scope"); return None; } std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) = ScopeOrNone.getValue(); if ((OrderingAddrSpace == SIAtomicAddrSpace::NONE) || ((OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) != OrderingAddrSpace)) { reportUnsupported(MI, "Unsupported atomic address space"); return None; } } return SIMemOpInfo(Ordering, Scope, OrderingAddrSpace, InstrAddrSpace, IsCrossAddressSpaceOrdering, FailureOrdering, IsNonTemporal); }
Optional<SIMemOpInfo> SIMemOpAccess::getAtomicCmpxchgOrRmwInfo( const MachineBasicBlock::iterator &MI) const { assert(MI->getDesc().TSFlags & SIInstrFlags::maybeAtomic); if (!(MI->mayLoad() && MI->mayStore())) return None; // Be conservative if there are no memory operands. if (MI->getNumMemOperands() == 0) return SIMemOpInfo(); return constructFromMIWithMMO(MI); }