summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
authorDaniel Sanders <daniel_l_sanders@apple.com>2017-10-15 02:41:12 +0000
committerDaniel Sanders <daniel_l_sanders@apple.com>2017-10-15 02:41:12 +0000
commit39690bdf429bc4aa0fb70ee454e6d602a77d0a39 (patch)
treef8d919028078cacc1cd69362fde65e7b1cde98a0 /llvm/include
parentb7c0b089f26af8150209af173af4c199b9e13531 (diff)
downloadbcm5719-llvm-39690bdf429bc4aa0fb70ee454e6d602a77d0a39.tar.gz
bcm5719-llvm-39690bdf429bc4aa0fb70ee454e6d602a77d0a39.zip
[globalisel][tablegen] Map ld and st to G_LOAD and G_STORE. NFC
Summary: There is an important mismatch between ISD::LOAD and G_LOAD (and likewise for ISD::STORE and G_STORE). In SelectionDAG, ISD::LOAD is a non-atomic load and atomic loads are handled by a separate node. However, this is not true of GlobalISel's G_LOAD. For G_LOAD, the MachineMemOperand indicates the atomicity of the operation. As a result, this mapping must also add a predicate that checks for non-atomic MachineMemOperands. This is NFC since these nodes always have predicates in practice and are therefore always rejected at the moment. Depends on D37443 Reviewers: ab, qcolombet, t.p.northover, rovka, aditya_nandakumar Reviewed By: qcolombet Subscribers: kristof.beyls, llvm-commits, igorb Differential Revision: https://reviews.llvm.org/D37445 llvm-svn: 315843
Diffstat (limited to 'llvm/include')
-rw-r--r--llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h3
-rw-r--r--llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h19
-rw-r--r--llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td22
3 files changed, 44 insertions, 0 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
index db9c5b713b7..3cc1d35cc5c 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
@@ -107,6 +107,9 @@ enum {
/// - InsnID - Instruction ID
/// - The predicate to test
GIM_CheckAPFloatImmPredicate,
+ /// Check a memory operation is non-atomic.
+ /// - InsnID - Instruction ID
+ GIM_CheckNonAtomic,
/// Check the type for the specified operand
/// - InsnID - Instruction ID
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
index f1bc8484096..d4cb1326fb8 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
@@ -209,6 +209,25 @@ bool InstructionSelector::executeMatchTable(
return false;
break;
}
+ case GIM_CheckNonAtomic: {
+ int64_t InsnID = MatchTable[CurrentIdx++];
+ DEBUG(dbgs() << CurrentIdx << ": GIM_CheckNonAtomic(MIs[" << InsnID
+ << "])\n");
+ assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
+ assert((State.MIs[InsnID]->getOpcode() == TargetOpcode::G_LOAD ||
+ State.MIs[InsnID]->getOpcode() == TargetOpcode::G_STORE) &&
+ "Expected G_LOAD/G_STORE");
+
+ if (!State.MIs[InsnID]->hasOneMemOperand())
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+
+ for (const auto &MMO : State.MIs[InsnID]->memoperands())
+ if (MMO->getOrdering() != AtomicOrdering::NotAtomic)
+ if (handleReject() == RejectAndGiveUp)
+ return false;
+ break;
+ }
case GIM_CheckType: {
int64_t InsnID = MatchTable[CurrentIdx++];
diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index 96245b251f9..c012b20fd7b 100644
--- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -23,6 +23,11 @@
class GINodeEquiv<Instruction i, SDNode node> {
Instruction I = i;
SDNode Node = node;
+
+ // SelectionDAG has separate nodes for atomic and non-atomic memory operations
+ // (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel
+ // stores this information in the MachineMemoryOperand.
+ bit CheckMMOIsNonAtomic = 0;
}
// These are defined in the same order as the G_* instructions.
@@ -72,6 +77,23 @@ def : GINodeEquiv<G_INTRINSIC_W_SIDE_EFFECTS, intrinsic_w_chain>;
def : GINodeEquiv<G_BR, br>;
def : GINodeEquiv<G_BSWAP, bswap>;
+// Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some
+// complications that tablegen must take care of. For example, Predicates such
+// as isSignExtLoad require that this is not a perfect 1:1 mapping since a
+// sign-extending load is (G_SEXT (G_LOAD x)) in GlobalISel. Additionally,
+// G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had
+// separate nodes for them. This GINodeEquiv maps the non-atomic loads to
+// G_LOAD with a non-atomic MachineMemOperand.
+def : GINodeEquiv<G_LOAD, ld> { let CheckMMOIsNonAtomic = 1; }
+// Broadly speaking G_STORE is equivalent to ISD::STORE but there are some
+// complications that tablegen must take care of. For example, predicates such
+// as isTruncStore require that this is not a perfect 1:1 mapping since a
+// truncating store is (G_STORE (G_TRUNCATE x)) in GlobalISel. Additionally,
+// G_STORE handles both atomic and non-atomic stores where as SelectionDAG had
+// separate nodes for them. This GINodeEquiv maps the non-atomic stores to
+// G_STORE with a non-atomic MachineMemOperand.
+def : GINodeEquiv<G_STORE, st> { let CheckMMOIsNonAtomic = 1; }
+
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
// Should be used on defs that subclass GIComplexOperandMatcher<>.
class GIComplexPatternEquiv<ComplexPattern seldag> {
OpenPOWER on IntegriCloud