diff options
-rw-r--r-- | llvm/include/llvm/Target/TargetSelectionDAG.td | 81 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeGenDAGPatterns.cpp | 54 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeGenDAGPatterns.h | 11 |
3 files changed, 115 insertions, 31 deletions
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td index 386cb4e6d63..98eaeda89c0 100644 --- a/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -678,6 +678,17 @@ class PatFrag<dag ops, dag frag, code pred = [{}], // cast<StoreSDNode>(N)->isTruncatingStore(); bit IsTruncStore = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Monotonic + bit IsAtomicOrderingMonotonic = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Acquire + bit IsAtomicOrderingAcquire = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Release + bit IsAtomicOrderingRelease = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::AcquireRelease + bit IsAtomicOrderingAcquireRelease = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::SequentiallyConsistent + bit IsAtomicOrderingSequentiallyConsistent = ?; + // cast<LoadSDNode>(N)->getMemoryVT() == MVT::<VT>; // cast<StoreSDNode>(N)->getMemoryVT() == MVT::<VT>; ValueType MemoryVT = ?; @@ -1137,48 +1148,58 @@ def setne : PatFrag<(ops node:$lhs, node:$rhs), multiclass binary_atomic_op_ord<SDNode atomic_op> { def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Monotonic; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingMonotonic = 1; + } def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Acquire; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquire = 1; + } def #NAME#_release : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Release; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingRelease = 1; + } def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::AcquireRelease; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquireRelease = 1; + } def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::SequentiallyConsistent; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingSequentiallyConsistent = 1; + } } multiclass ternary_atomic_op_ord<SDNode atomic_op> { def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Monotonic; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingMonotonic = 1; + } def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Acquire; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquire = 1; + } def #NAME#_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Release; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingRelease = 1; + } def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::AcquireRelease; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquireRelease = 1; + } def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val), [{ - return cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::SequentiallyConsistent; - }]>; + (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingSequentiallyConsistent = 1; + } } multiclass binary_atomic_op<SDNode atomic_op> { diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index b8ba5db6ef4..65b35623681 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -885,10 +885,30 @@ std::string TreePredicateFn::getPredCode() const { } if (isAtomic()) { - if (getMemoryVT() == nullptr) + if (getMemoryVT() == nullptr && !isAtomicOrderingMonotonic() && + !isAtomicOrderingAcquire() && !isAtomicOrderingRelease() && + !isAtomicOrderingAcquireRelease() && + !isAtomicOrderingSequentiallyConsistent()) PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), "IsAtomic cannot be used by itself"); + } else { + if (isAtomicOrderingMonotonic()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAtomicOrderingMonotonic requires IsAtomic"); + if (isAtomicOrderingAcquire()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAtomicOrderingAcquire requires IsAtomic"); + if (isAtomicOrderingRelease()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAtomicOrderingRelease requires IsAtomic"); + if (isAtomicOrderingAcquireRelease()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAtomicOrderingAcquireRelease requires IsAtomic"); + if (isAtomicOrderingSequentiallyConsistent()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAtomicOrderingSequentiallyConsistent requires IsAtomic"); } + if (isLoad() || isStore() || isAtomic()) { StringRef SDNodeName = isLoad() ? "LoadSDNode" : isStore() ? "StoreSDNode" : "AtomicSDNode"; @@ -901,6 +921,22 @@ std::string TreePredicateFn::getPredCode() const { .str(); } + if (isAtomic() && isAtomicOrderingMonotonic()) + Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " + "AtomicOrdering::Monotonic) return false;\n"; + if (isAtomic() && isAtomicOrderingAcquire()) + Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " + "AtomicOrdering::Acquire) return false;\n"; + if (isAtomic() && isAtomicOrderingRelease()) + Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " + "AtomicOrdering::Release) return false;\n"; + if (isAtomic() && isAtomicOrderingAcquireRelease()) + Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " + "AtomicOrdering::AcquireRelease) return false;\n"; + if (isAtomic() && isAtomicOrderingSequentiallyConsistent()) + Code += "if (cast<AtomicSDNode>(N)->getOrdering() != " + "AtomicOrdering::SequentiallyConsistent) return false;\n"; + if (isLoad() || isStore()) { StringRef SDNodeName = isLoad() ? "LoadSDNode" : "StoreSDNode"; @@ -1018,6 +1054,22 @@ bool TreePredicateFn::isNonTruncStore() const { bool TreePredicateFn::isTruncStore() const { return isPredefinedPredicateEqualTo("IsTruncStore", true); } +bool TreePredicateFn::isAtomicOrderingMonotonic() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingMonotonic", true); +} +bool TreePredicateFn::isAtomicOrderingAcquire() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquire", true); +} +bool TreePredicateFn::isAtomicOrderingRelease() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingRelease", true); +} +bool TreePredicateFn::isAtomicOrderingAcquireRelease() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingAcquireRelease", true); +} +bool TreePredicateFn::isAtomicOrderingSequentiallyConsistent() const { + return isPredefinedPredicateEqualTo("IsAtomicOrderingSequentiallyConsistent", + true); +} Record *TreePredicateFn::getMemoryVT() const { Record *R = getOrigPatFragRecord()->getRecord(); if (R->isValueUnset("MemoryVT")) diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h index 3a76ab25ea7..8b72bd6d90b 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -505,6 +505,17 @@ public: /// Is this predicate the predefined truncating store predicate? bool isTruncStore() const; + /// Is this predicate the predefined monotonic atomic predicate? + bool isAtomicOrderingMonotonic() const; + /// Is this predicate the predefined acquire atomic predicate? + bool isAtomicOrderingAcquire() const; + /// Is this predicate the predefined release atomic predicate? + bool isAtomicOrderingRelease() const; + /// Is this predicate the predefined acquire-release atomic predicate? + bool isAtomicOrderingAcquireRelease() const; + /// Is this predicate the predefined sequentially consistent atomic predicate? + bool isAtomicOrderingSequentiallyConsistent() 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; |