X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=lib%2FCodeGen%2FSelectionDAG%2FLegalizeTypes.cpp;h=34f99da49fa7f074542d77d93da6af391b45ad57;hb=4a6da60787fcc66c521288fbd139cf8afdca5957;hp=76b7527f68b555737a83385f408a2f483c7beb52;hpb=fcd8e9e3a21efb32172a6395e8697889962067e1;p=oota-llvm.git diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index 76b7527f68b..34f99da49fa 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -68,25 +68,29 @@ void DAGTypeLegalizer::run() { unsigned NumResults = N->getNumValues(); do { MVT::ValueType ResultVT = N->getValueType(i); - LegalizeAction Action = getTypeAction(ResultVT); - if (Action == Promote) { + switch (getTypeAction(ResultVT)) { + default: + assert(false && "Unknown action!"); + case Legal: + break; + case Promote: PromoteResult(N, i); goto NodeDone; - } else if (Action == Expand) { - // Expand can mean 1) split integer in half 2) scalarize single-element - // vector 3) split vector in half. - if (!MVT::isVector(ResultVT)) - ExpandResult(N, i); - else if (MVT::getVectorNumElements(ResultVT) == 1) - ScalarizeResult(N, i); // Scalarize the single-element vector. - else - SplitResult(N, i); // Split the vector in half. + case Expand: + ExpandResult(N, i); + goto NodeDone; + case FloatToInt: + FloatToIntResult(N, i); + goto NodeDone; + case Scalarize: + ScalarizeResult(N, i); + goto NodeDone; + case Split: + SplitResult(N, i); goto NodeDone; - } else { - assert(Action == Legal && "Unknown action!"); } } while (++i < NumResults); - + // Scan the operand list for the node, handling any nodes with operands that // are illegal. { @@ -94,25 +98,28 @@ void DAGTypeLegalizer::run() { bool NeedsRevisit = false; for (i = 0; i != NumOperands; ++i) { MVT::ValueType OpVT = N->getOperand(i).getValueType(); - LegalizeAction Action = getTypeAction(OpVT); - if (Action == Promote) { + switch (getTypeAction(OpVT)) { + default: + assert(false && "Unknown action!"); + case Legal: + continue; + case Promote: NeedsRevisit = PromoteOperand(N, i); break; - } else if (Action == Expand) { - // Expand can mean 1) split integer in half 2) scalarize single-element - // vector 3) split vector in half. - if (!MVT::isVector(OpVT)) { - NeedsRevisit = ExpandOperand(N, i); - } else if (MVT::getVectorNumElements(OpVT) == 1) { - // Scalarize the single-element vector. - NeedsRevisit = ScalarizeOperand(N, i); - } else { - NeedsRevisit = SplitOperand(N, i); // Split the vector in half. - } + case Expand: + NeedsRevisit = ExpandOperand(N, i); + break; + case FloatToInt: + NeedsRevisit = FloatToIntOperand(N, i); + break; + case Scalarize: + NeedsRevisit = ScalarizeOperand(N, i); + break; + case Split: + NeedsRevisit = SplitOperand(N, i); break; - } else { - assert(Action == Legal && "Unknown action!"); } + break; } // If the node needs revisiting, don't add all users to the worklist etc. @@ -130,7 +137,7 @@ NodeDone: for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); UI != E; ++UI) { - SDNode *User = *UI; + SDNode *User = UI->getUser(); int NodeID = User->getNodeId(); assert(NodeID != ReadyToProcess && NodeID != Processed && "Invalid node id for user of unprocessed node!"); @@ -173,25 +180,44 @@ NodeDone: #ifndef NDEBUG for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), E = DAG.allnodes_end(); I != E; ++I) { - if (I->getNodeId() == Processed) - continue; - cerr << "Unprocessed node: "; - I->dump(&DAG); cerr << "\n"; - - if (I->getNodeId() == NewNode) - cerr << "New node not 'noticed'?\n"; - else if (I->getNodeId() > 0) - cerr << "Operand not processed?\n"; - else if (I->getNodeId() == ReadyToProcess) - cerr << "Not added to worklist?\n"; - abort(); + bool Failed = false; + + // Check that all result types are legal. + for (unsigned i = 0, NumVals = I->getNumValues(); i < NumVals; ++i) + if (!isTypeLegal(I->getValueType(i))) { + cerr << "Result type " << i << " illegal!\n"; + Failed = true; + } + + // Check that all operand types are legal. + for (unsigned i = 0, NumOps = I->getNumOperands(); i < NumOps; ++i) + if (!isTypeLegal(I->getOperand(i).getValueType())) { + cerr << "Operand type " << i << " illegal!\n"; + Failed = true; + } + + if (I->getNodeId() != Processed) { + if (I->getNodeId() == NewNode) + cerr << "New node not 'noticed'?\n"; + else if (I->getNodeId() > 0) + cerr << "Operand not processed?\n"; + else if (I->getNodeId() == ReadyToProcess) + cerr << "Not added to worklist?\n"; + Failed = true; + } + + if (Failed) { + I->dump(&DAG); cerr << "\n"; + abort(); + } } #endif } -/// MarkNewNodes - The specified node is the root of a subtree of potentially -/// new nodes. Add the correct NodeId to mark it. -void DAGTypeLegalizer::MarkNewNodes(SDNode *N) { +/// AnalyzeNewNode - The specified node is the root of a subtree of potentially +/// new nodes. Correct any processed operands (this may change the node) and +/// calculate the NodeId. +void DAGTypeLegalizer::AnalyzeNewNode(SDNode *&N) { // If this was an existing node that is already done, we're done. if (N->getNodeId() != NewNode) return; @@ -203,39 +229,116 @@ void DAGTypeLegalizer::MarkNewNodes(SDNode *N) { // // As we walk the operands, keep track of the number of nodes that are // processed. If non-zero, this will become the new nodeid of this node. + // Already processed operands may need to be remapped to the node that + // replaced them, which can result in our node changing. Since remapping + // is rare, the code tries to minimize overhead in the non-remapping case. + + SmallVector NewOps; unsigned NumProcessed = 0; for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { - int OpId = N->getOperand(i).Val->getNodeId(); - if (OpId == NewNode) - MarkNewNodes(N->getOperand(i).Val); - else if (OpId == Processed) + SDOperand OrigOp = N->getOperand(i); + SDOperand Op = OrigOp; + + if (Op.Val->getNodeId() == Processed) + RemapNode(Op); + + if (Op.Val->getNodeId() == NewNode) + AnalyzeNewNode(Op.Val); + else if (Op.Val->getNodeId() == Processed) ++NumProcessed; + + if (!NewOps.empty()) { + // Some previous operand changed. Add this one to the list. + NewOps.push_back(Op); + } else if (Op != OrigOp) { + // This is the first operand to change - add all operands so far. + for (unsigned j = 0; j < i; ++j) + NewOps.push_back(N->getOperand(j)); + NewOps.push_back(Op); + } } - + + // Some operands changed - update the node. + if (!NewOps.empty()) + N = DAG.UpdateNodeOperands(SDOperand(N, 0), &NewOps[0], NewOps.size()).Val; + N->setNodeId(N->getNumOperands()-NumProcessed); if (N->getNodeId() == ReadyToProcess) Worklist.push_back(N); } +void DAGTypeLegalizer::SanityCheck(SDNode *N) { + for (SmallVector::iterator I = Worklist.begin(), + E = Worklist.end(); I != E; ++I) + assert(*I != N); + + for (DenseMap::iterator I = ReplacedNodes.begin(), + E = ReplacedNodes.end(); I != E; ++I) { + assert(I->first.Val != N); + assert(I->second.Val != N); + } + + for (DenseMap::iterator I = PromotedNodes.begin(), + E = PromotedNodes.end(); I != E; ++I) { + assert(I->first.Val != N); + assert(I->second.Val != N); + } + + for (DenseMap::iterator + I = FloatToIntedNodes.begin(), + E = FloatToIntedNodes.end(); I != E; ++I) { + assert(I->first.Val != N); + assert(I->second.Val != N); + } + + for (DenseMap::iterator I = ScalarizedNodes.begin(), + E = ScalarizedNodes.end(); I != E; ++I) { + assert(I->first.Val != N); + assert(I->second.Val != N); + } + + for (DenseMap >::iterator + I = ExpandedNodes.begin(), E = ExpandedNodes.end(); I != E; ++I) { + assert(I->first.Val != N); + assert(I->second.first.Val != N); + assert(I->second.second.Val != N); + } + + for (DenseMap >::iterator + I = SplitNodes.begin(), E = SplitNodes.end(); I != E; ++I) { + assert(I->first.Val != N); + assert(I->second.first.Val != N); + assert(I->second.second.Val != N); + } +} + namespace { /// NodeUpdateListener - This class is a DAGUpdateListener that listens for /// updates to nodes and recomputes their ready state. - class VISIBILITY_HIDDEN NodeUpdateListener : + class VISIBILITY_HIDDEN NodeUpdateListener : public SelectionDAG::DAGUpdateListener { DAGTypeLegalizer &DTL; public: NodeUpdateListener(DAGTypeLegalizer &dtl) : DTL(dtl) {} - + virtual void NodeDeleted(SDNode *N) { // Ignore deletes. + assert(N->getNodeId() != DAGTypeLegalizer::Processed && + N->getNodeId() != DAGTypeLegalizer::ReadyToProcess && + "RAUW deleted processed node!"); +#ifndef NDEBUG + DTL.SanityCheck(N); +#endif } - + virtual void NodeUpdated(SDNode *N) { // Node updates can mean pretty much anything. It is possible that an // operand was set to something already processed (f.e.) in which case - // this node could become ready. Recompoute its flags. - if (N->getNodeId() != DAGTypeLegalizer::ReadyToProcess) - DTL.ReanalyzeNodeFlags(N); + // this node could become ready. Recompute its flags. + assert(N->getNodeId() != DAGTypeLegalizer::Processed && + N->getNodeId() != DAGTypeLegalizer::ReadyToProcess && + "RAUW updated processed node!"); + DTL.ReanalyzeNode(N); } }; } @@ -246,11 +349,10 @@ namespace { /// of From to use To instead. void DAGTypeLegalizer::ReplaceValueWith(SDOperand From, SDOperand To) { if (From == To) return; - + // If expansion produced new nodes, make sure they are properly marked. - if (To.Val->getNodeId() == NewNode) - MarkNewNodes(To.Val); - + AnalyzeNewNode(To.Val); + // Anything that used the old node should now use the new one. Note that this // can potentially cause recursive merging. NodeUpdateListener NUL(*this); @@ -265,13 +367,13 @@ void DAGTypeLegalizer::ReplaceValueWith(SDOperand From, SDOperand To) { /// node's results. The from and to node must define identical result types. void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) { if (From == To) return; + + // If expansion produced new nodes, make sure they are properly marked. + AnalyzeNewNode(To); + assert(From->getNumValues() == To->getNumValues() && "Node results don't match"); - - // If expansion produced new nodes, make sure they are properly marked. - if (To->getNodeId() == NewNode) - MarkNewNodes(To); - + // Anything that used the old node should now use the new one. Note that this // can potentially cause recursive merging. NodeUpdateListener NUL(*this); @@ -290,7 +392,7 @@ void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) { /// RemapNode - If the specified value was already legalized to another value, /// replace it by that value. void DAGTypeLegalizer::RemapNode(SDOperand &N) { - DenseMap::iterator I = ReplacedNodes.find(N); + DenseMap::iterator I = ReplacedNodes.find(N); if (I != ReplacedNodes.end()) { // Use path compression to speed up future lookups if values get multiply // replaced with other values. @@ -300,24 +402,29 @@ void DAGTypeLegalizer::RemapNode(SDOperand &N) { } void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) { - if (Result.Val->getNodeId() == NewNode) - MarkNewNodes(Result.Val); + AnalyzeNewNode(Result.Val); SDOperand &OpEntry = PromotedNodes[Op]; assert(OpEntry.Val == 0 && "Node is already promoted!"); OpEntry = Result; } +void DAGTypeLegalizer::SetIntegerOp(SDOperand Op, SDOperand Result) { + AnalyzeNewNode(Result.Val); + + SDOperand &OpEntry = FloatToIntedNodes[Op]; + assert(OpEntry.Val == 0 && "Node is already converted to integer!"); + OpEntry = Result; +} + void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) { - if (Result.Val->getNodeId() == NewNode) - MarkNewNodes(Result.Val); - + AnalyzeNewNode(Result.Val); + SDOperand &OpEntry = ScalarizedNodes[Op]; assert(OpEntry.Val == 0 && "Node is already scalarized!"); OpEntry = Result; } - void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { std::pair &Entry = ExpandedNodes[Op]; @@ -329,17 +436,15 @@ void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, } void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewNode(Lo.Val); + AnalyzeNewNode(Hi.Val); + // Remember that this is the result of the node. std::pair &Entry = ExpandedNodes[Op]; assert(Entry.first.Val == 0 && "Node already expanded"); Entry.first = Lo; Entry.second = Hi; - - // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. - if (Lo.Val->getNodeId() == NewNode) - MarkNewNodes(Lo.Val); - if (Hi.Val->getNodeId() == NewNode) - MarkNewNodes(Hi.Val); } void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { @@ -352,20 +457,25 @@ void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { } void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewNode(Lo.Val); + AnalyzeNewNode(Hi.Val); + // Remember that this is the result of the node. std::pair &Entry = SplitNodes[Op]; assert(Entry.first.Val == 0 && "Node already split"); Entry.first = Lo; Entry.second = Hi; - - // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. - if (Lo.Val->getNodeId() == NewNode) - MarkNewNodes(Lo.Val); - if (Hi.Val->getNodeId() == NewNode) - MarkNewNodes(Hi.Val); } +/// BitConvertToInteger - Convert to an integer of the same size. +SDOperand DAGTypeLegalizer::BitConvertToInteger(SDOperand Op) { + return DAG.getNode(ISD::BIT_CONVERT, + MVT::getIntegerType(MVT::getSizeInBits(Op.getValueType())), + Op); +} + SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT) { // Create the stack frame object. @@ -377,64 +487,42 @@ SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, return DAG.getLoad(DestVT, Store, FIPtr, NULL, 0); } -/// HandleMemIntrinsic - This handles memcpy/memset/memmove with invalid -/// operands. This promotes or expands the operands as required. -SDOperand DAGTypeLegalizer::HandleMemIntrinsic(SDNode *N) { - // The chain and pointer [operands #0 and #1] are always valid types. - SDOperand Chain = N->getOperand(0); - SDOperand Ptr = N->getOperand(1); - SDOperand Op2 = N->getOperand(2); - - // Op #2 is either a value (memset) or a pointer. Promote it if required. - switch (getTypeAction(Op2.getValueType())) { - default: assert(0 && "Unknown action for pointer/value operand"); - case Legal: break; - case Promote: Op2 = GetPromotedOp(Op2); break; - } - - // The length could have any action required. - SDOperand Length = N->getOperand(3); - switch (getTypeAction(Length.getValueType())) { - default: assert(0 && "Unknown action for memop operand"); - case Legal: break; - case Promote: Length = GetPromotedZExtOp(Length); break; - case Expand: - SDOperand Dummy; // discard the high part. - GetExpandedOp(Length, Length, Dummy); - break; - } - - SDOperand Align = N->getOperand(4); - switch (getTypeAction(Align.getValueType())) { - default: assert(0 && "Unknown action for memop operand"); - case Legal: break; - case Promote: Align = GetPromotedZExtOp(Align); break; - } - - SDOperand AlwaysInline = N->getOperand(5); - switch (getTypeAction(AlwaysInline.getValueType())) { - default: assert(0 && "Unknown action for memop operand"); - case Legal: break; - case Promote: AlwaysInline = GetPromotedZExtOp(AlwaysInline); break; - } - - SDOperand Ops[] = { Chain, Ptr, Op2, Length, Align, AlwaysInline }; - return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6); +/// JoinIntegers - Build an integer with low bits Lo and high bits Hi. +SDOperand DAGTypeLegalizer::JoinIntegers(SDOperand Lo, SDOperand Hi) { + MVT::ValueType LVT = Lo.getValueType(); + MVT::ValueType HVT = Hi.getValueType(); + MVT::ValueType NVT = MVT::getIntegerType(MVT::getSizeInBits(LVT) + + MVT::getSizeInBits(HVT)); + + Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, Lo); + Hi = DAG.getNode(ISD::ANY_EXTEND, NVT, Hi); + Hi = DAG.getNode(ISD::SHL, NVT, Hi, DAG.getConstant(MVT::getSizeInBits(LVT), + TLI.getShiftAmountTy())); + return DAG.getNode(ISD::OR, NVT, Lo, Hi); } -/// SplitOp - Return the lower and upper halves of Op's bits in a value type -/// half the size of Op's. -void DAGTypeLegalizer::SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { - unsigned NVTBits = MVT::getSizeInBits(Op.getValueType())/2; - assert(MVT::getSizeInBits(Op.getValueType()) == 2*NVTBits && - "Cannot split odd sized integer type"); - MVT::ValueType NVT = MVT::getIntegerType(NVTBits); - Lo = DAG.getNode(ISD::TRUNCATE, NVT, Op); +/// SplitInteger - Return the lower LoVT bits of Op in Lo and the upper HiVT +/// bits in Hi. +void DAGTypeLegalizer::SplitInteger(SDOperand Op, + MVT::ValueType LoVT, MVT::ValueType HiVT, + SDOperand &Lo, SDOperand &Hi) { + assert(MVT::getSizeInBits(LoVT) + MVT::getSizeInBits(HiVT) == + MVT::getSizeInBits(Op.getValueType()) && "Invalid integer splitting!"); + Lo = DAG.getNode(ISD::TRUNCATE, LoVT, Op); Hi = DAG.getNode(ISD::SRL, Op.getValueType(), Op, - DAG.getConstant(NVTBits, TLI.getShiftAmountTy())); - Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi); + DAG.getConstant(MVT::getSizeInBits(LoVT), + TLI.getShiftAmountTy())); + Hi = DAG.getNode(ISD::TRUNCATE, HiVT, Hi); } +/// SplitInteger - Return the lower and upper halves of Op's bits in a value type +/// half the size of Op's. +void DAGTypeLegalizer::SplitInteger(SDOperand Op, + SDOperand &Lo, SDOperand &Hi) { + MVT::ValueType HalfVT = + MVT::getIntegerType(MVT::getSizeInBits(Op.getValueType())/2); + SplitInteger(Op, HalfVT, HalfVT, Lo, Hi); +} //===----------------------------------------------------------------------===// // Entry Point