From 22cde6a518782cafc2115ad8d8233f79c9e9d52e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 28 Jan 2006 08:25:58 +0000 Subject: [PATCH] move a bunch of code, no other change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25739 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 832 +++++++++++------------ 1 file changed, 415 insertions(+), 417 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index da35aadd13c..a7f488e0f0b 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -152,332 +152,6 @@ SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag) "Too many value types for ValueTypeActions to hold!"); } -/// ExpandLegalINT_TO_FP - This function is responsible for legalizing a -/// INT_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::ExpandLegalINT_TO_FP(bool isSigned, - SDOperand Op0, - MVT::ValueType DestVT) { - if (Op0.getValueType() == MVT::i32) { - // simple 32-bit [signed|unsigned] integer to float/double expansion - - // get the stack frame index of a 8 byte buffer - MachineFunction &MF = DAG.getMachineFunction(); - int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8); - // get address of 8 byte buffer - SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); - // word offset constant for Hi/Lo address computation - SDOperand WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy()); - // set up Hi and Lo (into buffer) address based on endian - SDOperand Hi, Lo; - if (TLI.isLittleEndian()) { - Hi = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff); - Lo = StackSlot; - } else { - Hi = StackSlot; - Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff); - } - // if signed map to unsigned space - SDOperand Op0Mapped; - if (isSigned) { - // constant used to invert sign bit (signed to unsigned mapping) - SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32); - Op0Mapped = DAG.getNode(ISD::XOR, MVT::i32, Op0, SignBit); - } else { - Op0Mapped = Op0; - } - // store the lo of the constructed double - based on integer input - SDOperand Store1 = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(), - Op0Mapped, Lo, DAG.getSrcValue(NULL)); - // initial hi portion of constructed double - SDOperand InitialHi = DAG.getConstant(0x43300000u, MVT::i32); - // store the hi of the constructed double - biased exponent - SDOperand Store2 = DAG.getNode(ISD::STORE, MVT::Other, Store1, - InitialHi, Hi, DAG.getSrcValue(NULL)); - // load the constructed double - SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot, - DAG.getSrcValue(NULL)); - // FP constant to bias correct the final result - SDOperand Bias = DAG.getConstantFP(isSigned ? - BitsToDouble(0x4330000080000000ULL) - : BitsToDouble(0x4330000000000000ULL), - MVT::f64); - // subtract the bias - SDOperand Sub = DAG.getNode(ISD::FSUB, MVT::f64, Load, Bias); - // final result - SDOperand Result; - // handle final rounding - if (DestVT == MVT::f64) { - // do nothing - Result = Sub; - } else { - // if f32 then cast to f32 - Result = DAG.getNode(ISD::FP_ROUND, MVT::f32, Sub); - } - return Result; - } - assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet"); - SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op0); - - SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Op0, - DAG.getConstant(0, Op0.getValueType()), - ISD::SETLT); - SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4); - SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), - SignSet, Four, Zero); - - // If the sign bit of the integer is set, the large number will be treated - // as a negative number. To counteract this, the dynamic code adds an - // offset depending on the data type. - uint64_t FF; - switch (Op0.getValueType()) { - default: assert(0 && "Unsupported integer type!"); - case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float) - case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float) - case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float) - case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float) - } - if (TLI.isLittleEndian()) FF <<= 32; - static Constant *FudgeFactor = ConstantUInt::get(Type::ULongTy, FF); - - SDOperand CPIdx = DAG.getConstantPool(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)); - } - - return DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg); -} - -/// PromoteLegalINT_TO_FP - This function is responsible for legalizing a -/// *INT_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::PromoteLegalINT_TO_FP(SDOperand LegalOp, - MVT::ValueType DestVT, - bool isSigned) { - // 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.isTypeLegal(NewInTy)) - break; // Can't use this datatype. - // FALL THROUGH. - case TargetLowering::Custom: - OpToUse = ISD::SINT_TO_FP; - break; - } - if (OpToUse) break; - if (isSigned) continue; - - // 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.isTypeLegal(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. - } - - // 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(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, - NewInTy, LegalOp)); -} - -/// PromoteLegalFP_TO_INT - This function is responsible for legalizing a -/// FP_TO_*INT 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 FP_TO_UINT or FP_TO_SINT -/// operation that returns a larger result. -SDOperand SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDOperand LegalOp, - MVT::ValueType DestVT, - bool isSigned) { - // First step, figure out the appropriate FP_TO*INT operation to use. - MVT::ValueType NewOutTy = DestVT; - - unsigned OpToUse = 0; - - // Scan for the appropriate larger type to use. - while (1) { - NewOutTy = (MVT::ValueType)(NewOutTy+1); - assert(MVT::isInteger(NewOutTy) && "Ran out of possibilities!"); - - // If the target supports FP_TO_SINT returning this type, use it. - switch (TLI.getOperationAction(ISD::FP_TO_SINT, NewOutTy)) { - default: break; - case TargetLowering::Legal: - if (!TLI.isTypeLegal(NewOutTy)) - break; // Can't use this datatype. - // FALL THROUGH. - case TargetLowering::Custom: - OpToUse = ISD::FP_TO_SINT; - break; - } - if (OpToUse) break; - - // If the target supports FP_TO_UINT of this type, use it. - switch (TLI.getOperationAction(ISD::FP_TO_UINT, NewOutTy)) { - default: break; - case TargetLowering::Legal: - if (!TLI.isTypeLegal(NewOutTy)) - break; // Can't use this datatype. - // FALL THROUGH. - case TargetLowering::Custom: - OpToUse = ISD::FP_TO_UINT; - break; - } - if (OpToUse) break; - - // Otherwise, try a larger type. - } - - // Okay, we found the operation and type to use. Truncate the result of the - // extended FP_TO_*INT operation to the desired size. - return DAG.getNode(ISD::TRUNCATE, DestVT, - DAG.getNode(OpToUse, NewOutTy, LegalOp)); -} - -/// ExpandBSWAP - Open code the operations for BSWAP of the specified operation. -/// -SDOperand SelectionDAGLegalize::ExpandBSWAP(SDOperand Op) { - MVT::ValueType VT = Op.getValueType(); - MVT::ValueType SHVT = TLI.getShiftAmountTy(); - SDOperand Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8; - switch (VT) { - default: assert(0 && "Unhandled Expand type in BSWAP!"); abort(); - case MVT::i16: - Tmp2 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT)); - Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT)); - return DAG.getNode(ISD::OR, VT, Tmp1, Tmp2); - case MVT::i32: - Tmp4 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(24, SHVT)); - Tmp3 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT)); - Tmp2 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT)); - Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(24, SHVT)); - Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(0xFF0000, VT)); - Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(0xFF00, VT)); - Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3); - Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1); - return DAG.getNode(ISD::OR, VT, Tmp4, Tmp2); - case MVT::i64: - Tmp8 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(56, SHVT)); - Tmp7 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(40, SHVT)); - Tmp6 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(24, SHVT)); - Tmp5 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT)); - Tmp4 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT)); - Tmp3 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(24, SHVT)); - Tmp2 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(40, SHVT)); - Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(56, SHVT)); - Tmp7 = DAG.getNode(ISD::AND, VT, Tmp7, DAG.getConstant(255ULL<<48, VT)); - Tmp6 = DAG.getNode(ISD::AND, VT, Tmp6, DAG.getConstant(255ULL<<40, VT)); - Tmp5 = DAG.getNode(ISD::AND, VT, Tmp5, DAG.getConstant(255ULL<<32, VT)); - Tmp4 = DAG.getNode(ISD::AND, VT, Tmp4, DAG.getConstant(255ULL<<24, VT)); - Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(255ULL<<16, VT)); - Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(255ULL<<8 , VT)); - Tmp8 = DAG.getNode(ISD::OR, VT, Tmp8, Tmp7); - Tmp6 = DAG.getNode(ISD::OR, VT, Tmp6, Tmp5); - Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3); - Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1); - Tmp8 = DAG.getNode(ISD::OR, VT, Tmp8, Tmp6); - Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp2); - return DAG.getNode(ISD::OR, VT, Tmp8, Tmp4); - } -} - -/// ExpandBitCount - Expand the specified bitcount instruction into operations. -/// -SDOperand SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDOperand Op) { - switch (Opc) { - default: assert(0 && "Cannot expand this yet!"); - case ISD::CTPOP: { - static const uint64_t mask[6] = { - 0x5555555555555555ULL, 0x3333333333333333ULL, - 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL, - 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL - }; - MVT::ValueType VT = Op.getValueType(); - MVT::ValueType ShVT = TLI.getShiftAmountTy(); - unsigned len = getSizeInBits(VT); - for (unsigned i = 0; (1U << i) <= (len / 2); ++i) { - //x = (x & mask[i][len/8]) + (x >> (1 << i) & mask[i][len/8]) - SDOperand Tmp2 = DAG.getConstant(mask[i], VT); - SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT); - Op = DAG.getNode(ISD::ADD, VT, DAG.getNode(ISD::AND, VT, Op, Tmp2), - DAG.getNode(ISD::AND, VT, - DAG.getNode(ISD::SRL, VT, Op, Tmp3),Tmp2)); - } - return Op; - } - case ISD::CTLZ: { - // for now, we do this: - // x = x | (x >> 1); - // x = x | (x >> 2); - // ... - // x = x | (x >>16); - // x = x | (x >>32); // for 64-bit input - // return popcount(~x); - // - // but see also: http://www.hackersdelight.org/HDcode/nlz.cc - MVT::ValueType VT = Op.getValueType(); - MVT::ValueType ShVT = TLI.getShiftAmountTy(); - unsigned len = getSizeInBits(VT); - for (unsigned i = 0; (1U << i) <= (len / 2); ++i) { - SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT); - Op = DAG.getNode(ISD::OR, VT, Op, DAG.getNode(ISD::SRL, VT, Op, Tmp3)); - } - Op = DAG.getNode(ISD::XOR, VT, Op, DAG.getConstant(~0ULL, VT)); - return DAG.getNode(ISD::CTPOP, VT, Op); - } - case ISD::CTTZ: { - // for now, we use: { return popcount(~x & (x - 1)); } - // unless the target has ctlz but not ctpop, in which case we use: - // { return 32 - nlz(~x & (x-1)); } - // see also http://www.hackersdelight.org/HDcode/ntz.cc - MVT::ValueType VT = Op.getValueType(); - SDOperand Tmp2 = DAG.getConstant(~0ULL, VT); - SDOperand Tmp3 = DAG.getNode(ISD::AND, VT, - DAG.getNode(ISD::XOR, VT, Op, Tmp2), - DAG.getNode(ISD::SUB, VT, Op, DAG.getConstant(1, VT))); - // If ISD::CTLZ is legal and CTPOP isn't, then do that instead. - if (!TLI.isOperationLegal(ISD::CTPOP, VT) && - TLI.isOperationLegal(ISD::CTLZ, VT)) - return DAG.getNode(ISD::SUB, VT, - DAG.getConstant(getSizeInBits(VT), VT), - DAG.getNode(ISD::CTLZ, VT, Tmp3)); - return DAG.getNode(ISD::CTPOP, VT, Tmp3); - } - } -} - - /// ComputeTopDownOrdering - Add the specified node to the Order list if it has /// not been visited yet and if all of its operands have already been visited. static void ComputeTopDownOrdering(SDNode *N, std::vector &Order, @@ -3416,111 +3090,435 @@ SDOperand SelectionDAGLegalize::ExpandLibCall(const char *Name, SDNode *Node, break; } - CallInfo.second = LegalizeOp(CallInfo.second); - SpliceCallInto(CallInfo.second, OutChain); - return Result; + CallInfo.second = LegalizeOp(CallInfo.second); + SpliceCallInto(CallInfo.second, OutChain); + return Result; +} + + +/// ExpandIntToFP - Expand a [US]INT_TO_FP operation, assuming that the +/// destination type is legal. +SDOperand SelectionDAGLegalize:: +ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) { + assert(isTypeLegal(DestTy) && "Destination type is not legal!"); + assert(getTypeAction(Source.getValueType()) == Expand && + "This is not an expansion!"); + assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!"); + + if (!isSigned) { + assert(Source.getValueType() == MVT::i64 && + "This only works for 64-bit -> FP"); + // The 64-bit value loaded will be incorrectly if the 'sign bit' of the + // incoming integer is set. To handle this, we dynamically test to see if + // it is set, and, if so, add a fudge factor. + SDOperand Lo, Hi; + ExpandOp(Source, Lo, Hi); + + // If this is unsigned, and not supported, first perform the conversion to + // signed, then adjust the result if the sign bit is set. + SDOperand SignedConv = ExpandIntToFP(true, DestTy, + DAG.getNode(ISD::BUILD_PAIR, Source.getValueType(), Lo, Hi)); + + SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Hi, + DAG.getConstant(0, Hi.getValueType()), + ISD::SETLT); + 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); + + SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); + CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); + SDOperand FudgeInReg; + if (DestTy == MVT::f32) + FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, + DAG.getSrcValue(NULL)); + else { + assert(DestTy == MVT::f64 && "Unexpected conversion"); + FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(), + CPIdx, DAG.getSrcValue(NULL), MVT::f32); + } + return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg); + } + + // Check to see if the target has a custom way to lower this. If so, use it. + switch (TLI.getOperationAction(ISD::SINT_TO_FP, Source.getValueType())) { + 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: { + SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy, + Source), DAG); + if (NV.Val) + return LegalizeOp(NV); + break; // The target decided this was legal after all + } + } + + // Expand the source, then glue it back together for the call. We must expand + // the source in case it is shared (this pass of legalize must traverse it). + SDOperand SrcLo, SrcHi; + ExpandOp(Source, SrcLo, SrcHi); + Source = DAG.getNode(ISD::BUILD_PAIR, Source.getValueType(), SrcLo, SrcHi); + + SDNode *OutChain = 0; + SDOperand InChain = FindInputOutputChains(Source.Val, OutChain, + DAG.getEntryNode()); + const char *FnName = 0; + if (DestTy == MVT::f32) + FnName = "__floatdisf"; + else { + assert(DestTy == MVT::f64 && "Unknown fp value type!"); + FnName = "__floatdidf"; + } + + SDOperand Callee = DAG.getExternalSymbol(FnName, TLI.getPointerTy()); + + TargetLowering::ArgListTy Args; + const Type *ArgTy = MVT::getTypeForValueType(Source.getValueType()); + + Args.push_back(std::make_pair(Source, ArgTy)); + + // We don't care about token chains for libcalls. We just use the entry + // node as our input and ignore the output chain. This allows us to place + // calls wherever we need them to satisfy data dependences. + const Type *RetTy = MVT::getTypeForValueType(DestTy); + + std::pair CallResult = + TLI.LowerCallTo(InChain, RetTy, false, CallingConv::C, true, + Callee, Args, DAG); + + SpliceCallInto(CallResult.second, OutChain); + return CallResult.first; +} + +/// ExpandLegalINT_TO_FP - This function is responsible for legalizing a +/// INT_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::ExpandLegalINT_TO_FP(bool isSigned, + SDOperand Op0, + MVT::ValueType DestVT) { + if (Op0.getValueType() == MVT::i32) { + // simple 32-bit [signed|unsigned] integer to float/double expansion + + // get the stack frame index of a 8 byte buffer + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8); + // get address of 8 byte buffer + SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); + // word offset constant for Hi/Lo address computation + SDOperand WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy()); + // set up Hi and Lo (into buffer) address based on endian + SDOperand Hi, Lo; + if (TLI.isLittleEndian()) { + Hi = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff); + Lo = StackSlot; + } else { + Hi = StackSlot; + Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff); + } + // if signed map to unsigned space + SDOperand Op0Mapped; + if (isSigned) { + // constant used to invert sign bit (signed to unsigned mapping) + SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32); + Op0Mapped = DAG.getNode(ISD::XOR, MVT::i32, Op0, SignBit); + } else { + Op0Mapped = Op0; + } + // store the lo of the constructed double - based on integer input + SDOperand Store1 = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(), + Op0Mapped, Lo, DAG.getSrcValue(NULL)); + // initial hi portion of constructed double + SDOperand InitialHi = DAG.getConstant(0x43300000u, MVT::i32); + // store the hi of the constructed double - biased exponent + SDOperand Store2 = DAG.getNode(ISD::STORE, MVT::Other, Store1, + InitialHi, Hi, DAG.getSrcValue(NULL)); + // load the constructed double + SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot, + DAG.getSrcValue(NULL)); + // FP constant to bias correct the final result + SDOperand Bias = DAG.getConstantFP(isSigned ? + BitsToDouble(0x4330000080000000ULL) + : BitsToDouble(0x4330000000000000ULL), + MVT::f64); + // subtract the bias + SDOperand Sub = DAG.getNode(ISD::FSUB, MVT::f64, Load, Bias); + // final result + SDOperand Result; + // handle final rounding + if (DestVT == MVT::f64) { + // do nothing + Result = Sub; + } else { + // if f32 then cast to f32 + Result = DAG.getNode(ISD::FP_ROUND, MVT::f32, Sub); + } + return Result; + } + assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet"); + SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op0); + + SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Op0, + DAG.getConstant(0, Op0.getValueType()), + ISD::SETLT); + SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4); + SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), + SignSet, Four, Zero); + + // If the sign bit of the integer is set, the large number will be treated + // as a negative number. To counteract this, the dynamic code adds an + // offset depending on the data type. + uint64_t FF; + switch (Op0.getValueType()) { + default: assert(0 && "Unsupported integer type!"); + case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float) + case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float) + case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float) + case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float) + } + if (TLI.isLittleEndian()) FF <<= 32; + static Constant *FudgeFactor = ConstantUInt::get(Type::ULongTy, FF); + + SDOperand CPIdx = DAG.getConstantPool(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)); + } + + return DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg); +} + +/// PromoteLegalINT_TO_FP - This function is responsible for legalizing a +/// *INT_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::PromoteLegalINT_TO_FP(SDOperand LegalOp, + MVT::ValueType DestVT, + bool isSigned) { + // 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.isTypeLegal(NewInTy)) + break; // Can't use this datatype. + // FALL THROUGH. + case TargetLowering::Custom: + OpToUse = ISD::SINT_TO_FP; + break; + } + if (OpToUse) break; + if (isSigned) continue; + + // 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.isTypeLegal(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. + } + + // 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(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, + NewInTy, LegalOp)); } +/// PromoteLegalFP_TO_INT - This function is responsible for legalizing a +/// FP_TO_*INT 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 FP_TO_UINT or FP_TO_SINT +/// operation that returns a larger result. +SDOperand SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDOperand LegalOp, + MVT::ValueType DestVT, + bool isSigned) { + // First step, figure out the appropriate FP_TO*INT operation to use. + MVT::ValueType NewOutTy = DestVT; -/// ExpandIntToFP - Expand a [US]INT_TO_FP operation, assuming that the -/// destination type is legal. -SDOperand SelectionDAGLegalize:: -ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) { - assert(isTypeLegal(DestTy) && "Destination type is not legal!"); - assert(getTypeAction(Source.getValueType()) == Expand && - "This is not an expansion!"); - assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!"); - - if (!isSigned) { - assert(Source.getValueType() == MVT::i64 && - "This only works for 64-bit -> FP"); - // The 64-bit value loaded will be incorrectly if the 'sign bit' of the - // incoming integer is set. To handle this, we dynamically test to see if - // it is set, and, if so, add a fudge factor. - SDOperand Lo, Hi; - ExpandOp(Source, Lo, Hi); + unsigned OpToUse = 0; - // If this is unsigned, and not supported, first perform the conversion to - // signed, then adjust the result if the sign bit is set. - SDOperand SignedConv = ExpandIntToFP(true, DestTy, - DAG.getNode(ISD::BUILD_PAIR, Source.getValueType(), Lo, Hi)); + // Scan for the appropriate larger type to use. + while (1) { + NewOutTy = (MVT::ValueType)(NewOutTy+1); + assert(MVT::isInteger(NewOutTy) && "Ran out of possibilities!"); - SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Hi, - DAG.getConstant(0, Hi.getValueType()), - ISD::SETLT); - 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); + // If the target supports FP_TO_SINT returning this type, use it. + switch (TLI.getOperationAction(ISD::FP_TO_SINT, NewOutTy)) { + default: break; + case TargetLowering::Legal: + if (!TLI.isTypeLegal(NewOutTy)) + break; // Can't use this datatype. + // FALL THROUGH. + case TargetLowering::Custom: + OpToUse = ISD::FP_TO_SINT; + break; + } + if (OpToUse) break; - SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); - CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); - SDOperand FudgeInReg; - if (DestTy == MVT::f32) - FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, - DAG.getSrcValue(NULL)); - else { - assert(DestTy == MVT::f64 && "Unexpected conversion"); - FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(), - CPIdx, DAG.getSrcValue(NULL), MVT::f32); + // If the target supports FP_TO_UINT of this type, use it. + switch (TLI.getOperationAction(ISD::FP_TO_UINT, NewOutTy)) { + default: break; + case TargetLowering::Legal: + if (!TLI.isTypeLegal(NewOutTy)) + break; // Can't use this datatype. + // FALL THROUGH. + case TargetLowering::Custom: + OpToUse = ISD::FP_TO_UINT; + break; } - return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg); - } + if (OpToUse) break; - // Check to see if the target has a custom way to lower this. If so, use it. - switch (TLI.getOperationAction(ISD::SINT_TO_FP, Source.getValueType())) { - 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: { - SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy, - Source), DAG); - if (NV.Val) - return LegalizeOp(NV); - break; // The target decided this was legal after all - } + // Otherwise, try a larger type. } - // Expand the source, then glue it back together for the call. We must expand - // the source in case it is shared (this pass of legalize must traverse it). - SDOperand SrcLo, SrcHi; - ExpandOp(Source, SrcLo, SrcHi); - Source = DAG.getNode(ISD::BUILD_PAIR, Source.getValueType(), SrcLo, SrcHi); + // Okay, we found the operation and type to use. Truncate the result of the + // extended FP_TO_*INT operation to the desired size. + return DAG.getNode(ISD::TRUNCATE, DestVT, + DAG.getNode(OpToUse, NewOutTy, LegalOp)); +} - SDNode *OutChain = 0; - SDOperand InChain = FindInputOutputChains(Source.Val, OutChain, - DAG.getEntryNode()); - const char *FnName = 0; - if (DestTy == MVT::f32) - FnName = "__floatdisf"; - else { - assert(DestTy == MVT::f64 && "Unknown fp value type!"); - FnName = "__floatdidf"; +/// ExpandBSWAP - Open code the operations for BSWAP of the specified operation. +/// +SDOperand SelectionDAGLegalize::ExpandBSWAP(SDOperand Op) { + MVT::ValueType VT = Op.getValueType(); + MVT::ValueType SHVT = TLI.getShiftAmountTy(); + SDOperand Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8; + switch (VT) { + default: assert(0 && "Unhandled Expand type in BSWAP!"); abort(); + case MVT::i16: + Tmp2 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT)); + return DAG.getNode(ISD::OR, VT, Tmp1, Tmp2); + case MVT::i32: + Tmp4 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(24, SHVT)); + Tmp3 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT)); + Tmp2 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(24, SHVT)); + Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(0xFF0000, VT)); + Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(0xFF00, VT)); + Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3); + Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1); + return DAG.getNode(ISD::OR, VT, Tmp4, Tmp2); + case MVT::i64: + Tmp8 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(56, SHVT)); + Tmp7 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(40, SHVT)); + Tmp6 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(24, SHVT)); + Tmp5 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT)); + Tmp4 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT)); + Tmp3 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(24, SHVT)); + Tmp2 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(40, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(56, SHVT)); + Tmp7 = DAG.getNode(ISD::AND, VT, Tmp7, DAG.getConstant(255ULL<<48, VT)); + Tmp6 = DAG.getNode(ISD::AND, VT, Tmp6, DAG.getConstant(255ULL<<40, VT)); + Tmp5 = DAG.getNode(ISD::AND, VT, Tmp5, DAG.getConstant(255ULL<<32, VT)); + Tmp4 = DAG.getNode(ISD::AND, VT, Tmp4, DAG.getConstant(255ULL<<24, VT)); + Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(255ULL<<16, VT)); + Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(255ULL<<8 , VT)); + Tmp8 = DAG.getNode(ISD::OR, VT, Tmp8, Tmp7); + Tmp6 = DAG.getNode(ISD::OR, VT, Tmp6, Tmp5); + Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3); + Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1); + Tmp8 = DAG.getNode(ISD::OR, VT, Tmp8, Tmp6); + Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp2); + return DAG.getNode(ISD::OR, VT, Tmp8, Tmp4); } - - SDOperand Callee = DAG.getExternalSymbol(FnName, TLI.getPointerTy()); - - TargetLowering::ArgListTy Args; - const Type *ArgTy = MVT::getTypeForValueType(Source.getValueType()); - - Args.push_back(std::make_pair(Source, ArgTy)); - - // We don't care about token chains for libcalls. We just use the entry - // node as our input and ignore the output chain. This allows us to place - // calls wherever we need them to satisfy data dependences. - const Type *RetTy = MVT::getTypeForValueType(DestTy); - - std::pair CallResult = - TLI.LowerCallTo(InChain, RetTy, false, CallingConv::C, true, - Callee, Args, DAG); - - SpliceCallInto(CallResult.second, OutChain); - return CallResult.first; } +/// ExpandBitCount - Expand the specified bitcount instruction into operations. +/// +SDOperand SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDOperand Op) { + switch (Opc) { + default: assert(0 && "Cannot expand this yet!"); + case ISD::CTPOP: { + static const uint64_t mask[6] = { + 0x5555555555555555ULL, 0x3333333333333333ULL, + 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL, + 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL + }; + MVT::ValueType VT = Op.getValueType(); + MVT::ValueType ShVT = TLI.getShiftAmountTy(); + unsigned len = getSizeInBits(VT); + for (unsigned i = 0; (1U << i) <= (len / 2); ++i) { + //x = (x & mask[i][len/8]) + (x >> (1 << i) & mask[i][len/8]) + SDOperand Tmp2 = DAG.getConstant(mask[i], VT); + SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT); + Op = DAG.getNode(ISD::ADD, VT, DAG.getNode(ISD::AND, VT, Op, Tmp2), + DAG.getNode(ISD::AND, VT, + DAG.getNode(ISD::SRL, VT, Op, Tmp3),Tmp2)); + } + return Op; + } + case ISD::CTLZ: { + // for now, we do this: + // x = x | (x >> 1); + // x = x | (x >> 2); + // ... + // x = x | (x >>16); + // x = x | (x >>32); // for 64-bit input + // return popcount(~x); + // + // but see also: http://www.hackersdelight.org/HDcode/nlz.cc + MVT::ValueType VT = Op.getValueType(); + MVT::ValueType ShVT = TLI.getShiftAmountTy(); + unsigned len = getSizeInBits(VT); + for (unsigned i = 0; (1U << i) <= (len / 2); ++i) { + SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT); + Op = DAG.getNode(ISD::OR, VT, Op, DAG.getNode(ISD::SRL, VT, Op, Tmp3)); + } + Op = DAG.getNode(ISD::XOR, VT, Op, DAG.getConstant(~0ULL, VT)); + return DAG.getNode(ISD::CTPOP, VT, Op); + } + case ISD::CTTZ: { + // for now, we use: { return popcount(~x & (x - 1)); } + // unless the target has ctlz but not ctpop, in which case we use: + // { return 32 - nlz(~x & (x-1)); } + // see also http://www.hackersdelight.org/HDcode/ntz.cc + MVT::ValueType VT = Op.getValueType(); + SDOperand Tmp2 = DAG.getConstant(~0ULL, VT); + SDOperand Tmp3 = DAG.getNode(ISD::AND, VT, + DAG.getNode(ISD::XOR, VT, Op, Tmp2), + DAG.getNode(ISD::SUB, VT, Op, DAG.getConstant(1, VT))); + // If ISD::CTLZ is legal and CTPOP isn't, then do that instead. + if (!TLI.isOperationLegal(ISD::CTPOP, VT) && + TLI.isOperationLegal(ISD::CTLZ, VT)) + return DAG.getNode(ISD::SUB, VT, + DAG.getConstant(getSizeInBits(VT), VT), + DAG.getNode(ISD::CTLZ, VT, Tmp3)); + return DAG.getNode(ISD::CTPOP, VT, Tmp3); + } + } +} /// ExpandOp - Expand the specified SDOperand into its two component pieces -- 2.34.1