diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-08-03 21:06:02 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-08-03 21:06:02 +0000 |
commit | 26689ac37ebec3b358588089415509285e558de9 (patch) | |
tree | 78baa33160fd79d898ce2211f57edab1ed05d16c /lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | |
parent | 866ec865424e670918a14df2a695691c3372faf0 (diff) |
New approach to r136737: insert the necessary fences for atomic ops in platform-independent code, since a bunch of platforms (ARM, Mips, PPC, Alpha are the relevant targets here) need to do essentially the same thing.
I think this completes the basic CodeGen for atomicrmw and cmpxchg.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136813 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 67 |
1 files changed, 59 insertions, 8 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 449f87ebda..bedc310dbb 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -3237,22 +3237,59 @@ void SelectionDAGBuilder::visitStore(const StoreInst &I) { DAG.setRoot(StoreNode); } +static SDValue InsertFenceForAtomic(SDValue Chain, AtomicOrdering Order, + bool Before, DebugLoc dl, + SelectionDAG &DAG, + const TargetLowering &TLI) { + // Fence, if necessary + if (Before) { + if (Order == AcquireRelease) + Order = Release; + else if (Order == Acquire || Order == Monotonic) + return Chain; + } else { + if (Order == AcquireRelease) + Order = Acquire; + else if (Order == Release || Order == Monotonic) + return Chain; + } + SDValue Ops[3]; + Ops[0] = Chain; + Ops[1] = DAG.getConstant(SequentiallyConsistent, TLI.getPointerTy()); + Ops[2] = DAG.getConstant(Order, TLI.getPointerTy()); + return DAG.getNode(ISD::ATOMIC_FENCE, dl, MVT::Other, Ops, 3); +} + void SelectionDAGBuilder::visitAtomicCmpXchg(const AtomicCmpXchgInst &I) { - SDValue Root = getRoot(); + DebugLoc dl = getCurDebugLoc(); + AtomicOrdering Order = I.getOrdering(); + + SDValue InChain = getRoot(); + + if (TLI.getInsertFencesForAtomic()) + InChain = InsertFenceForAtomic(InChain, Order, true, dl, DAG, TLI); + SDValue L = - DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, getCurDebugLoc(), + DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, dl, getValue(I.getCompareOperand()).getValueType().getSimpleVT(), - Root, + InChain, getValue(I.getPointerOperand()), getValue(I.getCompareOperand()), getValue(I.getNewValOperand()), MachinePointerInfo(I.getPointerOperand()), 0 /* Alignment */, I.getOrdering(), I.getSynchScope()); + + SDValue OutChain = L.getValue(1); + + if (TLI.getInsertFencesForAtomic()) + OutChain = InsertFenceForAtomic(OutChain, Order, false, dl, DAG, TLI); + setValue(&I, L); - DAG.setRoot(L.getValue(1)); + DAG.setRoot(OutChain); } void SelectionDAGBuilder::visitAtomicRMW(const AtomicRMWInst &I) { + DebugLoc dl = getCurDebugLoc(); ISD::NodeType NT; switch (I.getOperation()) { default: llvm_unreachable("Unknown atomicrmw operation"); return; @@ -3268,16 +3305,30 @@ void SelectionDAGBuilder::visitAtomicRMW(const AtomicRMWInst &I) { case AtomicRMWInst::UMax: NT = ISD::ATOMIC_LOAD_UMAX; break; case AtomicRMWInst::UMin: NT = ISD::ATOMIC_LOAD_UMIN; break; } + AtomicOrdering Order = I.getOrdering(); + + SDValue InChain = getRoot(); + + if (TLI.getInsertFencesForAtomic()) + InChain = InsertFenceForAtomic(InChain, Order, true, dl, DAG, TLI); + SDValue L = - DAG.getAtomic(NT, getCurDebugLoc(), + DAG.getAtomic(NT, dl, getValue(I.getValOperand()).getValueType().getSimpleVT(), - getRoot(), + InChain, getValue(I.getPointerOperand()), getValue(I.getValOperand()), I.getPointerOperand(), 0 /* Alignment */, - I.getOrdering(), I.getSynchScope()); + TLI.getInsertFencesForAtomic() ? Monotonic : Order, + I.getSynchScope()); + + SDValue OutChain = L.getValue(1); + + if (TLI.getInsertFencesForAtomic()) + OutChain = InsertFenceForAtomic(OutChain, Order, false, dl, DAG, TLI); + setValue(&I, L); - DAG.setRoot(L.getValue(1)); + DAG.setRoot(OutChain); } void SelectionDAGBuilder::visitFence(const FenceInst &I) { |