summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Target/TargetSelectionDAG.td81
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.cpp54
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.h11
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;
OpenPOWER on IntegriCloud