summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2016-04-18 21:48:55 +0000
committerTim Northover <tnorthover@apple.com>2016-04-18 21:48:55 +0000
commitb629c77692980a03cf4529cd39aff82f65e0478c (patch)
treef4f2b091954a44689c611a42511038eb733b3606 /llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
parent5235a1b603db838df51c91782ca98155d892ff9f (diff)
downloadbcm5719-llvm-b629c77692980a03cf4529cd39aff82f65e0478c.tar.gz
bcm5719-llvm-b629c77692980a03cf4529cd39aff82f65e0478c.zip
ARM: use a pseudo-instruction for cmpxchg at -O0.
The fast register-allocator cannot cope with inter-block dependencies without spilling. This is fine for ldrex/strex loops coming from atomicrmw instructions where any value produced within a block is dead by the end, but not for cmpxchg. So we lower a cmpxchg at -O0 via a pseudo-inst that gets expanded after regalloc. Fortunately this is at -O0 so we don't have to care about performance. This simplifies the various axes of expansion considerably: we assume a strong seq_cst operation and ensure ordering via the always-present DMB instructions rather than v8 acquire/release instructions. Should fix the 32-bit part of PR25526. llvm-svn: 266679
Diffstat (limited to 'llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 146fa6b32bd..ac1b7d474cb 100644
--- a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -253,6 +253,8 @@ private:
SDNode *SelectSMLAWSMULW(SDNode *N);
+ SDNode *SelectCMP_SWAP(SDNode *N);
+
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
/// inline asm expressions.
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
@@ -2597,6 +2599,34 @@ SDNode *ARMDAGToDAGISel::SelectSMLAWSMULW(SDNode *N) {
return nullptr;
}
+/// We've got special pseudo-instructions for these
+SDNode *ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
+ unsigned Opcode;
+ EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
+ if (MemTy == MVT::i8)
+ Opcode = ARM::CMP_SWAP_8;
+ else if (MemTy == MVT::i16)
+ Opcode = ARM::CMP_SWAP_16;
+ else if (MemTy == MVT::i32)
+ Opcode = ARM::CMP_SWAP_32;
+ else
+ llvm_unreachable("Unknown AtomicCmpSwap type");
+
+ SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
+ N->getOperand(0)};
+ SDNode *CmpSwap = CurDAG->getMachineNode(
+ Opcode, SDLoc(N),
+ CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops);
+
+ MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
+ MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
+ cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
+
+ ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
+ ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
+ return nullptr;
+}
+
SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) {
// The only time a CONCAT_VECTORS operation can have legal types is when
// two 64-bit vectors are concatenated to a 128-bit vector.
@@ -3493,6 +3523,9 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
case ISD::CONCAT_VECTORS:
return SelectConcatVector(N);
+
+ case ISD::ATOMIC_CMP_SWAP:
+ return SelectCMP_SWAP(N);
}
return SelectCode(N);
OpenPOWER on IntegriCloud