diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 46 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 41 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 34 |
3 files changed, 120 insertions, 1 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 429855db16..91e52a6c9e 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1153,6 +1153,31 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; } + case ISD::ATOMIC_LCS: + case ISD::ATOMIC_LAS: + case ISD::ATOMIC_SWAP: { + assert(((Node->getNumOperands() == 4 && Node->getOpcode() == ISD::ATOMIC_LCS) || + (Node->getNumOperands() == 3 && Node->getOpcode() == ISD::ATOMIC_LAS) || + (Node->getNumOperands() == 3 && Node->getOpcode() == ISD::ATOMIC_SWAP)) && + "Invalid MemBarrier node!"); + int num = Node->getOpcode() == ISD::ATOMIC_LCS ? 4 : 3; + MVT::ValueType VT = Node->getValueType(0); + switch (TLI.getOperationAction(ISD::ATOMIC_LCS, VT)) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Legal: { + SDOperand Ops[4]; + for (int x = 0; x < num; ++x) + Ops[x] = LegalizeOp(Node->getOperand(x)); + Result = DAG.UpdateNodeOperands(Result, &Ops[0], num); + AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0)); + AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1)); + return Result.getValue(Op.ResNo); + break; + } + } + break; + } + case ISD::Constant: { ConstantSDNode *CN = cast<ConstantSDNode>(Node); unsigned opAction = @@ -4228,6 +4253,27 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { break; } + case ISD::ATOMIC_LCS: { + Tmp2 = PromoteOp(Node->getOperand(2)); + Tmp3 = PromoteOp(Node->getOperand(3)); + Result = DAG.getAtomic(Node->getOpcode(), Node->getOperand(0), + Node->getOperand(1), Tmp2, Tmp3, + cast<AtomicSDNode>(Node)->getVT()); + // Remember that we legalized the chain. + AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1))); + break; + } + case ISD::ATOMIC_LAS: + case ISD::ATOMIC_SWAP: { + Tmp2 = PromoteOp(Node->getOperand(2)); + Result = DAG.getAtomic(Node->getOpcode(), Node->getOperand(0), + Node->getOperand(1), Tmp2, + cast<AtomicSDNode>(Node)->getVT()); + // Remember that we legalized the chain. + AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1))); + break; + } + case ISD::AND: case ISD::OR: case ISD::XOR: diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 28f612d8cd..803a38cbe1 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2427,6 +2427,43 @@ SDOperand SelectionDAG::getMemset(SDOperand Chain, SDOperand Dest, return getNode(ISD::MEMSET, MVT::Other, Ops, 6); } +SDOperand SelectionDAG::getAtomic(unsigned Opcode, SDOperand Chain, + SDOperand Ptr, SDOperand A2, + SDOperand A3, MVT::ValueType VT) { + assert(Opcode == ISD::ATOMIC_LCS && "Invalid Atomic Op"); + SDVTList VTs = getVTList(A2.getValueType(), MVT::Other); + FoldingSetNodeID ID; + SDOperand Ops[] = {Chain, Ptr, A2, A3}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 4); + ID.AddInteger((unsigned int)VT); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDOperand(E, 0); + SDNode* N = new AtomicSDNode(Opcode, VTs, Chain, Ptr, A2, A3, VT); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getAtomic(unsigned Opcode, SDOperand Chain, + SDOperand Ptr, SDOperand A2, + MVT::ValueType VT) { + assert((Opcode == ISD::ATOMIC_LAS || Opcode == ISD::ATOMIC_SWAP) + && "Invalid Atomic Op"); + SDVTList VTs = getVTList(A2.getValueType(), MVT::Other); + FoldingSetNodeID ID; + SDOperand Ops[] = {Chain, Ptr, A2}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 3); + ID.AddInteger((unsigned int)VT); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDOperand(E, 0); + SDNode* N = new AtomicSDNode(Opcode, VTs, Chain, Ptr, A2, VT); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDOperand(N, 0); +} + SDOperand SelectionDAG::getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr, const Value *SV, int SVOffset, @@ -3593,6 +3630,7 @@ void CondCodeSDNode::ANCHOR() {} void VTSDNode::ANCHOR() {} void LoadSDNode::ANCHOR() {} void StoreSDNode::ANCHOR() {} +void AtomicSDNode::ANCHOR() {} HandleSDNode::~HandleSDNode() { SDVTList VTs = { 0, 0 }; @@ -3821,6 +3859,9 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { } case ISD::MEMBARRIER: return "MemBarrier"; + case ISD::ATOMIC_LCS: return "AtomicLCS"; + case ISD::ATOMIC_LAS: return "AtomicLAS"; + case ISD::ATOMIC_SWAP: return "AtomicSWAP"; case ISD::PCMARKER: return "PCMarker"; case ISD::READCYCLECOUNTER: return "ReadCycleCounter"; case ISD::SRCVALUE: return "SrcValue"; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index d4e33b0d10..def4f9a018 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -221,7 +221,7 @@ static bool isSelector(Instruction *I) { /// isUsedOutsideOfDefiningBlock - Return true if this instruction is used by /// PHI nodes or outside of the basic block that defines it, or used by a -/// switch instruction, which may expand to multiple basic blocks. +/// switch or atomic instruction, which may expand to multiple basic blocks. static bool isUsedOutsideOfDefiningBlock(Instruction *I) { if (isa<PHINode>(I)) return true; BasicBlock *BB = I->getParent(); @@ -3059,6 +3059,38 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DAG.setRoot(DAG.getNode(ISD::MEMBARRIER, MVT::Other, &Ops[0], 6)); return 0; } + case Intrinsic::atomic_lcs: { + SDOperand Root = getRoot(); + SDOperand O3 = getValue(I.getOperand(3)); + SDOperand L = DAG.getAtomic(ISD::ATOMIC_LCS, Root, + getValue(I.getOperand(1)), + getValue(I.getOperand(2)), + O3, O3.getValueType()); + setValue(&I, L); + DAG.setRoot(L.getValue(1)); + return 0; + } + case Intrinsic::atomic_las: { + SDOperand Root = getRoot(); + SDOperand O2 = getValue(I.getOperand(2)); + SDOperand L = DAG.getAtomic(ISD::ATOMIC_LAS, Root, + getValue(I.getOperand(1)), + O2, O2.getValueType()); + setValue(&I, L); + DAG.setRoot(L.getValue(1)); + return 0; + } + case Intrinsic::atomic_swap: { + SDOperand Root = getRoot(); + SDOperand O2 = getValue(I.getOperand(2)); + SDOperand L = DAG.getAtomic(ISD::ATOMIC_SWAP, Root, + getValue(I.getOperand(1)), + O2, O2.getValueType()); + setValue(&I, L); + DAG.setRoot(L.getValue(1)); + return 0; + } + } } |