case ISD::SIGN_EXTEND:
case ISD::ZERO_EXTEND:
case ISD::ANY_EXTEND: Result = PromoteIntRes_INT_EXTEND(N); break;
- case ISD::FP_ROUND: Result = PromoteIntRes_FP_ROUND(N); break;
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT: Result = PromoteIntRes_FP_TO_XINT(N); break;
case ISD::SETCC: Result = PromoteIntRes_SETCC(N); break;
return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
}
-SDOperand DAGTypeLegalizer::PromoteIntRes_FP_ROUND(SDNode *N) {
- // NOTE: Assumes input is legal.
- if (N->getConstantOperandVal(1) == 0)
- return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(),
- N->getOperand(0), DAG.getValueType(N->getValueType(0)));
- // If the precision discard isn't needed, just return the operand unrounded.
- return N->getOperand(0);
-}
-
SDOperand DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) {
unsigned NewOpc = N->getOpcode();
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
case ExpandInteger:
case ExpandFloat:
break;
- case Scalarize:
+ case ScalarizeVector:
// Convert the element to an integer and promote it by hand.
return DAG.getNode(ISD::ANY_EXTEND, OutVT,
BitConvertToInteger(GetScalarizedVector(InOp)));
- case Split:
+ case SplitVector:
// For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split
// pieces of the input into integers and reassemble in the final type.
SDOperand Lo, Hi;
// The count is the same in the promoted type except if the original
// value was zero. This can be handled by setting the bit just off
// the top of the original type.
- Op = DAG.getNode(ISD::OR, NVT, Op,
- // FIXME: Do this using an APINT constant.
- DAG.getConstant(1UL << OVT.getSizeInBits(), NVT));
+ APInt TopBit(NVT.getSizeInBits(), 0);
+ TopBit.set(OVT.getSizeInBits());
+ Op = DAG.getNode(ISD::OR, NVT, Op, DAG.getConstant(TopBit, NVT));
return DAG.getNode(ISD::CTTZ, NVT, Op);
}
return Tmp;
}
+
//===----------------------------------------------------------------------===//
// Integer Operand Promotion
//===----------------------------------------------------------------------===//
MVT VT = N->getValueType(0);
SDOperand Op = N->getOperand(0);
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (VT == MVT::i64) {
+
+ if (VT == MVT::i32) {
+ if (Op.getValueType() == MVT::f32)
+ LC = RTLIB::FPTOSINT_F32_I32;
+ else if (Op.getValueType() == MVT::f64)
+ LC = RTLIB::FPTOSINT_F64_I32;
+ else if (Op.getValueType() == MVT::f80)
+ LC = RTLIB::FPTOSINT_F80_I32;
+ else if (Op.getValueType() == MVT::ppcf128)
+ LC = RTLIB::FPTOSINT_PPCF128_I32;
+ } else if (VT == MVT::i64) {
if (Op.getValueType() == MVT::f32)
LC = RTLIB::FPTOSINT_F32_I64;
else if (Op.getValueType() == MVT::f64)
LC = RTLIB::FPTOSINT_F80_I128;
else if (Op.getValueType() == MVT::ppcf128)
LC = RTLIB::FPTOSINT_PPCF128_I128;
- } else {
- assert(0 && "Unexpected fp-to-sint conversion!");
}
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-sint conversion!");
SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi);
}
MVT VT = N->getValueType(0);
SDOperand Op = N->getOperand(0);
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (VT == MVT::i64) {
+ if (VT == MVT::i32) {
+ if (Op.getValueType() == MVT::f32)
+ LC = RTLIB::FPTOUINT_F32_I32;
+ else if (Op.getValueType() == MVT::f64)
+ LC = RTLIB::FPTOUINT_F64_I32;
+ else if (Op.getValueType() == MVT::f80)
+ LC = RTLIB::FPTOUINT_F80_I32;
+ else if (Op.getValueType() == MVT::ppcf128)
+ LC = RTLIB::FPTOUINT_PPCF128_I32;
+ } else if (VT == MVT::i64) {
if (Op.getValueType() == MVT::f32)
LC = RTLIB::FPTOUINT_F32_I64;
else if (Op.getValueType() == MVT::f64)
LC = RTLIB::FPTOUINT_F80_I128;
else if (Op.getValueType() == MVT::ppcf128)
LC = RTLIB::FPTOUINT_PPCF128_I128;
- } else {
- assert(0 && "Unexpected fp-to-uint conversion!");
}
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-uint conversion!");
SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi);
}
MVT VT = N->getValueType(0);
MVT NVT = TLI.getTypeToTransformTo(VT);
- SDOperand Ch = N->getChain(); // Legalize the chain.
- SDOperand Ptr = N->getBasePtr(); // Legalize the pointer.
+ SDOperand Ch = N->getChain();
+ SDOperand Ptr = N->getBasePtr();
ISD::LoadExtType ExtType = N->getExtensionType();
int SVOffset = N->getSrcValueOffset();
unsigned Alignment = N->getAlignment();
}
// If nothing else, we can make a libcall.
- RTLIB::Libcall LC;
- switch (VT.getSimpleVT()) {
- default:
- assert(false && "Unsupported MUL!");
- case MVT::i64:
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (VT == MVT::i32)
+ LC = RTLIB::MUL_I32;
+ else if (VT == MVT::i64)
LC = RTLIB::MUL_I64;
- break;
- }
+ else if (VT == MVT::i128)
+ LC = RTLIB::MUL_I128;
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported MUL!");
SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
SplitInteger(MakeLibCall(LC, VT, Ops, 2, true/*sign irrelevant*/), Lo, Hi);
void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
- assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!");
+ MVT VT = N->getValueType(0);
+
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (VT == MVT::i32)
+ LC = RTLIB::SDIV_I32;
+ else if (VT == MVT::i64)
+ LC = RTLIB::SDIV_I64;
+ else if (VT == MVT::i128)
+ LC = RTLIB::SDIV_I128;
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!");
+
SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::SDIV_I64, N->getValueType(0), Ops, 2, true),
- Lo, Hi);
+ SplitInteger(MakeLibCall(LC, VT, Ops, 2, true), Lo, Hi);
}
void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
- assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!");
+ MVT VT = N->getValueType(0);
+
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (VT == MVT::i32)
+ LC = RTLIB::SREM_I32;
+ else if (VT == MVT::i64)
+ LC = RTLIB::SREM_I64;
+ else if (VT == MVT::i128)
+ LC = RTLIB::SREM_I128;
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!");
+
SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::SREM_I64, N->getValueType(0), Ops, 2, true),
- Lo, Hi);
+ SplitInteger(MakeLibCall(LC, VT, Ops, 2, true), Lo, Hi);
}
void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
- assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!");
+ MVT VT = N->getValueType(0);
+
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (VT == MVT::i32)
+ LC = RTLIB::UDIV_I32;
+ else if (VT == MVT::i64)
+ LC = RTLIB::UDIV_I64;
+ else if (VT == MVT::i128)
+ LC = RTLIB::UDIV_I128;
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UDIV!");
+
SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::UDIV_I64, N->getValueType(0), Ops, 2, false),
- Lo, Hi);
+ SplitInteger(MakeLibCall(LC, VT, Ops, 2, false), Lo, Hi);
}
void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
- assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!");
+ MVT VT = N->getValueType(0);
+
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (VT == MVT::i32)
+ LC = RTLIB::UREM_I32;
+ else if (VT == MVT::i64)
+ LC = RTLIB::UREM_I64;
+ else if (VT == MVT::i128)
+ LC = RTLIB::UREM_I128;
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UREM!");
+
SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::UREM_I64, N->getValueType(0), Ops, 2, false),
- Lo, Hi);
+ SplitInteger(MakeLibCall(LC, VT, Ops, 2, false), Lo, Hi);
}
void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N,
}
// Otherwise, emit a libcall.
- assert(VT == MVT::i64 && "Unsupported shift!");
-
- RTLIB::Libcall LC;
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
bool isSigned;
if (N->getOpcode() == ISD::SHL) {
- LC = RTLIB::SHL_I64;
isSigned = false; /*sign irrelevant*/
+ if (VT == MVT::i32)
+ LC = RTLIB::SHL_I32;
+ else if (VT == MVT::i64)
+ LC = RTLIB::SHL_I64;
+ else if (VT == MVT::i128)
+ LC = RTLIB::SHL_I128;
} else if (N->getOpcode() == ISD::SRL) {
- LC = RTLIB::SRL_I64;
isSigned = false;
+ if (VT == MVT::i32)
+ LC = RTLIB::SRL_I32;
+ else if (VT == MVT::i64)
+ LC = RTLIB::SRL_I64;
+ else if (VT == MVT::i128)
+ LC = RTLIB::SRL_I128;
} else {
assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
- LC = RTLIB::SRA_I64;
isSigned = true;
+ if (VT == MVT::i32)
+ LC = RTLIB::SRA_I32;
+ else if (VT == MVT::i64)
+ LC = RTLIB::SRA_I64;
+ else if (VT == MVT::i128)
+ LC = RTLIB::SRA_I128;
}
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported shift!");
SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned), Lo, Hi);
} else if (Amt == NVTBits) {
Lo = DAG.getConstant(0, NVT);
Hi = InL;
+ } else if (Amt == 1) {
+ // Emit this X << 1 as X+X.
+ SDVTList VTList = DAG.getVTList(NVT, MVT::Flag);
+ SDOperand LoOps[2] = { InL, InL };
+ Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+ SDOperand HiOps[3] = { InH, InH, Lo.getValue(1) };
+ Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
} else {
Lo = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt, ShTy));
Hi = DAG.getNode(ISD::OR, NVT,
case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break;
- case ISD::SINT_TO_FP:
- Res = ExpandIntOp_SINT_TO_FP(N->getOperand(0), N->getValueType(0));
- break;
- case ISD::UINT_TO_FP:
- Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0));
- break;
+ case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break;
+ case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N); break;
case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break;
case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL);
}
-SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source,
- MVT DestTy) {
- // We know the destination is legal, but that the input needs to be expanded.
- MVT SourceVT = Source.getValueType();
-
- // Check to see if the target has a custom way to lower this. If so, use it.
- switch (TLI.getOperationAction(ISD::SINT_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:
- SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy,
- Source), DAG);
- if (NV.Val) return NV;
- break; // The target lowered this.
- }
+SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDNode *N) {
+ SDOperand Op = N->getOperand(0);
+ MVT SrcVT = Op.getValueType();
+ MVT DstVT = N->getValueType(0);
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (SourceVT == MVT::i64) {
- if (DestTy == MVT::f32)
+ if (SrcVT == MVT::i32) {
+ if (DstVT == MVT::f32)
+ LC = RTLIB::SINTTOFP_I32_F32;
+ else if (DstVT == MVT::f64)
+ LC = RTLIB::SINTTOFP_I32_F64;
+ else if (DstVT == MVT::f80)
+ LC = RTLIB::SINTTOFP_I32_F80;
+ else if (DstVT == MVT::ppcf128)
+ LC = RTLIB::SINTTOFP_I32_PPCF128;
+ } else if (SrcVT == MVT::i64) {
+ if (DstVT == MVT::f32)
LC = RTLIB::SINTTOFP_I64_F32;
- else {
- assert(DestTy == MVT::f64 && "Unknown fp value type!");
+ else if (DstVT == MVT::f64)
LC = RTLIB::SINTTOFP_I64_F64;
- }
- } else if (SourceVT == MVT::i128) {
- if (DestTy == MVT::f32)
+ else if (DstVT == MVT::f80)
+ LC = RTLIB::SINTTOFP_I64_F80;
+ else if (DstVT == MVT::ppcf128)
+ LC = RTLIB::SINTTOFP_I64_PPCF128;
+ } else if (SrcVT == MVT::i128) {
+ if (DstVT == MVT::f32)
LC = RTLIB::SINTTOFP_I128_F32;
- else if (DestTy == MVT::f64)
+ else if (DstVT == MVT::f64)
LC = RTLIB::SINTTOFP_I128_F64;
- else if (DestTy == MVT::f80)
+ else if (DstVT == MVT::f80)
LC = RTLIB::SINTTOFP_I128_F80;
- else {
- assert(DestTy == MVT::ppcf128 && "Unknown fp value type!");
+ else if (DstVT == MVT::ppcf128)
LC = RTLIB::SINTTOFP_I128_PPCF128;
- }
- } else {
- assert(0 && "Unknown int value type!");
}
-
assert(LC != RTLIB::UNKNOWN_LIBCALL &&
"Don't know how to expand this SINT_TO_FP!");
- return MakeLibCall(LC, DestTy, &Source, 1, true);
-}
-SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDOperand Source,
- MVT DestTy) {
- // We know the destination is legal, but that the input needs to be expanded.
- assert(getTypeAction(Source.getValueType()) == ExpandInteger &&
- "This is not an expansion!");
+ return MakeLibCall(LC, DstVT, &Op, 1, true);
+}
- // 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 = ExpandIntOp_SINT_TO_FP(Source, DestTy);
+SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) {
+ SDOperand Op = N->getOperand(0);
+ MVT SrcVT = Op.getValueType();
+ MVT DstVT = N->getValueType(0);
+
+ if (TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) == TargetLowering::Custom){
+ // Do a signed conversion then adjust the result.
+ SDOperand SignedConv = DAG.getNode(ISD::SINT_TO_FP, DstVT, Op);
+ SignedConv = TLI.LowerOperation(SignedConv, DAG);
+
+ // The result of the signed conversion needs adjusting if the 'sign bit' of
+ // the incoming integer was set. To handle this, we dynamically test to see
+ // if it is set, and, if so, add a fudge factor.
+
+ const uint64_t F32TwoE32 = 0x4F800000ULL;
+ const uint64_t F32TwoE64 = 0x5F800000ULL;
+ const uint64_t F32TwoE128 = 0x7F800000ULL;
+
+ APInt FF(32, 0);
+ if (SrcVT == MVT::i32)
+ FF = APInt(32, F32TwoE32);
+ else if (SrcVT == MVT::i64)
+ FF = APInt(32, F32TwoE64);
+ else if (SrcVT == MVT::i128)
+ FF = APInt(32, F32TwoE128);
+ else
+ assert(false && "Unsupported UINT_TO_FP!");
+
+ // Check whether the sign bit is set.
+ SDOperand Lo, Hi;
+ GetExpandedInteger(Op, Lo, Hi);
+ SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi,
+ DAG.getConstant(0, Hi.getValueType()),
+ ISD::SETLT);
+
+ // Build a 64 bit pair (0, FF) in the constant pool, with FF in the lo bits.
+ SDOperand FudgePtr = DAG.getConstantPool(ConstantInt::get(FF.zext(64)),
+ TLI.getPointerTy());
+
+ // Get a pointer to FF if the sign bit was set, or to 0 otherwise.
+ SDOperand Zero = DAG.getIntPtrConstant(0);
+ SDOperand Four = DAG.getIntPtrConstant(4);
+ if (TLI.isBigEndian()) std::swap(Zero, Four);
+ SDOperand Offset = DAG.getNode(ISD::SELECT, Zero.getValueType(), SignSet,
+ Zero, Four);
+ FudgePtr = DAG.getNode(ISD::ADD, TLI.getPointerTy(), FudgePtr, Offset);
+
+ // Load the value out, extending it from f32 to the destination float type.
+ // FIXME: Avoid the extend by constructing the right constant pool?
+ SDOperand Fudge = DAG.getExtLoad(ISD::EXTLOAD, DstVT, DAG.getEntryNode(),
+ FudgePtr, NULL, 0, MVT::f32);
+ return DAG.getNode(ISD::FADD, DstVT, SignedConv, Fudge);
+ }
- // 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;
- GetExpandedInteger(Source, Lo, Hi);
-
- SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi,
- DAG.getConstant(0, Hi.getValueType()),
- ISD::SETLT);
- SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4);
- SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
- SignSet, Four, Zero);
- uint64_t FF = 0x5f800000ULL;
- if (TLI.isLittleEndian()) FF <<= 32;
- Constant *FudgeFactor = ConstantInt::get((Type*)Type::Int64Ty, 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, NULL, 0);
- else if (DestTy.bitsGT(MVT::f32))
- // FIXME: Avoid the extend by construction the right constantpool?
- FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(),
- CPIdx, NULL, 0, MVT::f32);
- else
- assert(0 && "Unexpected conversion");
+ // Otherwise, use a libcall.
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (SrcVT == MVT::i32) {
+ if (DstVT == MVT::f32)
+ LC = RTLIB::UINTTOFP_I32_F32;
+ else if (DstVT == MVT::f64)
+ LC = RTLIB::UINTTOFP_I32_F64;
+ else if (DstVT == MVT::f80)
+ LC = RTLIB::UINTTOFP_I32_F80;
+ else if (DstVT == MVT::ppcf128)
+ LC = RTLIB::UINTTOFP_I32_PPCF128;
+ } else if (SrcVT == MVT::i64) {
+ if (DstVT == MVT::f32)
+ LC = RTLIB::UINTTOFP_I64_F32;
+ else if (DstVT == MVT::f64)
+ LC = RTLIB::UINTTOFP_I64_F64;
+ else if (DstVT == MVT::f80)
+ LC = RTLIB::UINTTOFP_I64_F80;
+ else if (DstVT == MVT::ppcf128)
+ LC = RTLIB::UINTTOFP_I64_PPCF128;
+ } else if (SrcVT == MVT::i128) {
+ if (DstVT == MVT::f32)
+ LC = RTLIB::UINTTOFP_I128_F32;
+ else if (DstVT == MVT::f64)
+ LC = RTLIB::UINTTOFP_I128_F64;
+ else if (DstVT == MVT::f80)
+ LC = RTLIB::UINTTOFP_I128_F80;
+ else if (DstVT == MVT::ppcf128)
+ LC = RTLIB::UINTTOFP_I128_PPCF128;
+ }
+ assert(LC != RTLIB::UNKNOWN_LIBCALL &&
+ "Don't know how to expand this UINT_TO_FP!");
- return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
+ return MakeLibCall(LC, DstVT, &Op, 1, true);
}
SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) {