//===----------------------------------------------------------------------===//
#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::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::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);
+
+ 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::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break;
+ 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);
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);
}
/// 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()) {