diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index da35aadd13c4..a7f488e0f0b6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/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, @@ -3521,6 +3195,330 @@ ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) { 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; + + 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); + } + } +} /// ExpandOp - Expand the specified SDOperand into its two component pieces