X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSelectionDAG%2FLegalizeDAG.cpp;h=96b427bd8067a186aa383dedeffa44939798d6cd;hb=f9410141f703f4e8a6aba717617ef958249f6d13;hp=ba78b8166a60979028e85b8ed2d0507a6fe9aeb4;hpb=4fbd796a1251a27e6590765a0a34876f436a0af9;p=oota-llvm.git diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index ba78b8166a6..96b427bd806 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -163,7 +163,7 @@ 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. @@ -193,6 +193,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); @@ -280,11 +285,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. - std::vector TopOrder; - unsigned N = DAG.AssignTopologicalOrder(TopOrder); - for (unsigned i = N; i != 0; --i) - HandleOp(SDValue(TopOrder[i-1], 0)); - TopOrder.clear(); + 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(); @@ -446,7 +450,7 @@ static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, 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); } @@ -457,7 +461,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)); @@ -467,12 +471,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); } @@ -1260,9 +1265,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case TargetLowering::Custom: Result = TLI.LowerOperation(Result, DAG); break; - case TargetLowering::Expand: - Result = SDValue(TLI.ReplaceNodeResults(Op.getNode(), DAG),0); - break; case TargetLowering::Legal: break; } @@ -1681,8 +1683,7 @@ 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); @@ -1696,11 +1697,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); @@ -1893,10 +1891,10 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp3 = Node->getOperand(3); // RHS Tmp4 = Node->getOperand(1); // CC - LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4); + LegalizeSetCC(Node->getValueType(0), 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.getNode() == 0) { @@ -1988,7 +1986,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(); @@ -2093,7 +2091,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; @@ -2360,7 +2358,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); @@ -2368,7 +2366,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); @@ -2377,7 +2375,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); @@ -2480,7 +2478,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { ExpandOp(ST->getValue(), Lo, Hi); IncrementSize = Hi.getNode() ? Hi.getValueType().getSizeInBits()/8 : 0; - if (TLI.isBigEndian()) + if (Hi.getNode() && TLI.isBigEndian()) std::swap(Lo, Hi); } @@ -2779,9 +2777,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp4 = LegalizeOp(Node->getOperand(3)); // False SDValue CC = Node->getOperand(4); - LegalizeSetCCOperands(Tmp1, Tmp2, CC); + LegalizeSetCC(Node->getValueType(0), 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.getNode() == 0) { @@ -2805,7 +2803,7 @@ 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 @@ -3010,22 +3008,26 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { } if (Node->getOpcode() == ISD::MULHS && TLI.isOperationLegal(ISD::SMUL_LOHI, VT)) { - Result = SDValue(DAG.getNode(ISD::SMUL_LOHI, VTs, Tmp1, Tmp2).getNode(), 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).getNode(), 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).getNode(), 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).getNode(), 0); + Result = SDValue(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).getNode(), + 0); break; } @@ -3041,6 +3043,10 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { 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); @@ -3978,7 +3984,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; @@ -4670,6 +4676,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; } } @@ -4874,6 +4882,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. @@ -4997,8 +5049,10 @@ 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.getNode()) { // Splat of one value? @@ -5299,8 +5353,8 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, // 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 @@ -5400,7 +5454,8 @@ ExpandIntToFP(bool isSigned, MVT DestTy, SDValue Source) { 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)); + return LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, DestTy, LoResult, + HiResult)); } // Special case for i32 source to take advantage of UINTTOFP_I32_F32, etc. @@ -5418,6 +5473,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); @@ -5433,17 +5504,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"); @@ -5582,17 +5656,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); @@ -5831,7 +5908,7 @@ 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){ @@ -5899,7 +5976,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])), @@ -6207,11 +6284,8 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ break; } - // FIXME: should the LOAD_BIN and SWAP atomics get here too? Probably. - case ISD::ATOMIC_CMP_SWAP_8: - case ISD::ATOMIC_CMP_SWAP_16: - case ISD::ATOMIC_CMP_SWAP_32: case ISD::ATOMIC_CMP_SWAP_64: { + // This operation does not need a loop. SDValue Tmp = TLI.LowerOperation(Op, DAG); assert(Tmp.getNode() && "Node must be custom expanded!"); ExpandOp(Tmp.getValue(0), Lo, Hi); @@ -6220,7 +6294,28 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ 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. @@ -6400,7 +6495,6 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){ break; } } - // Expand the subcomponents. SDValue LHSL, LHSH, RHSL, RHSH; ExpandOp(Node->getOperand(0), LHSL, LHSH); @@ -6411,16 +6505,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: