//===----------------------------------------------------------------------===//
#include "LegalizeTypes.h"
-#include "llvm/Constants.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
DEBUG(cerr << "Promote integer result: "; N->dump(&DAG); cerr << "\n");
SDOperand Result = SDOperand();
+ // See if the target wants to custom expand this node.
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
+ TargetLowering::Custom) {
+ // If the target wants to, allow it to lower this itself.
+ if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
+ // Everything that once used N now uses P. We are guaranteed that the
+ // result value types of N and the result value types of P match.
+ ReplaceNodeWith(N, P);
+ return;
+ }
+ }
+
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
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;
case ISD::EXTRACT_VECTOR_ELT:
Result = PromoteIntRes_EXTRACT_VECTOR_ELT(N);
break;
+
+ case ISD::VAARG : Result = PromoteIntRes_VAARG(N); break;
}
// If Result is null, the sub-method took care of registering the result.
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 DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
}
+SDOperand DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) {
+ SDOperand Chain = N->getOperand(0); // Get the chain.
+ SDOperand Ptr = N->getOperand(1); // Get the pointer.
+ MVT VT = N->getValueType(0);
+
+ const Value *V = cast<SrcValueSDNode>(N->getOperand(2))->getValue();
+ SDOperand VAList = DAG.getLoad(TLI.getPointerTy(), Chain, Ptr, V, 0);
+
+ // Increment the arg pointer, VAList, to the next vaarg
+ // FIXME: should the ABI size be used for the increment? Think of
+ // x86 long double (10 bytes long, but aligned on 4 or 8 bytes) or
+ // integers of unusual size (such MVT::i1, which gives an increment
+ // of zero here!).
+ unsigned Increment = VT.getSizeInBits() / 8;
+ SDOperand Tmp = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList,
+ DAG.getConstant(Increment, TLI.getPointerTy()));
+
+ // Store the incremented VAList to the pointer.
+ Tmp = DAG.getStore(VAList.getValue(1), Tmp, Ptr, V, 0);
+
+ // Load the actual argument out of the arg pointer VAList.
+ Tmp = DAG.getExtLoad(ISD::EXTLOAD, TLI.getTypeToTransformTo(VT), Tmp,
+ VAList, NULL, 0, VT);
+
+ // Legalized the chain result - switch anything that used the old chain to
+ // use the new one.
+ ReplaceValueWith(SDOperand(N, 1), Tmp.getValue(1));
+ return Tmp;
+}
+
+
//===----------------------------------------------------------------------===//
// Integer Operand Promotion
//===----------------------------------------------------------------------===//
/// node may need promotion or expansion as well as the specified one.
bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "Promote integer operand: "; N->dump(&DAG); cerr << "\n");
- SDOperand Res;
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to promote this operator's operand!");
- abort();
+ SDOperand Res = SDOperand();
- case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break;
- case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
- case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
- case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break;
- case ISD::FP_EXTEND: Res = PromoteIntOp_FP_EXTEND(N); break;
- case ISD::FP_ROUND: Res = PromoteIntOp_FP_ROUND(N); break;
- case ISD::SINT_TO_FP:
- case ISD::UINT_TO_FP: Res = PromoteIntOp_INT_TO_FP(N); break;
- case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break;
-
- case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break;
- case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break;
- case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break;
- case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break;
-
- case ISD::STORE: Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
- OpNo); break;
-
- case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
- case ISD::INSERT_VECTOR_ELT:
- Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);
- break;
+ if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
+ == TargetLowering::Custom)
+ Res = TLI.LowerOperation(SDOperand(N, OpNo), DAG);
- case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break;
+ if (Res.Val == 0) {
+ switch (N->getOpcode()) {
+ default:
+ #ifndef NDEBUG
+ cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+ #endif
+ assert(0 && "Do not know how to promote this operator's operand!");
+ abort();
+
+ case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break;
+ case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
+ case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
+ case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break;
+ case ISD::FP_EXTEND: Res = PromoteIntOp_FP_EXTEND(N); break;
+ case ISD::FP_ROUND: Res = PromoteIntOp_FP_ROUND(N); break;
+ case ISD::SINT_TO_FP:
+ case ISD::UINT_TO_FP: Res = PromoteIntOp_INT_TO_FP(N); break;
+ case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break;
+
+ case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break;
+ case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break;
+ case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break;
+ case ISD::SELECT_CC: Res = PromoteIntOp_SELECT_CC(N, OpNo); break;
+ case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break;
+
+ case ISD::STORE: Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
+ OpNo); break;
+
+ case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
+ case ISD::INSERT_VECTOR_ELT:
+ Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);
+ break;
+
+ case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break;
+ }
}
// If the result is null, the sub-method took care of registering results etc.
}
SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) {
- assert(OpNo == 2 && "Don't know how to promote this operand");
+ assert(OpNo == 2 && "Don't know how to promote this operand!");
SDOperand LHS = N->getOperand(2);
SDOperand RHS = N->getOperand(3);
N->getOperand(1), LHS, RHS, N->getOperand(4));
}
+SDOperand DAGTypeLegalizer::PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo) {
+ assert(OpNo == 0 && "Don't know how to promote this operand!");
+
+ SDOperand LHS = N->getOperand(0);
+ SDOperand RHS = N->getOperand(1);
+ PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(4))->get());
+
+ // The CC (#4) and the possible return values (#2 and #3) have legal types.
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2),
+ N->getOperand(3), N->getOperand(4));
+}
+
SDOperand DAGTypeLegalizer::PromoteIntOp_SETCC(SDNode *N, unsigned OpNo) {
- assert(OpNo == 0 && "Don't know how to promote this operand");
+ assert(OpNo == 0 && "Don't know how to promote this operand!");
SDOperand LHS = N->getOperand(0);
SDOperand RHS = N->getOperand(1);
NewLHS = GetPromotedInteger(NewLHS);
NewRHS = GetPromotedInteger(NewRHS);
- // If this is an FP compare, the operands have already been extended.
- if (!NewLHS.getValueType().isInteger())
- return;
-
// Otherwise, we have to insert explicit sign or zero extends. Note
// that we could insert sign extends for ALL conditions, but zero extend
// is cheaper on many machines (an AND instead of two shifts), so prefer
// usually a simpler/cheaper operation, so prefer it.
NewLHS = DAG.getZeroExtendInReg(NewLHS, VT);
NewRHS = DAG.getZeroExtendInReg(NewRHS, VT);
- return;
+ break;
case ISD::SETGE:
case ISD::SETGT:
case ISD::SETLT:
DAG.getValueType(VT));
NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS,
DAG.getValueType(VT));
- return;
+ break;
}
}
Lo = Hi = SDOperand();
// See if the target wants to custom expand this node.
- if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
- TargetLowering::Custom) {
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
+ TargetLowering::Custom) {
// If the target wants to, allow it to lower this itself.
- if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
+ if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
// Everything that once used N now uses P. We are guaranteed that the
// result value types of N and the result value types of P match.
ReplaceNodeWith(N, P);
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();
GetExpandedInteger(N->getOperand(0), LL, LH);
GetExpandedInteger(N->getOperand(1), RL, RH);
unsigned OuterBitSize = VT.getSizeInBits();
- unsigned BitSize = NVT.getSizeInBits();
+ unsigned InnerBitSize = NVT.getSizeInBits();
unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
- if (DAG.MaskedValueIsZero(N->getOperand(0),
- APInt::getHighBitsSet(OuterBitSize, LHSSB)) &&
- DAG.MaskedValueIsZero(N->getOperand(1),
- APInt::getHighBitsSet(OuterBitSize, RHSSB))) {
+ APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize);
+ if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) &&
+ DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) {
// The inputs are both zero-extended.
if (HasUMUL_LOHI) {
// We can emit a umul_lohi.
return;
}
}
- if (LHSSB > BitSize && RHSSB > BitSize) {
+ if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) {
// The input values are both sign-extended.
if (HasSMUL_LOHI) {
// We can emit a smul_lohi.
Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
return;
}
+ if (HasMULHU) {
+ Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+ Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
+ RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
+ LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
+ Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
+ Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
+ return;
+ }
}
// If nothing else, we can make a libcall.
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (VT == MVT::i32)
+ LC = RTLIB::MUL_I32;
+ else if (VT == MVT::i64)
+ LC = RTLIB::MUL_I64;
+ 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(RTLIB::MUL_I64, VT, Ops, 2, true/*sign irrelevant*/),
- Lo, Hi);
+ 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,
/// node may need promotion or expansion as well as the specified one.
bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "Expand integer operand: "; N->dump(&DAG); cerr << "\n");
- SDOperand Res(0, 0);
+ SDOperand Res = SDOperand();
if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
== TargetLowering::Custom)
- Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+ Res = TLI.LowerOperation(SDOperand(N, OpNo), DAG);
if (Res.Val == 0) {
switch (N->getOpcode()) {
Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0));
break;
- case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break;
- case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break;
+ case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break;
+ case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
+ case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break;
case ISD::STORE:
Res = ExpandIntOp_STORE(cast<StoreSDNode>(N), OpNo);
}
SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source,
- MVT DestTy) {
+ 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.
+ // This can trigger when called from ExpandIntOp_UINT_TO_FP.
switch (TLI.getOperationAction(ISD::SINT_TO_FP, SourceVT)) {
default: assert(0 && "This action not implemented for this operation!");
case TargetLowering::Legal:
}
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (SourceVT == MVT::i64) {
+ if (SourceVT == MVT::i32) {
+ if (DestTy == MVT::f32)
+ LC = RTLIB::SINTTOFP_I32_F32;
+ else if (DestTy == MVT::f64)
+ LC = RTLIB::SINTTOFP_I32_F64;
+ else if (DestTy == MVT::f80)
+ LC = RTLIB::SINTTOFP_I32_F80;
+ else if (DestTy == MVT::ppcf128)
+ LC = RTLIB::SINTTOFP_I32_PPCF128;
+ } else if (SourceVT == MVT::i64) {
if (DestTy == MVT::f32)
LC = RTLIB::SINTTOFP_I64_F32;
- else {
- assert(DestTy == MVT::f64 && "Unknown fp value type!");
+ else if (DestTy == MVT::f64)
LC = RTLIB::SINTTOFP_I64_F64;
- }
+ else if (DestTy == MVT::f80)
+ LC = RTLIB::SINTTOFP_I64_F80;
+ else if (DestTy == MVT::ppcf128)
+ LC = RTLIB::SINTTOFP_I64_PPCF128;
} else if (SourceVT == MVT::i128) {
if (DestTy == MVT::f32)
LC = RTLIB::SINTTOFP_I128_F32;
LC = RTLIB::SINTTOFP_I128_F64;
else if (DestTy == MVT::f80)
LC = RTLIB::SINTTOFP_I128_F80;
- else {
- assert(DestTy == MVT::ppcf128 && "Unknown fp value type!");
+ else if (DestTy == 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_BR_CC(SDNode *N) {
SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
- ExpandSetCCOperands(NewLHS, NewRHS, CCCode);
+ IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode);
// If ExpandSetCCOperands returned a scalar, we need to compare the result
// against zero to select between true and false values.
N->getOperand(4));
}
+SDOperand DAGTypeLegalizer::ExpandIntOp_SELECT_CC(SDNode *N) {
+ SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
+ ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get();
+ IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode);
+
+ // If ExpandSetCCOperands returned a scalar, we need to compare the result
+ // against zero to select between true and false values.
+ if (NewRHS.Val == 0) {
+ NewRHS = DAG.getConstant(0, NewLHS.getValueType());
+ CCCode = ISD::SETNE;
+ }
+
+ // Update N to have the operands specified.
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS,
+ N->getOperand(2), N->getOperand(3),
+ DAG.getCondCode(CCCode));
+}
+
SDOperand DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) {
SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
- ExpandSetCCOperands(NewLHS, NewRHS, CCCode);
+ IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode);
// If ExpandSetCCOperands returned a scalar, use it.
- if (NewRHS.Val == 0) return NewLHS;
+ if (NewRHS.Val == 0) {
+ assert(NewLHS.getValueType() == N->getValueType(0) &&
+ "Unexpected setcc expansion!");
+ return NewLHS;
+ }
// Otherwise, update N to have the operands specified.
return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS,
DAG.getCondCode(CCCode));
}
-/// ExpandSetCCOperands - Expand the operands of a comparison. This code is
-/// shared among BR_CC, SELECT_CC, and SETCC handlers.
-void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
- ISD::CondCode &CCCode) {
+/// IntegerExpandSetCCOperands - Expand the operands of a comparison. This code
+/// is shared among BR_CC, SELECT_CC, and SETCC handlers.
+void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDOperand &NewLHS,
+ SDOperand &NewRHS,
+ ISD::CondCode &CCCode) {
SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
GetExpandedInteger(NewLHS, LHSLo, LHSHi);
GetExpandedInteger(NewRHS, RHSLo, RHSHi);
MVT VT = NewLHS.getValueType();
- if (VT == MVT::ppcf128) {
- // FIXME: This generated code sucks. We want to generate
- // FCMP crN, hi1, hi2
- // BNE crN, L:
- // FCMP crN, lo1, lo2
- // The following can be improved, but not that much.
- SDOperand Tmp1, Tmp2, Tmp3;
- Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ);
- Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, CCCode);
- Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
- Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETNE);
- Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode);
- Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
- NewLHS = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3);
- NewRHS = SDOperand(); // LHS is the result, not a compare.
- return;
- }
if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) {
- if (RHSLo == RHSHi)
- if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo))
+ if (RHSLo == RHSHi) {
+ if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo)) {
if (RHSCST->isAllOnesValue()) {
// Equality comparison to -1.
NewLHS = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi);
NewRHS = RHSLo;
return;
}
+ }
+ }
NewLHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo);
NewRHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi);