diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 16d4eeb9414..ee515fd3900 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -124,6 +124,10 @@ private: SDOperand &Hi); SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source); + + SDOperand ExpandLegalUINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT); + SDOperand PromoteLegalUINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT); + bool ExpandShift(unsigned Opc, SDOperand Op, SDOperand Amt, SDOperand &Lo, SDOperand &Hi); void ExpandShiftParts(unsigned NodeOp, SDOperand Op, SDOperand Amt, @@ -147,6 +151,102 @@ SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag) "Too many value types for ValueTypeActions to hold!"); } +/// ExpandLegalUINT_TO_FP - This function is responsible for legalizing a +/// UINT_TO_FP operation of the specified operand when the target requests that +/// we expand it. At this point, we know that the result and operand types are +/// legal for the target. +SDOperand SelectionDAGLegalize::ExpandLegalUINT_TO_FP(SDOperand Op0, + MVT::ValueType DestVT) { + assert(Op0.getValueType() == MVT::i32 && + "This code only works for i32 input: extend in the future"); + SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op0); + + SDOperand SignSet = DAG.getSetCC(ISD::SETLT, TLI.getSetCCResultTy(), + Op0, + DAG.getConstant(0, + Op0.getValueType())); + SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4); + SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), + SignSet, Four, Zero); + + uint64_t FF = 0x5f800000ULL; + if (TLI.isLittleEndian()) FF <<= 32; + static Constant *FudgeFactor = ConstantUInt::get(Type::ULongTy, FF); + + MachineConstantPool *CP = DAG.getMachineFunction().getConstantPool(); + SDOperand CPIdx = DAG.getConstantPool(CP->getConstantPoolIndex(FudgeFactor), + TLI.getPointerTy()); + CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); + SDOperand FudgeInReg; + if (DestVT == MVT::f32) + FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, + DAG.getSrcValue(NULL)); + else { + assert(DestVT == MVT::f64 && "Unexpected conversion"); + FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, + DAG.getEntryNode(), CPIdx, + DAG.getSrcValue(NULL), MVT::f32)); + } + + NeedsAnotherIteration = true; + return DAG.getNode(ISD::ADD, DestVT, Tmp1, FudgeInReg); +} + +/// PromoteLegalUINT_TO_FP - This function is responsible for legalizing a +/// UINT_TO_FP operation of the specified operand when the target requests that +/// we promote it. At this point, we know that the result and operand types are +/// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP +/// operation that takes a larger input. +SDOperand SelectionDAGLegalize::PromoteLegalUINT_TO_FP(SDOperand LegalOp, + MVT::ValueType DestVT) { + // First step, figure out the appropriate *INT_TO_FP operation to use. + MVT::ValueType NewInTy = LegalOp.getValueType(); + + unsigned OpToUse = 0; + + // Scan for the appropriate larger type to use. + while (1) { + NewInTy = (MVT::ValueType)(NewInTy+1); + assert(MVT::isInteger(NewInTy) && "Ran out of possibilities!"); + + // If the target supports SINT_TO_FP of this type, use it. + switch (TLI.getOperationAction(ISD::SINT_TO_FP, NewInTy)) { + default: break; + case TargetLowering::Legal: + if (!TLI.hasNativeSupportFor(NewInTy)) + break; // Can't use this datatype. + // FALL THROUGH. + case TargetLowering::Custom: + OpToUse = ISD::SINT_TO_FP; + break; + } + if (OpToUse) break; + + // If the target supports UINT_TO_FP of this type, use it. + switch (TLI.getOperationAction(ISD::UINT_TO_FP, NewInTy)) { + default: break; + case TargetLowering::Legal: + if (!TLI.hasNativeSupportFor(NewInTy)) + break; // Can't use this datatype. + // FALL THROUGH. + case TargetLowering::Custom: + OpToUse = ISD::UINT_TO_FP; + break; + } + if (OpToUse) break; + + // Otherwise, try a larger type. + } + + // Make sure to legalize any nodes we create here in the next pass. + NeedsAnotherIteration = true; + + // Okay, we found the operation and type to use. Zero extend our input to the + // desired type then run the operation on it. + return DAG.getNode(OpToUse, DestVT, + DAG.getNode(ISD::ZERO_EXTEND, NewInTy, LegalOp)); +} + void SelectionDAGLegalize::LegalizeDAG() { SDOperand OldRoot = DAG.getRoot(); SDOperand NewRoot = LegalizeOp(OldRoot); @@ -1338,42 +1438,23 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { switch (getTypeAction(Node->getOperand(0).getValueType())) { case Legal: //still made need to expand if the op is illegal, but the types are legal - if (Node->getOpcode() == ISD::UINT_TO_FP && - TLI.getOperationAction(Node->getOpcode(), - Node->getOperand(0).getValueType()) - == TargetLowering::Expand) { - SDOperand Op0 = LegalizeOp(Node->getOperand(0)); - Tmp1 = DAG.getNode(ISD::SINT_TO_FP, Node->getValueType(0), - Op0); - - SDOperand SignSet = DAG.getSetCC(ISD::SETLT, TLI.getSetCCResultTy(), - Op0, - DAG.getConstant(0, - Op0.getValueType())); - SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4); - SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), - SignSet, Four, Zero); - uint64_t FF = 0x5f800000ULL; - if (TLI.isLittleEndian()) FF <<= 32; - static Constant *FudgeFactor = ConstantUInt::get(Type::ULongTy, FF); - - MachineConstantPool *CP = DAG.getMachineFunction().getConstantPool(); - SDOperand CPIdx = DAG.getConstantPool(CP->getConstantPoolIndex(FudgeFactor), - TLI.getPointerTy()); - CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); - SDOperand FudgeInReg; - if (Node->getValueType(0) == MVT::f32) - FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, - DAG.getSrcValue(NULL)); - else { - assert(Node->getValueType(0) == MVT::f64 && "Unexpected conversion"); - FudgeInReg = - LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, - DAG.getEntryNode(), CPIdx, - DAG.getSrcValue(NULL), MVT::f32)); + if (Node->getOpcode() == ISD::UINT_TO_FP) { + switch (TLI.getOperationAction(Node->getOpcode(), + Node->getOperand(0).getValueType())) { + default: assert(0 && "Unknown operation action!"); + case TargetLowering::Expand: + Result = ExpandLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)), + Node->getValueType(0)); + AddLegalizedOperand(Op, Result); + return Result; + case TargetLowering::Promote: + Result = PromoteLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)), + Node->getValueType(0)); + AddLegalizedOperand(Op, Result); + return Result; + case TargetLowering::Legal: + break; } - Result = DAG.getNode(ISD::ADD, Node->getValueType(0), Tmp1, FudgeInReg); - break; } Tmp1 = LegalizeOp(Node->getOperand(0)); if (Tmp1 != Node->getOperand(0))