diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp similarity index 65% rename from lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp rename to lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp index c3bde9b129e..d4e5a458763 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -1,4 +1,4 @@ -//===-- LegalizeTypesFloatToInt.cpp - LegalizeTypes float to int support --===// +//===-------- LegalizeFloatTypes.cpp - Legalization of float types --------===// // // The LLVM Compiler Infrastructure // @@ -7,17 +7,23 @@ // //===----------------------------------------------------------------------===// // -// This file implements float to integer conversion for LegalizeTypes. This -// is the act of turning a computation in an invalid floating point type into -// a computation in an integer type of the same size. For example, turning -// f32 arithmetic into operations using i32. Also known as "soft float". -// The result is equivalent to bitcasting the float value to the integer type. +// This file implements float type expansion and conversion of float types to +// integer types on behalf of LegalizeTypes. +// Converting to integer is the act of turning a computation in an illegal +// floating point type into a computation in an integer type of the same size. +// For example, turning f32 arithmetic into operations using i32. Also known as +// "soft float". The result is equivalent to bitcasting the float value to the +// integer type. +// Expansion is the act of changing a computation in an illegal type to be a +// computation in multiple registers of a smaller type. For example, +// implementing ppcf128 arithmetic in two f64 registers. // //===----------------------------------------------------------------------===// -#include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/DerivedTypes.h" #include "LegalizeTypes.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" using namespace llvm; /// GetFPLibCall - Return the right libcall for the given floating point type. @@ -38,8 +44,8 @@ static RTLIB::Libcall GetFPLibCall(MVT VT, // Result Float to Integer Conversion. //===----------------------------------------------------------------------===// -void DAGTypeLegalizer::FloatToIntResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "FloatToInt node result " << ResNo << ": "; N->dump(&DAG); +void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Promote float result " << ResNo << ": "; N->dump(&DAG); cerr << "\n"); SDOperand R = SDOperand(); @@ -61,37 +67,37 @@ void DAGTypeLegalizer::FloatToIntResult(SDNode *N, unsigned ResNo) { switch (N->getOpcode()) { default: #ifndef NDEBUG - cerr << "FloatToIntResult #" << ResNo << ": "; + cerr << "PromoteFloatResult #" << ResNo << ": "; N->dump(&DAG); cerr << "\n"; #endif assert(0 && "Do not know how to convert the result of this operator!"); abort(); - case ISD::BIT_CONVERT: R = FloatToIntRes_BIT_CONVERT(N); break; - case ISD::BUILD_PAIR: R = FloatToIntRes_BUILD_PAIR(N); break; + case ISD::BIT_CONVERT: R = PromoteFloatRes_BIT_CONVERT(N); break; + case ISD::BUILD_PAIR: R = PromoteFloatRes_BUILD_PAIR(N); break; case ISD::ConstantFP: - R = FloatToIntRes_ConstantFP(cast(N)); + R = PromoteFloatRes_ConstantFP(cast(N)); break; - case ISD::FCOPYSIGN: R = FloatToIntRes_FCOPYSIGN(N); break; - case ISD::LOAD: R = FloatToIntRes_LOAD(N); break; + case ISD::FCOPYSIGN: R = PromoteFloatRes_FCOPYSIGN(N); break; + case ISD::LOAD: R = PromoteFloatRes_LOAD(N); break; case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: R = FloatToIntRes_XINT_TO_FP(N); break; + case ISD::UINT_TO_FP: R = PromoteFloatRes_XINT_TO_FP(N); break; - case ISD::FADD: R = FloatToIntRes_FADD(N); break; - case ISD::FMUL: R = FloatToIntRes_FMUL(N); break; - case ISD::FSUB: R = FloatToIntRes_FSUB(N); break; + case ISD::FADD: R = PromoteFloatRes_FADD(N); break; + case ISD::FMUL: R = PromoteFloatRes_FMUL(N); break; + case ISD::FSUB: R = PromoteFloatRes_FSUB(N); break; } // If R is null, the sub-method took care of registering the result. if (R.Val) - SetIntegerOp(SDOperand(N, ResNo), R); + SetPromotedFloat(SDOperand(N, ResNo), R); } -SDOperand DAGTypeLegalizer::FloatToIntRes_BIT_CONVERT(SDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatRes_BIT_CONVERT(SDNode *N) { return BitConvertToInteger(N->getOperand(0)); } -SDOperand DAGTypeLegalizer::FloatToIntRes_BUILD_PAIR(SDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatRes_BUILD_PAIR(SDNode *N) { // Convert the inputs to integers, and build a new pair out of them. return DAG.getNode(ISD::BUILD_PAIR, TLI.getTypeToTransformTo(N->getValueType(0)), @@ -99,15 +105,15 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_BUILD_PAIR(SDNode *N) { BitConvertToInteger(N->getOperand(1))); } -SDOperand DAGTypeLegalizer::FloatToIntRes_ConstantFP(ConstantFPSDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatRes_ConstantFP(ConstantFPSDNode *N) { return DAG.getConstant(N->getValueAPF().convertToAPInt(), TLI.getTypeToTransformTo(N->getValueType(0))); } -SDOperand DAGTypeLegalizer::FloatToIntRes_FADD(SDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatRes_FADD(SDNode *N) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)), - GetIntegerOp(N->getOperand(1)) }; + SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), + GetPromotedFloat(N->getOperand(1)) }; return MakeLibCall(GetFPLibCall(N->getValueType(0), RTLIB::ADD_F32, RTLIB::ADD_F64, @@ -116,8 +122,8 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_FADD(SDNode *N) { NVT, Ops, 2, false/*sign irrelevant*/); } -SDOperand DAGTypeLegalizer::FloatToIntRes_FCOPYSIGN(SDNode *N) { - SDOperand LHS = GetIntegerOp(N->getOperand(0)); +SDOperand DAGTypeLegalizer::PromoteFloatRes_FCOPYSIGN(SDNode *N) { + SDOperand LHS = GetPromotedFloat(N->getOperand(0)); SDOperand RHS = BitConvertToInteger(N->getOperand(1)); MVT LVT = LHS.getValueType(); @@ -155,10 +161,10 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_FCOPYSIGN(SDNode *N) { return DAG.getNode(ISD::OR, LVT, LHS, SignBit); } -SDOperand DAGTypeLegalizer::FloatToIntRes_FMUL(SDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatRes_FMUL(SDNode *N) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)), - GetIntegerOp(N->getOperand(1)) }; + SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), + GetPromotedFloat(N->getOperand(1)) }; return MakeLibCall(GetFPLibCall(N->getValueType(0), RTLIB::MUL_F32, RTLIB::MUL_F64, @@ -167,10 +173,10 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_FMUL(SDNode *N) { NVT, Ops, 2, false/*sign irrelevant*/); } -SDOperand DAGTypeLegalizer::FloatToIntRes_FSUB(SDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatRes_FSUB(SDNode *N) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)), - GetIntegerOp(N->getOperand(1)) }; + SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), + GetPromotedFloat(N->getOperand(1)) }; return MakeLibCall(GetFPLibCall(N->getValueType(0), RTLIB::SUB_F32, RTLIB::SUB_F64, @@ -179,7 +185,7 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_FSUB(SDNode *N) { NVT, Ops, 2, false/*sign irrelevant*/); } -SDOperand DAGTypeLegalizer::FloatToIntRes_LOAD(SDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatRes_LOAD(SDNode *N) { LoadSDNode *L = cast(N); MVT VT = N->getValueType(0); MVT NVT = TLI.getTypeToTransformTo(VT); @@ -200,7 +206,7 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_LOAD(SDNode *N) { return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, VT, NL)); } -SDOperand DAGTypeLegalizer::FloatToIntRes_XINT_TO_FP(SDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) { bool isSigned = N->getOpcode() == ISD::SINT_TO_FP; MVT DestVT = N->getValueType(0); SDOperand Op = N->getOperand(0); @@ -305,8 +311,8 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_XINT_TO_FP(SDNode *N) { // Operand Float to Integer Conversion.. //===----------------------------------------------------------------------===// -bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "FloatToInt node operand " << OpNo << ": "; N->dump(&DAG); +bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Promote float operand " << OpNo << ": "; N->dump(&DAG); cerr << "\n"); SDOperand Res(0, 0); @@ -321,13 +327,13 @@ bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) { switch (N->getOpcode()) { default: #ifndef NDEBUG - cerr << "FloatToIntOperand Op #" << OpNo << ": "; + cerr << "PromoteFloatOperand Op #" << OpNo << ": "; N->dump(&DAG); cerr << "\n"; #endif assert(0 && "Do not know how to convert this operator's operand!"); abort(); - case ISD::BIT_CONVERT: Res = FloatToIntOp_BIT_CONVERT(N); break; + case ISD::BIT_CONVERT: Res = PromoteFloatOp_BIT_CONVERT(N); break; } } @@ -351,7 +357,96 @@ bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) { return false; } -SDOperand DAGTypeLegalizer::FloatToIntOp_BIT_CONVERT(SDNode *N) { +SDOperand DAGTypeLegalizer::PromoteFloatOp_BIT_CONVERT(SDNode *N) { return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), - GetIntegerOp(N->getOperand(0))); + GetPromotedFloat(N->getOperand(0))); +} + + +//===----------------------------------------------------------------------===// +// Float Result Expansion +//===----------------------------------------------------------------------===// + +/// ExpandFloatResult - This method is called when the specified result of the +/// specified node is found to need expansion. At this point, the node may also +/// have invalid operands or may have other results that need promotion, we just +/// know that (at least) one result needs expansion. +void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Expand float result: "; N->dump(&DAG); cerr << "\n"); + SDOperand Lo, Hi; + Lo = Hi = SDOperand(); + + // See if the target wants to custom expand this node. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.ExpandOperationResult(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 + cerr << "ExpandFloatResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to expand the result of this operator!"); + abort(); + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.Val) + SetExpandedFloat(SDOperand(N, ResNo), Lo, Hi); +} + + +//===----------------------------------------------------------------------===// +// Float Operand Expansion +//===----------------------------------------------------------------------===// + +/// ExpandFloatOperand - This method is called when the specified operand of the +/// specified node is found to need expansion. At this point, all of the result +/// types of the node are known to be legal, but other operands of the node may +/// need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Expand float operand: "; N->dump(&DAG); cerr << "\n"); + SDOperand Res(0, 0); + + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) + == TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, 0), DAG); + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + cerr << "ExpandFloatOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; + #endif + assert(0 && "Do not know how to expand this operator's operand!"); + abort(); + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + // If the result is N, the sub-method updated N in place. Check to see if any + // operands are new, and if so, mark them. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of expansion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; } diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp similarity index 57% rename from lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp rename to lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 76bbd81858c..4b927fec082 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1,4 +1,4 @@ -//===-- LegalizeTypesExpand.cpp - Expansion for LegalizeTypes -------------===// +//===----- LegalizeIntegerTypes.cpp - Legalization of integer types -------===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,14 @@ // //===----------------------------------------------------------------------===// // -// This file implements expansion support for LegalizeTypes. Expansion is the -// act of changing a computation in an invalid type to be a computation in -// multiple registers of a smaller type. For example, implementing i64 -// arithmetic in two i32 registers (as is often needed on 32-bit targets, for -// example). +// This file implements integer type expansion and promotion for LegalizeTypes. +// Promotion is the act of changing a computation in an illegal type into a +// computation in a larger type. For example, implementing i8 arithmetic in an +// i32 register (often needed on powerpc). +// Expansion is the act of changing a computation in an illegal type into a +// computation in multiple registers of a smaller type. For example, +// implementing i64 arithmetic in two i32 registers (often needed on 32-bit +// targets). // //===----------------------------------------------------------------------===// @@ -20,20 +23,720 @@ using namespace llvm; //===----------------------------------------------------------------------===// -// Result Expansion +// Integer Result Promotion //===----------------------------------------------------------------------===// -/// ExpandResult - This method is called when the specified result of the +/// PromoteIntegerResult - This method is called when a result of a node is +/// found to be in need of promotion to a larger type. At this point, the node +/// may also have invalid operands or may have other results that need +/// expansion, we just know that (at least) one result needs promotion. +void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Promote integer result: "; N->dump(&DAG); cerr << "\n"); + SDOperand Result = SDOperand(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "PromoteIntegerResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to promote this operator!"); + abort(); + case ISD::UNDEF: Result = PromoteIntRes_UNDEF(N); break; + case ISD::Constant: Result = PromoteIntRes_Constant(N); break; + + case ISD::TRUNCATE: Result = PromoteIntRes_TRUNCATE(N); break; + 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::LOAD: Result = PromoteIntRes_LOAD(cast(N)); break; + case ISD::BUILD_PAIR: Result = PromoteIntRes_BUILD_PAIR(N); break; + case ISD::BIT_CONVERT: Result = PromoteIntRes_BIT_CONVERT(N); break; + + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: Result = PromoteIntRes_SimpleIntBinOp(N); break; + + case ISD::SDIV: + case ISD::SREM: Result = PromoteIntRes_SDIV(N); break; + + case ISD::UDIV: + case ISD::UREM: Result = PromoteIntRes_UDIV(N); break; + + case ISD::SHL: Result = PromoteIntRes_SHL(N); break; + case ISD::SRA: Result = PromoteIntRes_SRA(N); break; + case ISD::SRL: Result = PromoteIntRes_SRL(N); break; + + case ISD::SELECT: Result = PromoteIntRes_SELECT(N); break; + case ISD::SELECT_CC: Result = PromoteIntRes_SELECT_CC(N); break; + + case ISD::CTLZ: Result = PromoteIntRes_CTLZ(N); break; + case ISD::CTPOP: Result = PromoteIntRes_CTPOP(N); break; + case ISD::CTTZ: Result = PromoteIntRes_CTTZ(N); break; + + case ISD::EXTRACT_VECTOR_ELT: + Result = PromoteIntRes_EXTRACT_VECTOR_ELT(N); + break; + } + + // If Result is null, the sub-method took care of registering the result. + if (Result.Val) + SetPromotedInteger(SDOperand(N, ResNo), Result); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_UNDEF(SDNode *N) { + return DAG.getNode(ISD::UNDEF, TLI.getTypeToTransformTo(N->getValueType(0))); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_Constant(SDNode *N) { + MVT VT = N->getValueType(0); + // Zero extend things like i1, sign extend everything else. It shouldn't + // matter in theory which one we pick, but this tends to give better code? + unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + SDOperand Result = DAG.getNode(Opc, TLI.getTypeToTransformTo(VT), + SDOperand(N, 0)); + assert(isa(Result) && "Didn't constant fold ext?"); + return Result; +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_TRUNCATE(SDNode *N) { + SDOperand Res; + + switch (getTypeAction(N->getOperand(0).getValueType())) { + default: assert(0 && "Unknown type action!"); + case Legal: + case ExpandInteger: + Res = N->getOperand(0); + break; + case PromoteInteger: + Res = GetPromotedInteger(N->getOperand(0)); + break; + } + + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + assert(Res.getValueType().getSizeInBits() >= NVT.getSizeInBits() && + "Truncation doesn't make sense!"); + if (Res.getValueType() == NVT) + return Res; + + // Truncate to NVT instead of VT + return DAG.getNode(ISD::TRUNCATE, NVT, Res); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_INT_EXTEND(SDNode *N) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + + if (getTypeAction(N->getOperand(0).getValueType()) == PromoteInteger) { + SDOperand Res = GetPromotedInteger(N->getOperand(0)); + assert(Res.getValueType().getSizeInBits() <= NVT.getSizeInBits() && + "Extension doesn't make sense!"); + + // If the result and operand types are the same after promotion, simplify + // to an in-register extension. + if (NVT == Res.getValueType()) { + // The high bits are not guaranteed to be anything. Insert an extend. + if (N->getOpcode() == ISD::SIGN_EXTEND) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, + DAG.getValueType(N->getOperand(0).getValueType())); + if (N->getOpcode() == ISD::ZERO_EXTEND) + return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType()); + assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!"); + return Res; + } + } + + // Otherwise, just extend the original operand all the way to the larger type. + 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)); + + // If we're promoting a UINT to a larger size, check to see if the new node + // will be legal. If it isn't, check to see if FP_TO_SINT is legal, since + // we can use that instead. This allows us to generate better code for + // FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not + // legal, such as PowerPC. + if (N->getOpcode() == ISD::FP_TO_UINT) { + if (!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) && + (TLI.isOperationLegal(ISD::FP_TO_SINT, NVT) || + TLI.getOperationAction(ISD::FP_TO_SINT, NVT)==TargetLowering::Custom)) + NewOpc = ISD::FP_TO_SINT; + } + + return DAG.getNode(NewOpc, NVT, N->getOperand(0)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) { + assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0))) + && "SetCC type is not legal??"); + return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)), + N->getOperand(0), N->getOperand(1), N->getOperand(2)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) { + // FIXME: Add support for indexed loads. + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + ISD::LoadExtType ExtType = + ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType(); + SDOperand Res = DAG.getExtLoad(ExtType, NVT, N->getChain(), N->getBasePtr(), + N->getSrcValue(), N->getSrcValueOffset(), + N->getMemoryVT(), N->isVolatile(), + N->getAlignment()); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDOperand(N, 1), Res.getValue(1)); + return Res; +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_BUILD_PAIR(SDNode *N) { + // The pair element type may be legal, or may not promote to the same type as + // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases. + return DAG.getNode(ISD::ANY_EXTEND, + TLI.getTypeToTransformTo(N->getValueType(0)), + JoinIntegers(N->getOperand(0), N->getOperand(1))); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) { + SDOperand InOp = N->getOperand(0); + MVT InVT = InOp.getValueType(); + MVT NInVT = TLI.getTypeToTransformTo(InVT); + MVT OutVT = TLI.getTypeToTransformTo(N->getValueType(0)); + + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + break; + case Legal: + break; + case PromoteInteger: + if (OutVT.getSizeInBits() == NInVT.getSizeInBits()) + // The input promotes to the same size. Convert the promoted value. + return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedInteger(InOp)); + break; + case PromoteFloat: + // Promote the integer operand by hand. + return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetPromotedFloat(InOp)); + case ExpandInteger: + case ExpandFloat: + break; + case Scalarize: + // Convert the element to an integer and promote it by hand. + return DAG.getNode(ISD::ANY_EXTEND, OutVT, + BitConvertToInteger(GetScalarizedVector(InOp))); + case Split: + // 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; + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + InOp = DAG.getNode(ISD::ANY_EXTEND, + MVT::getIntegerVT(OutVT.getSizeInBits()), + JoinIntegers(Lo, Hi)); + return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp); + } + + // Otherwise, lower the bit-convert to a store/load from the stack, then + // promote the load. + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); + return PromoteIntRes_LOAD(cast(Op.Val)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SimpleIntBinOp(SDNode *N) { + // The input may have strange things in the top bits of the registers, but + // these operations don't care. They may have weird bits going out, but + // that too is okay if they are integer operations. + SDOperand LHS = GetPromotedInteger(N->getOperand(0)); + SDOperand RHS = GetPromotedInteger(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SDIV(SDNode *N) { + // Sign extend the input. + SDOperand LHS = GetPromotedInteger(N->getOperand(0)); + SDOperand RHS = GetPromotedInteger(N->getOperand(1)); + MVT VT = N->getValueType(0); + LHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, LHS.getValueType(), LHS, + DAG.getValueType(VT)); + RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, RHS.getValueType(), RHS, + DAG.getValueType(VT)); + + return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_UDIV(SDNode *N) { + // Zero extend the input. + SDOperand LHS = GetPromotedInteger(N->getOperand(0)); + SDOperand RHS = GetPromotedInteger(N->getOperand(1)); + MVT VT = N->getValueType(0); + LHS = DAG.getZeroExtendInReg(LHS, VT); + RHS = DAG.getZeroExtendInReg(RHS, VT); + + return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SHL(SDNode *N) { + return DAG.getNode(ISD::SHL, TLI.getTypeToTransformTo(N->getValueType(0)), + GetPromotedInteger(N->getOperand(0)), N->getOperand(1)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SRA(SDNode *N) { + // The input value must be properly sign extended. + MVT VT = N->getValueType(0); + MVT NVT = TLI.getTypeToTransformTo(VT); + SDOperand Res = GetPromotedInteger(N->getOperand(0)); + Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, DAG.getValueType(VT)); + return DAG.getNode(ISD::SRA, NVT, Res, N->getOperand(1)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SRL(SDNode *N) { + // The input value must be properly zero extended. + MVT VT = N->getValueType(0); + MVT NVT = TLI.getTypeToTransformTo(VT); + SDOperand Res = ZExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::SRL, NVT, Res, N->getOperand(1)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SELECT(SDNode *N) { + SDOperand LHS = GetPromotedInteger(N->getOperand(1)); + SDOperand RHS = GetPromotedInteger(N->getOperand(2)); + return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0),LHS,RHS); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SELECT_CC(SDNode *N) { + SDOperand LHS = GetPromotedInteger(N->getOperand(2)); + SDOperand RHS = GetPromotedInteger(N->getOperand(3)); + return DAG.getNode(ISD::SELECT_CC, LHS.getValueType(), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_CTLZ(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + MVT OVT = N->getValueType(0); + MVT NVT = Op.getValueType(); + // Zero extend to the promoted type and do the count there. + Op = DAG.getNode(ISD::CTLZ, NVT, DAG.getZeroExtendInReg(Op, OVT)); + // Subtract off the extra leading bits in the bigger type. + return DAG.getNode(ISD::SUB, NVT, Op, + DAG.getConstant(NVT.getSizeInBits() - + OVT.getSizeInBits(), NVT)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_CTPOP(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + MVT OVT = N->getValueType(0); + MVT NVT = Op.getValueType(); + // Zero extend to the promoted type and do the count there. + return DAG.getNode(ISD::CTPOP, NVT, DAG.getZeroExtendInReg(Op, OVT)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + MVT OVT = N->getValueType(0); + MVT NVT = Op.getValueType(); + // 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)); + return DAG.getNode(ISD::CTTZ, NVT, Op); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) { + MVT OldVT = N->getValueType(0); + SDOperand OldVec = N->getOperand(0); + unsigned OldElts = OldVec.getValueType().getVectorNumElements(); + + if (OldElts == 1) { + assert(!isTypeLegal(OldVec.getValueType()) && + "Legal one-element vector of a type needing promotion!"); + // It is tempting to follow GetScalarizedVector by a call to + // GetPromotedInteger, but this would be wrong because the + // scalarized value may not yet have been processed. + return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT), + GetScalarizedVector(OldVec)); + } + + // Convert to a vector half as long with an element type of twice the width, + // for example <4 x i16> -> <2 x i32>. + assert(!(OldElts & 1) && "Odd length vectors not supported!"); + MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); + assert(OldVT.isSimple() && NewVT.isSimple()); + + SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, + MVT::getVectorVT(NewVT, OldElts / 2), + OldVec); + + // Extract the element at OldIdx / 2 from the new vector. + SDOperand OldIdx = N->getOperand(1); + SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx, + DAG.getConstant(1, TLI.getShiftAmountTy())); + SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx); + + // Select the appropriate half of the element: Lo if OldIdx was even, + // Hi if it was odd. + SDOperand Lo = Elt; + SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt, + DAG.getConstant(OldVT.getSizeInBits(), + TLI.getShiftAmountTy())); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx, + DAG.getConstant(1, TLI.getShiftAmountTy())); + return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo); +} + +//===----------------------------------------------------------------------===// +// Integer Operand Promotion +//===----------------------------------------------------------------------===// + +/// PromoteIntegerOperand - This method is called when the specified operand of +/// the specified node is found to need promotion. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// 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(); + + 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(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. + if (!Res.Val) return false; + // If the result is N, the sub-method updated N in place. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of promotion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_ANY_EXTEND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_ZERO_EXTEND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); + return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType()); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_SIGN_EXTEND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, Op.getValueType(), + Op, DAG.getValueType(N->getOperand(0).getValueType())); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_TRUNCATE(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), Op); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_FP_EXTEND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::FP_EXTEND, N->getValueType(0), Op); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_FP_ROUND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Op, + DAG.getIntPtrConstant(0)); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_INT_TO_FP(SDNode *N) { + SDOperand In = GetPromotedInteger(N->getOperand(0)); + MVT OpVT = N->getOperand(0).getValueType(); + if (N->getOpcode() == ISD::UINT_TO_FP) + In = DAG.getZeroExtendInReg(In, OpVT); + else + In = DAG.getNode(ISD::SIGN_EXTEND_INREG, In.getValueType(), + In, DAG.getValueType(OpVT)); + + return DAG.UpdateNodeOperands(SDOperand(N, 0), In); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_BUILD_PAIR(SDNode *N) { + // Since the result type is legal, the operands must promote to it. + MVT OVT = N->getOperand(0).getValueType(); + SDOperand Lo = GetPromotedInteger(N->getOperand(0)); + SDOperand Hi = GetPromotedInteger(N->getOperand(1)); + assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?"); + + Lo = DAG.getZeroExtendInReg(Lo, OVT); + Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi, + DAG.getConstant(OVT.getSizeInBits(), + TLI.getShiftAmountTy())); + return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Only know how to promote condition"); + SDOperand Cond = GetPromotedInteger(N->getOperand(0)); // Promote condition. + + // The top bits of the promoted condition are not necessarily zero, ensure + // that the value is properly zero extended. + unsigned BitWidth = Cond.getValueSizeInBits(); + if (!DAG.MaskedValueIsZero(Cond, + APInt::getHighBitsSet(BitWidth, BitWidth-1))) + Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); + + // The chain (Op#0) and basic block destination (Op#2) are always legal types. + return DAG.UpdateNodeOperands(SDOperand(N, 0), Cond, N->getOperand(1), + N->getOperand(2)); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo) { + assert(OpNo == 1 && "only know how to promote condition"); + SDOperand Cond = GetPromotedInteger(N->getOperand(1)); // Promote condition. + + // The top bits of the promoted condition are not necessarily zero, ensure + // that the value is properly zero extended. + unsigned BitWidth = Cond.getValueSizeInBits(); + if (!DAG.MaskedValueIsZero(Cond, + APInt::getHighBitsSet(BitWidth, BitWidth-1))) + Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); + + // The chain (Op#0) and basic block destination (Op#2) are always legal types. + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), Cond, + N->getOperand(2)); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) { + assert(OpNo == 2 && "Don't know how to promote this operand"); + + SDOperand LHS = N->getOperand(2); + SDOperand RHS = N->getOperand(3); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(1))->get()); + + // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always + // legal types. + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_SETCC(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(N->getOperand(2))->get()); + + // The CC (#2) is always legal. + return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2)); +} + +/// PromoteSetCCOperands - Promote the operands of a comparison. This code is +/// shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS, + ISD::CondCode CCCode) { + MVT VT = NewLHS.getValueType(); + + // Get the promoted values. + 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 + // it. + switch (CCCode) { + default: assert(0 && "Unknown integer comparison!"); + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGE: + case ISD::SETUGT: + case ISD::SETULE: + case ISD::SETULT: + // ALL of these operations will work if we either sign or zero extend + // the operands (including the unsigned comparisons!). Zero extend is + // usually a simpler/cheaper operation, so prefer it. + NewLHS = DAG.getZeroExtendInReg(NewLHS, VT); + NewRHS = DAG.getZeroExtendInReg(NewRHS, VT); + return; + case ISD::SETGE: + case ISD::SETGT: + case ISD::SETLT: + case ISD::SETLE: + NewLHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewLHS.getValueType(), NewLHS, + DAG.getValueType(VT)); + NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS, + DAG.getValueType(VT)); + return; + } +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ + // FIXME: Add support for indexed stores. + SDOperand Ch = N->getChain(), Ptr = N->getBasePtr(); + int SVOffset = N->getSrcValueOffset(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + + SDOperand Val = GetPromotedInteger(N->getValue()); // Get promoted value. + + assert(!N->isTruncatingStore() && "Cannot promote this store operand!"); + + // Truncate the value and store the result. + return DAG.getTruncStore(Ch, Val, Ptr, N->getSrcValue(), + SVOffset, N->getMemoryVT(), + isVolatile, Alignment); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type is not. This implies + // that the vector is a power-of-two in length and that the element + // type does not have a strange size (eg: it is not i1). + MVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + assert(!(NumElts & 1) && "Legal vector of one illegal element?"); + + // Build a vector of half the length out of elements of twice the bitwidth. + // For example <4 x i16> -> <2 x i32>. + MVT OldVT = N->getOperand(0).getValueType(); + MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); + assert(OldVT.isSimple() && NewVT.isSimple()); + + std::vector NewElts; + NewElts.reserve(NumElts/2); + + for (unsigned i = 0; i < NumElts; i += 2) { + // Combine two successive elements into one promoted element. + SDOperand Lo = N->getOperand(i); + SDOperand Hi = N->getOperand(i+1); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + NewElts.push_back(JoinIntegers(Lo, Hi)); + } + + SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, + MVT::getVectorVT(NewVT, NewElts.size()), + &NewElts[0], NewElts.size()); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, + unsigned OpNo) { + if (OpNo == 1) { + // Promote the inserted value. This is valid because the type does not + // have to match the vector element type. + + // Check that any extra bits introduced will be truncated away. + assert(N->getOperand(1).getValueType().getSizeInBits() >= + N->getValueType(0).getVectorElementType().getSizeInBits() && + "Type of inserted value narrower than vector element type!"); + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + GetPromotedInteger(N->getOperand(1)), + N->getOperand(2)); + } + + assert(OpNo == 2 && "Different operand and result vector types?"); + + // Promote the index. + SDOperand Idx = N->getOperand(2); + Idx = DAG.getZeroExtendInReg(GetPromotedInteger(Idx), Idx.getValueType()); + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + N->getOperand(1), Idx); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_MEMBARRIER(SDNode *N) { + SDOperand NewOps[6]; + NewOps[0] = N->getOperand(0); + for (unsigned i = 1; i < array_lengthof(NewOps); ++i) { + SDOperand Flag = GetPromotedInteger(N->getOperand(i)); + NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1); + } + return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps, + array_lengthof(NewOps)); +} + + +//===----------------------------------------------------------------------===// +// Integer Result Expansion +//===----------------------------------------------------------------------===// + +/// ExpandIntegerResult - This method is called when the specified result of the /// specified node is found to need expansion. At this point, the node may also /// have invalid operands or may have other results that need promotion, we just /// know that (at least) one result needs expansion. -void DAGTypeLegalizer::ExpandResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Expand node result: "; N->dump(&DAG); cerr << "\n"); +void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Expand integer result: "; N->dump(&DAG); cerr << "\n"); SDOperand Lo, Hi; Lo = Hi = SDOperand(); // See if the target wants to custom expand this node. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == TargetLowering::Custom) { // If the target wants to, allow it to lower this itself. if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { @@ -47,69 +750,69 @@ void DAGTypeLegalizer::ExpandResult(SDNode *N, unsigned ResNo) { switch (N->getOpcode()) { default: #ifndef NDEBUG - cerr << "ExpandResult #" << ResNo << ": "; + cerr << "ExpandIntegerResult #" << ResNo << ": "; N->dump(&DAG); cerr << "\n"; #endif - assert(0 && "Do not know how to expand the result of this operator!"); + assert(0&&"Do not know how to expand the result of this operator!"); abort(); - - case ISD::UNDEF: ExpandResult_UNDEF(N, Lo, Hi); break; - case ISD::Constant: ExpandResult_Constant(N, Lo, Hi); break; - case ISD::BUILD_PAIR: ExpandResult_BUILD_PAIR(N, Lo, Hi); break; - case ISD::MERGE_VALUES: ExpandResult_MERGE_VALUES(N, Lo, Hi); break; - case ISD::ANY_EXTEND: ExpandResult_ANY_EXTEND(N, Lo, Hi); break; - case ISD::ZERO_EXTEND: ExpandResult_ZERO_EXTEND(N, Lo, Hi); break; - case ISD::SIGN_EXTEND: ExpandResult_SIGN_EXTEND(N, Lo, Hi); break; - case ISD::AssertZext: ExpandResult_AssertZext(N, Lo, Hi); break; - case ISD::TRUNCATE: ExpandResult_TRUNCATE(N, Lo, Hi); break; - case ISD::BIT_CONVERT: ExpandResult_BIT_CONVERT(N, Lo, Hi); break; - case ISD::SIGN_EXTEND_INREG: ExpandResult_SIGN_EXTEND_INREG(N, Lo, Hi); break; - case ISD::FP_TO_SINT: ExpandResult_FP_TO_SINT(N, Lo, Hi); break; - case ISD::FP_TO_UINT: ExpandResult_FP_TO_UINT(N, Lo, Hi); break; - case ISD::LOAD: ExpandResult_LOAD(cast(N), Lo, Hi); break; - + + case ISD::UNDEF: ExpandIntRes_UNDEF(N, Lo, Hi); break; + case ISD::Constant: ExpandIntRes_Constant(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandIntRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::MERGE_VALUES: ExpandIntRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::ANY_EXTEND: ExpandIntRes_ANY_EXTEND(N, Lo, Hi); break; + case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break; + case ISD::SIGN_EXTEND: ExpandIntRes_SIGN_EXTEND(N, Lo, Hi); break; + case ISD::AssertZext: ExpandIntRes_AssertZext(N, Lo, Hi); break; + case ISD::TRUNCATE: ExpandIntRes_TRUNCATE(N, Lo, Hi); break; + case ISD::BIT_CONVERT: ExpandIntRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::SIGN_EXTEND_INREG: ExpandIntRes_SIGN_EXTEND_INREG(N, Lo, Hi); break; + case ISD::FP_TO_SINT: ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break; + case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break; + case ISD::LOAD: ExpandIntRes_LOAD(cast(N), Lo, Hi); break; + case ISD::AND: case ISD::OR: - case ISD::XOR: ExpandResult_Logical(N, Lo, Hi); break; - case ISD::BSWAP: ExpandResult_BSWAP(N, Lo, Hi); break; + case ISD::XOR: ExpandIntRes_Logical(N, Lo, Hi); break; + case ISD::BSWAP: ExpandIntRes_BSWAP(N, Lo, Hi); break; case ISD::ADD: - case ISD::SUB: ExpandResult_ADDSUB(N, Lo, Hi); break; + case ISD::SUB: ExpandIntRes_ADDSUB(N, Lo, Hi); break; case ISD::ADDC: - case ISD::SUBC: ExpandResult_ADDSUBC(N, Lo, Hi); break; + case ISD::SUBC: ExpandIntRes_ADDSUBC(N, Lo, Hi); break; case ISD::ADDE: - case ISD::SUBE: ExpandResult_ADDSUBE(N, Lo, Hi); break; - case ISD::SELECT: ExpandResult_SELECT(N, Lo, Hi); break; - case ISD::SELECT_CC: ExpandResult_SELECT_CC(N, Lo, Hi); break; - case ISD::MUL: ExpandResult_MUL(N, Lo, Hi); break; - case ISD::SDIV: ExpandResult_SDIV(N, Lo, Hi); break; - case ISD::SREM: ExpandResult_SREM(N, Lo, Hi); break; - case ISD::UDIV: ExpandResult_UDIV(N, Lo, Hi); break; - case ISD::UREM: ExpandResult_UREM(N, Lo, Hi); break; + case ISD::SUBE: ExpandIntRes_ADDSUBE(N, Lo, Hi); break; + case ISD::SELECT: ExpandIntRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: ExpandIntRes_SELECT_CC(N, Lo, Hi); break; + case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break; + case ISD::SDIV: ExpandIntRes_SDIV(N, Lo, Hi); break; + case ISD::SREM: ExpandIntRes_SREM(N, Lo, Hi); break; + case ISD::UDIV: ExpandIntRes_UDIV(N, Lo, Hi); break; + case ISD::UREM: ExpandIntRes_UREM(N, Lo, Hi); break; case ISD::SHL: case ISD::SRA: - case ISD::SRL: ExpandResult_Shift(N, Lo, Hi); break; + case ISD::SRL: ExpandIntRes_Shift(N, Lo, Hi); break; - case ISD::CTLZ: ExpandResult_CTLZ(N, Lo, Hi); break; - case ISD::CTPOP: ExpandResult_CTPOP(N, Lo, Hi); break; - case ISD::CTTZ: ExpandResult_CTTZ(N, Lo, Hi); break; + case ISD::CTLZ: ExpandIntRes_CTLZ(N, Lo, Hi); break; + case ISD::CTPOP: ExpandIntRes_CTPOP(N, Lo, Hi); break; + case ISD::CTTZ: ExpandIntRes_CTTZ(N, Lo, Hi); break; case ISD::EXTRACT_VECTOR_ELT: - ExpandResult_EXTRACT_VECTOR_ELT(N, Lo, Hi); + ExpandIntRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; } // If Lo/Hi is null, the sub-method took care of registering results etc. if (Lo.Val) - SetExpandedOp(SDOperand(N, ResNo), Lo, Hi); + SetExpandedInteger(SDOperand(N, ResNo), Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_UNDEF(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); Lo = Hi = DAG.getNode(ISD::UNDEF, NVT); } -void DAGTypeLegalizer::ExpandResult_Constant(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); unsigned NBitWidth = NVT.getSizeInBits(); @@ -118,26 +821,26 @@ void DAGTypeLegalizer::ExpandResult_Constant(SDNode *N, Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT); } -void DAGTypeLegalizer::ExpandResult_BUILD_PAIR(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // Return the operands. Lo = N->getOperand(0); Hi = N->getOperand(1); } -void DAGTypeLegalizer::ExpandResult_MERGE_VALUES(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // A MERGE_VALUES node can produce any number of values. We know that the // first illegal one needs to be expanded into Lo/Hi. unsigned i; - + // The string of legal results gets turns into the input operands, which have // the same type. for (i = 0; isTypeLegal(N->getValueType(i)); ++i) ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); // The first illegal result must be the one that needs to be expanded. - GetExpandedOp(N->getOperand(i), Lo, Hi); + GetExpandedInteger(N->getOperand(i), Lo, Hi); // Legalize the rest of the results into the input operands whether they are // legal or not. @@ -146,7 +849,7 @@ void DAGTypeLegalizer::ExpandResult_MERGE_VALUES(SDNode *N, ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); } -void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); SDOperand Op = N->getOperand(0); @@ -157,9 +860,9 @@ void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N, } else { // For example, extension of an i48 to an i64. The operand type necessarily // promotes to the result type, so will end up being expanded too. - assert(getTypeAction(Op.getValueType()) == Promote && + assert(getTypeAction(Op.getValueType()) == PromoteInteger && "Only know how to promote this result!"); - SDOperand Res = GetPromotedOp(Op); + SDOperand Res = GetPromotedInteger(Op); assert(Res.getValueType() == N->getValueType(0) && "Operand over promoted?"); // Split the promoted operand. This will simplify when it is expanded. @@ -167,7 +870,7 @@ void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N, } } -void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_ZERO_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); SDOperand Op = N->getOperand(0); @@ -178,9 +881,9 @@ void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N, } else { // For example, extension of an i48 to an i64. The operand type necessarily // promotes to the result type, so will end up being expanded too. - assert(getTypeAction(Op.getValueType()) == Promote && + assert(getTypeAction(Op.getValueType()) == PromoteInteger && "Only know how to promote this result!"); - SDOperand Res = GetPromotedOp(Op); + SDOperand Res = GetPromotedInteger(Op); assert(Res.getValueType() == N->getValueType(0) && "Operand over promoted?"); // Split the promoted operand. This will simplify when it is expanded. @@ -191,7 +894,7 @@ void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N, } } -void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); SDOperand Op = N->getOperand(0); @@ -205,9 +908,9 @@ void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N, } else { // For example, extension of an i48 to an i64. The operand type necessarily // promotes to the result type, so will end up being expanded too. - assert(getTypeAction(Op.getValueType()) == Promote && + assert(getTypeAction(Op.getValueType()) == PromoteInteger && "Only know how to promote this result!"); - SDOperand Res = GetPromotedOp(Op); + SDOperand Res = GetPromotedInteger(Op); assert(Res.getValueType() == N->getValueType(0) && "Operand over promoted?"); // Split the promoted operand. This will simplify when it is expanded. @@ -219,9 +922,9 @@ void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N, } } -void DAGTypeLegalizer::ExpandResult_AssertZext(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_AssertZext(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - GetExpandedOp(N->getOperand(0), Lo, Hi); + GetExpandedInteger(N->getOperand(0), Lo, Hi); MVT NVT = Lo.getValueType(); MVT EVT = cast(N->getOperand(1))->getVT(); unsigned NVTBits = NVT.getSizeInBits(); @@ -237,7 +940,7 @@ void DAGTypeLegalizer::ExpandResult_AssertZext(SDNode *N, } } -void DAGTypeLegalizer::ExpandResult_TRUNCATE(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_TRUNCATE(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); Lo = DAG.getNode(ISD::TRUNCATE, NVT, N->getOperand(0)); @@ -247,7 +950,7 @@ void DAGTypeLegalizer::ExpandResult_TRUNCATE(SDNode *N, Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi); } -void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); SDOperand InOp = N->getOperand(0); @@ -258,23 +961,29 @@ void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N, default: assert(false && "Unknown type action!"); case Legal: - case Promote: + case PromoteInteger: break; - case Expand: - // Convert the expanded pieces of the input. - GetExpandedOp(InOp, Lo, Hi); + case PromoteFloat: + // Convert the integer operand instead. + SplitInteger(GetPromotedFloat(InOp), Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); return; - case FloatToInt: - // Convert the integer operand instead. - SplitInteger(GetIntegerOp(InOp), Lo, Hi); + case ExpandInteger: + // Convert the expanded pieces of the input. + GetExpandedInteger(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + case ExpandFloat: + // Convert the expanded pieces of the input. + GetExpandedFloat(InOp, Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); return; case Split: // Convert the split parts of the input if it was split in two. - GetSplitOp(InOp, Lo, Hi); + GetSplitVector(InOp, Lo, Hi); if (Lo.getValueType() == Hi.getValueType()) { if (TLI.isBigEndian()) std::swap(Lo, Hi); @@ -285,7 +994,7 @@ void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N, break; case Scalarize: // Convert the element instead. - SplitInteger(BitConvertToInteger(GetScalarizedOp(InOp)), Lo, Hi); + SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); return; @@ -293,12 +1002,12 @@ void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N, // Lower the bit-convert to a store/load from the stack, then expand the load. SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); - ExpandResult_LOAD(cast(Op.Val), Lo, Hi); + ExpandIntRes_LOAD(cast(Op.Val), Lo, Hi); } void DAGTypeLegalizer:: -ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - GetExpandedOp(N->getOperand(0), Lo, Hi); +ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + GetExpandedInteger(N->getOperand(0), Lo, Hi); MVT EVT = cast(N->getOperand(1))->getVT(); if (EVT.bitsLE(Lo.getValueType())) { @@ -321,7 +1030,7 @@ ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) { } } -void DAGTypeLegalizer::ExpandResult_FP_TO_SINT(SDNode *N, SDOperand &Lo, +void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT VT = N->getValueType(0); SDOperand Op = N->getOperand(0); @@ -350,7 +1059,7 @@ void DAGTypeLegalizer::ExpandResult_FP_TO_SINT(SDNode *N, SDOperand &Lo, SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_FP_TO_UINT(SDNode *N, SDOperand &Lo, +void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT VT = N->getValueType(0); SDOperand Op = N->getOperand(0); @@ -379,7 +1088,7 @@ void DAGTypeLegalizer::ExpandResult_FP_TO_UINT(SDNode *N, SDOperand &Lo, SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N, +void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, SDOperand &Lo, SDOperand &Hi) { // FIXME: Add support for indexed loads. MVT VT = N->getValueType(0); @@ -500,48 +1209,48 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N, ReplaceValueWith(SDOperand(N, 1), Ch); } -void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_Logical(SDNode *N, SDOperand &Lo, SDOperand &Hi) { SDOperand LL, LH, RL, RH; - GetExpandedOp(N->getOperand(0), LL, LH); - GetExpandedOp(N->getOperand(1), RL, RH); + GetExpandedInteger(N->getOperand(0), LL, LH); + GetExpandedInteger(N->getOperand(1), RL, RH); Lo = DAG.getNode(N->getOpcode(), LL.getValueType(), LL, RL); Hi = DAG.getNode(N->getOpcode(), LL.getValueType(), LH, RH); } -void DAGTypeLegalizer::ExpandResult_BSWAP(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_BSWAP(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - GetExpandedOp(N->getOperand(0), Hi, Lo); // Note swapped operands. + GetExpandedInteger(N->getOperand(0), Hi, Lo); // Note swapped operands. Lo = DAG.getNode(ISD::BSWAP, Lo.getValueType(), Lo); Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi); } -void DAGTypeLegalizer::ExpandResult_SELECT(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi) { SDOperand LL, LH, RL, RH; - GetExpandedOp(N->getOperand(1), LL, LH); - GetExpandedOp(N->getOperand(2), RL, RH); + GetExpandedInteger(N->getOperand(1), LL, LH); + GetExpandedInteger(N->getOperand(2), RL, RH); Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LL, RL); Hi = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LH, RH); } -void DAGTypeLegalizer::ExpandResult_SELECT_CC(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_SELECT_CC(SDNode *N, SDOperand &Lo, SDOperand &Hi) { SDOperand LL, LH, RL, RH; - GetExpandedOp(N->getOperand(2), LL, LH); - GetExpandedOp(N->getOperand(3), RL, RH); - Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), + GetExpandedInteger(N->getOperand(2), LL, LH); + GetExpandedInteger(N->getOperand(3), RL, RH); + Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), N->getOperand(1), LL, RL, N->getOperand(4)); - Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), + Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), N->getOperand(1), LH, RH, N->getOperand(4)); } -void DAGTypeLegalizer::ExpandResult_ADDSUB(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // Expand the subcomponents. SDOperand LHSL, LHSH, RHSL, RHSH; - GetExpandedOp(N->getOperand(0), LHSL, LHSH); - GetExpandedOp(N->getOperand(1), RHSL, RHSH); + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); SDOperand LoOps[2] = { LHSL, RHSL }; SDOperand HiOps[3] = { LHSH, RHSH }; @@ -557,12 +1266,12 @@ void DAGTypeLegalizer::ExpandResult_ADDSUB(SDNode *N, } } -void DAGTypeLegalizer::ExpandResult_ADDSUBC(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_ADDSUBC(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // Expand the subcomponents. SDOperand LHSL, LHSH, RHSL, RHSH; - GetExpandedOp(N->getOperand(0), LHSL, LHSH); - GetExpandedOp(N->getOperand(1), RHSL, RHSH); + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); SDOperand LoOps[2] = { LHSL, RHSL }; SDOperand HiOps[3] = { LHSH, RHSH }; @@ -582,12 +1291,12 @@ void DAGTypeLegalizer::ExpandResult_ADDSUBC(SDNode *N, ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1)); } -void DAGTypeLegalizer::ExpandResult_ADDSUBE(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_ADDSUBE(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // Expand the subcomponents. SDOperand LHSL, LHSH, RHSL, RHSH; - GetExpandedOp(N->getOperand(0), LHSL, LHSH); - GetExpandedOp(N->getOperand(1), RHSL, RHSH); + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); SDOperand LoOps[3] = { LHSL, RHSL, N->getOperand(2) }; SDOperand HiOps[3] = { LHSH, RHSH }; @@ -601,24 +1310,24 @@ void DAGTypeLegalizer::ExpandResult_ADDSUBE(SDNode *N, ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1)); } -void DAGTypeLegalizer::ExpandResult_MUL(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT VT = N->getValueType(0); MVT NVT = TLI.getTypeToTransformTo(VT); - + bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT); bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT); bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, NVT); bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, NVT); if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) { SDOperand LL, LH, RL, RH; - GetExpandedOp(N->getOperand(0), LL, LH); - GetExpandedOp(N->getOperand(1), RL, RH); + GetExpandedInteger(N->getOperand(0), LL, LH); + GetExpandedInteger(N->getOperand(1), RL, RH); unsigned OuterBitSize = VT.getSizeInBits(); unsigned BitSize = 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), @@ -672,7 +1381,7 @@ void DAGTypeLegalizer::ExpandResult_MUL(SDNode *N, Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_SDIV(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N, SDOperand &Lo, SDOperand &Hi) { assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!"); SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; @@ -680,7 +1389,7 @@ void DAGTypeLegalizer::ExpandResult_SDIV(SDNode *N, Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_SREM(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N, SDOperand &Lo, SDOperand &Hi) { assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!"); SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; @@ -688,7 +1397,7 @@ void DAGTypeLegalizer::ExpandResult_SREM(SDNode *N, Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_UDIV(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N, SDOperand &Lo, SDOperand &Hi) { assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!"); SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; @@ -696,7 +1405,7 @@ void DAGTypeLegalizer::ExpandResult_UDIV(SDNode *N, Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_UREM(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N, SDOperand &Lo, SDOperand &Hi) { assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!"); SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; @@ -704,11 +1413,11 @@ void DAGTypeLegalizer::ExpandResult_UREM(SDNode *N, Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT VT = N->getValueType(0); - - // If we can emit an efficient shift operation, do so now. Check to see if + + // If we can emit an efficient shift operation, do so now. Check to see if // the RHS is a constant. if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) return ExpandShiftByConstant(N, CN->getValue(), Lo, Hi); @@ -717,7 +1426,7 @@ void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N, // the low bits are variable, emit this shift in an optimized form. if (ExpandShiftWithKnownAmountBit(N, Lo, Hi)) return; - + // If this target supports shift_PARTS, use it. First, map to the _PARTS opc. unsigned PartsOpc; if (N->getOpcode() == ISD::SHL) { @@ -728,7 +1437,7 @@ void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N, assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); PartsOpc = ISD::SRA_PARTS; } - + // Next check to see if the target supports this SHL_PARTS operation or if it // will custom expand it. MVT NVT = TLI.getTypeToTransformTo(VT); @@ -737,8 +1446,8 @@ void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N, Action == TargetLowering::Custom) { // Expand the subcomponents. SDOperand LHSL, LHSH; - GetExpandedOp(N->getOperand(0), LHSL, LHSH); - + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + SDOperand Ops[] = { LHSL, LHSH, N->getOperand(1) }; MVT VT = LHSL.getValueType(); Lo = DAG.getNode(PartsOpc, DAG.getNodeValueTypes(VT, VT), 2, Ops, 3); @@ -767,10 +1476,10 @@ void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N, SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned), Lo, Hi); } -void DAGTypeLegalizer::ExpandResult_CTLZ(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_CTLZ(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // ctlz (HiLo) -> Hi != 0 ? ctlz(Hi) : (ctlz(Lo)+32) - GetExpandedOp(N->getOperand(0), Lo, Hi); + GetExpandedInteger(N->getOperand(0), Lo, Hi); MVT NVT = Lo.getValueType(); SDOperand HiNotZero = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi, @@ -785,20 +1494,20 @@ void DAGTypeLegalizer::ExpandResult_CTLZ(SDNode *N, Hi = DAG.getConstant(0, NVT); } -void DAGTypeLegalizer::ExpandResult_CTPOP(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_CTPOP(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // ctpop(HiLo) -> ctpop(Hi)+ctpop(Lo) - GetExpandedOp(N->getOperand(0), Lo, Hi); + GetExpandedInteger(N->getOperand(0), Lo, Hi); MVT NVT = Lo.getValueType(); Lo = DAG.getNode(ISD::ADD, NVT, DAG.getNode(ISD::CTPOP, NVT, Lo), DAG.getNode(ISD::CTPOP, NVT, Hi)); Hi = DAG.getConstant(0, NVT); } -void DAGTypeLegalizer::ExpandResult_CTTZ(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_CTTZ(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // cttz (HiLo) -> Lo != 0 ? cttz(Lo) : (cttz(Hi)+32) - GetExpandedOp(N->getOperand(0), Lo, Hi); + GetExpandedInteger(N->getOperand(0), Lo, Hi); MVT NVT = Lo.getValueType(); SDOperand LoNotZero = DAG.getSetCC(TLI.getSetCCResultType(Lo), Lo, @@ -813,7 +1522,7 @@ void DAGTypeLegalizer::ExpandResult_CTTZ(SDNode *N, Hi = DAG.getConstant(0, NVT); } -void DAGTypeLegalizer::ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, +void DAGTypeLegalizer::ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi) { SDOperand OldVec = N->getOperand(0); @@ -850,12 +1559,12 @@ void DAGTypeLegalizer::ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, /// ExpandShiftByConstant - N is a shift by a value that needs to be expanded, /// and the shift amount is a constant 'Amt'. Expand the operation. -void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, +void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, SDOperand &Lo, SDOperand &Hi) { // Expand the incoming operand to be shifted, so that we have its parts SDOperand InL, InH; - GetExpandedOp(N->getOperand(0), InL, InH); - + GetExpandedInteger(N->getOperand(0), InL, InH); + MVT NVT = InL.getValueType(); unsigned VTBits = N->getValueType(0).getSizeInBits(); unsigned NVTBits = NVT.getSizeInBits(); @@ -880,7 +1589,7 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, } return; } - + if (N->getOpcode() == ISD::SRL) { if (Amt > VTBits) { Lo = DAG.getConstant(0, NVT); @@ -901,7 +1610,7 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, } return; } - + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); if (Amt > VTBits) { Hi = Lo = DAG.getNode(ISD::SRA, NVT, InH, @@ -942,14 +1651,14 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) { APInt HighBitMask = APInt::getHighBitsSet(ShBits, ShBits - Log2_32(NVTBits)); APInt KnownZero, KnownOne; DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne); - + // If we don't know anything about the high bits, exit. if (((KnownZero|KnownOne) & HighBitMask) == 0) return false; // Get the incoming operand to be shifted. SDOperand InL, InH; - GetExpandedOp(N->getOperand(0), InL, InH); + GetExpandedInteger(N->getOperand(0), InL, InH); // If we know that any of the high bits of the shift amount are one, then we // can do this as a couple of simple shifts. @@ -957,7 +1666,7 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // Mask out the high bit, which we know is set. Amt = DAG.getNode(ISD::AND, ShTy, Amt, DAG.getConstant(~HighBitMask, ShTy)); - + switch (N->getOpcode()) { default: assert(0 && "Unknown shift"); case ISD::SHL: @@ -975,7 +1684,7 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) { return true; } } - + // If we know that all of the high bits of the shift amount are zero, then we // can do this as a couple of simple shifts. if ((KnownZero & HighBitMask) == HighBitMask) { @@ -990,7 +1699,7 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) { case ISD::SRL: case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break; } - + Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt); Hi = DAG.getNode(ISD::OR, NVT, DAG.getNode(Op1, NVT, InH, Amt), @@ -1003,60 +1712,60 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) { //===----------------------------------------------------------------------===// -// Operand Expansion +// Integer Operand Expansion //===----------------------------------------------------------------------===// -/// ExpandOperand - This method is called when the specified operand of the -/// specified node is found to need expansion. At this point, all of the result -/// types of the node are known to be legal, but other operands of the node may -/// need promotion or expansion as well as the specified one. -bool DAGTypeLegalizer::ExpandOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Expand node operand: "; N->dump(&DAG); cerr << "\n"); +/// ExpandIntegerOperand - This method is called when the specified operand of +/// the specified node is found to need expansion. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// 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); - + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) == TargetLowering::Custom) Res = TLI.LowerOperation(SDOperand(N, 0), DAG); - + if (Res.Val == 0) { switch (N->getOpcode()) { default: #ifndef NDEBUG - cerr << "ExpandOperand Op #" << OpNo << ": "; + cerr << "ExpandIntegerOperand Op #" << OpNo << ": "; N->dump(&DAG); cerr << "\n"; #endif assert(0 && "Do not know how to expand this operator's operand!"); abort(); - - case ISD::TRUNCATE: Res = ExpandOperand_TRUNCATE(N); break; - case ISD::BIT_CONVERT: Res = ExpandOperand_BIT_CONVERT(N); break; + + case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; + case ISD::BIT_CONVERT: Res = ExpandIntOp_BIT_CONVERT(N); break; case ISD::SINT_TO_FP: - Res = ExpandOperand_SINT_TO_FP(N->getOperand(0), N->getValueType(0)); + Res = ExpandIntOp_SINT_TO_FP(N->getOperand(0), N->getValueType(0)); break; case ISD::UINT_TO_FP: - Res = ExpandOperand_UINT_TO_FP(N->getOperand(0), N->getValueType(0)); + Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0)); break; - case ISD::EXTRACT_ELEMENT: Res = ExpandOperand_EXTRACT_ELEMENT(N); break; + case ISD::EXTRACT_ELEMENT: Res = ExpandIntOp_EXTRACT_ELEMENT(N); break; - case ISD::BR_CC: Res = ExpandOperand_BR_CC(N); break; - case ISD::SETCC: Res = ExpandOperand_SETCC(N); break; + case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; + case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; case ISD::STORE: - Res = ExpandOperand_STORE(cast(N), OpNo); + Res = ExpandIntOp_STORE(cast(N), OpNo); break; - case ISD::BUILD_VECTOR: Res = ExpandOperand_BUILD_VECTOR(N); break; + case ISD::BUILD_VECTOR: Res = ExpandIntOp_BUILD_VECTOR(N); break; } } - + // If the result is null, the sub-method took care of registering results etc. if (!Res.Val) return false; // If the result is N, the sub-method updated N in place. Check to see if any // operands are new, and if so, mark them. if (Res.Val == N) { // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit + // revisit N if it needs another step of expansion and allows us to visit // any new operands to N. ReanalyzeNode(N); return true; @@ -1064,19 +1773,19 @@ bool DAGTypeLegalizer::ExpandOperand(SDNode *N, unsigned OpNo) { assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && "Invalid operand expansion"); - + ReplaceValueWith(SDOperand(N, 0), Res); return false; } -SDOperand DAGTypeLegalizer::ExpandOperand_TRUNCATE(SDNode *N) { +SDOperand DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) { SDOperand InL, InH; - GetExpandedOp(N->getOperand(0), InL, InH); + GetExpandedInteger(N->getOperand(0), InL, InH); // Just truncate the low part of the source. return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL); } -SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) { +SDOperand DAGTypeLegalizer::ExpandIntOp_BIT_CONVERT(SDNode *N) { if (N->getValueType(0).isVector()) { // An illegal integer type is being converted to a legal vector type. // Make a two element vector out of the expanded parts and convert that @@ -1088,7 +1797,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) { if (isTypeLegal(NVT)) { SDOperand Parts[2]; - GetExpandedOp(N->getOperand(0), Parts[0], Parts[1]); + GetExpandedInteger(N->getOperand(0), Parts[0], Parts[1]); if (TLI.isBigEndian()) std::swap(Parts[0], Parts[1]); @@ -1102,11 +1811,11 @@ SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) { return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); } -SDOperand DAGTypeLegalizer::ExpandOperand_SINT_TO_FP(SDOperand Source, +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!"); @@ -1119,7 +1828,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_SINT_TO_FP(SDOperand Source, if (NV.Val) return NV; break; // The target lowered this. } - + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; if (SourceVT == MVT::i64) { if (DestTy == MVT::f32) @@ -1148,22 +1857,22 @@ SDOperand DAGTypeLegalizer::ExpandOperand_SINT_TO_FP(SDOperand Source, return MakeLibCall(LC, DestTy, &Source, 1, true); } -SDOperand DAGTypeLegalizer::ExpandOperand_UINT_TO_FP(SDOperand Source, +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()) == Expand && + assert(getTypeAction(Source.getValueType()) == ExpandInteger && "This is not an expansion!"); - + // 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 = ExpandOperand_SINT_TO_FP(Source, DestTy); + SDOperand SignedConv = ExpandIntOp_SINT_TO_FP(Source, DestTy); // 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; - GetExpandedOp(Source, Lo, Hi); - + GetExpandedInteger(Source, Lo, Hi); + SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi, DAG.getConstant(0, Hi.getValueType()), ISD::SETLT); @@ -1173,7 +1882,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_UINT_TO_FP(SDOperand Source, 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; @@ -1183,19 +1892,19 @@ SDOperand DAGTypeLegalizer::ExpandOperand_UINT_TO_FP(SDOperand Source, // FIXME: Avoid the extend by construction the right constantpool? FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(), CPIdx, NULL, 0, MVT::f32); - else + else assert(0 && "Unexpected conversion"); - + return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg); } -SDOperand DAGTypeLegalizer::ExpandOperand_EXTRACT_ELEMENT(SDNode *N) { +SDOperand DAGTypeLegalizer::ExpandIntOp_EXTRACT_ELEMENT(SDNode *N) { SDOperand Lo, Hi; - GetExpandedOp(N->getOperand(0), Lo, Hi); + GetExpandedInteger(N->getOperand(0), Lo, Hi); return cast(N->getOperand(1))->getValue() ? Hi : Lo; } -SDOperand DAGTypeLegalizer::ExpandOperand_BR_CC(SDNode *N) { +SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) { SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); ISD::CondCode CCCode = cast(N->getOperand(1))->get(); ExpandSetCCOperands(NewLHS, NewRHS, CCCode); @@ -1213,11 +1922,11 @@ SDOperand DAGTypeLegalizer::ExpandOperand_BR_CC(SDNode *N) { N->getOperand(4)); } -SDOperand DAGTypeLegalizer::ExpandOperand_SETCC(SDNode *N) { +SDOperand DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) { SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); ISD::CondCode CCCode = cast(N->getOperand(2))->get(); ExpandSetCCOperands(NewLHS, NewRHS, CCCode); - + // If ExpandSetCCOperands returned a scalar, use it. if (NewRHS.Val == 0) return NewLHS; @@ -1231,8 +1940,8 @@ SDOperand DAGTypeLegalizer::ExpandOperand_SETCC(SDNode *N) { void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, ISD::CondCode &CCCode) { SDOperand LHSLo, LHSHi, RHSLo, RHSHi; - GetExpandedOp(NewLHS, LHSLo, LHSHi); - GetExpandedOp(NewRHS, RHSLo, RHSHi); + GetExpandedInteger(NewLHS, LHSLo, LHSHi); + GetExpandedInteger(NewRHS, RHSLo, RHSHi); MVT VT = NewLHS.getValueType(); if (VT == MVT::ppcf128) { @@ -1262,14 +1971,14 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, NewRHS = RHSLo; return; } - + NewLHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo); NewRHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi); NewLHS = DAG.getNode(ISD::OR, NewLHS.getValueType(), NewLHS, NewRHS); NewRHS = DAG.getConstant(0, NewLHS.getValueType()); return; } - + // If this is a comparison of the sign bit, just look at the top part. // X > -1, x < 0 if (ConstantSDNode *CST = dyn_cast(NewRHS)) @@ -1279,7 +1988,7 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, NewRHS = RHSHi; return; } - + // FIXME: This generated code sucks. ISD::CondCode LowCC; switch (CCCode) { @@ -1293,11 +2002,11 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, case ISD::SETGE: case ISD::SETUGE: LowCC = ISD::SETUGE; break; } - + // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; - + // NOTE: on targets without efficient SELECT of bools, we can always use // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) TargetLowering::DAGCombinerInfo DagCombineInfo(DAG, false, true, NULL); @@ -1311,7 +2020,7 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, if (!Tmp2.Val) Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, DAG.getCondCode(CCCode)); - + ConstantSDNode *Tmp1C = dyn_cast(Tmp1.Val); ConstantSDNode *Tmp2C = dyn_cast(Tmp2.Val); if ((Tmp1C && Tmp1C->isNullValue()) || @@ -1328,7 +2037,7 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, NewRHS = SDOperand(); return; } - + NewLHS = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ, false, DagCombineInfo); if (!NewLHS.Val) @@ -1339,7 +2048,7 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, NewRHS = SDOperand(); } -SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) { +SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { // FIXME: Add support for indexed stores. assert(OpNo == 1 && "Can only expand the stored value so far"); @@ -1356,7 +2065,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) { if (!N->isTruncatingStore()) { unsigned IncrementSize = 0; - GetExpandedOp(N->getValue(), Lo, Hi); + GetExpandedInteger(N->getValue(), Lo, Hi); IncrementSize = Hi.getValueType().getSizeInBits()/8; if (TLI.isBigEndian()) @@ -1372,12 +2081,12 @@ SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) { isVolatile, MinAlign(Alignment, IncrementSize)); return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); } else if (N->getMemoryVT().bitsLE(NVT)) { - GetExpandedOp(N->getValue(), Lo, Hi); + GetExpandedInteger(N->getValue(), Lo, Hi); return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, N->getMemoryVT(), isVolatile, Alignment); } else if (TLI.isLittleEndian()) { // Little-endian - low bits are at low addresses. - GetExpandedOp(N->getValue(), Lo, Hi); + GetExpandedInteger(N->getValue(), Lo, Hi); Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVolatile, Alignment); @@ -1397,7 +2106,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) { } else { // Big-endian - high bits are at low addresses. Favor aligned stores at // the cost of some bit-fiddling. - GetExpandedOp(N->getValue(), Lo, Hi); + GetExpandedInteger(N->getValue(), Lo, Hi); MVT EVT = N->getMemoryVT(); unsigned EBytes = EVT.getStoreSizeInBits()/8; @@ -1432,7 +2141,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) { } } -SDOperand DAGTypeLegalizer::ExpandOperand_BUILD_VECTOR(SDNode *N) { +SDOperand DAGTypeLegalizer::ExpandIntOp_BUILD_VECTOR(SDNode *N) { // The vector type is legal but the element type needs expansion. MVT VecVT = N->getValueType(0); unsigned NumElts = VecVT.getVectorNumElements(); @@ -1449,7 +2158,7 @@ SDOperand DAGTypeLegalizer::ExpandOperand_BUILD_VECTOR(SDNode *N) { for (unsigned i = 0; i < NumElts; ++i) { SDOperand Lo, Hi; - GetExpandedOp(N->getOperand(i), Lo, Hi); + GetExpandedInteger(N->getOperand(i), Lo, Hi); if (TLI.isBigEndian()) std::swap(Lo, Hi); NewElts.push_back(Lo); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index 5b37c75f1fe..e469f255c36 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -42,7 +42,7 @@ void DAGTypeLegalizer::run() { // The root of the dag may dangle to deleted nodes until the type legalizer is // done. Set it to null to avoid confusion. DAG.setRoot(SDOperand()); - + // Walk all nodes in the graph, assigning them a NodeID of 'ReadyToProcess' // (and remembering them) if they are leaves and assigning 'NewNode' if // non-leaves. @@ -55,14 +55,14 @@ void DAGTypeLegalizer::run() { I->setNodeId(NewNode); } } - + // Now that we have a set of nodes to process, handle them all. while (!Worklist.empty()) { SDNode *N = Worklist.back(); Worklist.pop_back(); assert(N->getNodeId() == ReadyToProcess && "Node should be ready if on worklist!"); - + // Scan the values produced by the node, checking to see if any result // types are illegal. unsigned i = 0; @@ -74,14 +74,17 @@ void DAGTypeLegalizer::run() { assert(false && "Unknown action!"); case Legal: break; - case Promote: - PromoteResult(N, i); + case PromoteInteger: + PromoteIntegerResult(N, i); goto NodeDone; - case Expand: - ExpandResult(N, i); + case ExpandInteger: + ExpandIntegerResult(N, i); goto NodeDone; - case FloatToInt: - FloatToIntResult(N, i); + case PromoteFloat: + PromoteFloatResult(N, i); + goto NodeDone; + case ExpandFloat: + ExpandFloatResult(N, i); goto NodeDone; case Scalarize: ScalarizeResult(N, i); @@ -104,14 +107,17 @@ void DAGTypeLegalizer::run() { assert(false && "Unknown action!"); case Legal: continue; - case Promote: - NeedsRevisit = PromoteOperand(N, i); + case PromoteInteger: + NeedsRevisit = PromoteIntegerOperand(N, i); break; - case Expand: - NeedsRevisit = ExpandOperand(N, i); + case ExpandInteger: + NeedsRevisit = ExpandIntegerOperand(N, i); break; - case FloatToInt: - NeedsRevisit = FloatToIntOperand(N, i); + case PromoteFloat: + NeedsRevisit = PromoteFloatOperand(N, i); + break; + case ExpandFloat: + NeedsRevisit = ExpandFloatOperand(N, i); break; case Scalarize: NeedsRevisit = ScalarizeOperand(N, i); @@ -126,7 +132,7 @@ void DAGTypeLegalizer::run() { // If the node needs revisiting, don't add all users to the worklist etc. if (NeedsRevisit) continue; - + if (i == NumOperands) DEBUG(cerr << "Legally typed node: "; N->dump(&DAG); cerr << "\n"); } @@ -135,37 +141,37 @@ NodeDone: // If we reach here, the node was processed, potentially creating new nodes. // Mark it as processed and add its users to the worklist as appropriate. N->setNodeId(Processed); - + for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); UI != E; ++UI) { SDNode *User = UI->getUser(); int NodeID = User->getNodeId(); assert(NodeID != ReadyToProcess && NodeID != Processed && "Invalid node id for user of unprocessed node!"); - + // This node has two options: it can either be a new node or its Node ID // may be a count of the number of operands it has that are not ready. if (NodeID > 0) { User->setNodeId(NodeID-1); - + // If this was the last use it was waiting on, add it to the ready list. if (NodeID-1 == ReadyToProcess) Worklist.push_back(User); continue; } - + // Otherwise, this node is new: this is the first operand of it that // became ready. Its new NodeID is the number of operands it has minus 1 // (as this node is now processed). assert(NodeID == NewNode && "Unknown node ID!"); User->setNodeId(User->getNumOperands()-1); - + // If the node only has a single operand, it is now ready. if (User->getNumOperands() == 1) Worklist.push_back(User); } } - + // If the root changed (e.g. it was a dead load, update the root). DAG.setRoot(Dummy.getValue()); @@ -315,8 +321,8 @@ void DAGTypeLegalizer::ReplaceValueWith(SDOperand From, SDOperand To) { NodeUpdateListener NUL(*this); DAG.ReplaceAllUsesOfValueWith(From, To, &NUL); - // The old node may still be present in a map like ExpandedNodes or - // PromotedNodes. Inform maps about the replacement. + // The old node may still be present in a map like ExpandedIntegers or + // PromotedIntegers. Inform maps about the replacement. NoteReplacement(From, To); } @@ -336,8 +342,8 @@ void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) { NodeUpdateListener NUL(*this); DAG.ReplaceAllUsesWith(From, To, &NUL); - // The old node may still be present in a map like ExpandedNodes or - // PromotedNodes. Inform maps about the replacement. + // The old node may still be present in a map like ExpandedIntegers or + // PromotedIntegers. Inform maps about the replacement. for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) { assert(From->getValueType(i) == To->getValueType(i) && "Node results don't match"); @@ -380,29 +386,29 @@ void DAGTypeLegalizer::ExpungeNode(SDOperand N) { I->second = Replacement; } - for (DenseMap::iterator I = PromotedNodes.begin(), - E = PromotedNodes.end(); I != E; ++I) { + for (DenseMap::iterator I = PromotedIntegers.begin(), + E = PromotedIntegers.end(); I != E; ++I) { assert(I->first != N); if (I->second == N) I->second = Replacement; } - for (DenseMap::iterator I = FloatToIntedNodes.begin(), - E = FloatToIntedNodes.end(); I != E; ++I) { + for (DenseMap::iterator I = PromotedFloats.begin(), + E = PromotedFloats.end(); I != E; ++I) { assert(I->first != N); if (I->second == N) I->second = Replacement; } - for (DenseMap::iterator I = ScalarizedNodes.begin(), - E = ScalarizedNodes.end(); I != E; ++I) { + for (DenseMap::iterator I = ScalarizedVectors.begin(), + E = ScalarizedVectors.end(); I != E; ++I) { assert(I->first != N); if (I->second == N) I->second = Replacement; } for (DenseMap >::iterator - I = ExpandedNodes.begin(), E = ExpandedNodes.end(); I != E; ++I) { + I = ExpandedIntegers.begin(), E = ExpandedIntegers.end(); I != E; ++I){ assert(I->first != N); if (I->second.first == N) I->second.first = Replacement; @@ -411,7 +417,16 @@ void DAGTypeLegalizer::ExpungeNode(SDOperand N) { } for (DenseMap >::iterator - I = SplitNodes.begin(), E = SplitNodes.end(); I != E; ++I) { + I = ExpandedFloats.begin(), E = ExpandedFloats.end(); I != E; ++I) { + assert(I->first != N); + if (I->second.first == N) + I->second.first = Replacement; + if (I->second.second == N) + I->second.second = Replacement; + } + + for (DenseMap >::iterator + I = SplitVectors.begin(), E = SplitVectors.end(); I != E; ++I) { assert(I->first != N); if (I->second.first == N) I->second.first = Replacement; @@ -422,36 +437,36 @@ void DAGTypeLegalizer::ExpungeNode(SDOperand N) { } -void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) { +void DAGTypeLegalizer::SetPromotedInteger(SDOperand Op, SDOperand Result) { ExpungeNode(Result); AnalyzeNewNode(Result.Val); - SDOperand &OpEntry = PromotedNodes[Op]; + SDOperand &OpEntry = PromotedIntegers[Op]; assert(OpEntry.Val == 0 && "Node is already promoted!"); OpEntry = Result; } -void DAGTypeLegalizer::SetIntegerOp(SDOperand Op, SDOperand Result) { +void DAGTypeLegalizer::SetPromotedFloat(SDOperand Op, SDOperand Result) { ExpungeNode(Result); AnalyzeNewNode(Result.Val); - SDOperand &OpEntry = FloatToIntedNodes[Op]; + SDOperand &OpEntry = PromotedFloats[Op]; assert(OpEntry.Val == 0 && "Node is already converted to integer!"); OpEntry = Result; } -void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) { +void DAGTypeLegalizer::SetScalarizedVector(SDOperand Op, SDOperand Result) { ExpungeNode(Result); AnalyzeNewNode(Result.Val); - SDOperand &OpEntry = ScalarizedNodes[Op]; + SDOperand &OpEntry = ScalarizedVectors[Op]; assert(OpEntry.Val == 0 && "Node is already scalarized!"); OpEntry = Result; } -void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, - SDOperand &Hi) { - std::pair &Entry = ExpandedNodes[Op]; +void DAGTypeLegalizer::GetExpandedInteger(SDOperand Op, SDOperand &Lo, + SDOperand &Hi) { + std::pair &Entry = ExpandedIntegers[Op]; RemapNode(Entry.first); RemapNode(Entry.second); assert(Entry.first.Val && "Operand isn't expanded"); @@ -459,7 +474,8 @@ void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, Hi = Entry.second; } -void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { +void DAGTypeLegalizer::SetExpandedInteger(SDOperand Op, SDOperand Lo, + SDOperand Hi) { ExpungeNode(Lo); ExpungeNode(Hi); @@ -468,14 +484,41 @@ void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { AnalyzeNewNode(Hi.Val); // Remember that this is the result of the node. - std::pair &Entry = ExpandedNodes[Op]; + std::pair &Entry = ExpandedIntegers[Op]; assert(Entry.first.Val == 0 && "Node already expanded"); Entry.first = Lo; Entry.second = Hi; } -void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { - std::pair &Entry = SplitNodes[Op]; +void DAGTypeLegalizer::GetExpandedFloat(SDOperand Op, SDOperand &Lo, + SDOperand &Hi) { + std::pair &Entry = ExpandedFloats[Op]; + RemapNode(Entry.first); + RemapNode(Entry.second); + assert(Entry.first.Val && "Operand isn't expanded"); + Lo = Entry.first; + Hi = Entry.second; +} + +void DAGTypeLegalizer::SetExpandedFloat(SDOperand Op, SDOperand Lo, + SDOperand Hi) { + ExpungeNode(Lo); + ExpungeNode(Hi); + + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewNode(Lo.Val); + AnalyzeNewNode(Hi.Val); + + // Remember that this is the result of the node. + std::pair &Entry = ExpandedFloats[Op]; + assert(Entry.first.Val == 0 && "Node already expanded"); + Entry.first = Lo; + Entry.second = Hi; +} + +void DAGTypeLegalizer::GetSplitVector(SDOperand Op, SDOperand &Lo, + SDOperand &Hi) { + std::pair &Entry = SplitVectors[Op]; RemapNode(Entry.first); RemapNode(Entry.second); assert(Entry.first.Val && "Operand isn't split"); @@ -483,7 +526,8 @@ void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { Hi = Entry.second; } -void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { +void DAGTypeLegalizer::SetSplitVector(SDOperand Op, SDOperand Lo, + SDOperand Hi) { ExpungeNode(Lo); ExpungeNode(Hi); @@ -492,7 +536,7 @@ void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { AnalyzeNewNode(Hi.Val); // Remember that this is the result of the node. - std::pair &Entry = SplitNodes[Op]; + std::pair &Entry = SplitVectors[Op]; assert(Entry.first.Val == 0 && "Node already split"); Entry.first = Lo; Entry.second = Hi; @@ -505,11 +549,11 @@ SDOperand DAGTypeLegalizer::BitConvertToInteger(SDOperand Op) { return DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerVT(BitWidth), Op); } -SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, +SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, MVT DestVT) { // Create the stack frame object. SDOperand FIPtr = DAG.CreateStackTemporary(DestVT); - + // Emit a store to the stack slot. SDOperand Store = DAG.getStore(DAG.getEntryNode(), Op, FIPtr, NULL, 0); // Result is a load from the stack slot. @@ -605,6 +649,6 @@ SDOperand DAGTypeLegalizer::GetVectorElementPointer(SDOperand VecPtr, MVT EltVT, /// the graph. void SelectionDAG::LegalizeTypes() { if (ViewLegalizeTypesDAGs) viewGraph(); - + DAGTypeLegalizer(*this).run(); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index ba8f1069353..a472a296b5d 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -47,31 +47,32 @@ public: /// ReadyToProcess - All operands have been processed, so this node is ready /// to be handled. ReadyToProcess = 0, - + /// NewNode - This is a new node that was created in the process of /// legalizing some other node. NewNode = -1, - + /// Processed - This is a node that has already been processed. Processed = -2 - + // 1+ - This is a node which has this many unlegalized operands. }; private: enum LegalizeAction { - Legal, // The target natively supports this type. - Promote, // This type should be executed in a larger type. - Expand, // This type should be split into two types of half the size. - FloatToInt, // Convert a floating point type to an integer of the same size. - Scalarize, // Replace this one-element vector type with its element type. - Split // This vector type should be split into smaller vectors. + Legal, // The target natively supports this type. + PromoteInteger, // Replace this integer type with a larger one. + ExpandInteger, // Split this integer type into two of half the size. + PromoteFloat, // Convert this float type to a same size integer type. + ExpandFloat, // Split this float type into two of half the size. + Scalarize, // Replace this one-element vector type with its element type. + Split // This vector type should be split into smaller vectors. }; /// ValueTypeActions - This is a bitvector that contains two bits for each /// simple value type, where the two bits correspond to the LegalizeAction /// enum from TargetLowering. This can be queried with "getTypeAction(VT)". TargetLowering::ValueTypeActionImpl ValueTypeActions; - + /// getTypeAction - Return how we should legalize values of this type, either /// it is already legal, or we need to promote it to a larger integer type, or /// we need to expand it into multiple registers of a smaller integer type, or @@ -84,16 +85,19 @@ private: case TargetLowering::Legal: return Legal; case TargetLowering::Promote: - return Promote; + return PromoteInteger; case TargetLowering::Expand: // Expand can mean // 1) split scalar in half, 2) convert a float to an integer, // 3) scalarize a single-element vector, 4) split a vector in two. if (!VT.isVector()) { - if (VT.getSizeInBits() == TLI.getTypeToTransformTo(VT).getSizeInBits()) - return FloatToInt; + if (VT.isInteger()) + return ExpandInteger; + else if (VT.getSizeInBits() == + TLI.getTypeToTransformTo(VT).getSizeInBits()) + return PromoteFloat; else - return Expand; + return ExpandFloat; } else if (VT.getVectorNumElements() == 1) { return Scalarize; } else { @@ -107,26 +111,30 @@ private: return ValueTypeActions.getTypeAction(VT) == TargetLowering::Legal; } - /// PromotedNodes - For nodes that are below legal width, this map indicates - /// what promoted value to use. - DenseMap PromotedNodes; - - /// ExpandedNodes - For nodes that need to be expanded this map indicates - /// which operands are the expanded version of the input. - DenseMap > ExpandedNodes; + /// PromotedIntegers - For integer nodes that are below legal width, this map + /// indicates what promoted value to use. + DenseMap PromotedIntegers; - /// FloatToIntedNodes - For floating point nodes converted to integers of + /// ExpandedIntegers - For integer nodes that need to be expanded this map + /// indicates which operands are the expanded version of the input. + DenseMap > ExpandedIntegers; + + /// PromotedFloats - For floating point nodes converted to integers of /// the same size, this map indicates the converted value to use. - DenseMap FloatToIntedNodes; + DenseMap PromotedFloats; - /// ScalarizedNodes - For nodes that are <1 x ty>, this map indicates the + /// ExpandedFloats - For float nodes that need to be expanded this map + /// indicates which operands are the expanded version of the input. + DenseMap > ExpandedFloats; + + /// ScalarizedVectors - For nodes that are <1 x ty>, this map indicates the /// scalar value of type 'ty' to use. - DenseMap ScalarizedNodes; + DenseMap ScalarizedVectors; - /// SplitNodes - For nodes that need to be split this map indicates + /// SplitVectors - For nodes that need to be split this map indicates /// which operands are the expanded version of the input. - DenseMap > SplitNodes; - + DenseMap > SplitVectors; + /// ReplacedNodes - For nodes that have been replaced with another, /// indicates the replacement node to use. DenseMap ReplacedNodes; @@ -135,17 +143,17 @@ private: /// pushed onto this worklist, all operands of a node must have already been /// processed. SmallVector Worklist; - + public: explicit DAGTypeLegalizer(SelectionDAG &dag) : TLI(dag.getTargetLoweringInfo()), DAG(dag), ValueTypeActions(TLI.getValueTypeActions()) { assert(MVT::LAST_VALUETYPE <= 32 && "Too many value types for ValueTypeActions to hold!"); - } - + } + void run(); - + /// ReanalyzeNode - Recompute the NodeID and correct processed operands /// for the specified node, adding it to the worklist if ready. void ReanalyzeNode(SDNode *N) { @@ -183,174 +191,186 @@ private: SDOperand Index); //===--------------------------------------------------------------------===// - // Promotion Support: LegalizeTypesPromote.cpp + // Integer Promotion Support: LegalizeIntegerTypes.cpp //===--------------------------------------------------------------------===// - - SDOperand GetPromotedOp(SDOperand Op) { - SDOperand &PromotedOp = PromotedNodes[Op]; + + SDOperand GetPromotedInteger(SDOperand Op) { + SDOperand &PromotedOp = PromotedIntegers[Op]; RemapNode(PromotedOp); assert(PromotedOp.Val && "Operand wasn't promoted?"); return PromotedOp; } - void SetPromotedOp(SDOperand Op, SDOperand Result); - - /// GetPromotedZExtOp - Get a promoted operand and zero extend it to the final - /// size. - SDOperand GetPromotedZExtOp(SDOperand Op) { - MVT OldVT = Op.getValueType(); - Op = GetPromotedOp(Op); - return DAG.getZeroExtendInReg(Op, OldVT); - } - - // Result Promotion. - void PromoteResult(SDNode *N, unsigned ResNo); - SDOperand PromoteResult_BIT_CONVERT(SDNode *N); - SDOperand PromoteResult_BUILD_PAIR(SDNode *N); - SDOperand PromoteResult_Constant(SDNode *N); - SDOperand PromoteResult_CTLZ(SDNode *N); - SDOperand PromoteResult_CTPOP(SDNode *N); - SDOperand PromoteResult_CTTZ(SDNode *N); - SDOperand PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N); - SDOperand PromoteResult_FP_ROUND(SDNode *N); - SDOperand PromoteResult_FP_TO_XINT(SDNode *N); - SDOperand PromoteResult_INT_EXTEND(SDNode *N); - SDOperand PromoteResult_LOAD(LoadSDNode *N); - SDOperand PromoteResult_SDIV(SDNode *N); - SDOperand PromoteResult_SELECT (SDNode *N); - SDOperand PromoteResult_SELECT_CC(SDNode *N); - SDOperand PromoteResult_SETCC(SDNode *N); - SDOperand PromoteResult_SHL(SDNode *N); - SDOperand PromoteResult_SimpleIntBinOp(SDNode *N); - SDOperand PromoteResult_SRA(SDNode *N); - SDOperand PromoteResult_SRL(SDNode *N); - SDOperand PromoteResult_TRUNCATE(SDNode *N); - SDOperand PromoteResult_UDIV(SDNode *N); - SDOperand PromoteResult_UNDEF(SDNode *N); + void SetPromotedInteger(SDOperand Op, SDOperand Result); - // Operand Promotion. - bool PromoteOperand(SDNode *N, unsigned OperandNo); - SDOperand PromoteOperand_ANY_EXTEND(SDNode *N); - SDOperand PromoteOperand_BUILD_PAIR(SDNode *N); - SDOperand PromoteOperand_BR_CC(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_BRCOND(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_BUILD_VECTOR(SDNode *N); - SDOperand PromoteOperand_FP_EXTEND(SDNode *N); - SDOperand PromoteOperand_FP_ROUND(SDNode *N); - SDOperand PromoteOperand_INT_TO_FP(SDNode *N); - SDOperand PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_MEMBARRIER(SDNode *N); - SDOperand PromoteOperand_RET(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_SELECT(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_SETCC(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_SIGN_EXTEND(SDNode *N); - SDOperand PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo); - SDOperand PromoteOperand_TRUNCATE(SDNode *N); - SDOperand PromoteOperand_ZERO_EXTEND(SDNode *N); + /// ZExtPromotedInteger - Get a promoted operand and zero extend it to the + /// final size. + SDOperand ZExtPromotedInteger(SDOperand Op) { + MVT OldVT = Op.getValueType(); + Op = GetPromotedInteger(Op); + return DAG.getZeroExtendInReg(Op, OldVT); + } + + // Integer Result Promotion. + void PromoteIntegerResult(SDNode *N, unsigned ResNo); + SDOperand PromoteIntRes_BIT_CONVERT(SDNode *N); + SDOperand PromoteIntRes_BUILD_PAIR(SDNode *N); + SDOperand PromoteIntRes_Constant(SDNode *N); + SDOperand PromoteIntRes_CTLZ(SDNode *N); + SDOperand PromoteIntRes_CTPOP(SDNode *N); + SDOperand PromoteIntRes_CTTZ(SDNode *N); + SDOperand PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N); + SDOperand PromoteIntRes_FP_ROUND(SDNode *N); + SDOperand PromoteIntRes_FP_TO_XINT(SDNode *N); + SDOperand PromoteIntRes_INT_EXTEND(SDNode *N); + SDOperand PromoteIntRes_LOAD(LoadSDNode *N); + SDOperand PromoteIntRes_SDIV(SDNode *N); + SDOperand PromoteIntRes_SELECT (SDNode *N); + SDOperand PromoteIntRes_SELECT_CC(SDNode *N); + SDOperand PromoteIntRes_SETCC(SDNode *N); + SDOperand PromoteIntRes_SHL(SDNode *N); + SDOperand PromoteIntRes_SimpleIntBinOp(SDNode *N); + SDOperand PromoteIntRes_SRA(SDNode *N); + SDOperand PromoteIntRes_SRL(SDNode *N); + SDOperand PromoteIntRes_TRUNCATE(SDNode *N); + SDOperand PromoteIntRes_UDIV(SDNode *N); + SDOperand PromoteIntRes_UNDEF(SDNode *N); + + // Integer Operand Promotion. + bool PromoteIntegerOperand(SDNode *N, unsigned OperandNo); + SDOperand PromoteIntOp_ANY_EXTEND(SDNode *N); + SDOperand PromoteIntOp_BUILD_PAIR(SDNode *N); + SDOperand PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_BUILD_VECTOR(SDNode *N); + SDOperand PromoteIntOp_FP_EXTEND(SDNode *N); + SDOperand PromoteIntOp_FP_ROUND(SDNode *N); + SDOperand PromoteIntOp_INT_TO_FP(SDNode *N); + SDOperand PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_MEMBARRIER(SDNode *N); + SDOperand PromoteIntOp_SELECT(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_SETCC(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_SIGN_EXTEND(SDNode *N); + SDOperand PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_TRUNCATE(SDNode *N); + SDOperand PromoteIntOp_ZERO_EXTEND(SDNode *N); void PromoteSetCCOperands(SDOperand &LHS,SDOperand &RHS, ISD::CondCode Code); //===--------------------------------------------------------------------===// - // Expansion Support: LegalizeTypesExpand.cpp + // Integer Expansion Support: LegalizeIntegerTypes.cpp //===--------------------------------------------------------------------===// - - void GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi); - void SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi); - - // Result Expansion. - void ExpandResult(SDNode *N, unsigned ResNo); - void ExpandResult_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_ZERO_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_Logical (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_BSWAP (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_UDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_UREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_Shift (SDNode *N, SDOperand &Lo, SDOperand &Hi); - - void ExpandShiftByConstant(SDNode *N, unsigned Amt, + void GetExpandedInteger(SDOperand Op, SDOperand &Lo, SDOperand &Hi); + void SetExpandedInteger(SDOperand Op, SDOperand Lo, SDOperand Hi); + + // Integer Result Expansion. + void ExpandIntegerResult(SDNode *N, unsigned ResNo); + void ExpandIntRes_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_BIT_CONVERT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_MERGE_VALUES (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SIGN_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SIGN_EXTEND_INREG (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_ZERO_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + + void ExpandIntRes_Logical (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_BSWAP (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_UDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_UREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_Shift (SDNode *N, SDOperand &Lo, SDOperand &Hi); + + void ExpandShiftByConstant(SDNode *N, unsigned Amt, SDOperand &Lo, SDOperand &Hi); bool ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi); - // Operand Expansion. - bool ExpandOperand(SDNode *N, unsigned OperandNo); - SDOperand ExpandOperand_BIT_CONVERT(SDNode *N); - SDOperand ExpandOperand_BR_CC(SDNode *N); - SDOperand ExpandOperand_BUILD_VECTOR(SDNode *N); - SDOperand ExpandOperand_EXTRACT_ELEMENT(SDNode *N); - SDOperand ExpandOperand_SETCC(SDNode *N); - SDOperand ExpandOperand_SINT_TO_FP(SDOperand Source, MVT DestTy); - SDOperand ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo); - SDOperand ExpandOperand_TRUNCATE(SDNode *N); - SDOperand ExpandOperand_UINT_TO_FP(SDOperand Source, MVT DestTy); + // Integer Operand Expansion. + bool ExpandIntegerOperand(SDNode *N, unsigned OperandNo); + SDOperand ExpandIntOp_BIT_CONVERT(SDNode *N); + SDOperand ExpandIntOp_BR_CC(SDNode *N); + SDOperand ExpandIntOp_BUILD_VECTOR(SDNode *N); + SDOperand ExpandIntOp_EXTRACT_ELEMENT(SDNode *N); + SDOperand ExpandIntOp_SETCC(SDNode *N); + SDOperand ExpandIntOp_SINT_TO_FP(SDOperand Source, MVT DestTy); + SDOperand ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo); + SDOperand ExpandIntOp_TRUNCATE(SDNode *N); + SDOperand ExpandIntOp_UINT_TO_FP(SDOperand Source, MVT DestTy); void ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, ISD::CondCode &CCCode); - + //===--------------------------------------------------------------------===// - // Float to Integer Conversion Support: LegalizeTypesFloatToInt.cpp + // Float to Integer Conversion Support: LegalizeFloatTypes.cpp //===--------------------------------------------------------------------===// - SDOperand GetIntegerOp(SDOperand Op) { - SDOperand &IntegerOp = FloatToIntedNodes[Op]; - RemapNode(IntegerOp); - assert(IntegerOp.Val && "Operand wasn't converted to integer?"); - return IntegerOp; + SDOperand GetPromotedFloat(SDOperand Op) { + SDOperand &PromotedOp = PromotedFloats[Op]; + RemapNode(PromotedOp); + assert(PromotedOp.Val && "Operand wasn't converted to integer?"); + return PromotedOp; } - void SetIntegerOp(SDOperand Op, SDOperand Result); + void SetPromotedFloat(SDOperand Op, SDOperand Result); // Result Float to Integer Conversion. - void FloatToIntResult(SDNode *N, unsigned OpNo); - SDOperand FloatToIntRes_BIT_CONVERT(SDNode *N); - SDOperand FloatToIntRes_BUILD_PAIR(SDNode *N); - SDOperand FloatToIntRes_ConstantFP(ConstantFPSDNode *N); - SDOperand FloatToIntRes_FADD(SDNode *N); - SDOperand FloatToIntRes_FCOPYSIGN(SDNode *N); - SDOperand FloatToIntRes_FMUL(SDNode *N); - SDOperand FloatToIntRes_FSUB(SDNode *N); - SDOperand FloatToIntRes_LOAD(SDNode *N); - SDOperand FloatToIntRes_XINT_TO_FP(SDNode *N); + void PromoteFloatResult(SDNode *N, unsigned OpNo); + SDOperand PromoteFloatRes_BIT_CONVERT(SDNode *N); + SDOperand PromoteFloatRes_BUILD_PAIR(SDNode *N); + SDOperand PromoteFloatRes_ConstantFP(ConstantFPSDNode *N); + SDOperand PromoteFloatRes_FADD(SDNode *N); + SDOperand PromoteFloatRes_FCOPYSIGN(SDNode *N); + SDOperand PromoteFloatRes_FMUL(SDNode *N); + SDOperand PromoteFloatRes_FSUB(SDNode *N); + SDOperand PromoteFloatRes_LOAD(SDNode *N); + SDOperand PromoteFloatRes_XINT_TO_FP(SDNode *N); // Operand Float to Integer Conversion. - bool FloatToIntOperand(SDNode *N, unsigned OpNo); - SDOperand FloatToIntOp_BIT_CONVERT(SDNode *N); + bool PromoteFloatOperand(SDNode *N, unsigned OpNo); + SDOperand PromoteFloatOp_BIT_CONVERT(SDNode *N); //===--------------------------------------------------------------------===// - // Scalarization Support: LegalizeTypesScalarize.cpp + // Float Expansion Support: LegalizeFloatTypes.cpp //===--------------------------------------------------------------------===// - - SDOperand GetScalarizedOp(SDOperand Op) { - SDOperand &ScalarOp = ScalarizedNodes[Op]; - RemapNode(ScalarOp); - assert(ScalarOp.Val && "Operand wasn't scalarized?"); - return ScalarOp; + + void GetExpandedFloat(SDOperand Op, SDOperand &Lo, SDOperand &Hi); + void SetExpandedFloat(SDOperand Op, SDOperand Lo, SDOperand Hi); + + // Float Result Expansion. + void ExpandFloatResult(SDNode *N, unsigned ResNo); + + // Float Operand Expansion. + bool ExpandFloatOperand(SDNode *N, unsigned OperandNo); + + //===--------------------------------------------------------------------===// + // Scalarization Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + SDOperand GetScalarizedVector(SDOperand Op) { + SDOperand &ScalarizedOp = ScalarizedVectors[Op]; + RemapNode(ScalarizedOp); + assert(ScalarizedOp.Val && "Operand wasn't scalarized?"); + return ScalarizedOp; } - void SetScalarizedOp(SDOperand Op, SDOperand Result); - - // Result Vector Scalarization: <1 x ty> -> ty. + void SetScalarizedVector(SDOperand Op, SDOperand Result); + + // Vector Result Scalarization: <1 x ty> -> ty. void ScalarizeResult(SDNode *N, unsigned OpNo); SDOperand ScalarizeRes_BinOp(SDNode *N); SDOperand ScalarizeRes_UnaryOp(SDNode *N); @@ -363,20 +383,20 @@ private: SDOperand ScalarizeRes_UNDEF(SDNode *N); SDOperand ScalarizeRes_VECTOR_SHUFFLE(SDNode *N); - // Operand Vector Scalarization: <1 x ty> -> ty. + // Vector Operand Scalarization: <1 x ty> -> ty. bool ScalarizeOperand(SDNode *N, unsigned OpNo); SDOperand ScalarizeOp_BIT_CONVERT(SDNode *N); SDOperand ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N); SDOperand ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo); //===--------------------------------------------------------------------===// - // Vector Splitting Support: LegalizeTypesSplit.cpp + // Vector Splitting Support: LegalizeVectorTypes.cpp //===--------------------------------------------------------------------===// - - void GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi); - void SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi); - - // Result Vector Splitting: <128 x ty> -> 2 x <64 x ty>. + + void GetSplitVector(SDOperand Op, SDOperand &Lo, SDOperand &Hi); + void SetSplitVector(SDOperand Op, SDOperand Lo, SDOperand Hi); + + // Vector Result Splitting: <128 x ty> -> 2 x <64 x ty>. void SplitResult(SDNode *N, unsigned OpNo); void SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi); @@ -392,8 +412,8 @@ private: void SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi); void SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi); void SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - - // Operand Vector Splitting: <128 x ty> -> 2 x <64 x ty>. + + // Vector Operand Splitting: <128 x ty> -> 2 x <64 x ty>. bool SplitOperand(SDNode *N, unsigned OpNo); SDOperand SplitOp_BIT_CONVERT(SDNode *N); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp deleted file mode 100644 index 5c68fe2dc3d..00000000000 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp +++ /dev/null @@ -1,748 +0,0 @@ -//===-- LegalizeTypesPromote.cpp - Promotion for LegalizeTypes ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements promotion support for LegalizeTypes. Promotion is the -// act of changing a computation in an invalid type to be a computation in a -// larger type. For example, implementing i8 arithmetic in an i32 register (as -// is often needed on powerpc for example). -// -//===----------------------------------------------------------------------===// - -#include "LegalizeTypes.h" -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Result Promotion -//===----------------------------------------------------------------------===// - -/// PromoteResult - This method is called when a result of a node is found to be -/// in need of promotion to a larger type. At this point, the node may also -/// have invalid operands or may have other results that need expansion, we just -/// know that (at least) one result needs promotion. -void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Promote node result: "; N->dump(&DAG); cerr << "\n"); - SDOperand Result = SDOperand(); - - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "PromoteResult #" << ResNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to promote this operator!"); - abort(); - case ISD::UNDEF: Result = PromoteResult_UNDEF(N); break; - case ISD::Constant: Result = PromoteResult_Constant(N); break; - - case ISD::TRUNCATE: Result = PromoteResult_TRUNCATE(N); break; - case ISD::SIGN_EXTEND: - case ISD::ZERO_EXTEND: - case ISD::ANY_EXTEND: Result = PromoteResult_INT_EXTEND(N); break; - case ISD::FP_ROUND: Result = PromoteResult_FP_ROUND(N); break; - case ISD::FP_TO_SINT: - case ISD::FP_TO_UINT: Result = PromoteResult_FP_TO_XINT(N); break; - case ISD::SETCC: Result = PromoteResult_SETCC(N); break; - case ISD::LOAD: Result = PromoteResult_LOAD(cast(N)); break; - case ISD::BUILD_PAIR: Result = PromoteResult_BUILD_PAIR(N); break; - case ISD::BIT_CONVERT: Result = PromoteResult_BIT_CONVERT(N); break; - - case ISD::AND: - case ISD::OR: - case ISD::XOR: - case ISD::ADD: - case ISD::SUB: - case ISD::MUL: Result = PromoteResult_SimpleIntBinOp(N); break; - - case ISD::SDIV: - case ISD::SREM: Result = PromoteResult_SDIV(N); break; - - case ISD::UDIV: - case ISD::UREM: Result = PromoteResult_UDIV(N); break; - - case ISD::SHL: Result = PromoteResult_SHL(N); break; - case ISD::SRA: Result = PromoteResult_SRA(N); break; - case ISD::SRL: Result = PromoteResult_SRL(N); break; - - case ISD::SELECT: Result = PromoteResult_SELECT(N); break; - case ISD::SELECT_CC: Result = PromoteResult_SELECT_CC(N); break; - - case ISD::CTLZ: Result = PromoteResult_CTLZ(N); break; - case ISD::CTPOP: Result = PromoteResult_CTPOP(N); break; - case ISD::CTTZ: Result = PromoteResult_CTTZ(N); break; - - case ISD::EXTRACT_VECTOR_ELT: - Result = PromoteResult_EXTRACT_VECTOR_ELT(N); - break; - } - - // If Result is null, the sub-method took care of registering the result. - if (Result.Val) - SetPromotedOp(SDOperand(N, ResNo), Result); -} - -SDOperand DAGTypeLegalizer::PromoteResult_UNDEF(SDNode *N) { - return DAG.getNode(ISD::UNDEF, TLI.getTypeToTransformTo(N->getValueType(0))); -} - -SDOperand DAGTypeLegalizer::PromoteResult_Constant(SDNode *N) { - MVT VT = N->getValueType(0); - // Zero extend things like i1, sign extend everything else. It shouldn't - // matter in theory which one we pick, but this tends to give better code? - unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; - SDOperand Result = DAG.getNode(Opc, TLI.getTypeToTransformTo(VT), - SDOperand(N, 0)); - assert(isa(Result) && "Didn't constant fold ext?"); - return Result; -} - -SDOperand DAGTypeLegalizer::PromoteResult_TRUNCATE(SDNode *N) { - SDOperand Res; - - switch (getTypeAction(N->getOperand(0).getValueType())) { - default: assert(0 && "Unknown type action!"); - case Legal: - case Expand: - Res = N->getOperand(0); - break; - case Promote: - Res = GetPromotedOp(N->getOperand(0)); - break; - } - - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - assert(Res.getValueType().getSizeInBits() >= NVT.getSizeInBits() && - "Truncation doesn't make sense!"); - if (Res.getValueType() == NVT) - return Res; - - // Truncate to NVT instead of VT - return DAG.getNode(ISD::TRUNCATE, NVT, Res); -} - -SDOperand DAGTypeLegalizer::PromoteResult_INT_EXTEND(SDNode *N) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - - if (getTypeAction(N->getOperand(0).getValueType()) == Promote) { - SDOperand Res = GetPromotedOp(N->getOperand(0)); - assert(Res.getValueType().getSizeInBits() <= NVT.getSizeInBits() && - "Extension doesn't make sense!"); - - // If the result and operand types are the same after promotion, simplify - // to an in-register extension. - if (NVT == Res.getValueType()) { - // The high bits are not guaranteed to be anything. Insert an extend. - if (N->getOpcode() == ISD::SIGN_EXTEND) - return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, - DAG.getValueType(N->getOperand(0).getValueType())); - if (N->getOpcode() == ISD::ZERO_EXTEND) - return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType()); - assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!"); - return Res; - } - } - - // Otherwise, just extend the original operand all the way to the larger type. - return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_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::PromoteResult_FP_TO_XINT(SDNode *N) { - SDOperand Op = N->getOperand(0); - // If the operand needed to be promoted, do so now. - if (getTypeAction(Op.getValueType()) == Promote) - // The input result is prerounded, so we don't have to do anything special. - Op = GetPromotedOp(Op); - - unsigned NewOpc = N->getOpcode(); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - - // If we're promoting a UINT to a larger size, check to see if the new node - // will be legal. If it isn't, check to see if FP_TO_SINT is legal, since - // we can use that instead. This allows us to generate better code for - // FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not - // legal, such as PowerPC. - if (N->getOpcode() == ISD::FP_TO_UINT) { - if (!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) && - (TLI.isOperationLegal(ISD::FP_TO_SINT, NVT) || - TLI.getOperationAction(ISD::FP_TO_SINT, NVT)==TargetLowering::Custom)) - NewOpc = ISD::FP_TO_SINT; - } - - return DAG.getNode(NewOpc, NVT, Op); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) { - assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0))) - && "SetCC type is not legal??"); - return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)), - N->getOperand(0), N->getOperand(1), N->getOperand(2)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) { - // FIXME: Add support for indexed loads. - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - ISD::LoadExtType ExtType = - ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType(); - SDOperand Res = DAG.getExtLoad(ExtType, NVT, N->getChain(), N->getBasePtr(), - N->getSrcValue(), N->getSrcValueOffset(), - N->getMemoryVT(), N->isVolatile(), - N->getAlignment()); - - // Legalized the chain result - switch anything that used the old chain to - // use the new one. - ReplaceValueWith(SDOperand(N, 1), Res.getValue(1)); - return Res; -} - -SDOperand DAGTypeLegalizer::PromoteResult_BUILD_PAIR(SDNode *N) { - // The pair element type may be legal, or may not promote to the same type as - // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases. - return DAG.getNode(ISD::ANY_EXTEND, - TLI.getTypeToTransformTo(N->getValueType(0)), - JoinIntegers(N->getOperand(0), N->getOperand(1))); -} - -SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) { - SDOperand InOp = N->getOperand(0); - MVT InVT = InOp.getValueType(); - MVT NInVT = TLI.getTypeToTransformTo(InVT); - MVT OutVT = TLI.getTypeToTransformTo(N->getValueType(0)); - - switch (getTypeAction(InVT)) { - default: - assert(false && "Unknown type action!"); - break; - case Legal: - break; - case Promote: - if (OutVT.getSizeInBits() == NInVT.getSizeInBits()) - // The input promotes to the same size. Convert the promoted value. - return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedOp(InOp)); - break; - case Expand: - break; - case FloatToInt: - // Promote the integer operand by hand. - return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetIntegerOp(InOp)); - case Scalarize: - // Convert the element to an integer and promote it by hand. - return DAG.getNode(ISD::ANY_EXTEND, OutVT, - BitConvertToInteger(GetScalarizedOp(InOp))); - case Split: - // 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; - GetSplitOp(N->getOperand(0), Lo, Hi); - Lo = BitConvertToInteger(Lo); - Hi = BitConvertToInteger(Hi); - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - InOp = DAG.getNode(ISD::ANY_EXTEND, - MVT::getIntegerVT(OutVT.getSizeInBits()), - JoinIntegers(Lo, Hi)); - return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp); - } - - // Otherwise, lower the bit-convert to a store/load from the stack, then - // promote the load. - SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); - return PromoteResult_LOAD(cast(Op.Val)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) { - // The input may have strange things in the top bits of the registers, but - // these operations don't care. They may have weird bits going out, but - // that too is okay if they are integer operations. - SDOperand LHS = GetPromotedOp(N->getOperand(0)); - SDOperand RHS = GetPromotedOp(N->getOperand(1)); - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SDIV(SDNode *N) { - // Sign extend the input. - SDOperand LHS = GetPromotedOp(N->getOperand(0)); - SDOperand RHS = GetPromotedOp(N->getOperand(1)); - MVT VT = N->getValueType(0); - LHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, LHS.getValueType(), LHS, - DAG.getValueType(VT)); - RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, RHS.getValueType(), RHS, - DAG.getValueType(VT)); - - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); -} - -SDOperand DAGTypeLegalizer::PromoteResult_UDIV(SDNode *N) { - // Zero extend the input. - SDOperand LHS = GetPromotedOp(N->getOperand(0)); - SDOperand RHS = GetPromotedOp(N->getOperand(1)); - MVT VT = N->getValueType(0); - LHS = DAG.getZeroExtendInReg(LHS, VT); - RHS = DAG.getZeroExtendInReg(RHS, VT); - - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SHL(SDNode *N) { - return DAG.getNode(ISD::SHL, TLI.getTypeToTransformTo(N->getValueType(0)), - GetPromotedOp(N->getOperand(0)), N->getOperand(1)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SRA(SDNode *N) { - // The input value must be properly sign extended. - MVT VT = N->getValueType(0); - MVT NVT = TLI.getTypeToTransformTo(VT); - SDOperand Res = GetPromotedOp(N->getOperand(0)); - Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, DAG.getValueType(VT)); - return DAG.getNode(ISD::SRA, NVT, Res, N->getOperand(1)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SRL(SDNode *N) { - // The input value must be properly zero extended. - MVT VT = N->getValueType(0); - MVT NVT = TLI.getTypeToTransformTo(VT); - SDOperand Res = GetPromotedZExtOp(N->getOperand(0)); - return DAG.getNode(ISD::SRL, NVT, Res, N->getOperand(1)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SELECT(SDNode *N) { - SDOperand LHS = GetPromotedOp(N->getOperand(1)); - SDOperand RHS = GetPromotedOp(N->getOperand(2)); - return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0),LHS,RHS); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SELECT_CC(SDNode *N) { - SDOperand LHS = GetPromotedOp(N->getOperand(2)); - SDOperand RHS = GetPromotedOp(N->getOperand(3)); - return DAG.getNode(ISD::SELECT_CC, LHS.getValueType(), N->getOperand(0), - N->getOperand(1), LHS, RHS, N->getOperand(4)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_CTLZ(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - MVT OVT = N->getValueType(0); - MVT NVT = Op.getValueType(); - // Zero extend to the promoted type and do the count there. - Op = DAG.getNode(ISD::CTLZ, NVT, DAG.getZeroExtendInReg(Op, OVT)); - // Subtract off the extra leading bits in the bigger type. - return DAG.getNode(ISD::SUB, NVT, Op, - DAG.getConstant(NVT.getSizeInBits() - - OVT.getSizeInBits(), NVT)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_CTPOP(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - MVT OVT = N->getValueType(0); - MVT NVT = Op.getValueType(); - // Zero extend to the promoted type and do the count there. - return DAG.getNode(ISD::CTPOP, NVT, DAG.getZeroExtendInReg(Op, OVT)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_CTTZ(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - MVT OVT = N->getValueType(0); - MVT NVT = Op.getValueType(); - // 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)); - return DAG.getNode(ISD::CTTZ, NVT, Op); -} - -SDOperand DAGTypeLegalizer::PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N) { - MVT OldVT = N->getValueType(0); - SDOperand OldVec = N->getOperand(0); - unsigned OldElts = OldVec.getValueType().getVectorNumElements(); - - if (OldElts == 1) { - assert(!isTypeLegal(OldVec.getValueType()) && - "Legal one-element vector of a type needing promotion!"); - // It is tempting to follow GetScalarizedOp by a call to GetPromotedOp, - // but this would be wrong because the scalarized value may not yet have - // been processed. - return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT), - GetScalarizedOp(OldVec)); - } - - // Convert to a vector half as long with an element type of twice the width, - // for example <4 x i16> -> <2 x i32>. - assert(!(OldElts & 1) && "Odd length vectors not supported!"); - MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); - assert(OldVT.isSimple() && NewVT.isSimple()); - - SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, - MVT::getVectorVT(NewVT, OldElts / 2), - OldVec); - - // Extract the element at OldIdx / 2 from the new vector. - SDOperand OldIdx = N->getOperand(1); - SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx, - DAG.getConstant(1, TLI.getShiftAmountTy())); - SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx); - - // Select the appropriate half of the element: Lo if OldIdx was even, - // Hi if it was odd. - SDOperand Lo = Elt; - SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt, - DAG.getConstant(OldVT.getSizeInBits(), - TLI.getShiftAmountTy())); - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx, - DAG.getConstant(1, TLI.getShiftAmountTy())); - return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo); -} - -//===----------------------------------------------------------------------===// -// Operand Promotion -//===----------------------------------------------------------------------===// - -/// PromoteOperand - This method is called when the specified operand of the -/// specified node is found to need promotion. At this point, all of the result -/// types of the node are known to be legal, but other operands of the node may -/// need promotion or expansion as well as the specified one. -bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Promote node operand: "; N->dump(&DAG); cerr << "\n"); - SDOperand Res; - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "PromoteOperand 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 = PromoteOperand_ANY_EXTEND(N); break; - case ISD::ZERO_EXTEND: Res = PromoteOperand_ZERO_EXTEND(N); break; - case ISD::SIGN_EXTEND: Res = PromoteOperand_SIGN_EXTEND(N); break; - case ISD::TRUNCATE: Res = PromoteOperand_TRUNCATE(N); break; - case ISD::FP_EXTEND: Res = PromoteOperand_FP_EXTEND(N); break; - case ISD::FP_ROUND: Res = PromoteOperand_FP_ROUND(N); break; - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: Res = PromoteOperand_INT_TO_FP(N); break; - case ISD::BUILD_PAIR: Res = PromoteOperand_BUILD_PAIR(N); break; - - case ISD::SELECT: Res = PromoteOperand_SELECT(N, OpNo); break; - case ISD::BRCOND: Res = PromoteOperand_BRCOND(N, OpNo); break; - case ISD::BR_CC: Res = PromoteOperand_BR_CC(N, OpNo); break; - case ISD::SETCC: Res = PromoteOperand_SETCC(N, OpNo); break; - - case ISD::STORE: Res = PromoteOperand_STORE(cast(N), - OpNo); break; - - case ISD::BUILD_VECTOR: Res = PromoteOperand_BUILD_VECTOR(N); break; - case ISD::INSERT_VECTOR_ELT: - Res = PromoteOperand_INSERT_VECTOR_ELT(N, OpNo); - break; - - case ISD::RET: Res = PromoteOperand_RET(N, OpNo); break; - - case ISD::MEMBARRIER: Res = PromoteOperand_MEMBARRIER(N); break; - } - - // If the result is null, the sub-method took care of registering results etc. - if (!Res.Val) return false; - // If the result is N, the sub-method updated N in place. - if (Res.Val == N) { - // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit - // any new operands to N. - ReanalyzeNode(N); - return true; - } - - assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && - "Invalid operand expansion"); - - ReplaceValueWith(SDOperand(N, 0), Res); - return false; -} - -SDOperand DAGTypeLegalizer::PromoteOperand_ANY_EXTEND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - return DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_ZERO_EXTEND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); - return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType()); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_SIGN_EXTEND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); - return DAG.getNode(ISD::SIGN_EXTEND_INREG, Op.getValueType(), - Op, DAG.getValueType(N->getOperand(0).getValueType())); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_TRUNCATE(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), Op); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_FP_EXTEND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - return DAG.getNode(ISD::FP_EXTEND, N->getValueType(0), Op); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_FP_ROUND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Op, - DAG.getIntPtrConstant(0)); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_INT_TO_FP(SDNode *N) { - SDOperand In = GetPromotedOp(N->getOperand(0)); - MVT OpVT = N->getOperand(0).getValueType(); - if (N->getOpcode() == ISD::UINT_TO_FP) - In = DAG.getZeroExtendInReg(In, OpVT); - else - In = DAG.getNode(ISD::SIGN_EXTEND_INREG, In.getValueType(), - In, DAG.getValueType(OpVT)); - - return DAG.UpdateNodeOperands(SDOperand(N, 0), In); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_PAIR(SDNode *N) { - // Since the result type is legal, the operands must promote to it. - MVT OVT = N->getOperand(0).getValueType(); - SDOperand Lo = GetPromotedOp(N->getOperand(0)); - SDOperand Hi = GetPromotedOp(N->getOperand(1)); - assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?"); - - Lo = DAG.getZeroExtendInReg(Lo, OVT); - Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi, - DAG.getConstant(OVT.getSizeInBits(), - TLI.getShiftAmountTy())); - return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_SELECT(SDNode *N, unsigned OpNo) { - assert(OpNo == 0 && "Only know how to promote condition"); - SDOperand Cond = GetPromotedOp(N->getOperand(0)); // Promote the condition. - - // The top bits of the promoted condition are not necessarily zero, ensure - // that the value is properly zero extended. - unsigned BitWidth = Cond.getValueSizeInBits(); - if (!DAG.MaskedValueIsZero(Cond, - APInt::getHighBitsSet(BitWidth, BitWidth-1))) - Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); - - // The chain (Op#0) and basic block destination (Op#2) are always legal types. - return DAG.UpdateNodeOperands(SDOperand(N, 0), Cond, N->getOperand(1), - N->getOperand(2)); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_BRCOND(SDNode *N, unsigned OpNo) { - assert(OpNo == 1 && "only know how to promote condition"); - SDOperand Cond = GetPromotedOp(N->getOperand(1)); // Promote the condition. - - // The top bits of the promoted condition are not necessarily zero, ensure - // that the value is properly zero extended. - unsigned BitWidth = Cond.getValueSizeInBits(); - if (!DAG.MaskedValueIsZero(Cond, - APInt::getHighBitsSet(BitWidth, BitWidth-1))) - Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); - - // The chain (Op#0) and basic block destination (Op#2) are always legal types. - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), Cond, - N->getOperand(2)); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_BR_CC(SDNode *N, unsigned OpNo) { - assert(OpNo == 2 && "Don't know how to promote this operand"); - - SDOperand LHS = N->getOperand(2); - SDOperand RHS = N->getOperand(3); - PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(1))->get()); - - // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always - // legal types. - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), - N->getOperand(1), LHS, RHS, N->getOperand(4)); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_SETCC(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(N->getOperand(2))->get()); - - // The CC (#2) is always legal. - return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2)); -} - -/// PromoteSetCCOperands - Promote the operands of a comparison. This code is -/// shared among BR_CC, SELECT_CC, and SETCC handlers. -void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS, - ISD::CondCode CCCode) { - MVT VT = NewLHS.getValueType(); - - // Get the promoted values. - NewLHS = GetPromotedOp(NewLHS); - NewRHS = GetPromotedOp(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 - // it. - switch (CCCode) { - default: assert(0 && "Unknown integer comparison!"); - case ISD::SETEQ: - case ISD::SETNE: - case ISD::SETUGE: - case ISD::SETUGT: - case ISD::SETULE: - case ISD::SETULT: - // ALL of these operations will work if we either sign or zero extend - // the operands (including the unsigned comparisons!). Zero extend is - // usually a simpler/cheaper operation, so prefer it. - NewLHS = DAG.getZeroExtendInReg(NewLHS, VT); - NewRHS = DAG.getZeroExtendInReg(NewRHS, VT); - return; - case ISD::SETGE: - case ISD::SETGT: - case ISD::SETLT: - case ISD::SETLE: - NewLHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewLHS.getValueType(), NewLHS, - DAG.getValueType(VT)); - NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS, - DAG.getValueType(VT)); - return; - } -} - -SDOperand DAGTypeLegalizer::PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo){ - // FIXME: Add support for indexed stores. - SDOperand Ch = N->getChain(), Ptr = N->getBasePtr(); - int SVOffset = N->getSrcValueOffset(); - unsigned Alignment = N->getAlignment(); - bool isVolatile = N->isVolatile(); - - SDOperand Val = GetPromotedOp(N->getValue()); // Get promoted value. - - assert(!N->isTruncatingStore() && "Cannot promote this store operand!"); - - // Truncate the value and store the result. - return DAG.getTruncStore(Ch, Val, Ptr, N->getSrcValue(), - SVOffset, N->getMemoryVT(), - isVolatile, Alignment); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_VECTOR(SDNode *N) { - // The vector type is legal but the element type is not. This implies - // that the vector is a power-of-two in length and that the element - // type does not have a strange size (eg: it is not i1). - MVT VecVT = N->getValueType(0); - unsigned NumElts = VecVT.getVectorNumElements(); - assert(!(NumElts & 1) && "Legal vector of one illegal element?"); - - // Build a vector of half the length out of elements of twice the bitwidth. - // For example <4 x i16> -> <2 x i32>. - MVT OldVT = N->getOperand(0).getValueType(); - MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); - assert(OldVT.isSimple() && NewVT.isSimple()); - - std::vector NewElts; - NewElts.reserve(NumElts/2); - - for (unsigned i = 0; i < NumElts; i += 2) { - // Combine two successive elements into one promoted element. - SDOperand Lo = N->getOperand(i); - SDOperand Hi = N->getOperand(i+1); - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - NewElts.push_back(JoinIntegers(Lo, Hi)); - } - - SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, - MVT::getVectorVT(NewVT, NewElts.size()), - &NewElts[0], NewElts.size()); - - // Convert the new vector to the old vector type. - return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, - unsigned OpNo) { - if (OpNo == 1) { - // Promote the inserted value. This is valid because the type does not - // have to match the vector element type. - - // Check that any extra bits introduced will be truncated away. - assert(N->getOperand(1).getValueType().getSizeInBits() >= - N->getValueType(0).getVectorElementType().getSizeInBits() && - "Type of inserted value narrower than vector element type!"); - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), - GetPromotedOp(N->getOperand(1)), - N->getOperand(2)); - } - - assert(OpNo == 2 && "Different operand and result vector types?"); - - // Promote the index. - SDOperand Idx = N->getOperand(2); - Idx = DAG.getZeroExtendInReg(GetPromotedOp(Idx), Idx.getValueType()); - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), - N->getOperand(1), Idx); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_RET(SDNode *N, unsigned OpNo) { - assert(!(OpNo & 1) && "Return values should be legally typed!"); - assert((N->getNumOperands() & 1) && "Wrong number of operands!"); - - // It's a flag. Promote all the flags in one hit, as an optimization. - SmallVector NewValues(N->getNumOperands()); - NewValues[0] = N->getOperand(0); // The chain - for (unsigned i = 1, e = N->getNumOperands(); i < e; i += 2) { - // The return value. - NewValues[i] = N->getOperand(i); - - // The flag. - SDOperand Flag = N->getOperand(i + 1); - if (getTypeAction(Flag.getValueType()) == Promote) - // The promoted value may have rubbish in the new bits, but that - // doesn't matter because those bits aren't queried anyway. - Flag = GetPromotedOp(Flag); - NewValues[i + 1] = Flag; - } - - return DAG.UpdateNodeOperands(SDOperand (N, 0), - &NewValues[0], NewValues.size()); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_MEMBARRIER(SDNode *N) { - SDOperand NewOps[6]; - NewOps[0] = N->getOperand(0); - for (unsigned i = 1; i < array_lengthof(NewOps); ++i) { - SDOperand Flag = GetPromotedOp(N->getOperand(i)); - NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1); - } - return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps, - array_lengthof(NewOps)); -} diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp deleted file mode 100644 index 9f758ff0888..00000000000 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp +++ /dev/null @@ -1,233 +0,0 @@ -//===-- LegalizeTypesScalarize.cpp - Scalarization for LegalizeTypes ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements scalarization support for LegalizeTypes. Scalarization -// is the act of changing a computation in an invalid single-element vector type -// to be a computation in its scalar element type. For example, implementing -// <1 x f32> arithmetic in a scalar f32 register. This is needed as a base case -// when scalarizing vector arithmetic like <4 x f32>, which eventually -// decomposes to scalars if the target doesn't support v4f32 or v2f32 types. -// -//===----------------------------------------------------------------------===// - -#include "LegalizeTypes.h" -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Result Vector Scalarization: <1 x ty> -> ty. -//===----------------------------------------------------------------------===// - -void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG); - cerr << "\n"); - SDOperand R = SDOperand(); - - // FIXME: Custom lowering for scalarization? -#if 0 - // See if the target wants to custom expand this node. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) { - // If the target wants to, allow it to lower this itself. - if (SDNode *P = TLI.ExpandOperationResult(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; - } - } -#endif - - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "ScalarizeResult #" << ResNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to scalarize the result of this operator!"); - abort(); - - case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break; - case ISD::LOAD: R = ScalarizeRes_LOAD(cast(N)); break; - case ISD::ADD: - case ISD::FADD: - case ISD::SUB: - case ISD::FSUB: - case ISD::MUL: - case ISD::FMUL: - case ISD::SDIV: - case ISD::UDIV: - case ISD::FDIV: - case ISD::SREM: - case ISD::UREM: - case ISD::FREM: - case ISD::FPOW: - case ISD::AND: - case ISD::OR: - case ISD::XOR: R = ScalarizeRes_BinOp(N); break; - case ISD::FNEG: - case ISD::FABS: - case ISD::FSQRT: - case ISD::FSIN: - case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break; - case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break; - case ISD::BUILD_VECTOR: R = N->getOperand(0); break; - case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break; - case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break; - case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break; - case ISD::SELECT: R = ScalarizeRes_SELECT(N); break; - } - - // If R is null, the sub-method took care of registering the result. - if (R.Val) - SetScalarizedOp(SDOperand(N, ResNo), R); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) { - return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType()); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) { - // FIXME: Add support for indexed loads. - SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(), - N->getChain(), N->getBasePtr(), - N->getSrcValue(), N->getSrcValueOffset(), - N->isVolatile(), N->getAlignment()); - - // Legalized the chain result - switch anything that used the old chain to - // use the new one. - ReplaceValueWith(SDOperand(N, 1), Result.getValue(1)); - return Result; -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) { - SDOperand LHS = GetScalarizedOp(N->getOperand(0)); - SDOperand RHS = GetScalarizedOp(N->getOperand(1)); - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) { - SDOperand Op = GetScalarizedOp(N->getOperand(0)); - return DAG.getNode(N->getOpcode(), Op.getValueType(), Op); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) { - SDOperand Op = GetScalarizedOp(N->getOperand(0)); - return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1)); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) { - // The value to insert may have a wider type than the vector element type, - // so be sure to truncate it to the element type if necessary. - SDOperand Op = N->getOperand(1); - MVT EltVT = N->getValueType(0).getVectorElementType(); - if (Op.getValueType().bitsGT(EltVT)) - Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op); - assert(Op.getValueType() == EltVT && "Invalid type for inserted value!"); - return Op; -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) { - // Figure out if the scalar is the LHS or RHS and return it. - SDOperand EltNum = N->getOperand(2).getOperand(0); - unsigned Op = cast(EltNum)->getValue() != 0; - return GetScalarizedOp(N->getOperand(Op)); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) { - MVT NewVT = N->getValueType(0).getVectorElementType(); - return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0)); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) { - SDOperand LHS = GetScalarizedOp(N->getOperand(1)); - return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS, - GetScalarizedOp(N->getOperand(2))); -} - - -//===----------------------------------------------------------------------===// -// Operand Vector Scalarization <1 x ty> -> ty. -//===----------------------------------------------------------------------===// - -bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG); - cerr << "\n"); - SDOperand Res(0, 0); - - // FIXME: Should we support custom lowering for scalarization? -#if 0 - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) - Res = TLI.LowerOperation(SDOperand(N, 0), DAG); -#endif - - if (Res.Val == 0) { - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "ScalarizeOperand Op #" << OpNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to scalarize this operator's operand!"); - abort(); - - case ISD::BIT_CONVERT: - Res = ScalarizeOp_BIT_CONVERT(N); break; - - case ISD::EXTRACT_VECTOR_ELT: - Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break; - - case ISD::STORE: - Res = ScalarizeOp_STORE(cast(N), OpNo); break; - } - } - - // If the result is null, the sub-method took care of registering results etc. - if (!Res.Val) return false; - - // If the result is N, the sub-method updated N in place. Check to see if any - // operands are new, and if so, mark them. - if (Res.Val == N) { - // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit - // any new operands to N. - ReanalyzeNode(N); - return true; - } - - assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && - "Invalid operand expansion"); - - ReplaceValueWith(SDOperand(N, 0), Res); - return false; -} - -/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs -/// to be scalarized, it must be <1 x ty>. Convert the element instead. -SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) { - SDOperand Elt = GetScalarizedOp(N->getOperand(0)); - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt); -} - -/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be -/// scalarized, it must be <1 x ty>, so just return the element, ignoring the -/// index. -SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) { - return GetScalarizedOp(N->getOperand(0)); -} - -/// ScalarizeOp_STORE - If the value to store is a vector that needs to be -/// scalarized, it must be <1 x ty>. Just store the element. -SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) { - // FIXME: Add support for indexed stores. - assert(OpNo == 1 && "Do not know how to scalarize this operand!"); - return DAG.getStore(N->getChain(), GetScalarizedOp(N->getOperand(1)), - N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), - N->isVolatile(), N->getAlignment()); -} diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp similarity index 68% rename from lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp rename to lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index 74aae7f4c82..392a923a10e 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -1,4 +1,4 @@ -//===-- LegalizeTypesSplit.cpp - Vector Splitting for LegalizeTypes -------===// +//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,14 @@ // //===----------------------------------------------------------------------===// // -// This file implements vector splitting support for LegalizeTypes. Vector -// splitting is the act of changing a computation in an invalid vector type to +// This file performs vector type splitting and scalarization for LegalizeTypes. +// Scalarization is the act of changing a computation in an illegal one-element +// vector type to be a computation in its scalar element type. For example, +// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed +// as a base case when scalarizing vector arithmetic like <4 x f32>, which +// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32 +// types. +// Splitting is the act of changing a computation in an invalid vector type to // be a computation in multiple vectors of a smaller type. For example, // implementing <128 x f32> operations in terms of two <64 x f32> operations. // @@ -17,6 +23,220 @@ #include "LegalizeTypes.h" using namespace llvm; +//===----------------------------------------------------------------------===// +// Result Vector Scalarization: <1 x ty> -> ty. +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG); + cerr << "\n"); + SDOperand R = SDOperand(); + + // FIXME: Custom lowering for scalarization? +#if 0 + // See if the target wants to custom expand this node. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.ExpandOperationResult(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; + } + } +#endif + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "ScalarizeResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to scalarize the result of this operator!"); + abort(); + + case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break; + case ISD::LOAD: R = ScalarizeRes_LOAD(cast(N)); break; + case ISD::ADD: + case ISD::FADD: + case ISD::SUB: + case ISD::FSUB: + case ISD::MUL: + case ISD::FMUL: + case ISD::SDIV: + case ISD::UDIV: + case ISD::FDIV: + case ISD::SREM: + case ISD::UREM: + case ISD::FREM: + case ISD::FPOW: + case ISD::AND: + case ISD::OR: + case ISD::XOR: R = ScalarizeRes_BinOp(N); break; + case ISD::FNEG: + case ISD::FABS: + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break; + case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break; + case ISD::BUILD_VECTOR: R = N->getOperand(0); break; + case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break; + case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break; + case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break; + case ISD::SELECT: R = ScalarizeRes_SELECT(N); break; + } + + // If R is null, the sub-method took care of registering the result. + if (R.Val) + SetScalarizedVector(SDOperand(N, ResNo), R); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) { + return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType()); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) { + // FIXME: Add support for indexed loads. + SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(), + N->getChain(), N->getBasePtr(), + N->getSrcValue(), N->getSrcValueOffset(), + N->isVolatile(), N->getAlignment()); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDOperand(N, 1), Result.getValue(1)); + return Result; +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) { + SDOperand LHS = GetScalarizedVector(N->getOperand(0)); + SDOperand RHS = GetScalarizedVector(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) { + SDOperand Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(N->getOpcode(), Op.getValueType(), Op); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) { + SDOperand Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1)); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) { + // The value to insert may have a wider type than the vector element type, + // so be sure to truncate it to the element type if necessary. + SDOperand Op = N->getOperand(1); + MVT EltVT = N->getValueType(0).getVectorElementType(); + if (Op.getValueType().bitsGT(EltVT)) + Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op); + assert(Op.getValueType() == EltVT && "Invalid type for inserted value!"); + return Op; +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) { + // Figure out if the scalar is the LHS or RHS and return it. + SDOperand EltNum = N->getOperand(2).getOperand(0); + unsigned Op = cast(EltNum)->getValue() != 0; + return GetScalarizedVector(N->getOperand(Op)); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) { + MVT NewVT = N->getValueType(0).getVectorElementType(); + return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0)); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) { + SDOperand LHS = GetScalarizedVector(N->getOperand(1)); + return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS, + GetScalarizedVector(N->getOperand(2))); +} + + +//===----------------------------------------------------------------------===// +// Operand Vector Scalarization <1 x ty> -> ty. +//===----------------------------------------------------------------------===// + +bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG); + cerr << "\n"); + SDOperand Res(0, 0); + + // FIXME: Should we support custom lowering for scalarization? +#if 0 + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, 0), DAG); +#endif + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "ScalarizeOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to scalarize this operator's operand!"); + abort(); + + case ISD::BIT_CONVERT: + Res = ScalarizeOp_BIT_CONVERT(N); break; + + case ISD::EXTRACT_VECTOR_ELT: + Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break; + + case ISD::STORE: + Res = ScalarizeOp_STORE(cast(N), OpNo); break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + + // If the result is N, the sub-method updated N in place. Check to see if any + // operands are new, and if so, mark them. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of promotion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} + +/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs +/// to be scalarized, it must be <1 x ty>. Convert the element instead. +SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) { + SDOperand Elt = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt); +} + +/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be +/// scalarized, it must be <1 x ty>, so just return the element, ignoring the +/// index. +SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) { + return GetScalarizedVector(N->getOperand(0)); +} + +/// ScalarizeOp_STORE - If the value to store is a vector that needs to be +/// scalarized, it must be <1 x ty>. Just store the element. +SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) { + // FIXME: Add support for indexed stores. + assert(OpNo == 1 && "Do not know how to scalarize this operand!"); + return DAG.getStore(N->getChain(), GetScalarizedVector(N->getOperand(1)), + N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), + N->isVolatile(), N->getAlignment()); +} + + /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector /// type that needs to be split. This handles non-power of two vectors. static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) { @@ -46,10 +266,10 @@ static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) { void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { DEBUG(cerr << "Split node result: "; N->dump(&DAG); cerr << "\n"); SDOperand Lo, Hi; - + #if 0 // See if the target wants to custom expand this node. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == TargetLowering::Custom) { // If the target wants to, allow it to lower this itself. if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { @@ -60,7 +280,7 @@ void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { } } #endif - + switch (N->getOpcode()) { default: #ifndef NDEBUG @@ -69,7 +289,7 @@ void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { #endif assert(0 && "Do not know how to split the result of this operator!"); abort(); - + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; case ISD::LOAD: SplitRes_LOAD(cast(N), Lo, Hi); break; case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break; @@ -109,10 +329,10 @@ void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break; case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; } - + // If Lo/Hi is null, the sub-method took care of registering results etc. if (Lo.Val) - SetSplitOp(SDOperand(N, ResNo), Lo, Hi); + SetSplitVector(SDOperand(N, ResNo), Lo, Hi); } void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { @@ -123,19 +343,19 @@ void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { Hi = DAG.getNode(ISD::UNDEF, HiVT); } -void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD, +void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD, SDOperand &Lo, SDOperand &Hi) { // FIXME: Add support for indexed loads. MVT LoVT, HiVT; GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT); - + SDOperand Ch = LD->getChain(); SDOperand Ptr = LD->getBasePtr(); const Value *SV = LD->getSrcValue(); int SVOffset = LD->getSrcValueOffset(); unsigned Alignment = LD->getAlignment(); bool isVolatile = LD->isVolatile(); - + Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); unsigned IncrementSize = LoVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, @@ -143,12 +363,12 @@ void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD, SVOffset += IncrementSize; Alignment = MinAlign(Alignment, IncrementSize); Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); - + // Build a factor node to remember that this load is independent of the // other one. SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), Hi.getValue(1)); - + // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDOperand(LD, 1), TF); @@ -165,7 +385,7 @@ void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand Vec = N->getOperand(0); SDOperand Elt = N->getOperand(1); SDOperand Idx = N->getOperand(2); - GetSplitOp(Vec, Lo, Hi); + GetSplitVector(Vec, Lo, Hi); if (ConstantSDNode *CIdx = dyn_cast(Idx)) { unsigned IdxVal = CIdx->getValue(); @@ -195,7 +415,7 @@ void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SplitRes_LOAD(cast(Load.Val), Lo, Hi); } -void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, +void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // Build the low part. SDOperand Mask = N->getOperand(2); @@ -206,7 +426,7 @@ void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, unsigned LoNumElts = LoVT.getVectorNumElements(); unsigned NumElements = Mask.getNumOperands(); - // Insert all of the elements from the input that are needed. We use + // Insert all of the elements from the input that are needed. We use // buildvector of extractelement here because the input vectors will have // to be legalized, so this makes the code simpler. for (unsigned i = 0; i != LoNumElts; ++i) { @@ -221,7 +441,7 @@ void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, } Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &Ops[0], Ops.size()); Ops.clear(); - + for (unsigned i = LoNumElts; i != NumElements; ++i) { unsigned Idx = cast(Mask.getOperand(i))->getValue(); SDOperand InVec = N->getOperand(0); @@ -235,19 +455,19 @@ void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size()); } -void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, +void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT LoVT, HiVT; GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); unsigned LoNumElts = LoVT.getVectorNumElements(); SmallVector LoOps(N->op_begin(), N->op_begin()+LoNumElts); Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &LoOps[0], LoOps.size()); - + SmallVector HiOps(N->op_begin()+LoNumElts, N->op_end()); Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size()); } -void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N, +void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // FIXME: Handle non-power-of-two vectors? unsigned NumSubvectors = N->getNumOperands() / 2; @@ -262,12 +482,12 @@ void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N, SmallVector LoOps(N->op_begin(), N->op_begin()+NumSubvectors); Lo = DAG.getNode(ISD::CONCAT_VECTORS, LoVT, &LoOps[0], LoOps.size()); - + SmallVector HiOps(N->op_begin()+NumSubvectors, N->op_end()); Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size()); } -void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, +void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // We know the result is a vector. The input may be either a vector or a // scalar value. @@ -282,16 +502,20 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, default: assert(false && "Unknown type action!"); case Legal: - case FloatToInt: - case Promote: + case PromoteInteger: + case PromoteFloat: case Scalarize: break; - case Expand: + case ExpandInteger: + case ExpandFloat: // A scalar to vector conversion, where the scalar needs expansion. // If the vector is being split in two then we can just convert the // expanded pieces. if (LoVT == HiVT) { - GetExpandedOp(InOp, Lo, Hi); + if (InVT.isInteger()) + GetExpandedInteger(InOp, Lo, Hi); + else + GetExpandedFloat(InOp, Lo, Hi); if (TLI.isBigEndian()) std::swap(Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); @@ -302,7 +526,7 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, case Split: // If the input is a vector that needs to be split, convert each split // piece of the input now. - GetSplitOp(InOp, Lo, Hi); + GetSplitVector(InOp, Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); return; @@ -324,10 +548,10 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { SDOperand LHSLo, LHSHi; - GetSplitOp(N->getOperand(0), LHSLo, LHSHi); + GetSplitVector(N->getOperand(0), LHSLo, LHSHi); SDOperand RHSLo, RHSHi; - GetSplitOp(N->getOperand(1), RHSLo, RHSHi); - + GetSplitVector(N->getOperand(1), RHSLo, RHSHi); + Lo = DAG.getNode(N->getOpcode(), LHSLo.getValueType(), LHSLo, RHSLo); Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi); } @@ -337,13 +561,13 @@ void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT LoVT, HiVT; GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - GetSplitOp(N->getOperand(0), Lo, Hi); + GetSplitVector(N->getOperand(0), Lo, Hi); Lo = DAG.getNode(N->getOpcode(), LoVT, Lo); Hi = DAG.getNode(N->getOpcode(), HiVT, Hi); } void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - GetSplitOp(N->getOperand(0), Lo, Hi); + GetSplitVector(N->getOperand(0), Lo, Hi); Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1)); Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1)); } @@ -351,9 +575,9 @@ void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) { void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){ SDOperand LL, LH, RL, RH; - GetSplitOp(N->getOperand(1), LL, LH); - GetSplitOp(N->getOperand(2), RL, RH); - + GetSplitVector(N->getOperand(1), LL, LH); + GetSplitVector(N->getOperand(2), RL, RH); + SDOperand Cond = N->getOperand(0); Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL); Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH); @@ -371,13 +595,13 @@ void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { DEBUG(cerr << "Split node operand: "; N->dump(&DAG); cerr << "\n"); SDOperand Res(0, 0); - + #if 0 - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == TargetLowering::Custom) Res = TLI.LowerOperation(SDOperand(N, 0), DAG); #endif - + if (Res.Val == 0) { switch (N->getOpcode()) { default: @@ -397,10 +621,10 @@ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break; } } - + // If the result is null, the sub-method took care of registering results etc. if (!Res.Val) return false; - + // If the result is N, the sub-method updated N in place. Check to see if any // operands are new, and if so, mark them. if (Res.Val == N) { @@ -413,7 +637,7 @@ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && "Invalid operand expansion"); - + ReplaceValueWith(SDOperand(N, 0), Res); return false; } @@ -421,23 +645,23 @@ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) { // FIXME: Add support for indexed stores. assert(OpNo == 1 && "Can only split the stored value"); - + SDOperand Ch = N->getChain(); SDOperand Ptr = N->getBasePtr(); int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); bool isVol = N->isVolatile(); SDOperand Lo, Hi; - GetSplitOp(N->getOperand(1), Lo, Hi); + GetSplitVector(N->getOperand(1), Lo, Hi); unsigned IncrementSize = Lo.getValueType().getSizeInBits()/8; Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment); - + // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, DAG.getIntPtrConstant(IncrementSize)); - + Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, isVol, MinAlign(Alignment, IncrementSize)); return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); @@ -448,11 +672,11 @@ SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) { // FIXME: Returns of gcc generic vectors larger than a legal vector // type should be returned by reference! SDOperand Lo, Hi; - GetSplitOp(N->getOperand(1), Lo, Hi); + GetSplitVector(N->getOperand(1), Lo, Hi); SDOperand Chain = N->getOperand(0); // The chain. SDOperand Sign = N->getOperand(2); // Signness - + return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign); } @@ -461,7 +685,7 @@ SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) { // end up being split all the way down to individual components. Convert the // split pieces into integers and reassemble. SDOperand Lo, Hi; - GetSplitOp(N->getOperand(0), Lo, Hi); + GetSplitVector(N->getOperand(0), Lo, Hi); Lo = BitConvertToInteger(Lo); Hi = BitConvertToInteger(Hi); @@ -482,7 +706,7 @@ SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) { assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!"); SDOperand Lo, Hi; - GetSplitOp(Vec, Lo, Hi); + GetSplitVector(Vec, Lo, Hi); uint64_t LoElts = Lo.getValueType().getVectorNumElements(); @@ -510,7 +734,7 @@ SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) { MVT SubVT = N->getValueType(0); SDOperand Idx = N->getOperand(1); SDOperand Lo, Hi; - GetSplitOp(N->getOperand(0), Lo, Hi); + GetSplitVector(N->getOperand(0), Lo, Hi); uint64_t LoElts = Lo.getValueType().getVectorNumElements(); uint64_t IdxVal = cast(Idx)->getValue();