X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSelectionDAG%2FLegalizeDAG.cpp;h=5866e1a9f97f233f0cb80b22991aef1eb6c4a7f5;hb=9a6b92de4c2207b427f3b9cd67cd122dafc5b6c6;hp=d8d45d04eb72f5b535363b9228995aea5479656e;hpb=24dc346a16397bf740d8d961cd1ebec8d2f46957;p=oota-llvm.git diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index d8d45d04eb7..5866e1a9f97 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -86,12 +86,12 @@ class VISIBILITY_HIDDEN SelectionDAGLegalize { DenseMap PromotedNodes; /// ExpandedNodes - For nodes that need to be expanded this map indicates - /// which which operands are the expanded version of the input. This allows + /// which operands are the expanded version of the input. This allows /// us to avoid expanding the same node more than once. DenseMap > ExpandedNodes; /// SplitNodes - For vector nodes that need to be split, this map indicates - /// which which operands are the split version of the input. This allows us + /// which operands are the split version of the input. This allows us /// to avoid splitting the same node more than once. std::map > SplitNodes; @@ -100,6 +100,11 @@ class VISIBILITY_HIDDEN SelectionDAGLegalize { /// processed to the result. std::map ScalarizedNodes; + /// WidenNodes - For nodes that need to be widened from one vector type to + /// another, this contains the mapping of those that we have already widen. + /// This allows us to avoid widening more than once. + std::map WidenNodes; + void AddLegalizedOperand(SDValue From, SDValue To) { LegalizedNodes.insert(std::make_pair(From, To)); // If someone requests legalization of the new node, return itself. @@ -112,6 +117,12 @@ class VISIBILITY_HIDDEN SelectionDAGLegalize { // If someone requests legalization of the new node, return itself. LegalizedNodes.insert(std::make_pair(To, To)); } + void AddWidenedOperand(SDValue From, SDValue To) { + bool isNew = WidenNodes.insert(std::make_pair(From, To)).second; + assert(isNew && "Got into the map somehow?"); + // If someone requests legalization of the new node, return itself. + LegalizedNodes.insert(std::make_pair(To, To)); + } public: explicit SelectionDAGLegalize(SelectionDAG &DAG); @@ -163,12 +174,20 @@ private: /// ExpandOp - Expand the specified SDValue into its two component pieces /// Lo&Hi. Note that the Op MUST be an expanded type. As a result of this, - /// the LegalizeNodes map is filled in for any results that are not expanded, + /// the LegalizedNodes map is filled in for any results that are not expanded, /// the ExpandedNodes map is filled in for any results that are expanded, and /// the Lo/Hi values are returned. This applies to integer types and Vector /// types. void ExpandOp(SDValue O, SDValue &Lo, SDValue &Hi); + /// WidenVectorOp - Widen a vector operation to a wider type given by WidenVT + /// (e.g., v3i32 to v4i32). The produced value will have the correct value + /// for the existing elements but no guarantee is made about the new elements + /// at the end of the vector: it may be zero, ones, or garbage. This is useful + /// when we have an instruction operating on an illegal vector type and we + /// want to widen it to do the computation on a legal wider vector type. + SDValue WidenVectorOp(SDValue Op, MVT WidenVT); + /// SplitVectorOp - Given an operand of vector type, break it down into /// two smaller values. void SplitVectorOp(SDValue O, SDValue &Lo, SDValue &Hi); @@ -178,6 +197,62 @@ private: /// scalar (e.g. f32) value. SDValue ScalarizeVectorOp(SDValue O); + /// Useful 16 element vector type that is used to pass operands for widening. + typedef SmallVector SDValueVector; + + /// LoadWidenVectorOp - Load a vector for a wider type. Returns true if + /// the LdChain contains a single load and false if it contains a token + /// factor for multiple loads. It takes + /// Result: location to return the result + /// LdChain: location to return the load chain + /// Op: load operation to widen + /// NVT: widen vector result type we want for the load + bool LoadWidenVectorOp(SDValue& Result, SDValue& LdChain, + SDValue Op, MVT NVT); + + /// Helper genWidenVectorLoads - Helper function to generate a set of + /// loads to load a vector with a resulting wider type. It takes + /// LdChain: list of chains for the load we have generated + /// Chain: incoming chain for the ld vector + /// BasePtr: base pointer to load from + /// SV: memory disambiguation source value + /// SVOffset: memory disambiugation offset + /// Alignment: alignment of the memory + /// isVolatile: volatile load + /// LdWidth: width of memory that we want to load + /// ResType: the wider result result type for the resulting loaded vector + SDValue genWidenVectorLoads(SDValueVector& LdChain, SDValue Chain, + SDValue BasePtr, const Value *SV, + int SVOffset, unsigned Alignment, + bool isVolatile, unsigned LdWidth, + MVT ResType); + + /// StoreWidenVectorOp - Stores a widen vector into non widen memory + /// location. It takes + /// ST: store node that we want to replace + /// Chain: incoming store chain + /// BasePtr: base address of where we want to store into + SDValue StoreWidenVectorOp(StoreSDNode *ST, SDValue Chain, + SDValue BasePtr); + + /// Helper genWidenVectorStores - Helper function to generate a set of + /// stores to store a widen vector into non widen memory + // It takes + // StChain: list of chains for the stores we have generated + // Chain: incoming chain for the ld vector + // BasePtr: base pointer to load from + // SV: memory disambiguation source value + // SVOffset: memory disambiugation offset + // Alignment: alignment of the memory + // isVolatile: volatile lod + // ValOp: value to store + // StWidth: width of memory that we want to store + void genWidenVectorStores(SDValueVector& StChain, SDValue Chain, + SDValue BasePtr, const Value *SV, + int SVOffset, unsigned Alignment, + bool isVolatile, SDValue ValOp, + unsigned StWidth); + /// isShuffleLegal - Return non-null if a vector shuffle is legal with the /// specified mask and type. Targets can specify exactly which masks they /// support and the code generator is tasked with not creating illegal masks. @@ -193,6 +268,11 @@ private: SmallPtrSet &NodesLeadingTo); void LegalizeSetCCOperands(SDValue &LHS, SDValue &RHS, SDValue &CC); + void LegalizeSetCCCondCode(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC); + void LegalizeSetCC(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC) { + LegalizeSetCCOperands(LHS, RHS, CC); + LegalizeSetCCCondCode(VT, LHS, RHS, CC); + } SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned, SDValue &Hi); @@ -201,6 +281,7 @@ private: SDValue EmitStackConvert(SDValue SrcOp, MVT SlotVT, MVT DestVT); SDValue ExpandBUILD_VECTOR(SDNode *Node); SDValue ExpandSCALAR_TO_VECTOR(SDNode *Node); + SDValue LegalizeINT_TO_FP(SDValue Result, bool isSigned, MVT DestTy, SDValue Op); SDValue ExpandLegalINT_TO_FP(bool isSigned, SDValue LegalOp, MVT DestVT); SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, MVT DestVT, bool isSigned); SDValue PromoteLegalFP_TO_INT(SDValue LegalOp, MVT DestVT, bool isSigned); @@ -248,7 +329,7 @@ SDNode *SelectionDAGLegalize::isShuffleLegal(MVT VT, SDValue Mask) const { if (InOp.getOpcode() == ISD::UNDEF) Ops.push_back(DAG.getNode(ISD::UNDEF, EltVT)); else { - unsigned InEltNo = cast(InOp)->getValue(); + unsigned InEltNo = cast(InOp)->getZExtValue(); Ops.push_back(DAG.getConstant(InEltNo*NumEltsGrowth+j, EltVT)); } } @@ -259,7 +340,7 @@ SDNode *SelectionDAGLegalize::isShuffleLegal(MVT VT, SDValue Mask) const { break; } } - return TLI.isShuffleMaskLegal(Mask, VT) ? Mask.Val : 0; + return TLI.isShuffleMaskLegal(Mask, VT) ? Mask.getNode() : 0; } SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag) @@ -269,45 +350,6 @@ SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag) "Too many value types for ValueTypeActions to hold!"); } -/// ComputeTopDownOrdering - Compute a top-down ordering of the dag, where Order -/// contains all of a nodes operands before it contains the node. -static void ComputeTopDownOrdering(SelectionDAG &DAG, - SmallVector &Order) { - - DenseMap Visited; - std::vector Worklist; - Worklist.reserve(128); - - // Compute ordering from all of the leaves in the graphs, those (like the - // entry node) that have no operands. - for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), - E = DAG.allnodes_end(); I != E; ++I) { - if (I->getNumOperands() == 0) { - Visited[I] = 0 - 1U; - Worklist.push_back(I); - } - } - - while (!Worklist.empty()) { - SDNode *N = Worklist.back(); - Worklist.pop_back(); - - if (++Visited[N] != N->getNumOperands()) - continue; // Haven't visited all operands yet - - Order.push_back(N); - - // Now that we have N in, add anything that uses it if all of their operands - // are now done. - Worklist.insert(Worklist.end(), N->use_begin(), N->use_end()); - } - - assert(Order.size() == Visited.size() && - Order.size() == DAG.allnodes_size() && - "Error: DAG is cyclic!"); -} - - void SelectionDAGLegalize::LegalizeDAG() { LastCALLSEQ_END = DAG.getEntryNode(); IsLegalizingCall = false; @@ -318,11 +360,10 @@ void SelectionDAGLegalize::LegalizeDAG() { // practice however, this causes us to run out of stack space on large basic // blocks. To avoid this problem, compute an ordering of the nodes where each // node is only legalized after all of its operands are legalized. - SmallVector Order; - ComputeTopDownOrdering(DAG, Order); - - for (unsigned i = 0, e = Order.size(); i != e; ++i) - HandleOp(SDValue(Order[i], 0)); + DAG.AssignTopologicalOrder(); + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = prior(DAG.allnodes_end()); I != next(E); ++I) + HandleOp(SDValue(I, 0)); // Finally, it's possible the root changed. Get the new root. SDValue OldRoot = DAG.getRoot(); @@ -334,6 +375,7 @@ void SelectionDAGLegalize::LegalizeDAG() { PromotedNodes.clear(); SplitNodes.clear(); ScalarizedNodes.clear(); + WidenNodes.clear(); // Remove dead nodes now. DAG.RemoveDeadNodes(); @@ -388,7 +430,7 @@ static SDNode *FindCallStartFromCallEnd(SDNode *Node) { assert(Node->getOperand(0).getValueType() == MVT::Other && "Node doesn't have a token chain argument!"); - return FindCallStartFromCallEnd(Node->getOperand(0).Val); + return FindCallStartFromCallEnd(Node->getOperand(0).getNode()); } /// LegalizeAllNodesNotLeadingTo - Recursively walk the uses of N, looking to @@ -425,7 +467,7 @@ bool SelectionDAGLegalize::LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, bool OperandsLeadToDest = false; for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) OperandsLeadToDest |= // If an operand leads to Dest, so do we. - LegalizeAllNodesNotLeadingTo(N->getOperand(i).Val, Dest, NodesLeadingTo); + LegalizeAllNodesNotLeadingTo(N->getOperand(i).getNode(), Dest, NodesLeadingTo); if (OperandsLeadToDest) { NodesLeadingTo.insert(N); @@ -437,14 +479,27 @@ bool SelectionDAGLegalize::LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, return false; } -/// HandleOp - Legalize, Promote, or Expand the specified operand as +/// HandleOp - Legalize, Promote, Widen, or Expand the specified operand as /// appropriate for its type. void SelectionDAGLegalize::HandleOp(SDValue Op) { MVT VT = Op.getValueType(); switch (getTypeAction(VT)) { default: assert(0 && "Bad type action!"); case Legal: (void)LegalizeOp(Op); break; - case Promote: (void)PromoteOp(Op); break; + case Promote: + if (!VT.isVector()) { + (void)PromoteOp(Op); + break; + } + else { + // See if we can widen otherwise use Expand to either scalarize or split + MVT WidenVT = TLI.getWidenVectorType(VT); + if (WidenVT != MVT::Other) { + (void) WidenVectorOp(Op, WidenVT); + break; + } + // else fall thru to expand since we can't widen the vector + } case Expand: if (!VT.isVector()) { // If this is an illegal scalar, expand it into its two component @@ -458,7 +513,7 @@ void SelectionDAGLegalize::HandleOp(SDValue Op) { // scalar operation. (void)ScalarizeVectorOp(Op); } else { - // Otherwise, this is an illegal multiple element vector. + // This is an illegal multiple element vector. // Split it in half and legalize both parts. SDValue X, Y; SplitVectorOp(Op, X, Y); @@ -480,11 +535,11 @@ static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, // an FP extending load is the same cost as a normal load (such as on the x87 // fp stack or PPC FP unit). MVT VT = CFP->getValueType(0); - ConstantFP *LLVMC = ConstantFP::get(CFP->getValueAPF()); + ConstantFP *LLVMC = const_cast(CFP->getConstantFPValue()); if (!UseCP) { if (VT!=MVT::f64 && VT!=MVT::f32) assert(0 && "Invalid type expansion"); - return DAG.getConstant(LLVMC->getValueAPF().convertToAPInt(), + return DAG.getConstant(LLVMC->getValueAPF().bitcastToAPInt(), (VT == MVT::f64) ? MVT::i64 : MVT::i32); } @@ -495,7 +550,7 @@ static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, if (CFP->isValueValidForType(SVT, CFP->getValueAPF()) && // Only do this if the target has a native EXTLOAD instruction from // smaller type. - TLI.isLoadXLegal(ISD::EXTLOAD, SVT) && + TLI.isLoadExtLegal(ISD::EXTLOAD, SVT) && TLI.ShouldShrinkFPConstant(OrigVT)) { const Type *SType = SVT.getTypeForMVT(); LLVMC = cast(ConstantExpr::getFPTrunc(LLVMC, SType)); @@ -505,12 +560,13 @@ static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, } SDValue CPIdx = DAG.getConstantPool(LLVMC, TLI.getPointerTy()); + unsigned Alignment = 1 << cast(CPIdx)->getAlignment(); if (Extend) return DAG.getExtLoad(ISD::EXTLOAD, OrigVT, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), - 0, VT); + 0, VT, false, Alignment); return DAG.getLoad(OrigVT, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, false, Alignment); } @@ -705,7 +761,7 @@ SDValue SelectionDAGLegalize::UnrollVectorOp(SDValue Op) { MVT VT = Op.getValueType(); assert(isTypeLegal(VT) && "Caller should expand or promote operands that are not legal!"); - assert(Op.Val->getNumValues() == 1 && + assert(Op.getNode()->getNumValues() == 1 && "Can't unroll a vector with multiple results!"); unsigned NE = VT.getVectorNumElements(); MVT EltVT = VT.getVectorElementType(); @@ -771,11 +827,11 @@ PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx) { MVT PtrVT = TLI.getPointerTy(); SDValue StackPtr = DAG.CreateStackTemporary(VT); - int SPFI = cast(StackPtr.Val)->getIndex(); + int SPFI = cast(StackPtr.getNode())->getIndex(); // Store the vector. SDValue Ch = DAG.getStore(DAG.getEntryNode(), Tmp1, StackPtr, - PseudoSourceValue::getFixedStack(SPFI), 0); + PseudoSourceValue::getFixedStack(SPFI), 0); // Truncate or zero extend offset to target pointer type. unsigned CastOpc = IdxVT.bitsGT(PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; @@ -802,7 +858,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { assert(isTypeLegal(Op.getValueType()) && "Caller should expand or promote operands that are not legal!"); - SDNode *Node = Op.Val; + SDNode *Node = Op.getNode(); // If this operation defines any values that cannot be represented in a // register on this target, make sure to expand or promote them. @@ -859,7 +915,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) AddLegalizedOperand(Op.getValue(i), Result.getValue(i)); - return Result.getValue(Op.ResNo); + return Result.getValue(Op.getResNo()); } // Otherwise this is an unhandled builtin node. splat. #ifndef NDEBUG @@ -877,7 +933,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { default: assert(0 && "This action is not supported yet!"); case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Op, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; // FALLTHROUGH if the target doesn't want to lower this op after all. case TargetLowering::Legal: break; @@ -888,7 +944,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // The only option for these nodes is to custom lower them. If the target // does not custom lower them, then return zero. Tmp1 = TLI.LowerOperation(Op, DAG); - if (Tmp1.Val) + if (Tmp1.getNode()) Result = Tmp1; else Result = DAG.getConstant(0, TLI.getPointerTy()); @@ -899,7 +955,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { default: assert(0 && "This action is not supported yet!"); case TargetLowering::Custom: Result = TLI.LowerOperation(Op, DAG); - if (Result.Val) break; + if (Result.getNode()) break; // Fall Thru case TargetLowering::Legal: Result = DAG.getConstant(0, VT); @@ -919,7 +975,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Result = TLI.LowerOperation(Op, DAG); - if (Result.Val) break; + if (Result.getNode()) break; // Fall Thru case TargetLowering::Legal: { SDValue Ops[] = { DAG.getConstant(0, VT), Tmp1 }; @@ -928,9 +984,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } } } - if (Result.Val->getNumValues() == 1) break; + if (Result.getNode()->getNumValues() == 1) break; - assert(Result.Val->getNumValues() == 2 && + assert(Result.getNode()->getNumValues() == 2 && "Cannot return more than two values!"); // Since we produced two values, make sure to remember that we @@ -939,7 +995,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp2 = LegalizeOp(Result.getValue(1)); AddLegalizedOperand(Op.getValue(0), Tmp1); AddLegalizedOperand(Op.getValue(1), Tmp2); - return Op.ResNo ? Tmp2 : Tmp1; + return Op.getResNo() ? Tmp2 : Tmp1; case ISD::EHSELECTION: { Tmp1 = LegalizeOp(Node->getOperand(0)); Tmp2 = LegalizeOp(Node->getOperand(1)); @@ -953,7 +1009,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Result = TLI.LowerOperation(Op, DAG); - if (Result.Val) break; + if (Result.getNode()) break; // Fall Thru case TargetLowering::Legal: { SDValue Ops[] = { DAG.getConstant(0, VT), Tmp2 }; @@ -962,9 +1018,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } } } - if (Result.Val->getNumValues() == 1) break; + if (Result.getNode()->getNumValues() == 1) break; - assert(Result.Val->getNumValues() == 2 && + assert(Result.getNode()->getNumValues() == 2 && "Cannot return more than two values!"); // Since we produced two values, make sure to remember that we @@ -973,7 +1029,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp2 = LegalizeOp(Result.getValue(1)); AddLegalizedOperand(Op.getValue(0), Tmp1); AddLegalizedOperand(Op.getValue(1), Tmp2); - return Op.ResNo ? Tmp2 : Tmp1; + return Op.getResNo() ? Tmp2 : Tmp1; case ISD::EH_RETURN: { MVT VT = Node->getValueType(0); // The only "good" option for this node is to custom lower it. @@ -981,7 +1037,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { default: assert(0 && "This action is not supported at all!"); case TargetLowering::Custom: Result = TLI.LowerOperation(Op, DAG); - if (Result.Val) break; + if (Result.getNode()) break; // Fall Thru case TargetLowering::Legal: // Target does not know, how to lower this, lower to noop @@ -997,7 +1053,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case ISD::MERGE_VALUES: // Legalize eliminates MERGE_VALUES nodes. - Result = Node->getOperand(Op.ResNo); + Result = Node->getOperand(Op.getResNo()); break; case ISD::CopyFromReg: Tmp1 = LegalizeOp(Node->getOperand(0)); @@ -1018,7 +1074,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // legalized both of them. AddLegalizedOperand(Op.getValue(0), Result); AddLegalizedOperand(Op.getValue(1), Result.getValue(1)); - return Result.getValue(Op.ResNo); + return Result.getValue(Op.getResNo()); case ISD::UNDEF: { MVT VT = Op.getValueType(); switch (TLI.getOperationAction(ISD::UNDEF, VT)) { @@ -1050,20 +1106,20 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (TLI.getOperationAction(Node->getOpcode(), MVT::Other) == TargetLowering::Custom) { Tmp3 = TLI.LowerOperation(Result, DAG); - if (Tmp3.Val) Result = Tmp3; + if (Tmp3.getNode()) Result = Tmp3; } - if (Result.Val->getNumValues() == 1) break; + if (Result.getNode()->getNumValues() == 1) break; // Must have return value and chain result. - assert(Result.Val->getNumValues() == 2 && + assert(Result.getNode()->getNumValues() == 2 && "Cannot return more than two values!"); // Since loads produce two values, make sure to remember that we // legalized both of them. AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1)); - return Result.getValue(Op.ResNo); + return Result.getValue(Op.getResNo()); } case ISD::DBG_STOPPOINT: @@ -1219,7 +1275,10 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; } - case ISD::ATOMIC_CMP_SWAP: { + case ISD::ATOMIC_CMP_SWAP_8: + case ISD::ATOMIC_CMP_SWAP_16: + case ISD::ATOMIC_CMP_SWAP_32: + case ISD::ATOMIC_CMP_SWAP_64: { unsigned int num_operands = 4; assert(Node->getNumOperands() == num_operands && "Invalid Atomic node!"); SDValue Ops[4]; @@ -1237,19 +1296,52 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1)); - return Result.getValue(Op.ResNo); - } - case ISD::ATOMIC_LOAD_ADD: - case ISD::ATOMIC_LOAD_SUB: - case ISD::ATOMIC_LOAD_AND: - case ISD::ATOMIC_LOAD_OR: - case ISD::ATOMIC_LOAD_XOR: - case ISD::ATOMIC_LOAD_NAND: - case ISD::ATOMIC_LOAD_MIN: - case ISD::ATOMIC_LOAD_MAX: - case ISD::ATOMIC_LOAD_UMIN: - case ISD::ATOMIC_LOAD_UMAX: - case ISD::ATOMIC_SWAP: { + return Result.getValue(Op.getResNo()); + } + case ISD::ATOMIC_LOAD_ADD_8: + case ISD::ATOMIC_LOAD_SUB_8: + case ISD::ATOMIC_LOAD_AND_8: + case ISD::ATOMIC_LOAD_OR_8: + case ISD::ATOMIC_LOAD_XOR_8: + case ISD::ATOMIC_LOAD_NAND_8: + case ISD::ATOMIC_LOAD_MIN_8: + case ISD::ATOMIC_LOAD_MAX_8: + case ISD::ATOMIC_LOAD_UMIN_8: + case ISD::ATOMIC_LOAD_UMAX_8: + case ISD::ATOMIC_SWAP_8: + case ISD::ATOMIC_LOAD_ADD_16: + case ISD::ATOMIC_LOAD_SUB_16: + case ISD::ATOMIC_LOAD_AND_16: + case ISD::ATOMIC_LOAD_OR_16: + case ISD::ATOMIC_LOAD_XOR_16: + case ISD::ATOMIC_LOAD_NAND_16: + case ISD::ATOMIC_LOAD_MIN_16: + case ISD::ATOMIC_LOAD_MAX_16: + case ISD::ATOMIC_LOAD_UMIN_16: + case ISD::ATOMIC_LOAD_UMAX_16: + case ISD::ATOMIC_SWAP_16: + case ISD::ATOMIC_LOAD_ADD_32: + case ISD::ATOMIC_LOAD_SUB_32: + case ISD::ATOMIC_LOAD_AND_32: + case ISD::ATOMIC_LOAD_OR_32: + case ISD::ATOMIC_LOAD_XOR_32: + case ISD::ATOMIC_LOAD_NAND_32: + case ISD::ATOMIC_LOAD_MIN_32: + case ISD::ATOMIC_LOAD_MAX_32: + case ISD::ATOMIC_LOAD_UMIN_32: + case ISD::ATOMIC_LOAD_UMAX_32: + case ISD::ATOMIC_SWAP_32: + case ISD::ATOMIC_LOAD_ADD_64: + case ISD::ATOMIC_LOAD_SUB_64: + case ISD::ATOMIC_LOAD_AND_64: + case ISD::ATOMIC_LOAD_OR_64: + case ISD::ATOMIC_LOAD_XOR_64: + case ISD::ATOMIC_LOAD_NAND_64: + case ISD::ATOMIC_LOAD_MIN_64: + case ISD::ATOMIC_LOAD_MAX_64: + case ISD::ATOMIC_LOAD_UMIN_64: + case ISD::ATOMIC_LOAD_UMAX_64: + case ISD::ATOMIC_SWAP_64: { unsigned int num_operands = 3; assert(Node->getNumOperands() == num_operands && "Invalid Atomic node!"); SDValue Ops[3]; @@ -1262,15 +1354,12 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Custom: Result = TLI.LowerOperation(Result, DAG); break; - case TargetLowering::Expand: - Result = SDValue(TLI.ReplaceNodeResults(Op.Val, DAG),0); - break; case TargetLowering::Legal: break; } AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1)); - return Result.getValue(Op.ResNo); + return Result.getValue(Op.getResNo()); } case ISD::Constant: { ConstantSDNode *CN = cast(Node); @@ -1282,7 +1371,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (opAction == TargetLowering::Custom) { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) + if (Tmp1.getNode()) Result = Tmp1; } break; @@ -1300,7 +1389,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Tmp3 = TLI.LowerOperation(Result, DAG); - if (Tmp3.Val) { + if (Tmp3.getNode()) { Result = Tmp3; break; } @@ -1346,30 +1435,30 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::CALL: // The only option for this is to custom lower it. Tmp3 = TLI.LowerOperation(Result.getValue(0), DAG); - assert(Tmp3.Val && "Target didn't custom lower this node!"); + assert(Tmp3.getNode() && "Target didn't custom lower this node!"); // A call within a calling sequence must be legalized to something // other than the normal CALLSEQ_END. Violating this gets Legalize // into an infinite loop. assert ((!IsLegalizingCall || Node->getOpcode() != ISD::CALL || - Tmp3.Val->getOpcode() != ISD::CALLSEQ_END) && + Tmp3.getNode()->getOpcode() != ISD::CALLSEQ_END) && "Nested CALLSEQ_START..CALLSEQ_END not supported."); // The number of incoming and outgoing values should match; unless the final // outgoing value is a flag. - assert((Tmp3.Val->getNumValues() == Result.Val->getNumValues() || - (Tmp3.Val->getNumValues() == Result.Val->getNumValues() + 1 && - Tmp3.Val->getValueType(Tmp3.Val->getNumValues() - 1) == + assert((Tmp3.getNode()->getNumValues() == Result.getNode()->getNumValues() || + (Tmp3.getNode()->getNumValues() == Result.getNode()->getNumValues() + 1 && + Tmp3.getNode()->getValueType(Tmp3.getNode()->getNumValues() - 1) == MVT::Flag)) && "Lowering call/formal_arguments produced unexpected # results!"); // Since CALL/FORMAL_ARGUMENTS nodes produce multiple values, make sure to // remember that we legalized all of them, so it doesn't get relegalized. - for (unsigned i = 0, e = Tmp3.Val->getNumValues(); i != e; ++i) { - if (Tmp3.Val->getValueType(i) == MVT::Flag) + for (unsigned i = 0, e = Tmp3.getNode()->getNumValues(); i != e; ++i) { + if (Tmp3.getNode()->getValueType(i) == MVT::Flag) continue; Tmp1 = LegalizeOp(Tmp3.getValue(i)); - if (Op.ResNo == i) + if (Op.getResNo() == i) Tmp2 = Tmp1; AddLegalizedOperand(SDValue(Node, i), Tmp1); } @@ -1378,7 +1467,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp1 = LegalizeOp(Node->getOperand(0)); ConstantSDNode *idx = dyn_cast(Node->getOperand(1)); assert(idx && "Operand must be a constant"); - Tmp2 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0)); + Tmp2 = DAG.getTargetConstant(idx->getAPIntValue(), idx->getValueType(0)); Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); } break; @@ -1387,7 +1476,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp2 = LegalizeOp(Node->getOperand(1)); ConstantSDNode *idx = dyn_cast(Node->getOperand(2)); assert(idx && "Operand must be a constant"); - Tmp3 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0)); + Tmp3 = DAG.getTargetConstant(idx->getAPIntValue(), idx->getValueType(0)); Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3); } break; @@ -1396,13 +1485,13 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { default: assert(0 && "This action is not supported yet!"); case TargetLowering::Custom: Tmp3 = TLI.LowerOperation(Result, DAG); - if (Tmp3.Val) { + if (Tmp3.getNode()) { Result = Tmp3; break; } // FALLTHROUGH case TargetLowering::Expand: - Result = ExpandBUILD_VECTOR(Result.Val); + Result = ExpandBUILD_VECTOR(Result.getNode()); break; } break; @@ -1417,6 +1506,12 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { default: assert(0 && "Cannot expand insert element operand"); case Legal: Tmp2 = LegalizeOp(Node->getOperand(1)); break; case Promote: Tmp2 = PromoteOp(Node->getOperand(1)); break; + case Expand: + // FIXME: An alternative would be to check to see if the target is not + // going to custom lower this operation, we could bitcast to half elt + // width and perform two inserts at that width, if that is legal. + Tmp2 = Node->getOperand(1); + break; } Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3); @@ -1427,11 +1522,13 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Tmp4 = TLI.LowerOperation(Result, DAG); - if (Tmp4.Val) { + if (Tmp4.getNode()) { Result = Tmp4; break; } // FALLTHROUGH + case TargetLowering::Promote: + // Fall thru for vector case case TargetLowering::Expand: { // If the insert index is a constant, codegen this as a scalar_to_vector, // then a shuffle that inserts it into the right position in the vector. @@ -1453,7 +1550,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // elt 0 of the RHS. SmallVector ShufOps; for (unsigned i = 0; i != NumElts; ++i) { - if (i != InsertPos->getValue()) + if (i != InsertPos->getZExtValue()) ShufOps.push_back(DAG.getConstant(i, ShufMaskEltVT)); else ShufOps.push_back(DAG.getConstant(NumElts, ShufMaskEltVT)); @@ -1487,7 +1584,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Tmp3 = TLI.LowerOperation(Result, DAG); - if (Tmp3.Val) { + if (Tmp3.getNode()) { Result = Tmp3; break; } @@ -1511,7 +1608,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Tmp3 = TLI.LowerOperation(Result, DAG); - if (Tmp3.Val) { + if (Tmp3.getNode()) { Result = Tmp3; break; } @@ -1529,7 +1626,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Ops.push_back(DAG.getNode(ISD::UNDEF, EltVT)); } else { assert(isa(Arg) && "Invalid VECTOR_SHUFFLE mask!"); - unsigned Idx = cast(Arg)->getValue(); + unsigned Idx = cast(Arg)->getZExtValue(); if (Idx < NumElems) Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, Tmp1, DAG.getConstant(Idx, PtrVT))); @@ -1552,7 +1649,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Convert the shuffle mask to the right # elements. Tmp3 = SDValue(isShuffleLegal(OVT, Node->getOperand(2)), 0); - assert(Tmp3.Val && "Shuffle not legal?"); + assert(Tmp3.getNode() && "Shuffle not legal?"); Result = DAG.getNode(ISD::VECTOR_SHUFFLE, NVT, Tmp1, Tmp2, Tmp3); Result = DAG.getNode(ISD::BIT_CONVERT, OVT, Result); break; @@ -1574,6 +1671,26 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = ExpandEXTRACT_SUBVECTOR(Result); break; + case ISD::CONCAT_VECTORS: { + // Use extract/insert/build vector for now. We might try to be + // more clever later. + MVT PtrVT = TLI.getPointerTy(); + SmallVector Ops; + unsigned NumOperands = Node->getNumOperands(); + for (unsigned i=0; i < NumOperands; ++i) { + SDValue SubOp = Node->getOperand(i); + MVT VVT = SubOp.getNode()->getValueType(0); + MVT EltVT = VVT.getVectorElementType(); + unsigned NumSubElem = VVT.getVectorNumElements(); + for (unsigned j=0; j < NumSubElem; ++j) { + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, SubOp, + DAG.getConstant(j, PtrVT))); + } + } + return LegalizeOp(DAG.getNode(ISD::BUILD_VECTOR, Node->getValueType(0), + &Ops[0], Ops.size())); + } + case ISD::CALLSEQ_START: { SDNode *CallEnd = FindCallEndFromCallStart(Node); @@ -1582,7 +1699,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // are inserted *before* the CALLSEQ_START. {SmallPtrSet NodesLeadingTo; for (unsigned i = 0, e = CallEnd->getNumOperands(); i != e; ++i) - LegalizeAllNodesNotLeadingTo(CallEnd->getOperand(i).Val, Node, + LegalizeAllNodesNotLeadingTo(CallEnd->getOperand(i).getNode(), Node, NodesLeadingTo); } @@ -1626,7 +1743,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::CALLSEQ_END: // If the CALLSEQ_START node hasn't been legalized first, legalize it. This // will cause this node to be legalized as well as handling libcalls right. - if (LastCALLSEQ_END.Val != Node) { + if (LastCALLSEQ_END.getNode() != Node) { LegalizeOp(SDValue(FindCallStartFromCallEnd(Node), 0)); DenseMap::iterator I = LegalizedNodes.find(Op); assert(I != LegalizedNodes.end() && @@ -1663,7 +1780,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); if (Node->getNumValues() == 2) AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1)); - return Result.getValue(Op.ResNo); + return Result.getValue(Op.getResNo()); case ISD::DYNAMIC_STACKALLOC: { MVT VT = Node->getValueType(0); Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. @@ -1683,13 +1800,12 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Chain the dynamic stack allocation so that it doesn't modify the stack // pointer when other instructions are using the stack. - Chain = DAG.getCALLSEQ_START(Chain, - DAG.getConstant(0, TLI.getPointerTy())); + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true)); SDValue Size = Tmp2.getOperand(1); SDValue SP = DAG.getCopyFromReg(Chain, SPReg, VT); Chain = SP.getValue(1); - unsigned Align = cast(Tmp3)->getValue(); + unsigned Align = cast(Tmp3)->getZExtValue(); unsigned StackAlign = TLI.getTargetMachine().getFrameInfo()->getStackAlignment(); if (Align > StackAlign) @@ -1698,11 +1814,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp1 = DAG.getNode(ISD::SUB, VT, SP, Size); // Value Chain = DAG.getCopyToReg(Chain, SPReg, Tmp1); // Output chain - Tmp2 = - DAG.getCALLSEQ_END(Chain, - DAG.getConstant(0, TLI.getPointerTy()), - DAG.getConstant(0, TLI.getPointerTy()), - SDValue()); + Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true), + DAG.getIntPtrConstant(0, true), SDValue()); Tmp1 = LegalizeOp(Tmp1); Tmp2 = LegalizeOp(Tmp2); @@ -1710,7 +1823,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } case TargetLowering::Custom: Tmp3 = TLI.LowerOperation(Tmp1, DAG); - if (Tmp3.Val) { + if (Tmp3.getNode()) { Tmp1 = LegalizeOp(Tmp3); Tmp2 = LegalizeOp(Tmp3.getValue(1)); } @@ -1722,7 +1835,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // legalized both of them. AddLegalizedOperand(SDValue(Node, 0), Tmp1); AddLegalizedOperand(SDValue(Node, 1), Tmp2); - return Op.ResNo ? Tmp2 : Tmp1; + return Op.getResNo() ? Tmp2 : Tmp1; } case ISD::INLINEASM: { SmallVector Ops(Node->op_begin(), Node->op_end()); @@ -1736,7 +1849,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { bool HasInFlag = Ops.back().getValueType() == MVT::Flag; for (unsigned i = 2, e = Ops.size()-HasInFlag; i < e; ) { - unsigned NumVals = cast(Ops[i])->getValue() >> 3; + unsigned NumVals = cast(Ops[i])->getZExtValue() >> 3; for (++i; NumVals; ++i, --NumVals) { SDValue Op = LegalizeOp(Ops[i]); if (Op != Ops[i]) { @@ -1758,7 +1871,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // INLINE asm returns a chain and flag, make sure to add both to the map. AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1)); - return Result.getValue(Op.ResNo); + return Result.getValue(Op.getResNo()); } case ISD::BR: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. @@ -1799,7 +1912,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; case TargetLowering::Expand: { SDValue Chain = Result.getOperand(0); @@ -1868,7 +1981,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; case TargetLowering::Expand: // Expand brcond's setcc into its constituent parts and create a BR_CC @@ -1895,13 +2008,13 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp3 = Node->getOperand(3); // RHS Tmp4 = Node->getOperand(1); // CC - LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4); + LegalizeSetCC(TLI.getSetCCResultType(Tmp2), Tmp2, Tmp3, Tmp4); LastCALLSEQ_END = DAG.getEntryNode(); - // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, + // If we didn't get both a LHS and RHS back from LegalizeSetCC, // the LHS is a legal SETCC itself. In this case, we need to compare // the result against zero to select between true and false values. - if (Tmp3.Val == 0) { + if (Tmp3.getNode() == 0) { Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); Tmp4 = DAG.getCondCode(ISD::SETNE); } @@ -1914,7 +2027,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp4 = TLI.LowerOperation(Result, DAG); - if (Tmp4.Val) Result = Tmp4; + if (Tmp4.getNode()) Result = Tmp4; break; } break; @@ -1939,7 +2052,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { unsigned ABIAlignment = TLI.getTargetData()-> getABITypeAlignment(LD->getMemoryVT().getTypeForMVT()); if (LD->getAlignment() < ABIAlignment){ - Result = ExpandUnalignedLoad(cast(Result.Val), DAG, + Result = ExpandUnalignedLoad(cast(Result.getNode()), DAG, TLI); Tmp3 = Result.getOperand(0); Tmp4 = Result.getOperand(1); @@ -1950,7 +2063,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Tmp3, DAG); - if (Tmp1.Val) { + if (Tmp1.getNode()) { Tmp3 = LegalizeOp(Tmp1); Tmp4 = LegalizeOp(Tmp1.getValue(1)); } @@ -1973,7 +2086,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // legalized both of them. AddLegalizedOperand(SDValue(Node, 0), Tmp3); AddLegalizedOperand(SDValue(Node, 1), Tmp4); - return Op.ResNo ? Tmp4 : Tmp3; + return Op.getResNo() ? Tmp4 : Tmp3; } else { MVT SrcVT = LD->getMemoryVT(); unsigned SrcWidth = SrcVT.getSizeInBits(); @@ -1990,7 +2103,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // nice to have an effective generic way of getting these benefits... // Until such a way is found, don't insist on promoting i1 here. (SrcVT != MVT::i1 || - TLI.getLoadXAction(ExtType, MVT::i1) == TargetLowering::Promote)) { + TLI.getLoadExtAction(ExtType, MVT::i1) == TargetLowering::Promote)) { // Promote to a byte-sized load if not loading an integral number of // bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24. unsigned NewWidth = SrcVT.getStoreSizeInBits(); @@ -2095,7 +2208,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp1 = LegalizeOp(Result); Tmp2 = LegalizeOp(Ch); } else { - switch (TLI.getLoadXAction(ExtType, SrcVT)) { + switch (TLI.getLoadExtAction(ExtType, SrcVT)) { default: assert(0 && "This action is not supported yet!"); case TargetLowering::Custom: isCustom = true; @@ -2107,7 +2220,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (isCustom) { Tmp3 = TLI.LowerOperation(Result, DAG); - if (Tmp3.Val) { + if (Tmp3.getNode()) { Tmp1 = LegalizeOp(Tmp3); Tmp2 = LegalizeOp(Tmp3.getValue(1)); } @@ -2118,7 +2231,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { unsigned ABIAlignment = TLI.getTargetData()-> getABITypeAlignment(LD->getMemoryVT().getTypeForMVT()); if (LD->getAlignment() < ABIAlignment){ - Result = ExpandUnalignedLoad(cast(Result.Val), DAG, + Result = ExpandUnalignedLoad(cast(Result.getNode()), DAG, TLI); Tmp1 = Result.getOperand(0); Tmp2 = Result.getOperand(1); @@ -2162,7 +2275,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // both of them. AddLegalizedOperand(SDValue(Node, 0), Tmp1); AddLegalizedOperand(SDValue(Node, 1), Tmp2); - return Op.ResNo ? Tmp2 : Tmp1; + return Op.getResNo() ? Tmp2 : Tmp1; } } case ISD::EXTRACT_ELEMENT: { @@ -2170,7 +2283,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { switch (getTypeAction(OpTy)) { default: assert(0 && "EXTRACT_ELEMENT action for type unimplemented!"); case Legal: - if (cast(Node->getOperand(1))->getValue()) { + if (cast(Node->getOperand(1))->getZExtValue()) { // 1 -> Hi Result = DAG.getNode(ISD::SRL, OpTy, Node->getOperand(0), DAG.getConstant(OpTy.getSizeInBits()/2, @@ -2185,7 +2298,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case Expand: // Get both the low and high parts. ExpandOp(Node->getOperand(0), Tmp1, Tmp2); - if (cast(Node->getOperand(1))->getValue()) + if (cast(Node->getOperand(1))->getZExtValue()) Result = Tmp2; // 1 -> Hi else Result = Tmp1; // 0 -> Lo @@ -2246,14 +2359,14 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (TLI.isBigEndian()) std::swap(Lo, Hi); - if (Hi.Val) + if (Hi.getNode()) Result = DAG.getNode(ISD::RET, MVT::Other, Tmp1, Lo, Tmp3, Hi,Tmp3); else Result = DAG.getNode(ISD::RET, MVT::Other, Tmp1, Lo, Tmp3); Result = LegalizeOp(Result); } else { - SDNode *InVal = Tmp2.Val; - int InIx = Tmp2.ResNo; + SDNode *InVal = Tmp2.getNode(); + int InIx = Tmp2.getResNo(); unsigned NumElems = InVal->getValueType(InIx).getVectorNumElements(); MVT EVT = InVal->getValueType(InIx).getVectorElementType(); @@ -2312,7 +2425,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { ExpandOp(Node->getOperand(i), Lo, Hi); NewValues.push_back(Lo); NewValues.push_back(Node->getOperand(i+1)); - if (Hi.Val) { + if (Hi.getNode()) { NewValues.push_back(Hi); NewValues.push_back(Node->getOperand(i+1)); } @@ -2337,7 +2450,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; } } @@ -2362,7 +2475,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (CFP->getValueType(0) == MVT::f32 && getTypeAction(MVT::i32) == Legal) { Tmp3 = DAG.getConstant(CFP->getValueAPF(). - convertToAPInt().zextOrTrunc(32), + bitcastToAPInt().zextOrTrunc(32), MVT::i32); Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), SVOffset, isVolatile, Alignment); @@ -2370,7 +2483,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } else if (CFP->getValueType(0) == MVT::f64) { // If this target supports 64-bit registers, do a single 64-bit store. if (getTypeAction(MVT::i64) == Legal) { - Tmp3 = DAG.getConstant(CFP->getValueAPF().convertToAPInt(). + Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt(). zextOrTrunc(64), MVT::i64); Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), SVOffset, isVolatile, Alignment); @@ -2379,7 +2492,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Otherwise, if the target supports 32-bit registers, use 2 32-bit // stores. If the target supports neither 32- nor 64-bits, this // xform is certainly not worth it. - const APInt &IntVal =CFP->getValueAPF().convertToAPInt(); + const APInt &IntVal =CFP->getValueAPF().bitcastToAPInt(); SDValue Lo = DAG.getConstant(APInt(IntVal).trunc(32), MVT::i32); SDValue Hi = DAG.getConstant(IntVal.lshr(32).trunc(32), MVT::i32); if (TLI.isBigEndian()) std::swap(Lo, Hi); @@ -2413,13 +2526,13 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { unsigned ABIAlignment = TLI.getTargetData()-> getABITypeAlignment(ST->getMemoryVT().getTypeForMVT()); if (ST->getAlignment() < ABIAlignment) - Result = ExpandUnalignedStore(cast(Result.Val), DAG, + Result = ExpandUnalignedStore(cast(Result.getNode()), DAG, TLI); } break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; case TargetLowering::Promote: assert(VT.isVector() && "Unknown legal promote case!"); @@ -2433,14 +2546,16 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; } case Promote: - // Truncate the value and store the result. - Tmp3 = PromoteOp(ST->getValue()); - Result = DAG.getTruncStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, ST->getMemoryVT(), - isVolatile, Alignment); - break; - - case Expand: + if (!ST->getMemoryVT().isVector()) { + // Truncate the value and store the result. + Tmp3 = PromoteOp(ST->getValue()); + Result = DAG.getTruncStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset, ST->getMemoryVT(), + isVolatile, Alignment); + break; + } + // Fall thru to expand for vector + case Expand: { unsigned IncrementSize = 0; SDValue Lo, Hi; @@ -2448,8 +2563,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // the product of the element size in bytes, and the number of elements // in the high half of the vector. if (ST->getValue().getValueType().isVector()) { - SDNode *InVal = ST->getValue().Val; - int InIx = ST->getValue().ResNo; + SDNode *InVal = ST->getValue().getNode(); + int InIx = ST->getValue().getResNo(); MVT InVT = InVal->getValueType(InIx); unsigned NumElems = InVT.getVectorNumElements(); MVT EVT = InVT.getVectorElementType(); @@ -2474,22 +2589,31 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = LegalizeOp(Result); break; } else { - SplitVectorOp(ST->getValue(), Lo, Hi); - IncrementSize = Lo.Val->getValueType(0).getVectorNumElements() * - EVT.getSizeInBits()/8; + // Check if we have widen this node with another value + std::map::iterator I = + WidenNodes.find(ST->getValue()); + if (I != WidenNodes.end()) { + Result = StoreWidenVectorOp(ST, Tmp1, Tmp2); + break; + } + else { + SplitVectorOp(ST->getValue(), Lo, Hi); + IncrementSize = Lo.getNode()->getValueType(0).getVectorNumElements() * + EVT.getSizeInBits()/8; + } } } else { ExpandOp(ST->getValue(), Lo, Hi); - IncrementSize = Hi.Val ? Hi.getValueType().getSizeInBits()/8 : 0; + IncrementSize = Hi.getNode() ? Hi.getValueType().getSizeInBits()/8 : 0; - if (TLI.isBigEndian()) + if (Hi.getNode() && TLI.isBigEndian()) std::swap(Lo, Hi); } Lo = DAG.getStore(Tmp1, Lo, Tmp2, ST->getSrcValue(), SVOffset, isVolatile, Alignment); - if (Hi.Val == NULL) { + if (Hi.getNode() == NULL) { // Must be int <-> float one-to-one expansion. Result = Lo; break; @@ -2505,6 +2629,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { SVOffset, isVolatile, Alignment); Result = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); break; + } // case Expand } } else { switch (getTypeAction(ST->getValue().getValueType())) { @@ -2512,9 +2637,12 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp3 = LegalizeOp(ST->getValue()); break; case Promote: - // We can promote the value, the truncstore will still take care of it. - Tmp3 = PromoteOp(ST->getValue()); - break; + if (!ST->getValue().getValueType().isVector()) { + // We can promote the value, the truncstore will still take care of it. + Tmp3 = PromoteOp(ST->getValue()); + break; + } + // Vector case falls through to expand case Expand: // Just store the low part. This may become a non-trunc store, so make // sure to use getTruncStore, not UpdateNodeOperands below. @@ -2600,7 +2728,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { unsigned ABIAlignment = TLI.getTargetData()-> getABITypeAlignment(ST->getMemoryVT().getTypeForMVT()); if (ST->getAlignment() < ABIAlignment) - Result = ExpandUnalignedStore(cast(Result.Val), DAG, + Result = ExpandUnalignedStore(cast(Result.getNode()), DAG, TLI); } break; @@ -2634,7 +2762,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp3 = TLI.LowerOperation(Result, DAG); - if (Tmp3.Val) { + if (Tmp3.getNode()) { Tmp1 = LegalizeOp(Tmp3); Tmp2 = LegalizeOp(Tmp3.getValue(1)); } @@ -2657,7 +2785,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // legalized both of them. AddLegalizedOperand(SDValue(Node, 0), Tmp1); AddLegalizedOperand(SDValue(Node, 1), Tmp2); - return Op.ResNo ? Tmp2 : Tmp1; + return Op.getResNo() ? Tmp2 : Tmp1; case ISD::STACKRESTORE: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. @@ -2669,7 +2797,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; case TargetLowering::Expand: // Expand to CopyToReg if the target set @@ -2713,6 +2841,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the condition. break; case Promote: { + assert(!Node->getOperand(0).getValueType().isVector() && "not possible"); Tmp1 = PromoteOp(Node->getOperand(0)); // Promote the condition. // Make sure the condition is either zero or one. unsigned BitWidth = Tmp1.getValueSizeInBits(); @@ -2732,7 +2861,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; } case TargetLowering::Expand: @@ -2781,12 +2910,12 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp4 = LegalizeOp(Node->getOperand(3)); // False SDValue CC = Node->getOperand(4); - LegalizeSetCCOperands(Tmp1, Tmp2, CC); + LegalizeSetCC(TLI.getSetCCResultType(Tmp1), Tmp1, Tmp2, CC); - // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, + // If we didn't get both a LHS and RHS back from LegalizeSetCC, // the LHS is a legal SETCC itself. In this case, we need to compare // the result against zero to select between true and false values. - if (Tmp2.Val == 0) { + if (Tmp2.getNode() == 0) { Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); CC = DAG.getCondCode(ISD::SETNE); } @@ -2798,7 +2927,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; } break; @@ -2807,12 +2936,12 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp1 = Node->getOperand(0); Tmp2 = Node->getOperand(1); Tmp3 = Node->getOperand(2); - LegalizeSetCCOperands(Tmp1, Tmp2, Tmp3); + LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, Tmp3); // If we had to Expand the SetCC operands into a SELECT node, then it may // not always be possible to return a true LHS & RHS. In this case, just // return the value we legalized, returned in the LHS - if (Tmp2.Val == 0) { + if (Tmp2.getNode() == 0) { Result = Tmp1; break; } @@ -2826,7 +2955,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3); if (isCustom) { Tmp4 = TLI.LowerOperation(Result, DAG); - if (Tmp4.Val) Result = Tmp4; + if (Tmp4.getNode()) Result = Tmp4; } break; case TargetLowering::Promote: { @@ -2884,7 +3013,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; } break; @@ -2908,15 +3037,15 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) { + if (Tmp1.getNode()) { SDValue Tmp2, RetVal(0, 0); for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) { Tmp2 = LegalizeOp(Tmp1.getValue(i)); AddLegalizedOperand(SDValue(Node, i), Tmp2); - if (i == Op.ResNo) + if (i == Op.getResNo()) RetVal = Tmp2; } - assert(RetVal.Val && "Illegal result number"); + assert(RetVal.getNode() && "Illegal result number"); return RetVal; } break; @@ -2926,7 +3055,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // legalized all of them. for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) AddLegalizedOperand(SDValue(Node, i), Result.getValue(i)); - return Result.getValue(Op.ResNo); + return Result.getValue(Op.getResNo()); } // Binary operators @@ -2970,20 +3099,20 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); - + switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { default: assert(0 && "BinOp legalize operation not supported"); case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) { + if (Tmp1.getNode()) { Result = Tmp1; break; } // Fall through if the custom lower can't deal with the operation case TargetLowering::Expand: { MVT VT = Op.getValueType(); - + // See if multiply or divide can be lowered using two-result operations. SDVTList VTs = DAG.getVTList(VT, VT); if (Node->getOpcode() == ISD::MUL) { @@ -3006,31 +3135,35 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { OpToUse = ISD::UMUL_LOHI; } if (OpToUse) { - Result = SDValue(DAG.getNode(OpToUse, VTs, Tmp1, Tmp2).Val, 0); + Result = SDValue(DAG.getNode(OpToUse, VTs, Tmp1, Tmp2).getNode(), 0); break; } } if (Node->getOpcode() == ISD::MULHS && TLI.isOperationLegal(ISD::SMUL_LOHI, VT)) { - Result = SDValue(DAG.getNode(ISD::SMUL_LOHI, VTs, Tmp1, Tmp2).Val, 1); + Result = SDValue(DAG.getNode(ISD::SMUL_LOHI, VTs, Tmp1, Tmp2).getNode(), + 1); break; } if (Node->getOpcode() == ISD::MULHU && TLI.isOperationLegal(ISD::UMUL_LOHI, VT)) { - Result = SDValue(DAG.getNode(ISD::UMUL_LOHI, VTs, Tmp1, Tmp2).Val, 1); + Result = SDValue(DAG.getNode(ISD::UMUL_LOHI, VTs, Tmp1, Tmp2).getNode(), + 1); break; } if (Node->getOpcode() == ISD::SDIV && TLI.isOperationLegal(ISD::SDIVREM, VT)) { - Result = SDValue(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).Val, 0); + Result = SDValue(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).getNode(), + 0); break; } if (Node->getOpcode() == ISD::UDIV && TLI.isOperationLegal(ISD::UDIVREM, VT)) { - Result = SDValue(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).Val, 0); + Result = SDValue(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).getNode(), + 0); break; } - + // Check to see if we have a libcall for this operator. RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; bool isSigned = false; @@ -3039,10 +3172,14 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::SDIV: if (VT == MVT::i32) { LC = Node->getOpcode() == ISD::UDIV - ? RTLIB::UDIV_I32 : RTLIB::SDIV_I32; + ? RTLIB::UDIV_I32 : RTLIB::SDIV_I32; isSigned = Node->getOpcode() == ISD::SDIV; } break; + case ISD::MUL: + if (VT == MVT::i32) + LC = RTLIB::MUL_I32; + break; case ISD::FPOW: LC = GetFPLibCall(VT, RTLIB::POW_F32, RTLIB::POW_F64, RTLIB::POW_F80, RTLIB::POW_PPCF128); @@ -3054,7 +3191,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = ExpandLibCall(LC, Node, isSigned, Dummy); break; } - + assert(Node->getValueType(0).isVector() && "Cannot expand this binary operator!"); // Expand the operation into a bunch of nasty scalar code. @@ -3115,7 +3252,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { default: assert(0 && "Operation not supported"); case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; case TargetLowering::Legal: break; case TargetLowering::Expand: { @@ -3218,7 +3355,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); if (isCustom) { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; } break; case TargetLowering::Expand: { @@ -3230,12 +3367,12 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { SDVTList VTs = DAG.getVTList(VT, VT); if (Node->getOpcode() == ISD::SREM && TLI.isOperationLegal(ISD::SDIVREM, VT)) { - Result = SDValue(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).Val, 1); + Result = SDValue(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).getNode(), 1); break; } if (Node->getOpcode() == ISD::UREM && TLI.isOperationLegal(ISD::UDIVREM, VT)) { - Result = SDValue(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).Val, 1); + Result = SDValue(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).getNode(), 1); break; } @@ -3290,7 +3427,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (isCustom) { Tmp2 = TLI.LowerOperation(Result, DAG); - if (Tmp2.Val) { + if (Tmp2.getNode()) { Result = LegalizeOp(Tmp2); Tmp1 = LegalizeOp(Tmp2.getValue(1)); } @@ -3300,9 +3437,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { const Value *V = cast(Node->getOperand(2))->getValue(); SDValue VAList = DAG.getLoad(TLI.getPointerTy(), Tmp1, Tmp2, V, 0); // Increment the pointer, VAList, to the next vaarg - Tmp3 = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList, - DAG.getConstant(VT.getSizeInBits()/8, - TLI.getPointerTy())); + Tmp3 = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList, + DAG.getConstant(TLI.getTargetData()->getABITypeSize(VT.getTypeForMVT()), + TLI.getPointerTy())); // Store the incremented VAList to the legalized pointer Tmp3 = DAG.getStore(VAList.getValue(1), Tmp3, Tmp2, V, 0); // Load the actual argument out of the pointer VAList @@ -3316,7 +3453,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // legalized both of them. AddLegalizedOperand(SDValue(Node, 0), Result); AddLegalizedOperand(SDValue(Node, 1), Tmp1); - return Op.ResNo ? Tmp1 : Result; + return Op.getResNo() ? Tmp1 : Result; } case ISD::VACOPY: @@ -3334,7 +3471,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Node->getOperand(3), Node->getOperand(4)); if (isCustom) { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; } break; case TargetLowering::Expand: @@ -3361,7 +3498,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2)); if (isCustom) { Tmp1 = TLI.LowerOperation(Tmp1, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; } break; case TargetLowering::Expand: @@ -3381,7 +3518,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Legal: break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; } break; @@ -3399,7 +3536,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; break; case TargetLowering::Promote: assert(0 && "Do not know how to promote ROTL/ROTR"); @@ -3446,7 +3583,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) == TargetLowering::Custom) { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) { + if (Tmp1.getNode()) { Result = Tmp1; } } @@ -3492,6 +3629,16 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::FSQRT: case ISD::FSIN: case ISD::FCOS: + case ISD::FLOG: + case ISD::FLOG2: + case ISD::FLOG10: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FTRUNC: + case ISD::FFLOOR: + case ISD::FCEIL: + case ISD::FRINT: + case ISD::FNEARBYINT: Tmp1 = LegalizeOp(Node->getOperand(0)); switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { case TargetLowering::Promote: @@ -3502,7 +3649,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.UpdateNodeOperands(Result, Tmp1); if (isCustom) { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; } break; case TargetLowering::Expand: @@ -3525,7 +3672,17 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } case ISD::FSQRT: case ISD::FSIN: - case ISD::FCOS: { + case ISD::FCOS: + case ISD::FLOG: + case ISD::FLOG2: + case ISD::FLOG10: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FTRUNC: + case ISD::FFLOOR: + case ISD::FCEIL: + case ISD::FRINT: + case ISD::FNEARBYINT: { MVT VT = Node->getValueType(0); // Expand unsupported unary vector operators by unrolling them. @@ -3548,6 +3705,47 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { LC = GetFPLibCall(VT, RTLIB::COS_F32, RTLIB::COS_F64, RTLIB::COS_F80, RTLIB::COS_PPCF128); break; + case ISD::FLOG: + LC = GetFPLibCall(VT, RTLIB::LOG_F32, RTLIB::LOG_F64, + RTLIB::LOG_F80, RTLIB::LOG_PPCF128); + break; + case ISD::FLOG2: + LC = GetFPLibCall(VT, RTLIB::LOG2_F32, RTLIB::LOG2_F64, + RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128); + break; + case ISD::FLOG10: + LC = GetFPLibCall(VT, RTLIB::LOG10_F32, RTLIB::LOG10_F64, + RTLIB::LOG10_F80, RTLIB::LOG10_PPCF128); + break; + case ISD::FEXP: + LC = GetFPLibCall(VT, RTLIB::EXP_F32, RTLIB::EXP_F64, + RTLIB::EXP_F80, RTLIB::EXP_PPCF128); + break; + case ISD::FEXP2: + LC = GetFPLibCall(VT, RTLIB::EXP2_F32, RTLIB::EXP2_F64, + RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128); + break; + case ISD::FTRUNC: + LC = GetFPLibCall(VT, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128); + break; + case ISD::FFLOOR: + LC = GetFPLibCall(VT, RTLIB::FLOOR_F32, RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80, RTLIB::FLOOR_PPCF128); + break; + case ISD::FCEIL: + LC = GetFPLibCall(VT, RTLIB::CEIL_F32, RTLIB::CEIL_F64, + RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128); + break; + case ISD::FRINT: + LC = GetFPLibCall(VT, RTLIB::RINT_F32, RTLIB::RINT_F64, + RTLIB::RINT_F80, RTLIB::RINT_PPCF128); + break; + case ISD::FNEARBYINT: + LC = GetFPLibCall(VT, RTLIB::NEARBYINT_F32, RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, RTLIB::NEARBYINT_PPCF128); + break; + break; default: assert(0 && "Unreachable!"); } SDValue Dummy; @@ -3581,8 +3779,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } else if (Op.getOperand(0).getValueType().isVector()) { // The input has to be a vector type, we have to either scalarize it, pack // it, or convert it based on whether the input vector type is legal. - SDNode *InVal = Node->getOperand(0).Val; - int InIx = Node->getOperand(0).ResNo; + SDNode *InVal = Node->getOperand(0).getNode(); + int InIx = Node->getOperand(0).getResNo(); unsigned NumElems = InVal->getValueType(InIx).getVectorNumElements(); MVT EVT = InVal->getValueType(InIx).getVectorElementType(); @@ -3618,56 +3816,55 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } } break; - - // Conversion operators. The source and destination have different types. - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: { - bool isSigned = Node->getOpcode() == ISD::SINT_TO_FP; - switch (getTypeAction(Node->getOperand(0).getValueType())) { - case Legal: - switch (TLI.getOperationAction(Node->getOpcode(), - Node->getOperand(0).getValueType())) { - default: assert(0 && "Unknown operation action!"); - case TargetLowering::Custom: - isCustom = true; - // FALLTHROUGH - case TargetLowering::Legal: + case ISD::CONVERT_RNDSAT: { + ISD::CvtCode CvtCode = cast(Node)->getCvtCode(); + switch (CvtCode) { + default: assert(0 && "Unknown cvt code!"); + case ISD::CVT_SF: + case ISD::CVT_UF: + break; + case ISD::CVT_FF: + case ISD::CVT_FS: + case ISD::CVT_FU: + case ISD::CVT_SS: + case ISD::CVT_SU: + case ISD::CVT_US: + case ISD::CVT_UU: { + SDValue DTyOp = Node->getOperand(1); + SDValue STyOp = Node->getOperand(2); + SDValue RndOp = Node->getOperand(3); + SDValue SatOp = Node->getOperand(4); + switch (getTypeAction(Node->getOperand(0).getValueType())) { + case Expand: assert(0 && "Shouldn't need to expand other operators here!"); + case Legal: Tmp1 = LegalizeOp(Node->getOperand(0)); - Result = DAG.UpdateNodeOperands(Result, Tmp1); - if (isCustom) { + Result = DAG.UpdateNodeOperands(Result, Tmp1, DTyOp, STyOp, + RndOp, SatOp); + if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) == + TargetLowering::Custom) { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; } break; - case TargetLowering::Expand: - Result = ExpandLegalINT_TO_FP(isSigned, - LegalizeOp(Node->getOperand(0)), - Node->getValueType(0)); - break; - case TargetLowering::Promote: - Result = PromoteLegalINT_TO_FP(LegalizeOp(Node->getOperand(0)), - Node->getValueType(0), - isSigned); + case Promote: + Result = PromoteOp(Node->getOperand(0)); + // For FP, make Op1 a i32 + + Result = DAG.getConvertRndSat(Result.getValueType(), Result, + DTyOp, STyOp, RndOp, SatOp, CvtCode); break; } break; - case Expand: - Result = ExpandIntToFP(Node->getOpcode() == ISD::SINT_TO_FP, - Node->getValueType(0), Node->getOperand(0)); - break; - case Promote: - Tmp1 = PromoteOp(Node->getOperand(0)); - if (isSigned) { - Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, Tmp1.getValueType(), - Tmp1, DAG.getValueType(Node->getOperand(0).getValueType())); - } else { - Tmp1 = DAG.getZeroExtendInReg(Tmp1, - Node->getOperand(0).getValueType()); - } - Result = DAG.UpdateNodeOperands(Result, Tmp1); - Result = LegalizeOp(Result); // The 'op' is not necessarily legal! - break; } + } // end switch CvtCode + break; + } + // Conversion operators. The source and destination have different types. + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: { + bool isSigned = Node->getOpcode() == ISD::SINT_TO_FP; + Result = LegalizeINT_TO_FP(Result, isSigned, + Node->getValueType(0), Node->getOperand(0)); break; } case ISD::TRUNCATE: @@ -3705,7 +3902,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.UpdateNodeOperands(Result, Tmp1); if (isCustom) { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; } break; case TargetLowering::Promote: @@ -3847,7 +4044,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) == TargetLowering::Custom) { Tmp1 = TLI.LowerOperation(Result, DAG); - if (Tmp1.Val) Result = Tmp1; + if (Tmp1.getNode()) Result = Tmp1; } break; case Promote: @@ -3919,7 +4116,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.UpdateNodeOperands(Result, Ops, 6); // The only option for this node is to custom lower it. Result = TLI.LowerOperation(Result, DAG); - assert(Result.Val && "Should always custom lower!"); + assert(Result.getNode() && "Should always custom lower!"); // Since trampoline produces two values, make sure to remember that we // legalized both of them. @@ -3927,7 +4124,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = LegalizeOp(Result); AddLegalizedOperand(SDValue(Node, 0), Result); AddLegalizedOperand(SDValue(Node, 1), Tmp1); - return Op.ResNo ? Tmp1 : Result; + return Op.getResNo() ? Tmp1 : Result; } case ISD::FLT_ROUNDS_: { MVT VT = Node->getValueType(0); @@ -3935,7 +4132,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { default: assert(0 && "This action not supported for this op yet!"); case TargetLowering::Custom: Result = TLI.LowerOperation(Op, DAG); - if (Result.Val) break; + if (Result.getNode()) break; // Fall Thru case TargetLowering::Legal: // If this operation is not supported, lower it to constant 1 @@ -3954,7 +4151,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case TargetLowering::Custom: Result = TLI.LowerOperation(Op, DAG); - if (Result.Val) break; + if (Result.getNode()) break; // Fall Thru case TargetLowering::Expand: // If this operation is not supported, lower it to 'abort()' call @@ -3962,7 +4159,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { TargetLowering::ArgListTy Args; std::pair CallResult = TLI.LowerCallTo(Tmp1, Type::VoidTy, - false, false, false, CallingConv::C, false, + false, false, false, false, CallingConv::C, false, DAG.getExternalSymbol("abort", TLI.getPointerTy()), Args, DAG); Result = CallResult.second; @@ -3999,7 +4196,7 @@ SDValue SelectionDAGLegalize::PromoteOp(SDValue Op) { SDValue Tmp1, Tmp2, Tmp3; SDValue Result; - SDNode *Node = Op.Val; + SDNode *Node = Op.getNode(); DenseMap::iterator I = PromotedNodes.find(Op); if (I != PromotedNodes.end()) return I->second; @@ -4079,6 +4276,19 @@ SDValue SelectionDAGLegalize::PromoteOp(SDValue Op) { break; } break; + case ISD::CONVERT_RNDSAT: { + ISD::CvtCode CvtCode = cast(Node)->getCvtCode(); + assert ((CvtCode == ISD::CVT_SS || CvtCode == ISD::CVT_SU || + CvtCode == ISD::CVT_US || CvtCode == ISD::CVT_UU || + CvtCode == ISD::CVT_SF || CvtCode == ISD::CVT_UF) && + "can only promote integers"); + Result = DAG.getConvertRndSat(NVT, Node->getOperand(0), + Node->getOperand(1), Node->getOperand(2), + Node->getOperand(3), Node->getOperand(4), + CvtCode); + break; + + } case ISD::BIT_CONVERT: Result = EmitStackConvert(Node->getOperand(0), Node->getValueType(0), Node->getValueType(0)); @@ -4178,9 +4388,19 @@ SDValue SelectionDAGLegalize::PromoteOp(SDValue Op) { // precision, and these operations don't modify precision at all. break; + case ISD::FLOG: + case ISD::FLOG2: + case ISD::FLOG10: + case ISD::FEXP: + case ISD::FEXP2: case ISD::FSQRT: case ISD::FSIN: case ISD::FCOS: + case ISD::FTRUNC: + case ISD::FFLOOR: + case ISD::FCEIL: + case ISD::FRINT: + case ISD::FNEARBYINT: Tmp1 = PromoteOp(Node->getOperand(0)); assert(Tmp1.getValueType() == NVT); Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1); @@ -4189,19 +4409,26 @@ SDValue SelectionDAGLegalize::PromoteOp(SDValue Op) { DAG.getValueType(VT)); break; + case ISD::FPOW: case ISD::FPOWI: { - // Promote f32 powi to f64 powi. Note that this could insert a libcall + // Promote f32 pow(i) to f64 pow(i). Note that this could insert a libcall // directly as well, which may be better. Tmp1 = PromoteOp(Node->getOperand(0)); + Tmp2 = Node->getOperand(1); + if (Node->getOpcode() == ISD::FPOW) + Tmp2 = PromoteOp(Tmp2); assert(Tmp1.getValueType() == NVT); - Result = DAG.getNode(ISD::FPOWI, NVT, Tmp1, Node->getOperand(1)); + Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2); if (NoExcessFPPrecision) Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, DAG.getValueType(VT)); break; } - case ISD::ATOMIC_CMP_SWAP: { + case ISD::ATOMIC_CMP_SWAP_8: + case ISD::ATOMIC_CMP_SWAP_16: + case ISD::ATOMIC_CMP_SWAP_32: + case ISD::ATOMIC_CMP_SWAP_64: { AtomicSDNode* AtomNode = cast(Node); Tmp2 = PromoteOp(Node->getOperand(2)); Tmp3 = PromoteOp(Node->getOperand(3)); @@ -4213,17 +4440,50 @@ SDValue SelectionDAGLegalize::PromoteOp(SDValue Op) { AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1))); break; } - case ISD::ATOMIC_LOAD_ADD: - case ISD::ATOMIC_LOAD_SUB: - case ISD::ATOMIC_LOAD_AND: - case ISD::ATOMIC_LOAD_OR: - case ISD::ATOMIC_LOAD_XOR: - case ISD::ATOMIC_LOAD_NAND: - case ISD::ATOMIC_LOAD_MIN: - case ISD::ATOMIC_LOAD_MAX: - case ISD::ATOMIC_LOAD_UMIN: - case ISD::ATOMIC_LOAD_UMAX: - case ISD::ATOMIC_SWAP: { + case ISD::ATOMIC_LOAD_ADD_8: + case ISD::ATOMIC_LOAD_SUB_8: + case ISD::ATOMIC_LOAD_AND_8: + case ISD::ATOMIC_LOAD_OR_8: + case ISD::ATOMIC_LOAD_XOR_8: + case ISD::ATOMIC_LOAD_NAND_8: + case ISD::ATOMIC_LOAD_MIN_8: + case ISD::ATOMIC_LOAD_MAX_8: + case ISD::ATOMIC_LOAD_UMIN_8: + case ISD::ATOMIC_LOAD_UMAX_8: + case ISD::ATOMIC_SWAP_8: + case ISD::ATOMIC_LOAD_ADD_16: + case ISD::ATOMIC_LOAD_SUB_16: + case ISD::ATOMIC_LOAD_AND_16: + case ISD::ATOMIC_LOAD_OR_16: + case ISD::ATOMIC_LOAD_XOR_16: + case ISD::ATOMIC_LOAD_NAND_16: + case ISD::ATOMIC_LOAD_MIN_16: + case ISD::ATOMIC_LOAD_MAX_16: + case ISD::ATOMIC_LOAD_UMIN_16: + case ISD::ATOMIC_LOAD_UMAX_16: + case ISD::ATOMIC_SWAP_16: + case ISD::ATOMIC_LOAD_ADD_32: + case ISD::ATOMIC_LOAD_SUB_32: + case ISD::ATOMIC_LOAD_AND_32: + case ISD::ATOMIC_LOAD_OR_32: + case ISD::ATOMIC_LOAD_XOR_32: + case ISD::ATOMIC_LOAD_NAND_32: + case ISD::ATOMIC_LOAD_MIN_32: + case ISD::ATOMIC_LOAD_MAX_32: + case ISD::ATOMIC_LOAD_UMIN_32: + case ISD::ATOMIC_LOAD_UMAX_32: + case ISD::ATOMIC_SWAP_32: + case ISD::ATOMIC_LOAD_ADD_64: + case ISD::ATOMIC_LOAD_SUB_64: + case ISD::ATOMIC_LOAD_AND_64: + case ISD::ATOMIC_LOAD_OR_64: + case ISD::ATOMIC_LOAD_XOR_64: + case ISD::ATOMIC_LOAD_NAND_64: + case ISD::ATOMIC_LOAD_MIN_64: + case ISD::ATOMIC_LOAD_MAX_64: + case ISD::ATOMIC_LOAD_UMIN_64: + case ISD::ATOMIC_LOAD_UMAX_64: + case ISD::ATOMIC_SWAP_64: { AtomicSDNode* AtomNode = cast(Node); Tmp2 = PromoteOp(Node->getOperand(2)); Result = DAG.getAtomic(Node->getOpcode(), AtomNode->getChain(), @@ -4435,7 +4695,7 @@ SDValue SelectionDAGLegalize::PromoteOp(SDValue Op) { break; } - assert(Result.Val && "Didn't set a result!"); + assert(Result.getNode() && "Didn't set a result!"); // Make sure the result is itself legal. Result = LegalizeOp(Result); @@ -4465,7 +4725,7 @@ SDValue SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDValue Op) { Vec = LegalizeOp(Vec); Op = DAG.UpdateNodeOperands(Op, Vec, Idx); SDValue Tmp3 = TLI.LowerOperation(Op, DAG); - if (Tmp3.Val) + if (Tmp3.getNode()) return Tmp3; break; } @@ -4476,6 +4736,9 @@ SDValue SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDValue Op) { return Op; } break; + case TargetLowering::Promote: + assert(TVT.isVector() && "not vector type"); + // fall thru to expand since vectors are by default are promote case TargetLowering::Expand: break; } @@ -4488,11 +4751,11 @@ SDValue SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDValue Op) { ConstantSDNode *CIdx = cast(Idx); SDValue Lo, Hi; SplitVectorOp(Vec, Lo, Hi); - if (CIdx->getValue() < NumLoElts) { + if (CIdx->getZExtValue() < NumLoElts) { Vec = Lo; } else { Vec = Hi; - Idx = DAG.getConstant(CIdx->getValue() - NumLoElts, + Idx = DAG.getConstant(CIdx->getZExtValue() - NumLoElts, Idx.getValueType()); } @@ -4540,11 +4803,12 @@ SDValue SelectionDAGLegalize::ExpandEXTRACT_SUBVECTOR(SDValue Op) { ConstantSDNode *CIdx = cast(Idx); SDValue Lo, Hi; SplitVectorOp(Vec, Lo, Hi); - if (CIdx->getValue() < NumElems/2) { + if (CIdx->getZExtValue() < NumElems/2) { Vec = Lo; } else { Vec = Hi; - Idx = DAG.getConstant(CIdx->getValue() - NumElems/2, Idx.getValueType()); + Idx = DAG.getConstant(CIdx->getZExtValue() - NumElems/2, + Idx.getValueType()); } // It's now an extract from the appropriate high or low part. Recurse. @@ -4603,6 +4867,8 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS, DAG.getValueType(VT)); Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2, DAG.getValueType(VT)); + Tmp1 = LegalizeOp(Tmp1); // Relegalize new nodes. + Tmp2 = LegalizeOp(Tmp2); // Relegalize new nodes. break; } } @@ -4671,14 +4937,14 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS, SDValue Dummy; SDValue Ops[2] = { LHS, RHS }; - Tmp1 = ExpandLibCall(LC1, DAG.getMergeValues(Ops, 2).Val, + Tmp1 = ExpandLibCall(LC1, DAG.getMergeValues(Ops, 2).getNode(), false /*sign irrelevant*/, Dummy); Tmp2 = DAG.getConstant(0, MVT::i32); CC = DAG.getCondCode(TLI.getCmpLibcallCC(LC1)); if (LC2 != RTLIB::UNKNOWN_LIBCALL) { Tmp1 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(Tmp1), Tmp1, Tmp2, CC); - LHS = ExpandLibCall(LC2, DAG.getMergeValues(Ops, 2).Val, + LHS = ExpandLibCall(LC2, DAG.getMergeValues(Ops, 2).getNode(), false /*sign irrelevant*/, Dummy); Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(LHS), LHS, Tmp2, DAG.getCondCode(TLI.getCmpLibcallCC(LC2))); @@ -4697,14 +4963,16 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS, if (VT==MVT::ppcf128) { // FIXME: This generated code sucks. We want to generate - // FCMP crN, hi1, hi2 + // FCMPU crN, hi1, hi2 // BNE crN, L: - // FCMP crN, lo1, lo2 + // FCMPU crN, lo1, lo2 // The following can be improved, but not that much. - Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ); + Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, + ISD::SETOEQ); Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, CCCode); Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2); - Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETNE); + Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, + ISD::SETUNE); Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode); Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2); Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3); @@ -4765,16 +5033,16 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS, TargetLowering::DAGCombinerInfo DagCombineInfo(DAG, false, true, NULL); Tmp1 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC, false, DagCombineInfo); - if (!Tmp1.Val) + if (!Tmp1.getNode()) Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC); Tmp2 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode, false, DagCombineInfo); - if (!Tmp2.Val) + if (!Tmp2.getNode()) Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,CC); - ConstantSDNode *Tmp1C = dyn_cast(Tmp1.Val); - ConstantSDNode *Tmp2C = dyn_cast(Tmp2.Val); + ConstantSDNode *Tmp1C = dyn_cast(Tmp1.getNode()); + ConstantSDNode *Tmp2C = dyn_cast(Tmp2.getNode()); if ((Tmp1C && Tmp1C->isNullValue()) || (Tmp2C && Tmp2C->isNullValue() && (CCCode == ISD::SETLE || CCCode == ISD::SETGE || @@ -4790,7 +5058,7 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS, } else { Result = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ, false, DagCombineInfo); - if (!Result.Val) + if (!Result.getNode()) Result=DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ); Result = LegalizeOp(DAG.getNode(ISD::SELECT, Tmp1.getValueType(), @@ -4805,6 +5073,50 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS, RHS = Tmp2; } +/// LegalizeSetCCCondCode - Legalize a SETCC with given LHS and RHS and +/// condition code CC on the current target. This routine assumes LHS and rHS +/// have already been legalized by LegalizeSetCCOperands. It expands SETCC with +/// illegal condition code into AND / OR of multiple SETCC values. +void SelectionDAGLegalize::LegalizeSetCCCondCode(MVT VT, + SDValue &LHS, SDValue &RHS, + SDValue &CC) { + MVT OpVT = LHS.getValueType(); + ISD::CondCode CCCode = cast(CC)->get(); + switch (TLI.getCondCodeAction(CCCode, OpVT)) { + default: assert(0 && "Unknown condition code action!"); + case TargetLowering::Legal: + // Nothing to do. + break; + case TargetLowering::Expand: { + ISD::CondCode CC1 = ISD::SETCC_INVALID, CC2 = ISD::SETCC_INVALID; + unsigned Opc = 0; + switch (CCCode) { + default: assert(0 && "Don't know how to expand this condition!"); abort(); + case ISD::SETOEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOGT: CC1 = ISD::SETGT; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOGE: CC1 = ISD::SETGE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOLT: CC1 = ISD::SETLT; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOLE: CC1 = ISD::SETLE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETONE: CC1 = ISD::SETNE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETUEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUGT: CC1 = ISD::SETGT; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUGE: CC1 = ISD::SETGE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETULT: CC1 = ISD::SETLT; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETULE: CC1 = ISD::SETLE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUNE: CC1 = ISD::SETNE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + // FIXME: Implement more expansions. + } + + SDValue SetCC1 = DAG.getSetCC(VT, LHS, RHS, CC1); + SDValue SetCC2 = DAG.getSetCC(VT, LHS, RHS, CC2); + LHS = DAG.getNode(Opc, VT, SetCC1, SetCC2); + RHS = SDValue(); + CC = SDValue(); + break; + } + } +} + /// EmitStackConvert - Emit a store/load combination to the stack. This stores /// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does /// a load from the stack slot to DestVT, extending it if needed. @@ -4915,10 +5227,10 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { for (unsigned i = 0, e = NumElems; i != e; ++i) { if (ConstantFPSDNode *V = dyn_cast(Node->getOperand(i))) { - CV.push_back(ConstantFP::get(V->getValueAPF())); + CV.push_back(const_cast(V->getConstantFPValue())); } else if (ConstantSDNode *V = dyn_cast(Node->getOperand(i))) { - CV.push_back(ConstantInt::get(V->getAPIntValue())); + CV.push_back(const_cast(V->getConstantIntValue())); } else { assert(Node->getOperand(i).getOpcode() == ISD::UNDEF); const Type *OpNTy = @@ -4928,11 +5240,13 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { } Constant *CP = ConstantVector::get(CV); SDValue CPIdx = DAG.getConstantPool(CP, TLI.getPointerTy()); + unsigned Alignment = 1 << cast(CPIdx)->getAlignment(); return DAG.getLoad(VT, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, Alignment); } - if (SplatValue.Val) { // Splat of one value? + if (SplatValue.getNode()) { // Splat of one value? // Build the shuffle constant vector: <0, 0, 0, 0> MVT MaskVT = MVT::getIntVectorWithNumElements(NumElems); SDValue Zero = DAG.getConstant(0, MaskVT.getVectorElementType()); @@ -5069,8 +5383,8 @@ bool SelectionDAGLegalize::ExpandShift(unsigned Opc, SDValue Op,SDValue Amt, unsigned NVTBits = NVT.getSizeInBits(); // Handle the case when Amt is an immediate. - if (ConstantSDNode *CN = dyn_cast(Amt.Val)) { - unsigned Cst = CN->getValue(); + if (ConstantSDNode *CN = dyn_cast(Amt.getNode())) { + unsigned Cst = CN->getZExtValue(); // Expand the incoming operand to be shifted, so that we have its parts SDValue InL, InH; ExpandOp(Op, InL, InH); @@ -5225,13 +5539,13 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, Args.push_back(Entry); } SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), - TLI.getPointerTy()); + TLI.getPointerTy()); // Splice the libcall in wherever FindInputOutputChains tells us to. const Type *RetTy = Node->getValueType(0).getTypeForMVT(); std::pair CallInfo = - TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, CallingConv::C, - false, Callee, Args, DAG); + TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, + CallingConv::C, false, Callee, Args, DAG); // Legalize the call sequence, starting with the chain. This will advance // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that @@ -5250,6 +5564,62 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, return Result; } +/// LegalizeINT_TO_FP - Legalize a [US]INT_TO_FP operation. +/// +SDValue SelectionDAGLegalize:: +LegalizeINT_TO_FP(SDValue Result, bool isSigned, MVT DestTy, SDValue Op) { + bool isCustom = false; + SDValue Tmp1; + switch (getTypeAction(Op.getValueType())) { + case Legal: + switch (TLI.getOperationAction(isSigned ? ISD::SINT_TO_FP : ISD::UINT_TO_FP, + Op.getValueType())) { + default: assert(0 && "Unknown operation action!"); + case TargetLowering::Custom: + isCustom = true; + // FALLTHROUGH + case TargetLowering::Legal: + Tmp1 = LegalizeOp(Op); + if (Result.getNode()) + Result = DAG.UpdateNodeOperands(Result, Tmp1); + else + Result = DAG.getNode(isSigned ? ISD::SINT_TO_FP : ISD::UINT_TO_FP, + DestTy, Tmp1); + if (isCustom) { + Tmp1 = TLI.LowerOperation(Result, DAG); + if (Tmp1.getNode()) Result = Tmp1; + } + break; + case TargetLowering::Expand: + Result = ExpandLegalINT_TO_FP(isSigned, LegalizeOp(Op), DestTy); + break; + case TargetLowering::Promote: + Result = PromoteLegalINT_TO_FP(LegalizeOp(Op), DestTy, isSigned); + break; + } + break; + case Expand: + Result = ExpandIntToFP(isSigned, DestTy, Op); + break; + case Promote: + Tmp1 = PromoteOp(Op); + if (isSigned) { + Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, Tmp1.getValueType(), + Tmp1, DAG.getValueType(Op.getValueType())); + } else { + Tmp1 = DAG.getZeroExtendInReg(Tmp1, + Op.getValueType()); + } + if (Result.getNode()) + Result = DAG.UpdateNodeOperands(Result, Tmp1); + else + Result = DAG.getNode(isSigned ? ISD::SINT_TO_FP : ISD::UINT_TO_FP, + DestTy, Tmp1); + Result = LegalizeOp(Result); // The 'op' is not necessarily legal! + break; + } + return Result; +} /// ExpandIntToFP - Expand a [US]INT_TO_FP operation. /// @@ -5258,6 +5628,27 @@ ExpandIntToFP(bool isSigned, MVT DestTy, SDValue Source) { MVT SourceVT = Source.getValueType(); bool ExpandSource = getTypeAction(SourceVT) == Expand; + // Expand unsupported int-to-fp vector casts by unrolling them. + if (DestTy.isVector()) { + if (!ExpandSource) + return LegalizeOp(UnrollVectorOp(Source)); + MVT DestEltTy = DestTy.getVectorElementType(); + if (DestTy.getVectorNumElements() == 1) { + SDValue Scalar = ScalarizeVectorOp(Source); + SDValue Result = LegalizeINT_TO_FP(SDValue(), isSigned, + DestEltTy, Scalar); + return DAG.getNode(ISD::BUILD_VECTOR, DestTy, Result); + } + SDValue Lo, Hi; + SplitVectorOp(Source, Lo, Hi); + MVT SplitDestTy = MVT::getVectorVT(DestEltTy, + DestTy.getVectorNumElements() / 2); + SDValue LoResult = LegalizeINT_TO_FP(SDValue(), isSigned, SplitDestTy, Lo); + SDValue HiResult = LegalizeINT_TO_FP(SDValue(), isSigned, SplitDestTy, Hi); + return LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, DestTy, LoResult, + HiResult)); + } + // Special case for i32 source to take advantage of UINTTOFP_I32_F32, etc. if (!isSigned && SourceVT != MVT::i32) { // The integer value loaded will be incorrectly if the 'sign bit' of the @@ -5273,6 +5664,22 @@ ExpandIntToFP(bool isSigned, MVT DestTy, SDValue Source) { Hi = Source; } + // Check to see if the target has a custom way to lower this. If so, use + // it. (Note we've already expanded the operand in this case.) + switch (TLI.getOperationAction(ISD::UINT_TO_FP, SourceVT)) { + default: assert(0 && "This action not implemented for this operation!"); + case TargetLowering::Legal: + case TargetLowering::Expand: + break; // This case is handled below. + case TargetLowering::Custom: { + SDValue NV = TLI.LowerOperation(DAG.getNode(ISD::UINT_TO_FP, DestTy, + Source), DAG); + if (NV.getNode()) + return LegalizeOp(NV); + break; // The target decided this was legal after all + } + } + // If this is unsigned, and not supported, first perform the conversion to // signed, then adjust the result if the sign bit is set. SDValue SignedConv = ExpandIntToFP(true, DestTy, Source); @@ -5288,17 +5695,20 @@ ExpandIntToFP(bool isSigned, MVT DestTy, SDValue Source) { static Constant *FudgeFactor = ConstantInt::get(Type::Int64Ty, FF); SDValue CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); + unsigned Alignment = 1 << cast(CPIdx)->getAlignment(); CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); + Alignment = std::min(Alignment, 4u); SDValue FudgeInReg; if (DestTy == MVT::f32) FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, Alignment); else if (DestTy.bitsGT(MVT::f32)) // FIXME: Avoid the extend by construction the right constantpool? FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, - MVT::f32); + MVT::f32, false, Alignment); else assert(0 && "Unexpected conversion"); @@ -5325,7 +5735,7 @@ ExpandIntToFP(bool isSigned, MVT DestTy, SDValue Source) { case TargetLowering::Custom: { SDValue NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy, Source), DAG); - if (NV.Val) + if (NV.getNode()) return LegalizeOp(NV); break; // The target decided this was legal after all } @@ -5346,8 +5756,8 @@ ExpandIntToFP(bool isSigned, MVT DestTy, SDValue Source) { Source = DAG.getNode(ISD::SINT_TO_FP, DestTy, Source); SDValue HiPart; - SDValue Result = ExpandLibCall(LC, Source.Val, isSigned, HiPart); - if (Result.getValueType() != DestTy && HiPart.Val) + SDValue Result = ExpandLibCall(LC, Source.getNode(), isSigned, HiPart); + if (Result.getValueType() != DestTy && HiPart.getNode()) Result = DAG.getNode(ISD::BUILD_PAIR, DestTy, Result, HiPart); return Result; } @@ -5437,17 +5847,20 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, static Constant *FudgeFactor = ConstantInt::get(Type::Int64Ty, FF); SDValue CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); + unsigned Alignment = 1 << cast(CPIdx)->getAlignment(); CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); + Alignment = std::min(Alignment, 4u); SDValue FudgeInReg; if (DestVT == MVT::f32) FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, Alignment); else { FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, DestVT, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, - MVT::f32)); + MVT::f32, false, Alignment)); } return DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg); @@ -5563,8 +5976,8 @@ SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp, // the target lowering hooks to expand it. Just keep the low part of the // expanded operation, we know that we're truncating anyway. if (getTypeAction(NewOutTy) == Expand) { - Operation = SDValue(TLI.ReplaceNodeResults(Operation.Val, DAG), 0); - assert(Operation.Val && "Didn't return anything"); + Operation = SDValue(TLI.ReplaceNodeResults(Operation.getNode(), DAG), 0); + assert(Operation.getNode() && "Didn't return anything"); } // Truncate the result of the extended FP_TO_*INT operation to the desired @@ -5686,13 +6099,13 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op) { /// ExpandOp - Expand the specified SDValue into its two component pieces /// Lo&Hi. Note that the Op MUST be an expanded type. As a result of this, the -/// LegalizeNodes map is filled in for any results that are not expanded, the +/// LegalizedNodes map is filled in for any results that are not expanded, the /// ExpandedNodes map is filled in for any results that are expanded, and the /// Lo/Hi values are returned. void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ MVT VT = Op.getValueType(); MVT NVT = TLI.getTypeToTransformTo(VT); - SDNode *Node = Op.Val; + SDNode *Node = Op.getNode(); assert(getTypeAction(VT) == Expand && "Not an expanded type!"); assert(((NVT.isInteger() && NVT.bitsLT(VT)) || VT.isFloatingPoint() || VT.isVector()) && "Cannot expand to FP value or to larger int value!"); @@ -5718,9 +6131,9 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ Src = DAG.getNode(ISD::BUILD_PAIR, VT, SrcLo, SrcHi); SDValue Result = TLI.LowerOperation( DAG.getNode(ISD::FP_ROUND_INREG, VT, Src, Op.getOperand(1)), DAG); - assert(Result.Val->getOpcode() == ISD::BUILD_PAIR); - Lo = Result.Val->getOperand(0); - Hi = Result.Val->getOperand(1); + assert(Result.getNode()->getOpcode() == ISD::BUILD_PAIR); + Lo = Result.getNode()->getOperand(0); + Hi = Result.getNode()->getOperand(1); break; } // fall through @@ -5732,11 +6145,10 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ abort(); case ISD::EXTRACT_ELEMENT: ExpandOp(Node->getOperand(0), Lo, Hi); - if (cast(Node->getOperand(1))->getValue()) + if (cast(Node->getOperand(1))->getZExtValue()) return ExpandOp(Hi, Lo, Hi); return ExpandOp(Lo, Lo, Hi); case ISD::EXTRACT_VECTOR_ELT: - assert(VT==MVT::i64 && "Do not know how to expand this operator!"); // ExpandEXTRACT_VECTOR_ELT tolerates invalid result types. Lo = ExpandEXTRACT_VECTOR_ELT(Op); return ExpandOp(Lo, Lo, Hi); @@ -5754,7 +6166,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ case ISD::ConstantFP: { ConstantFPSDNode *CFP = cast(Node); if (CFP->getValueType(0) == MVT::ppcf128) { - APInt api = CFP->getValueAPF().convertToAPInt(); + APInt api = CFP->getValueAPF().bitcastToAPInt(); Lo = DAG.getConstantFP(APFloat(APInt(64, 1, &api.getRawData()[1])), MVT::f64); Hi = DAG.getConstantFP(APFloat(APInt(64, 1, &api.getRawData()[0])), @@ -5778,7 +6190,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ break; } // FIXME: For now only expand i64,chain = MERGE_VALUES (x, y) - assert(Op.ResNo == 0 && Node->getNumValues() == 2 && + assert(Op.getResNo() == 0 && Node->getNumValues() == 2 && Op.getValue(1).getValueType() == MVT::Other && "unhandled MERGE_VALUES"); ExpandOp(Op.getOperand(0), Lo, Hi); @@ -5863,12 +6275,13 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ SDValue Ch = LD->getChain(); // Legalize the chain. SDValue Ptr = LD->getBasePtr(); // Legalize the pointer. ISD::LoadExtType ExtType = LD->getExtensionType(); + const Value *SV = LD->getSrcValue(); int SVOffset = LD->getSrcValueOffset(); unsigned Alignment = LD->getAlignment(); bool isVolatile = LD->isVolatile(); if (ExtType == ISD::NON_EXTLOAD) { - Lo = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset, + Lo = DAG.getLoad(NVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); if (VT == MVT::f32 || VT == MVT::f64) { // f32->i32 or f64->i64 one to one expansion. @@ -5886,7 +6299,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ DAG.getIntPtrConstant(IncrementSize)); SVOffset += IncrementSize; Alignment = MinAlign(Alignment, IncrementSize); - Hi = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset, + Hi = DAG.getLoad(NVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); // Build a factor node to remember that this load is independent of the @@ -5904,7 +6317,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ if ((VT == MVT::f64 && EVT == MVT::f32) || (VT == MVT::ppcf128 && (EVT==MVT::f64 || EVT==MVT::f32))) { // f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND - SDValue Load = DAG.getLoad(EVT, Ch, Ptr, LD->getSrcValue(), + SDValue Load = DAG.getLoad(EVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); // Remember that we legalized the chain. AddLegalizedOperand(SDValue(Node, 1), LegalizeOp(Load.getValue(1))); @@ -5913,10 +6326,10 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ } if (EVT == NVT) - Lo = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), + Lo = DAG.getLoad(NVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); else - Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, LD->getSrcValue(), + Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, SV, SVOffset, EVT, isVolatile, Alignment); @@ -6042,7 +6455,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ } // Turn this into a load/store pair by default. - if (Tmp.Val == 0) + if (Tmp.getNode() == 0) Tmp = EmitStackConvert(Node->getOperand(0), VT, VT); ExpandOp(Tmp, Lo, Hi); @@ -6054,23 +6467,45 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ TargetLowering::Custom && "Must custom expand ReadCycleCounter"); SDValue Tmp = TLI.LowerOperation(Op, DAG); - assert(Tmp.Val && "Node must be custom expanded!"); + assert(Tmp.getNode() && "Node must be custom expanded!"); ExpandOp(Tmp.getValue(0), Lo, Hi); AddLegalizedOperand(SDValue(Node, 1), // Remember we legalized the chain. LegalizeOp(Tmp.getValue(1))); break; } - case ISD::ATOMIC_CMP_SWAP: { + case ISD::ATOMIC_CMP_SWAP_64: { + // This operation does not need a loop. SDValue Tmp = TLI.LowerOperation(Op, DAG); - assert(Tmp.Val && "Node must be custom expanded!"); + assert(Tmp.getNode() && "Node must be custom expanded!"); ExpandOp(Tmp.getValue(0), Lo, Hi); AddLegalizedOperand(SDValue(Node, 1), // Remember we legalized the chain. LegalizeOp(Tmp.getValue(1))); break; } - + case ISD::ATOMIC_LOAD_ADD_64: + case ISD::ATOMIC_LOAD_SUB_64: + case ISD::ATOMIC_LOAD_AND_64: + case ISD::ATOMIC_LOAD_OR_64: + case ISD::ATOMIC_LOAD_XOR_64: + case ISD::ATOMIC_LOAD_NAND_64: + case ISD::ATOMIC_SWAP_64: { + // These operations require a loop to be generated. We can't do that yet, + // so substitute a target-dependent pseudo and expand that later. + SDValue In2Lo, In2Hi, In2; + ExpandOp(Op.getOperand(2), In2Lo, In2Hi); + In2 = DAG.getNode(ISD::BUILD_PAIR, VT, In2Lo, In2Hi); + AtomicSDNode* Anode = cast(Node); + SDValue Replace = + DAG.getAtomic(Op.getOpcode(), Op.getOperand(0), Op.getOperand(1), In2, + Anode->getSrcValue(), Anode->getAlignment()); + SDValue Result = TLI.LowerOperation(Replace, DAG); + ExpandOp(Result.getValue(0), Lo, Hi); + // Remember that we legalized the chain. + AddLegalizedOperand(SDValue(Node,1), LegalizeOp(Result.getValue(1))); + break; + } // These operators cannot be expanded directly, emit them as calls to // library functions. @@ -6087,7 +6522,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ // Now that the custom expander is done, expand the result, which is still // VT. - if (Op.Val) { + if (Op.getNode()) { ExpandOp(Op, Lo, Hi); break; } @@ -6112,7 +6547,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ Op = TLI.LowerOperation(DAG.getNode(ISD::FP_TO_UINT, VT, Op), DAG); // Now that the custom expander is done, expand the result. - if (Op.Val) { + if (Op.getNode()) { ExpandOp(Op, Lo, Hi); break; } @@ -6131,7 +6566,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ if (TLI.getOperationAction(ISD::SHL, VT) == TargetLowering::Custom) { SDValue Op = DAG.getNode(ISD::SHL, VT, Node->getOperand(0), ShiftAmt); Op = TLI.LowerOperation(Op, DAG); - if (Op.Val) { + if (Op.getNode()) { // Now that the custom expander is done, expand the result, which is // still VT. ExpandOp(Op, Lo, Hi); @@ -6181,7 +6616,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ if (TLI.getOperationAction(ISD::SRA, VT) == TargetLowering::Custom) { SDValue Op = DAG.getNode(ISD::SRA, VT, Node->getOperand(0), ShiftAmt); Op = TLI.LowerOperation(Op, DAG); - if (Op.Val) { + if (Op.getNode()) { // Now that the custom expander is done, expand the result, which is // still VT. ExpandOp(Op, Lo, Hi); @@ -6213,7 +6648,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ if (TLI.getOperationAction(ISD::SRL, VT) == TargetLowering::Custom) { SDValue Op = DAG.getNode(ISD::SRL, VT, Node->getOperand(0), ShiftAmt); Op = TLI.LowerOperation(Op, DAG); - if (Op.Val) { + if (Op.getNode()) { // Now that the custom expander is done, expand the result, which is // still VT. ExpandOp(Op, Lo, Hi); @@ -6245,12 +6680,11 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ if (TLI.getOperationAction(Node->getOpcode(), VT) == TargetLowering::Custom) { SDValue Result = TLI.LowerOperation(Op, DAG); - if (Result.Val) { + if (Result.getNode()) { ExpandOp(Result, Lo, Hi); break; } } - // Expand the subcomponents. SDValue LHSL, LHSH, RHSL, RHSH; ExpandOp(Node->getOperand(0), LHSL, LHSH); @@ -6261,16 +6695,55 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ LoOps[1] = RHSL; HiOps[0] = LHSH; HiOps[1] = RHSH; - if (Node->getOpcode() == ISD::ADD) { - Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); + + //cascaded check to see if any smaller size has a a carry flag. + unsigned OpV = Node->getOpcode() == ISD::ADD ? ISD::ADDC : ISD::SUBC; + bool hasCarry = false; + for (unsigned BitSize = NVT.getSizeInBits(); BitSize != 0; BitSize /= 2) { + MVT AVT = MVT::getIntegerVT(BitSize); + if (TLI.isOperationLegal(OpV, AVT)) { + hasCarry = true; + break; + } + } + + if(hasCarry) { + if (Node->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3); + } + break; } else { - Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3); + if (Node->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADD, VTList, LoOps, 2); + Hi = DAG.getNode(ISD::ADD, VTList, HiOps, 2); + SDValue Cmp1 = DAG.getSetCC(TLI.getSetCCResultType(Lo), + Lo, LoOps[0], ISD::SETULT); + SDValue Carry1 = DAG.getNode(ISD::SELECT, NVT, Cmp1, + DAG.getConstant(1, NVT), + DAG.getConstant(0, NVT)); + SDValue Cmp2 = DAG.getSetCC(TLI.getSetCCResultType(Lo), + Lo, LoOps[1], ISD::SETULT); + SDValue Carry2 = DAG.getNode(ISD::SELECT, NVT, Cmp2, + DAG.getConstant(1, NVT), + Carry1); + Hi = DAG.getNode(ISD::ADD, NVT, Hi, Carry2); + } else { + Lo = DAG.getNode(ISD::SUB, VTList, LoOps, 2); + Hi = DAG.getNode(ISD::SUB, VTList, HiOps, 2); + SDValue Cmp = DAG.getSetCC(NVT, LoOps[0], LoOps[1], ISD::SETULT); + SDValue Borrow = DAG.getNode(ISD::SELECT, NVT, Cmp, + DAG.getConstant(1, NVT), + DAG.getConstant(0, NVT)); + Hi = DAG.getNode(ISD::SUB, NVT, Hi, Borrow); + } + break; } - break; } case ISD::ADDC: @@ -6318,7 +6791,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ // If the target wants to custom expand this, let them. if (TLI.getOperationAction(ISD::MUL, VT) == TargetLowering::Custom) { SDValue New = TLI.LowerOperation(Op, DAG); - if (New.Val) { + if (New.getNode()) { ExpandOp(New, Lo, Hi); break; } @@ -6343,7 +6816,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ if (HasUMUL_LOHI) { // We can emit a umul_lohi. Lo = DAG.getNode(ISD::UMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL); - Hi = SDValue(Lo.Val, 1); + Hi = SDValue(Lo.getNode(), 1); break; } if (HasMULHU) { @@ -6358,7 +6831,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ if (HasSMUL_LOHI) { // We can emit a smul_lohi. Lo = DAG.getNode(ISD::SMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL); - Hi = SDValue(Lo.Val, 1); + Hi = SDValue(Lo.getNode(), 1); break; } if (HasMULHS) { @@ -6460,16 +6933,21 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ Lo = ExpandLibCall(LC, Node, true, Hi); break; } - case ISD::FPOWI: - Lo = ExpandLibCall(GetFPLibCall(VT, RTLIB::POWI_F32, - RTLIB::POWI_F64, - RTLIB::POWI_F80, - RTLIB::POWI_PPCF128), - Node, false, Hi); - break; case ISD::FSQRT: case ISD::FSIN: - case ISD::FCOS: { + case ISD::FCOS: + case ISD::FLOG: + case ISD::FLOG2: + case ISD::FLOG10: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FTRUNC: + case ISD::FFLOOR: + case ISD::FCEIL: + case ISD::FRINT: + case ISD::FNEARBYINT: + case ISD::FPOW: + case ISD::FPOWI: { RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; switch(Node->getOpcode()) { case ISD::FSQRT: @@ -6484,6 +6962,54 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ LC = GetFPLibCall(VT, RTLIB::COS_F32, RTLIB::COS_F64, RTLIB::COS_F80, RTLIB::COS_PPCF128); break; + case ISD::FLOG: + LC = GetFPLibCall(VT, RTLIB::LOG_F32, RTLIB::LOG_F64, + RTLIB::LOG_F80, RTLIB::LOG_PPCF128); + break; + case ISD::FLOG2: + LC = GetFPLibCall(VT, RTLIB::LOG2_F32, RTLIB::LOG2_F64, + RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128); + break; + case ISD::FLOG10: + LC = GetFPLibCall(VT, RTLIB::LOG10_F32, RTLIB::LOG10_F64, + RTLIB::LOG10_F80, RTLIB::LOG10_PPCF128); + break; + case ISD::FEXP: + LC = GetFPLibCall(VT, RTLIB::EXP_F32, RTLIB::EXP_F64, + RTLIB::EXP_F80, RTLIB::EXP_PPCF128); + break; + case ISD::FEXP2: + LC = GetFPLibCall(VT, RTLIB::EXP2_F32, RTLIB::EXP2_F64, + RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128); + break; + case ISD::FTRUNC: + LC = GetFPLibCall(VT, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128); + break; + case ISD::FFLOOR: + LC = GetFPLibCall(VT, RTLIB::FLOOR_F32, RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80, RTLIB::FLOOR_PPCF128); + break; + case ISD::FCEIL: + LC = GetFPLibCall(VT, RTLIB::CEIL_F32, RTLIB::CEIL_F64, + RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128); + break; + case ISD::FRINT: + LC = GetFPLibCall(VT, RTLIB::RINT_F32, RTLIB::RINT_F64, + RTLIB::RINT_F80, RTLIB::RINT_PPCF128); + break; + case ISD::FNEARBYINT: + LC = GetFPLibCall(VT, RTLIB::NEARBYINT_F32, RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, RTLIB::NEARBYINT_PPCF128); + break; + case ISD::FPOW: + LC = GetFPLibCall(VT, RTLIB::POW_F32, RTLIB::POW_F64, RTLIB::POW_F80, + RTLIB::POW_PPCF128); + break; + case ISD::FPOWI: + LC = GetFPLibCall(VT, RTLIB::POWI_F32, RTLIB::POWI_F64, RTLIB::POWI_F80, + RTLIB::POWI_PPCF128); + break; default: assert(0 && "Unreachable!"); } Lo = ExpandLibCall(LC, Node, false, Hi); @@ -6546,7 +7072,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ ? DAG.getNode(ISD::SIGN_EXTEND_INREG, Tmp.getValueType(), Tmp, DAG.getValueType(SrcVT)) : DAG.getZeroExtendInReg(Tmp, SrcVT); - Node = DAG.UpdateNodeOperands(Op, Tmp).Val; + Node = DAG.UpdateNodeOperands(Op, Tmp).getNode(); SrcVT = Node->getOperand(0).getValueType(); } @@ -6607,7 +7133,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ // is a type that requires multi-step expansion. if (getTypeAction(NVT) != Expand && NVT != MVT::isVoid) { Lo = LegalizeOp(Lo); - if (Hi.Val) + if (Hi.getNode()) // Don't legalize the high part if it is expanded to a single node. Hi = LegalizeOp(Hi); } @@ -6623,7 +7149,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, SDValue &Hi) { assert(Op.getValueType().isVector() && "Cannot split non-vector type!"); - SDNode *Node = Op.Val; + SDNode *Node = Op.getNode(); unsigned NumElements = Op.getValueType().getVectorNumElements(); assert(NumElements > 1 && "Cannot split a single element vector!"); @@ -6661,7 +7187,7 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, case ISD::INSERT_VECTOR_ELT: { if (ConstantSDNode *Idx = dyn_cast(Node->getOperand(2))) { SplitVectorOp(Node->getOperand(0), Lo, Hi); - unsigned Index = Idx->getValue(); + unsigned Index = Idx->getZExtValue(); SDValue ScalarOp = Node->getOperand(1); if (Index < NewNumElts_Lo) Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT_Lo, Lo, ScalarOp, @@ -6692,7 +7218,7 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, Ops.push_back(DAG.getNode(ISD::UNDEF, NewEltVT)); continue; } - unsigned Idx = cast(IdxNode)->getValue(); + unsigned Idx = cast(IdxNode)->getZExtValue(); SDValue InVec = Node->getOperand(0); if (Idx >= NumElements) { InVec = Node->getOperand(1); @@ -6710,7 +7236,7 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, Ops.push_back(DAG.getNode(ISD::UNDEF, NewEltVT)); continue; } - unsigned Idx = cast(IdxNode)->getValue(); + unsigned Idx = cast(IdxNode)->getZExtValue(); SDValue InVec = Node->getOperand(0); if (Idx >= NumElements) { InVec = Node->getOperand(1); @@ -6739,16 +7265,34 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, Lo = Node->getOperand(0); Hi = Node->getOperand(1); } else { - SmallVector LoOps(Node->op_begin(), - Node->op_begin()+NewNumSubvectors); + SmallVector LoOps(Node->op_begin(), + Node->op_begin()+NewNumSubvectors); Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Lo, &LoOps[0], LoOps.size()); - SmallVector HiOps(Node->op_begin()+NewNumSubvectors, + SmallVector HiOps(Node->op_begin()+NewNumSubvectors, Node->op_end()); Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Hi, &HiOps[0], HiOps.size()); } break; } + case ISD::EXTRACT_SUBVECTOR: { + SDValue Vec = Op.getOperand(0); + SDValue Idx = Op.getOperand(1); + MVT IdxVT = Idx.getValueType(); + + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Lo, Vec, Idx); + ConstantSDNode *CIdx = dyn_cast(Idx); + if (CIdx) { + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Hi, Vec, + DAG.getConstant(CIdx->getZExtValue() + NewNumElts_Lo, + IdxVT)); + } else { + Idx = DAG.getNode(ISD::ADD, IdxVT, Idx, + DAG.getConstant(NewNumElts_Lo, IdxVT)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Hi, Vec, Idx); + } + break; + } case ISD::SELECT: { SDValue Cond = Node->getOperand(0); @@ -6817,6 +7361,7 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, LH, RH); break; } + case ISD::FP_ROUND: case ISD::FPOWI: { SDValue L, H; SplitVectorOp(Node->getOperand(0), L, H); @@ -6833,10 +7378,20 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, case ISD::FSQRT: case ISD::FSIN: case ISD::FCOS: + case ISD::FLOG: + case ISD::FLOG2: + case ISD::FLOG10: + case ISD::FEXP: + case ISD::FEXP2: case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: { + case ISD::UINT_TO_FP: + case ISD::TRUNCATE: + case ISD::ANY_EXTEND: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::FP_EXTEND: { SDValue L, H; SplitVectorOp(Node->getOperand(0), L, H); @@ -6844,22 +7399,53 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, H); break; } + case ISD::CONVERT_RNDSAT: { + ISD::CvtCode CvtCode = cast(Node)->getCvtCode(); + SDValue L, H; + SplitVectorOp(Node->getOperand(0), L, H); + SDValue DTyOpL = DAG.getValueType(NewVT_Lo); + SDValue DTyOpH = DAG.getValueType(NewVT_Hi); + SDValue STyOpL = DAG.getValueType(L.getValueType()); + SDValue STyOpH = DAG.getValueType(H.getValueType()); + + SDValue RndOp = Node->getOperand(3); + SDValue SatOp = Node->getOperand(4); + + Lo = DAG.getConvertRndSat(NewVT_Lo, L, DTyOpL, STyOpL, + RndOp, SatOp, CvtCode); + Hi = DAG.getConvertRndSat(NewVT_Hi, H, DTyOpH, STyOpH, + RndOp, SatOp, CvtCode); + break; + } case ISD::LOAD: { LoadSDNode *LD = cast(Node); SDValue Ch = LD->getChain(); SDValue Ptr = LD->getBasePtr(); + ISD::LoadExtType ExtType = LD->getExtensionType(); const Value *SV = LD->getSrcValue(); int SVOffset = LD->getSrcValueOffset(); + MVT MemoryVT = LD->getMemoryVT(); unsigned Alignment = LD->getAlignment(); bool isVolatile = LD->isVolatile(); - Lo = DAG.getLoad(NewVT_Lo, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); - unsigned IncrementSize = NewNumElts_Lo * NewEltVT.getSizeInBits()/8; + assert(LD->isUnindexed() && "Indexed vector loads are not supported yet!"); + SDValue Offset = DAG.getNode(ISD::UNDEF, Ptr.getValueType()); + + MVT MemNewEltVT = MemoryVT.getVectorElementType(); + MVT MemNewVT_Lo = MVT::getVectorVT(MemNewEltVT, NewNumElts_Lo); + MVT MemNewVT_Hi = MVT::getVectorVT(MemNewEltVT, NewNumElts_Hi); + + Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, + NewVT_Lo, Ch, Ptr, Offset, + SV, SVOffset, MemNewVT_Lo, isVolatile, Alignment); + unsigned IncrementSize = NewNumElts_Lo * MemNewEltVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, DAG.getIntPtrConstant(IncrementSize)); SVOffset += IncrementSize; Alignment = MinAlign(Alignment, IncrementSize); - Hi = DAG.getLoad(NewVT_Hi, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); + Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, + NewVT_Hi, Ch, Ptr, Offset, + SV, SVOffset, MemNewVT_Hi, isVolatile, Alignment); // Build a factor node to remember that this load is independent of the // other one. @@ -6882,7 +7468,7 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, unsigned LdAlign = TLI.getTargetData()->getPrefTypeAlignment( Op.getValueType().getTypeForMVT()); SDValue Ptr = DAG.CreateStackTemporary(InOp.getValueType(), LdAlign); - int FI = cast(Ptr.Val)->getIndex(); + int FI = cast(Ptr.getNode())->getIndex(); SDValue St = DAG.getStore(DAG.getEntryNode(), InOp, Ptr, @@ -6910,7 +7496,7 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo, /// scalar (e.g. f32) value. SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) { assert(Op.getValueType().isVector() && "Bad ScalarizeVectorOp invocation!"); - SDNode *Node = Op.Val; + SDNode *Node = Op.getNode(); MVT NewVT = Op.getValueType().getVectorElementType(); assert(Op.getValueType().getVectorNumElements() == 1); @@ -6951,11 +7537,36 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) { case ISD::FSQRT: case ISD::FSIN: case ISD::FCOS: + case ISD::FLOG: + case ISD::FLOG2: + case ISD::FLOG10: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + case ISD::TRUNCATE: + case ISD::FP_EXTEND: Result = DAG.getNode(Node->getOpcode(), NewVT, ScalarizeVectorOp(Node->getOperand(0))); break; + case ISD::CONVERT_RNDSAT: { + SDValue Op0 = ScalarizeVectorOp(Node->getOperand(0)); + Result = DAG.getConvertRndSat(NewVT, Op0, + DAG.getValueType(NewVT), + DAG.getValueType(Op0.getValueType()), + Node->getOperand(3), + Node->getOperand(4), + cast(Node)->getCvtCode()); + break; + } case ISD::FPOWI: + case ISD::FP_ROUND: Result = DAG.getNode(Node->getOpcode(), NewVT, ScalarizeVectorOp(Node->getOperand(0)), @@ -6965,11 +7576,20 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) { LoadSDNode *LD = cast(Node); SDValue Ch = LegalizeOp(LD->getChain()); // Legalize the chain. SDValue Ptr = LegalizeOp(LD->getBasePtr()); // Legalize the pointer. - + ISD::LoadExtType ExtType = LD->getExtensionType(); const Value *SV = LD->getSrcValue(); int SVOffset = LD->getSrcValueOffset(); - Result = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset, - LD->isVolatile(), LD->getAlignment()); + MVT MemoryVT = LD->getMemoryVT(); + unsigned Alignment = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + + assert(LD->isUnindexed() && "Indexed vector loads are not supported yet!"); + SDValue Offset = DAG.getNode(ISD::UNDEF, Ptr.getValueType()); + + Result = DAG.getLoad(ISD::UNINDEXED, ExtType, + NewVT, Ch, Ptr, Offset, SV, SVOffset, + MemoryVT.getVectorElementType(), + isVolatile, Alignment); // Remember that we legalized the chain. AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1))); @@ -6990,15 +7610,15 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) { case ISD::VECTOR_SHUFFLE: { // Figure out if the scalar is the LHS or RHS and return it. SDValue EltNum = Node->getOperand(2).getOperand(0); - if (cast(EltNum)->getValue()) + if (cast(EltNum)->getZExtValue()) Result = ScalarizeVectorOp(Node->getOperand(1)); else Result = ScalarizeVectorOp(Node->getOperand(0)); break; } case ISD::EXTRACT_SUBVECTOR: - Result = Node->getOperand(0); - assert(Result.getValueType() == NewVT); + Result = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, Node->getOperand(0), + Node->getOperand(1)); break; case ISD::BIT_CONVERT: { SDValue Op0 = Op.getOperand(0); @@ -7039,6 +7659,766 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) { } +SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) { + std::map::iterator I = WidenNodes.find(Op); + if (I != WidenNodes.end()) return I->second; + + MVT VT = Op.getValueType(); + assert(VT.isVector() && "Cannot widen non-vector type!"); + + SDValue Result; + SDNode *Node = Op.getNode(); + MVT EVT = VT.getVectorElementType(); + + unsigned NumElts = VT.getVectorNumElements(); + unsigned NewNumElts = WidenVT.getVectorNumElements(); + assert(NewNumElts > NumElts && "Cannot widen to smaller type!"); + assert(NewNumElts < 17); + + // When widen is called, it is assumed that it is more efficient to use a + // wide type. The default action is to widen to operation to a wider legal + // vector type and then do the operation if it is legal by calling LegalizeOp + // again. If there is no vector equivalent, we will unroll the operation, do + // it, and rebuild the vector. If most of the operations are vectorizible to + // the legal type, the resulting code will be more efficient. If this is not + // the case, the resulting code will preform badly as we end up generating + // code to pack/unpack the results. It is the function that calls widen + // that is responsible for seeing this doesn't happen. + switch (Node->getOpcode()) { + default: +#ifndef NDEBUG + Node->dump(&DAG); +#endif + assert(0 && "Unexpected operation in WidenVectorOp!"); + break; + case ISD::CopyFromReg: + assert(0 && "CopyFromReg doesn't need widening!"); + case ISD::Constant: + case ISD::ConstantFP: + // To build a vector of these elements, clients should call BuildVector + // and with each element instead of creating a node with a vector type + assert(0 && "Unexpected operation in WidenVectorOp!"); + case ISD::VAARG: + // Variable Arguments with vector types doesn't make any sense to me + assert(0 && "Unexpected operation in WidenVectorOp!"); + break; + case ISD::UNDEF: + Result = DAG.getNode(ISD::UNDEF, WidenVT); + break; + case ISD::BUILD_VECTOR: { + // Build a vector with undefined for the new nodes + SDValueVector NewOps(Node->op_begin(), Node->op_end()); + for (unsigned i = NumElts; i < NewNumElts; ++i) { + NewOps.push_back(DAG.getNode(ISD::UNDEF,EVT)); + } + Result = DAG.getNode(ISD::BUILD_VECTOR, WidenVT, &NewOps[0], NewOps.size()); + break; + } + case ISD::INSERT_VECTOR_ELT: { + SDValue Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); + Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, WidenVT, Tmp1, + Node->getOperand(1), Node->getOperand(2)); + break; + } + case ISD::VECTOR_SHUFFLE: { + SDValue Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); + SDValue Tmp2 = WidenVectorOp(Node->getOperand(1), WidenVT); + // VECTOR_SHUFFLE 3rd operand must be a constant build vector that is + // used as permutation array. We build the vector here instead of widening + // because we don't want to legalize and have it turned to something else. + SDValue PermOp = Node->getOperand(2); + SDValueVector NewOps; + MVT PVT = PermOp.getValueType().getVectorElementType(); + for (unsigned i = 0; i < NumElts; ++i) { + if (PermOp.getOperand(i).getOpcode() == ISD::UNDEF) { + NewOps.push_back(PermOp.getOperand(i)); + } else { + unsigned Idx = + cast(PermOp.getOperand(i))->getZExtValue(); + if (Idx < NumElts) { + NewOps.push_back(PermOp.getOperand(i)); + } + else { + NewOps.push_back(DAG.getConstant(Idx + NewNumElts - NumElts, + PermOp.getOperand(i).getValueType())); + } + } + } + for (unsigned i = NumElts; i < NewNumElts; ++i) { + NewOps.push_back(DAG.getNode(ISD::UNDEF,PVT)); + } + + SDValue Tmp3 = DAG.getNode(ISD::BUILD_VECTOR, + MVT::getVectorVT(PVT, NewOps.size()), + &NewOps[0], NewOps.size()); + + Result = DAG.getNode(ISD::VECTOR_SHUFFLE, WidenVT, Tmp1, Tmp2, Tmp3); + break; + } + case ISD::LOAD: { + // If the load widen returns true, we can use a single load for the + // vector. Otherwise, it is returning a token factor for multiple + // loads. + SDValue TFOp; + if (LoadWidenVectorOp(Result, TFOp, Op, WidenVT)) + AddLegalizedOperand(Op.getValue(1), LegalizeOp(TFOp.getValue(1))); + else + AddLegalizedOperand(Op.getValue(1), LegalizeOp(TFOp.getValue(0))); + break; + } + + case ISD::BIT_CONVERT: { + SDValue Tmp1 = Node->getOperand(0); + // Converts between two different types so we need to determine + // the correct widen type for the input operand. + MVT TVT = Tmp1.getValueType(); + assert(TVT.isVector() && "can not widen non vector type"); + MVT TEVT = TVT.getVectorElementType(); + assert(WidenVT.getSizeInBits() % EVT.getSizeInBits() == 0 && + "can not widen bit bit convert that are not multiple of element type"); + MVT TWidenVT = MVT::getVectorVT(TEVT, + WidenVT.getSizeInBits()/EVT.getSizeInBits()); + Tmp1 = WidenVectorOp(Tmp1, TWidenVT); + assert(Tmp1.getValueType().getSizeInBits() == WidenVT.getSizeInBits()); + Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1); + + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } + + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: { + SDValue Tmp1 = Node->getOperand(0); + // Converts between two different types so we need to determine + // the correct widen type for the input operand. + MVT TVT = Tmp1.getValueType(); + assert(TVT.isVector() && "can not widen non vector type"); + MVT TEVT = TVT.getVectorElementType(); + MVT TWidenVT = MVT::getVectorVT(TEVT, NewNumElts); + Tmp1 = WidenVectorOp(Tmp1, TWidenVT); + assert(Tmp1.getValueType().getVectorNumElements() == NewNumElts); + Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1); + + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } + + case ISD::FP_EXTEND: + assert(0 && "Case not implemented. Dynamically dead with 2 FP types!"); + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + case ISD::FP_ROUND: + case ISD::SIGN_EXTEND_INREG: + case ISD::FABS: + case ISD::FNEG: + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: + case ISD::CTPOP: + case ISD::CTTZ: + case ISD::CTLZ: { + // Unary op widening + SDValue Tmp1; + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + + Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); + assert(Tmp1.getValueType() == WidenVT); + Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } + case ISD::CONVERT_RNDSAT: { + SDValue RndOp = Node->getOperand(3); + SDValue SatOp = Node->getOperand(4); + + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + + SDValue SrcOp = Node->getOperand(0); + + // Converts between two different types so we need to determine + // the correct widen type for the input operand. + MVT SVT = SrcOp.getValueType(); + assert(SVT.isVector() && "can not widen non vector type"); + MVT SEVT = SVT.getVectorElementType(); + MVT SWidenVT = MVT::getVectorVT(SEVT, NewNumElts); + + SrcOp = WidenVectorOp(SrcOp, SWidenVT); + assert(SrcOp.getValueType() == WidenVT); + SDValue DTyOp = DAG.getValueType(WidenVT); + SDValue STyOp = DAG.getValueType(SrcOp.getValueType()); + ISD::CvtCode CvtCode = cast(Node)->getCvtCode(); + + Result = DAG.getConvertRndSat(WidenVT, SrcOp, DTyOp, STyOp, + RndOp, SatOp, CvtCode); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } + case ISD::FPOW: + case ISD::FPOWI: + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: + case ISD::MULHS: + case ISD::MULHU: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::SDIV: + case ISD::SREM: + case ISD::FDIV: + case ISD::FREM: + case ISD::FCOPYSIGN: + case ISD::UDIV: + case ISD::UREM: + case ISD::BSWAP: { + // Binary op widening + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + + SDValue Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); + SDValue Tmp2 = WidenVectorOp(Node->getOperand(1), WidenVT); + assert(Tmp1.getValueType() == WidenVT && Tmp2.getValueType() == WidenVT); + Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1, Tmp2); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code by first + // Widening to the right type and then unroll the beast. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: { + // Binary op with one non vector operand + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + + SDValue Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); + assert(Tmp1.getValueType() == WidenVT); + Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1, Node->getOperand(1)); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } + case ISD::EXTRACT_VECTOR_ELT: { + SDValue Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT); + assert(Tmp1.getValueType() == WidenVT); + Result = DAG.getNode(Node->getOpcode(), EVT, Tmp1, Node->getOperand(1)); + break; + } + case ISD::CONCAT_VECTORS: { + // We concurrently support only widen on a multiple of the incoming vector. + // We could widen on a multiple of the incoming operand if necessary. + unsigned NumConcat = NewNumElts / NumElts; + assert(NewNumElts % NumElts == 0 && "Can widen only a multiple of vector"); + std::vector UnOps(NumElts, DAG.getNode(ISD::UNDEF, + VT.getVectorElementType())); + SDValue UndefVal = DAG.getNode(ISD::BUILD_VECTOR, VT, + &UnOps[0], UnOps.size()); + SmallVector MOps; + MOps.push_back(Op); + for (unsigned i = 1; i != NumConcat; ++i) { + MOps.push_back(UndefVal); + } + Result = LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, WidenVT, + &MOps[0], MOps.size())); + break; + } + case ISD::EXTRACT_SUBVECTOR: { + SDValue Tmp1 = Node->getOperand(0); + SDValue Idx = Node->getOperand(1); + ConstantSDNode *CIdx = dyn_cast(Idx); + if (CIdx && CIdx->getZExtValue() == 0) { + // Since we are access the start of the vector, the incoming + // vector type might be the proper. + MVT Tmp1VT = Tmp1.getValueType(); + if (Tmp1VT == WidenVT) + return Tmp1; + else { + unsigned Tmp1VTNumElts = Tmp1VT.getVectorNumElements(); + if (Tmp1VTNumElts < NewNumElts) + Result = WidenVectorOp(Tmp1, WidenVT); + else + Result = DAG.getNode(ISD::EXTRACT_SUBVECTOR, WidenVT, Tmp1, Idx); + } + } else if (NewNumElts % NumElts == 0) { + // Widen the extracted subvector. + unsigned NumConcat = NewNumElts / NumElts; + SDValue UndefVal = DAG.getNode(ISD::UNDEF, VT); + SmallVector MOps; + MOps.push_back(Op); + for (unsigned i = 1; i != NumConcat; ++i) { + MOps.push_back(UndefVal); + } + Result = LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, WidenVT, + &MOps[0], MOps.size())); + } else { + assert(0 && "can not widen extract subvector"); + // This could be implemented using insert and build vector but I would + // like to see when this happens. + } + break; + } + + case ISD::SELECT: { + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + + // Determine new condition widen type and widen + SDValue Cond1 = Node->getOperand(0); + MVT CondVT = Cond1.getValueType(); + assert(CondVT.isVector() && "can not widen non vector type"); + MVT CondEVT = CondVT.getVectorElementType(); + MVT CondWidenVT = MVT::getVectorVT(CondEVT, NewNumElts); + Cond1 = WidenVectorOp(Cond1, CondWidenVT); + assert(Cond1.getValueType() == CondWidenVT && "Condition not widen"); + + SDValue Tmp1 = WidenVectorOp(Node->getOperand(1), WidenVT); + SDValue Tmp2 = WidenVectorOp(Node->getOperand(2), WidenVT); + assert(Tmp1.getValueType() == WidenVT && Tmp2.getValueType() == WidenVT); + Result = DAG.getNode(Node->getOpcode(), WidenVT, Cond1, Tmp1, Tmp2); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code by first + // Widening to the right type and then unroll the beast. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } + + case ISD::SELECT_CC: { + TargetLowering::LegalizeAction action = + TLI.getOperationAction(Node->getOpcode(), WidenVT); + + // Determine new condition widen type and widen + SDValue Cond1 = Node->getOperand(0); + SDValue Cond2 = Node->getOperand(1); + MVT CondVT = Cond1.getValueType(); + assert(CondVT.isVector() && "can not widen non vector type"); + assert(CondVT == Cond2.getValueType() && "mismatch lhs/rhs"); + MVT CondEVT = CondVT.getVectorElementType(); + MVT CondWidenVT = MVT::getVectorVT(CondEVT, NewNumElts); + Cond1 = WidenVectorOp(Cond1, CondWidenVT); + Cond2 = WidenVectorOp(Cond2, CondWidenVT); + assert(Cond1.getValueType() == CondWidenVT && + Cond2.getValueType() == CondWidenVT && "condition not widen"); + + SDValue Tmp1 = WidenVectorOp(Node->getOperand(2), WidenVT); + SDValue Tmp2 = WidenVectorOp(Node->getOperand(3), WidenVT); + assert(Tmp1.getValueType() == WidenVT && Tmp2.getValueType() == WidenVT && + "operands not widen"); + Result = DAG.getNode(Node->getOpcode(), WidenVT, Cond1, Cond2, Tmp1, + Tmp2, Node->getOperand(4)); + switch (action) { + default: assert(0 && "action not supported"); + case TargetLowering::Legal: + break; + case TargetLowering::Promote: + // We defer the promotion to when we legalize the op + break; + case TargetLowering::Expand: + // Expand the operation into a bunch of nasty scalar code by first + // Widening to the right type and then unroll the beast. + Result = LegalizeOp(UnrollVectorOp(Result)); + break; + } + break; + } + case ISD::VSETCC: { + // Determine widen for the operand + SDValue Tmp1 = Node->getOperand(0); + MVT TmpVT = Tmp1.getValueType(); + assert(TmpVT.isVector() && "can not widen non vector type"); + MVT TmpEVT = TmpVT.getVectorElementType(); + MVT TmpWidenVT = MVT::getVectorVT(TmpEVT, NewNumElts); + Tmp1 = WidenVectorOp(Tmp1, TmpWidenVT); + SDValue Tmp2 = WidenVectorOp(Node->getOperand(1), TmpWidenVT); + Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1, Tmp2, + Node->getOperand(2)); + break; + } + case ISD::ATOMIC_CMP_SWAP_8: + case ISD::ATOMIC_CMP_SWAP_16: + case ISD::ATOMIC_CMP_SWAP_32: + case ISD::ATOMIC_CMP_SWAP_64: + case ISD::ATOMIC_LOAD_ADD_8: + case ISD::ATOMIC_LOAD_SUB_8: + case ISD::ATOMIC_LOAD_AND_8: + case ISD::ATOMIC_LOAD_OR_8: + case ISD::ATOMIC_LOAD_XOR_8: + case ISD::ATOMIC_LOAD_NAND_8: + case ISD::ATOMIC_LOAD_MIN_8: + case ISD::ATOMIC_LOAD_MAX_8: + case ISD::ATOMIC_LOAD_UMIN_8: + case ISD::ATOMIC_LOAD_UMAX_8: + case ISD::ATOMIC_SWAP_8: + case ISD::ATOMIC_LOAD_ADD_16: + case ISD::ATOMIC_LOAD_SUB_16: + case ISD::ATOMIC_LOAD_AND_16: + case ISD::ATOMIC_LOAD_OR_16: + case ISD::ATOMIC_LOAD_XOR_16: + case ISD::ATOMIC_LOAD_NAND_16: + case ISD::ATOMIC_LOAD_MIN_16: + case ISD::ATOMIC_LOAD_MAX_16: + case ISD::ATOMIC_LOAD_UMIN_16: + case ISD::ATOMIC_LOAD_UMAX_16: + case ISD::ATOMIC_SWAP_16: + case ISD::ATOMIC_LOAD_ADD_32: + case ISD::ATOMIC_LOAD_SUB_32: + case ISD::ATOMIC_LOAD_AND_32: + case ISD::ATOMIC_LOAD_OR_32: + case ISD::ATOMIC_LOAD_XOR_32: + case ISD::ATOMIC_LOAD_NAND_32: + case ISD::ATOMIC_LOAD_MIN_32: + case ISD::ATOMIC_LOAD_MAX_32: + case ISD::ATOMIC_LOAD_UMIN_32: + case ISD::ATOMIC_LOAD_UMAX_32: + case ISD::ATOMIC_SWAP_32: + case ISD::ATOMIC_LOAD_ADD_64: + case ISD::ATOMIC_LOAD_SUB_64: + case ISD::ATOMIC_LOAD_AND_64: + case ISD::ATOMIC_LOAD_OR_64: + case ISD::ATOMIC_LOAD_XOR_64: + case ISD::ATOMIC_LOAD_NAND_64: + case ISD::ATOMIC_LOAD_MIN_64: + case ISD::ATOMIC_LOAD_MAX_64: + case ISD::ATOMIC_LOAD_UMIN_64: + case ISD::ATOMIC_LOAD_UMAX_64: + case ISD::ATOMIC_SWAP_64: { + // For now, we assume that using vectors for these operations don't make + // much sense so we just split it. We return an empty result + SDValue X, Y; + SplitVectorOp(Op, X, Y); + return Result; + break; + } + + } // end switch (Node->getOpcode()) + + assert(Result.getNode() && "Didn't set a result!"); + if (Result != Op) + Result = LegalizeOp(Result); + + AddWidenedOperand(Op, Result); + return Result; +} + +// Utility function to find a legal vector type and its associated element +// type from a preferred width and whose vector type must be the same size +// as the VVT. +// TLI: Target lowering used to determine legal types +// Width: Preferred width of element type +// VVT: Vector value type whose size we must match. +// Returns VecEVT and EVT - the vector type and its associated element type +static void FindWidenVecType(TargetLowering &TLI, unsigned Width, MVT VVT, + MVT& EVT, MVT& VecEVT) { + // We start with the preferred width, make it a power of 2 and see if + // we can find a vector type of that width. If not, we reduce it by + // another power of 2. If we have widen the type, a vector of bytes should + // always be legal. + assert(TLI.isTypeLegal(VVT)); + unsigned EWidth = Width + 1; + do { + assert(EWidth > 0); + EWidth = (1 << Log2_32(EWidth-1)); + EVT = MVT::getIntegerVT(EWidth); + unsigned NumEVT = VVT.getSizeInBits()/EWidth; + VecEVT = MVT::getVectorVT(EVT, NumEVT); + } while (!TLI.isTypeLegal(VecEVT) || + VVT.getSizeInBits() != VecEVT.getSizeInBits()); +} + +SDValue SelectionDAGLegalize::genWidenVectorLoads(SDValueVector& LdChain, + SDValue Chain, + SDValue BasePtr, + const Value *SV, + int SVOffset, + unsigned Alignment, + bool isVolatile, + unsigned LdWidth, + MVT ResType) { + // We assume that we have good rules to handle loading power of two loads so + // we break down the operations to power of 2 loads. The strategy is to + // load the largest power of 2 that we can easily transform to a legal vector + // and then insert into that vector, and the cast the result into the legal + // vector that we want. This avoids unnecessary stack converts. + // TODO: If the Ldwidth is legal, alignment is the same as the LdWidth, and + // the load is nonvolatile, we an use a wider load for the value. + // Find a vector length we can load a large chunk + MVT EVT, VecEVT; + unsigned EVTWidth; + FindWidenVecType(TLI, LdWidth, ResType, EVT, VecEVT); + EVTWidth = EVT.getSizeInBits(); + + SDValue LdOp = DAG.getLoad(EVT, Chain, BasePtr, SV, SVOffset, + isVolatile, Alignment); + SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, VecEVT, LdOp); + LdChain.push_back(LdOp.getValue(1)); + + // Check if we can load the element with one instruction + if (LdWidth == EVTWidth) { + return DAG.getNode(ISD::BIT_CONVERT, ResType, VecOp); + } + + // The vector element order is endianness dependent. + unsigned Idx = 1; + LdWidth -= EVTWidth; + unsigned Offset = 0; + + while (LdWidth > 0) { + unsigned Increment = EVTWidth / 8; + Offset += Increment; + BasePtr = DAG.getNode(ISD::ADD, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + + if (LdWidth < EVTWidth) { + // Our current type we are using is too large, use a smaller size by + // using a smaller power of 2 + unsigned oEVTWidth = EVTWidth; + FindWidenVecType(TLI, LdWidth, ResType, EVT, VecEVT); + EVTWidth = EVT.getSizeInBits(); + // Readjust position and vector position based on new load type + Idx = Idx * (oEVTWidth/EVTWidth); + VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, VecOp); + } + + SDValue LdOp = DAG.getLoad(EVT, Chain, BasePtr, SV, + SVOffset+Offset, isVolatile, + MinAlign(Alignment, Offset)); + LdChain.push_back(LdOp.getValue(1)); + VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, VecEVT, VecOp, LdOp, + DAG.getIntPtrConstant(Idx++)); + + LdWidth -= EVTWidth; + } + + return DAG.getNode(ISD::BIT_CONVERT, ResType, VecOp); +} + +bool SelectionDAGLegalize::LoadWidenVectorOp(SDValue& Result, + SDValue& TFOp, + SDValue Op, + MVT NVT) { + // TODO: Add support for ConcatVec and the ability to load many vector + // types (e.g., v4i8). This will not work when a vector register + // to memory mapping is strange (e.g., vector elements are not + // stored in some sequential order). + + // It must be true that the widen vector type is bigger than where + // we need to load from. + LoadSDNode *LD = cast(Op.getNode()); + MVT LdVT = LD->getMemoryVT(); + assert(LdVT.isVector() && NVT.isVector()); + assert(LdVT.getVectorElementType() == NVT.getVectorElementType()); + + // Load information + SDValue Chain = LD->getChain(); + SDValue BasePtr = LD->getBasePtr(); + int SVOffset = LD->getSrcValueOffset(); + unsigned Alignment = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + const Value *SV = LD->getSrcValue(); + unsigned int LdWidth = LdVT.getSizeInBits(); + + // Load value as a large register + SDValueVector LdChain; + Result = genWidenVectorLoads(LdChain, Chain, BasePtr, SV, SVOffset, + Alignment, isVolatile, LdWidth, NVT); + + if (LdChain.size() == 1) { + TFOp = LdChain[0]; + return true; + } + else { + TFOp=DAG.getNode(ISD::TokenFactor, MVT::Other, &LdChain[0], LdChain.size()); + return false; + } +} + + +void SelectionDAGLegalize::genWidenVectorStores(SDValueVector& StChain, + SDValue Chain, + SDValue BasePtr, + const Value *SV, + int SVOffset, + unsigned Alignment, + bool isVolatile, + SDValue ValOp, + unsigned StWidth) { + // Breaks the stores into a series of power of 2 width stores. For any + // width, we convert the vector to the vector of element size that we + // want to store. This avoids requiring a stack convert. + + // Find a width of the element type we can store with + MVT VVT = ValOp.getValueType(); + MVT EVT, VecEVT; + unsigned EVTWidth; + FindWidenVecType(TLI, StWidth, VVT, EVT, VecEVT); + EVTWidth = EVT.getSizeInBits(); + + SDValue VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, ValOp); + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EVT, VecOp, + DAG.getIntPtrConstant(0)); + SDValue StOp = DAG.getStore(Chain, EOp, BasePtr, SV, SVOffset, + isVolatile, Alignment); + StChain.push_back(StOp); + + // Check if we are done + if (StWidth == EVTWidth) { + return; + } + + unsigned Idx = 1; + StWidth -= EVTWidth; + unsigned Offset = 0; + + while (StWidth > 0) { + unsigned Increment = EVTWidth / 8; + Offset += Increment; + BasePtr = DAG.getNode(ISD::ADD, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + + if (StWidth < EVTWidth) { + // Our current type we are using is too large, use a smaller size by + // using a smaller power of 2 + unsigned oEVTWidth = EVTWidth; + FindWidenVecType(TLI, StWidth, VVT, EVT, VecEVT); + EVTWidth = EVT.getSizeInBits(); + // Readjust position and vector position based on new load type + Idx = Idx * (oEVTWidth/EVTWidth); + VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, VecOp); + } + + EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EVT, VecOp, + DAG.getIntPtrConstant(Idx++)); + StChain.push_back(DAG.getStore(Chain, EOp, BasePtr, SV, + SVOffset + Offset, isVolatile, + MinAlign(Alignment, Offset))); + StWidth -= EVTWidth; + } +} + + +SDValue SelectionDAGLegalize::StoreWidenVectorOp(StoreSDNode *ST, + SDValue Chain, + SDValue BasePtr) { + // TODO: It might be cleaner if we can use SplitVector and have more legal + // vector types that can be stored into memory (e.g., v4xi8 can + // be stored as a word). This will not work when a vector register + // to memory mapping is strange (e.g., vector elements are not + // stored in some sequential order). + + MVT StVT = ST->getMemoryVT(); + SDValue ValOp = ST->getValue(); + + // Check if we have widen this node with another value + std::map::iterator I = WidenNodes.find(ValOp); + if (I != WidenNodes.end()) + ValOp = I->second; + + MVT VVT = ValOp.getValueType(); + + // It must be true that we the widen vector type is bigger than where + // we need to store. + assert(StVT.isVector() && VVT.isVector()); + assert(StVT.getSizeInBits() < VVT.getSizeInBits()); + assert(StVT.getVectorElementType() == VVT.getVectorElementType()); + + // Store value + SDValueVector StChain; + genWidenVectorStores(StChain, Chain, BasePtr, ST->getSrcValue(), + ST->getSrcValueOffset(), ST->getAlignment(), + ST->isVolatile(), ValOp, StVT.getSizeInBits()); + if (StChain.size() == 1) + return StChain[0]; + else + return DAG.getNode(ISD::TokenFactor, MVT::Other,&StChain[0],StChain.size()); +} + + // SelectionDAG::Legalize - This is the entry point for the file. // void SelectionDAG::Legalize() {