From: Daniel Sanders Date: Thu, 30 Nov 2017 21:05:59 +0000 (+0000) Subject: [globalisel][tablegen] Add support for relative AtomicOrderings X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=053346db8cecee4da27aba2d9ed54b2ef351e960;p=llvm [globalisel][tablegen] Add support for relative AtomicOrderings No test yet because the relevant rules are blocked on the atomic_load, and atomic_store nodes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319475 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 726a702d96b..e599a1b179e 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -115,6 +115,8 @@ enum { /// - InsnID - Instruction ID /// - Ordering - The AtomicOrdering value GIM_CheckAtomicOrdering, + GIM_CheckAtomicOrderingOrStrongerThan, + GIM_CheckAtomicOrderingWeakerThan, /// Check the type for the specified operand /// - InsnID - Instruction ID diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h index 8848274d22e..ac2c055ab14 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h @@ -244,6 +244,44 @@ bool InstructionSelector::executeMatchTable( return false; break; } + case GIM_CheckAtomicOrderingOrStrongerThan: { + int64_t InsnID = MatchTable[CurrentIdx++]; + AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << CurrentIdx + << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs[" + << InsnID << "], " << (uint64_t)Ordering << ")\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + + if (!State.MIs[InsnID]->hasOneMemOperand()) + if (handleReject() == RejectAndGiveUp) + return false; + + for (const auto &MMO : State.MIs[InsnID]->memoperands()) + if (!isAtLeastOrStrongerThan(MMO->getOrdering(), Ordering)) + if (handleReject() == RejectAndGiveUp) + return false; + break; + } + case GIM_CheckAtomicOrderingWeakerThan: { + int64_t InsnID = MatchTable[CurrentIdx++]; + AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << CurrentIdx + << ": GIM_CheckAtomicOrderingWeakerThan(MIs[" + << InsnID << "], " << (uint64_t)Ordering << ")\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + + if (!State.MIs[InsnID]->hasOneMemOperand()) + if (handleReject() == RejectAndGiveUp) + return false; + + for (const auto &MMO : State.MIs[InsnID]->memoperands()) + if (!isStrongerThan(Ordering, MMO->getOrdering())) + if (handleReject() == RejectAndGiveUp) + return false; + break; + } case GIM_CheckType: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t OpIdx = MatchTable[CurrentIdx++]; diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 98eaeda89c0..06caa21d288 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -689,6 +689,14 @@ class PatFrag(N)->getOrdering() == AtomicOrdering::SequentiallyConsistent bit IsAtomicOrderingSequentiallyConsistent = ?; + // isAcquireOrStronger(cast(N)->getOrdering()) + // !isAcquireOrStronger(cast(N)->getOrdering()) + bit IsAtomicOrderingAcquireOrStronger = ?; + + // isReleaseOrStronger(cast(N)->getOrdering()) + // !isReleaseOrStronger(cast(N)->getOrdering()) + bit IsAtomicOrderingReleaseOrStronger = ?; + // cast(N)->getMemoryVT() == MVT::; // cast(N)->getMemoryVT() == MVT::; ValueType MemoryVT = ?; diff --git a/lib/Target/AArch64/AArch64InstrAtomics.td b/lib/Target/AArch64/AArch64InstrAtomics.td index 4c61c3510ba..153bcf75cbc 100644 --- a/lib/Target/AArch64/AArch64InstrAtomics.td +++ b/lib/Target/AArch64/AArch64InstrAtomics.td @@ -30,18 +30,18 @@ def : Pat<(atomic_fence (imm), (imm)), (DMB (i32 0xb))>; // A atomic load operation that actually needs acquire semantics. class acquiring_load - : PatFrag<(ops node:$ptr), (base node:$ptr), [{ - AtomicOrdering Ordering = cast(N)->getOrdering(); - return isAcquireOrStronger(Ordering); -}]>; + : PatFrag<(ops node:$ptr), (base node:$ptr)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquireOrStronger = 1; +} // An atomic load operation that does not need either acquire or release // semantics. class relaxed_load - : PatFrag<(ops node:$ptr), (base node:$ptr), [{ - AtomicOrdering Ordering = cast(N)->getOrdering(); - return !isAcquireOrStronger(Ordering); -}]>; + : PatFrag<(ops node:$ptr), (base node:$ptr)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquireOrStronger = 0; +} // 8-bit loads def : Pat<(acquiring_load GPR64sp:$ptr), (LDARB GPR64sp:$ptr)>; @@ -113,19 +113,17 @@ def : Pat<(relaxed_load // A store operation that actually needs release semantics. class releasing_store - : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{ - AtomicOrdering Ordering = cast(N)->getOrdering(); - assert(Ordering != AtomicOrdering::AcquireRelease && - "unexpected store ordering"); - return isReleaseOrStronger(Ordering); -}]>; + : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingReleaseOrStronger = 1; +} // An atomic store operation that doesn't actually need to be atomic on AArch64. class relaxed_store - : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val), [{ - AtomicOrdering Ordering = cast(N)->getOrdering(); - return !isReleaseOrStronger(Ordering); -}]>; + : PatFrag<(ops node:$ptr, node:$val), (base node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingReleaseOrStronger = 0; +} // 8-bit stores def : Pat<(releasing_store GPR64sp:$ptr, GPR32:$val), diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 65b35623681..51473f06da7 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -888,7 +888,11 @@ std::string TreePredicateFn::getPredCode() const { if (getMemoryVT() == nullptr && !isAtomicOrderingMonotonic() && !isAtomicOrderingAcquire() && !isAtomicOrderingRelease() && !isAtomicOrderingAcquireRelease() && - !isAtomicOrderingSequentiallyConsistent()) + !isAtomicOrderingSequentiallyConsistent() && + !isAtomicOrderingAcquireOrStronger() && + !isAtomicOrderingReleaseOrStronger() && + !isAtomicOrderingWeakerThanAcquire() && + !isAtomicOrderingWeakerThanRelease()) PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), "IsAtomic cannot be used by itself"); } else { @@ -907,6 +911,15 @@ std::string TreePredicateFn::getPredCode() const { if (isAtomicOrderingSequentiallyConsistent()) PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), "IsAtomicOrderingSequentiallyConsistent requires IsAtomic"); + if (isAtomicOrderingAcquireOrStronger()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAtomicOrderingAcquireOrStronger requires IsAtomic"); + if (isAtomicOrderingReleaseOrStronger()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAtomicOrderingReleaseOrStronger requires IsAtomic"); + if (isAtomicOrderingWeakerThanAcquire()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAtomicOrderingWeakerThanAcquire requires IsAtomic"); } if (isLoad() || isStore() || isAtomic()) { @@ -937,6 +950,20 @@ std::string TreePredicateFn::getPredCode() const { Code += "if (cast(N)->getOrdering() != " "AtomicOrdering::SequentiallyConsistent) return false;\n"; + if (isAtomic() && isAtomicOrderingAcquireOrStronger()) + Code += "if (!isAcquireOrStronger(cast(N)->getOrdering())) " + "return false;\n"; + if (isAtomic() && isAtomicOrderingWeakerThanAcquire()) + Code += "if (isAcquireOrStronger(cast(N)->getOrdering())) " + "return false;\n"; + + if (isAtomic() && isAtomicOrderingReleaseOrStronger()) + Code += "if (!isReleaseOrStronger(cast(N)->getOrdering())) " + "return false;\n"; + if (isAtomic() && isAtomicOrderingWeakerThanRelease()) + Code += "if (isReleaseOrStronger(cast(N)->getOrdering())) " + "return false;\n"; + if (isLoad() || isStore()) { StringRef SDNodeName = isLoad() ? "LoadSDNode" : "StoreSDNode"; @@ -1070,6 +1097,18 @@ bool TreePredicateFn::isAtomicOrderingSequentiallyConsistent() const { return isPredefinedPredicateEqualTo("IsAtomicOrderingSequentiallyConsistent", true); } +bool TreePredicateFn::isAtomicOrderingAcquireOrStronger() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger", true); +} +bool TreePredicateFn::isAtomicOrderingWeakerThanAcquire() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireOrStronger", false); +} +bool TreePredicateFn::isAtomicOrderingReleaseOrStronger() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger", true); +} +bool TreePredicateFn::isAtomicOrderingWeakerThanRelease() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingReleaseOrStronger", false); +} Record *TreePredicateFn::getMemoryVT() const { Record *R = getOrigPatFragRecord()->getRecord(); if (R->isValueUnset("MemoryVT")) diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 8b72bd6d90b..afbcb10a4b6 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -516,6 +516,16 @@ public: /// Is this predicate the predefined sequentially consistent atomic predicate? bool isAtomicOrderingSequentiallyConsistent() const; + /// Is this predicate the predefined acquire-or-stronger atomic predicate? + bool isAtomicOrderingAcquireOrStronger() const; + /// Is this predicate the predefined weaker-than-acquire atomic predicate? + bool isAtomicOrderingWeakerThanAcquire() const; + + /// Is this predicate the predefined release-or-stronger atomic predicate? + bool isAtomicOrderingReleaseOrStronger() const; + /// Is this predicate the predefined weaker-than-release atomic predicate? + bool isAtomicOrderingWeakerThanRelease() const; + /// If non-null, indicates that this predicate is a predefined memory VT /// predicate for a load/store and returns the ValueType record for the memory VT. Record *getMemoryVT() const; diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp index d9048c231c2..062fe59d820 100644 --- a/utils/TableGen/GlobalISelEmitter.cpp +++ b/utils/TableGen/GlobalISelEmitter.cpp @@ -230,6 +230,14 @@ static std::string explainPredicates(const TreePatternNode *N) { Explanation += " acq_rel"; if (P.isAtomicOrderingSequentiallyConsistent()) Explanation += " seq_cst"; + if (P.isAtomicOrderingAcquireOrStronger()) + Explanation += " >=acquire"; + if (P.isAtomicOrderingWeakerThanAcquire()) + Explanation += " getKind() == IPM_AtomicOrderingMMO; @@ -1339,9 +1362,15 @@ public: void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule, unsigned InsnVarID) const override { - Table << MatchTable::Opcode("GIM_CheckAtomicOrdering") - << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID) - << MatchTable::Comment("Order") + StringRef Opcode = "GIM_CheckAtomicOrdering"; + + if (Comparator == AO_OrStronger) + Opcode = "GIM_CheckAtomicOrderingOrStrongerThan"; + if (Comparator == AO_WeakerThan) + Opcode = "GIM_CheckAtomicOrderingWeakerThan"; + + Table << MatchTable::Opcode(Opcode) << MatchTable::Comment("MI") + << MatchTable::IntValue(InsnVarID) << MatchTable::Comment("Order") << MatchTable::NamedValue(("(int64_t)AtomicOrdering::" + Order).str()) << MatchTable::LineBreak; } @@ -2554,6 +2583,28 @@ Expected GlobalISelEmitter::createAndImportSelDAGMatcher( "SequentiallyConsistent"); continue; } + + if (Predicate.isAtomicOrderingAcquireOrStronger()) { + InsnMatcher.addPredicate( + "Acquire", AtomicOrderingMMOPredicateMatcher::AO_OrStronger); + continue; + } + if (Predicate.isAtomicOrderingWeakerThanAcquire()) { + InsnMatcher.addPredicate( + "Acquire", AtomicOrderingMMOPredicateMatcher::AO_WeakerThan); + continue; + } + + if (Predicate.isAtomicOrderingReleaseOrStronger()) { + InsnMatcher.addPredicate( + "Release", AtomicOrderingMMOPredicateMatcher::AO_OrStronger); + continue; + } + if (Predicate.isAtomicOrderingWeakerThanRelease()) { + InsnMatcher.addPredicate( + "Release", AtomicOrderingMMOPredicateMatcher::AO_WeakerThan); + continue; + } } return failedImport("Src pattern child has predicate (" +