diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 293 |
1 files changed, 217 insertions, 76 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 4a686bc227de..b8a3dd014901 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -18,6 +18,7 @@ //===----------------------------------------------------------------------===// #include "LegalizeTypes.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/KnownBits.h" @@ -96,8 +97,14 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { case ISD::EXTRACT_SUBVECTOR: Res = PromoteIntRes_EXTRACT_SUBVECTOR(N); break; + case ISD::INSERT_SUBVECTOR: + Res = PromoteIntRes_INSERT_SUBVECTOR(N); break; + case ISD::VECTOR_REVERSE: + Res = PromoteIntRes_VECTOR_REVERSE(N); break; case ISD::VECTOR_SHUFFLE: Res = PromoteIntRes_VECTOR_SHUFFLE(N); break; + case ISD::VECTOR_SPLICE: + Res = PromoteIntRes_VECTOR_SPLICE(N); break; case ISD::INSERT_VECTOR_ELT: Res = PromoteIntRes_INSERT_VECTOR_ELT(N); break; case ISD::BUILD_VECTOR: @@ -106,6 +113,7 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { Res = PromoteIntRes_SCALAR_TO_VECTOR(N); break; case ISD::SPLAT_VECTOR: Res = PromoteIntRes_SPLAT_VECTOR(N); break; + case ISD::STEP_VECTOR: Res = PromoteIntRes_STEP_VECTOR(N); break; case ISD::CONCAT_VECTORS: Res = PromoteIntRes_CONCAT_VECTORS(N); break; @@ -455,6 +463,16 @@ SDValue DAGTypeLegalizer::PromoteIntRes_BSWAP(SDNode *N) { EVT NVT = Op.getValueType(); SDLoc dl(N); + // If the larger BSWAP isn't supported by the target, try to expand now. + // If we expand later we'll end up with more operations since we lost the + // original type. We only do this for scalars since we have a shuffle + // based lowering for vectors in LegalizeVectorOps. + if (!OVT.isVector() && + !TLI.isOperationLegalOrCustomOrPromote(ISD::BSWAP, NVT)) { + if (SDValue Res = TLI.expandBSWAP(N, DAG)) + return DAG.getNode(ISD::ANY_EXTEND, dl, NVT, Res); + } + unsigned DiffBits = NVT.getScalarSizeInBits() - OVT.getScalarSizeInBits(); EVT ShiftVT = getShiftAmountTyForConstant(NVT, TLI, DAG); return DAG.getNode(ISD::SRL, dl, NVT, DAG.getNode(ISD::BSWAP, dl, NVT, Op), @@ -467,6 +485,16 @@ SDValue DAGTypeLegalizer::PromoteIntRes_BITREVERSE(SDNode *N) { EVT NVT = Op.getValueType(); SDLoc dl(N); + // If the larger BITREVERSE isn't supported by the target, try to expand now. + // If we expand later we'll end up with more operations since we lost the + // original type. We only do this for scalars since we have a shuffle + // based lowering for vectors in LegalizeVectorOps. + if (!OVT.isVector() && OVT.isSimple() && + !TLI.isOperationLegalOrCustomOrPromote(ISD::BITREVERSE, NVT)) { + if (SDValue Res = TLI.expandBITREVERSE(N, DAG)) + return DAG.getNode(ISD::ANY_EXTEND, dl, NVT, Res); + } + unsigned DiffBits = NVT.getScalarSizeInBits() - OVT.getScalarSizeInBits(); EVT ShiftVT = getShiftAmountTyForConstant(NVT, TLI, DAG); return DAG.getNode(ISD::SRL, dl, NVT, @@ -763,6 +791,19 @@ SDValue DAGTypeLegalizer::PromoteIntRes_ADDSUBSHLSAT(SDNode *N) { EVT PromotedType = Op1Promoted.getValueType(); unsigned NewBits = PromotedType.getScalarSizeInBits(); + if (Opcode == ISD::UADDSAT) { + APInt MaxVal = APInt::getAllOnesValue(OldBits).zext(NewBits); + SDValue SatMax = DAG.getConstant(MaxVal, dl, PromotedType); + SDValue Add = + DAG.getNode(ISD::ADD, dl, PromotedType, Op1Promoted, Op2Promoted); + return DAG.getNode(ISD::UMIN, dl, PromotedType, Add, SatMax); + } + + // USUBSAT can always be promoted as long as we have zero-extended the args. + if (Opcode == ISD::USUBSAT) + return DAG.getNode(ISD::USUBSAT, dl, PromotedType, Op1Promoted, + Op2Promoted); + // Shift cannot use a min/max expansion, we can't detect overflow if all of // the bits have been shifted out. if (IsShift || TLI.isOperationLegalOrCustom(Opcode, PromotedType)) { @@ -773,8 +814,6 @@ SDValue DAGTypeLegalizer::PromoteIntRes_ADDSUBSHLSAT(SDNode *N) { case ISD::SSHLSAT: ShiftOp = ISD::SRA; break; - case ISD::UADDSAT: - case ISD::USUBSAT: case ISD::USHLSAT: ShiftOp = ISD::SRL; break; @@ -795,32 +834,18 @@ SDValue DAGTypeLegalizer::PromoteIntRes_ADDSUBSHLSAT(SDNode *N) { SDValue Result = DAG.getNode(Opcode, dl, PromotedType, Op1Promoted, Op2Promoted); return DAG.getNode(ShiftOp, dl, PromotedType, Result, ShiftAmount); - } else { - if (Opcode == ISD::USUBSAT) { - SDValue Max = - DAG.getNode(ISD::UMAX, dl, PromotedType, Op1Promoted, Op2Promoted); - return DAG.getNode(ISD::SUB, dl, PromotedType, Max, Op2Promoted); - } - - if (Opcode == ISD::UADDSAT) { - APInt MaxVal = APInt::getAllOnesValue(OldBits).zext(NewBits); - SDValue SatMax = DAG.getConstant(MaxVal, dl, PromotedType); - SDValue Add = - DAG.getNode(ISD::ADD, dl, PromotedType, Op1Promoted, Op2Promoted); - return DAG.getNode(ISD::UMIN, dl, PromotedType, Add, SatMax); - } - - unsigned AddOp = Opcode == ISD::SADDSAT ? ISD::ADD : ISD::SUB; - APInt MinVal = APInt::getSignedMinValue(OldBits).sext(NewBits); - APInt MaxVal = APInt::getSignedMaxValue(OldBits).sext(NewBits); - SDValue SatMin = DAG.getConstant(MinVal, dl, PromotedType); - SDValue SatMax = DAG.getConstant(MaxVal, dl, PromotedType); - SDValue Result = - DAG.getNode(AddOp, dl, PromotedType, Op1Promoted, Op2Promoted); - Result = DAG.getNode(ISD::SMIN, dl, PromotedType, Result, SatMax); - Result = DAG.getNode(ISD::SMAX, dl, PromotedType, Result, SatMin); - return Result; } + + unsigned AddOp = Opcode == ISD::SADDSAT ? ISD::ADD : ISD::SUB; + APInt MinVal = APInt::getSignedMinValue(OldBits).sext(NewBits); + APInt MaxVal = APInt::getSignedMaxValue(OldBits).sext(NewBits); + SDValue SatMin = DAG.getConstant(MinVal, dl, PromotedType); + SDValue SatMax = DAG.getConstant(MaxVal, dl, PromotedType); + SDValue Result = + DAG.getNode(AddOp, dl, PromotedType, Op1Promoted, Op2Promoted); + Result = DAG.getNode(ISD::SMIN, dl, PromotedType, Result, SatMax); + Result = DAG.getNode(ISD::SMAX, dl, PromotedType, Result, SatMin); + return Result; } SDValue DAGTypeLegalizer::PromoteIntRes_MULFIX(SDNode *N) { @@ -1217,17 +1242,17 @@ SDValue DAGTypeLegalizer::PromoteIntRes_TRUNCATE(SDNode *N) { case TargetLowering::TypeSplitVector: { EVT InVT = InOp.getValueType(); assert(InVT.isVector() && "Cannot split scalar types"); - unsigned NumElts = InVT.getVectorNumElements(); - assert(NumElts == NVT.getVectorNumElements() && + ElementCount NumElts = InVT.getVectorElementCount(); + assert(NumElts == NVT.getVectorElementCount() && "Dst and Src must have the same number of elements"); - assert(isPowerOf2_32(NumElts) && + assert(isPowerOf2_32(NumElts.getKnownMinValue()) && "Promoted vector type must be a power of two"); SDValue EOp1, EOp2; GetSplitVector(InOp, EOp1, EOp2); EVT HalfNVT = EVT::getVectorVT(*DAG.getContext(), NVT.getScalarType(), - NumElts/2); + NumElts.divideCoefficientBy(2)); EOp1 = DAG.getNode(ISD::TRUNCATE, dl, HalfNVT, EOp1); EOp2 = DAG.getNode(ISD::TRUNCATE, dl, HalfNVT, EOp2); @@ -1535,6 +1560,8 @@ bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { case ISD::VECREDUCE_SMIN: case ISD::VECREDUCE_UMAX: case ISD::VECREDUCE_UMIN: Res = PromoteIntOp_VECREDUCE(N); break; + + case ISD::SET_ROUNDING: Res = PromoteIntOp_SET_ROUNDING(N); break; } // If the result is null, the sub-method took care of registering results etc. @@ -1963,8 +1990,37 @@ SDValue DAGTypeLegalizer::PromoteIntOp_PREFETCH(SDNode *N, unsigned OpNo) { } SDValue DAGTypeLegalizer::PromoteIntOp_FPOWI(SDNode *N) { - SDValue Op = SExtPromotedInteger(N->getOperand(1)); - return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), Op), 0); + // FIXME: Support for promotion of STRICT_FPOWI is not implemented yet. + assert(N->getOpcode() == ISD::FPOWI && "No STRICT_FPOWI support here yet."); + + // The integer operand is the last operand in FPOWI (so the result and + // floating point operand is already type legalized). + + // We can't just promote the exponent type in FPOWI, since we want to lower + // the node to a libcall and we if we promote to a type larger than + // sizeof(int) the libcall might not be according to the targets ABI. Instead + // we rewrite to a libcall here directly, letting makeLibCall handle promotion + // if the target accepts it according to shouldSignExtendTypeInLibCall. + RTLIB::Libcall LC = RTLIB::getPOWI(N->getValueType(0)); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fpowi."); + if (!TLI.getLibcallName(LC)) { + // Some targets don't have a powi libcall; use pow instead. + // FIXME: Implement this if some target needs it. + DAG.getContext()->emitError("Don't know how to promote fpowi to fpow"); + return DAG.getUNDEF(N->getValueType(0)); + } + // The exponent should fit in a sizeof(int) type for the libcall to be valid. + assert(DAG.getLibInfo().getIntSize() == + N->getOperand(1).getValueType().getSizeInBits() && + "POWI exponent should match with sizeof(int) when doing the libcall."); + TargetLowering::MakeLibCallOptions CallOptions; + CallOptions.setSExt(true); + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + std::pair<SDValue, SDValue> Tmp = + TLI.makeLibCall(DAG, LC, N->getValueType(0), Ops, + CallOptions, SDLoc(N), SDValue()); + ReplaceValueWith(SDValue(N, 0), Tmp.first); + return SDValue(); } SDValue DAGTypeLegalizer::PromoteIntOp_VECREDUCE(SDNode *N) { @@ -2000,6 +2056,11 @@ SDValue DAGTypeLegalizer::PromoteIntOp_VECREDUCE(SDNode *N) { return DAG.getNode(ISD::TRUNCATE, dl, VT, Reduce); } +SDValue DAGTypeLegalizer::PromoteIntOp_SET_ROUNDING(SDNode *N) { + SDValue Op = ZExtPromotedInteger(N->getOperand(1)); + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), Op), 0); +} + //===----------------------------------------------------------------------===// // Integer Result Expansion //===----------------------------------------------------------------------===// @@ -2186,6 +2247,10 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { case ISD::FSHR: ExpandIntRes_FunnelShift(N, Lo, Hi); break; + + case ISD::VSCALE: + ExpandIntRes_VSCALE(N, Lo, Hi); + break; } // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -2197,7 +2262,7 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { std::pair <SDValue, SDValue> DAGTypeLegalizer::ExpandAtomic(SDNode *Node) { unsigned Opc = Node->getOpcode(); MVT VT = cast<AtomicSDNode>(Node)->getMemoryVT().getSimpleVT(); - AtomicOrdering order = cast<AtomicSDNode>(Node)->getOrdering(); + AtomicOrdering order = cast<AtomicSDNode>(Node)->getMergedOrdering(); // Lower to outline atomic libcall if outline atomics enabled, // or to sync libcall otherwise RTLIB::Libcall LC = RTLIB::getOUTLINE_ATOMIC(Opc, order, VT); @@ -3598,18 +3663,16 @@ void DAGTypeLegalizer::ExpandIntRes_DIVFIX(SDNode *N, SDValue &Lo, void DAGTypeLegalizer::ExpandIntRes_SADDSUBO(SDNode *Node, SDValue &Lo, SDValue &Hi) { + assert((Node->getOpcode() == ISD::SADDO || Node->getOpcode() == ISD::SSUBO) && + "Node has unexpected Opcode"); SDValue LHS = Node->getOperand(0); SDValue RHS = Node->getOperand(1); SDLoc dl(Node); SDValue Ovf; - unsigned CarryOp; - switch(Node->getOpcode()) { - default: llvm_unreachable("Node has unexpected Opcode"); - case ISD::SADDO: CarryOp = ISD::SADDO_CARRY; break; - case ISD::SSUBO: CarryOp = ISD::SSUBO_CARRY; break; - } + bool IsAdd = Node->getOpcode() == ISD::SADDO; + unsigned CarryOp = IsAdd ? ISD::SADDO_CARRY : ISD::SSUBO_CARRY; bool HasCarryOp = TLI.isOperationLegalOrCustom( CarryOp, TLI.getTypeToExpandTo(*DAG.getContext(), LHS.getValueType())); @@ -3621,8 +3684,7 @@ void DAGTypeLegalizer::ExpandIntRes_SADDSUBO(SDNode *Node, GetExpandedInteger(RHS, RHSL, RHSH); SDVTList VTList = DAG.getVTList(LHSL.getValueType(), Node->getValueType(1)); - Lo = DAG.getNode(Node->getOpcode() == ISD::SADDO ? - ISD::UADDO : ISD::USUBO, dl, VTList, { LHSL, RHSL }); + Lo = DAG.getNode(IsAdd ? ISD::UADDO : ISD::USUBO, dl, VTList, {LHSL, RHSL}); Hi = DAG.getNode(CarryOp, dl, VTList, { LHSH, RHSH, Lo.getValue(1) }); Ovf = Hi.getValue(1); @@ -3636,28 +3698,36 @@ void DAGTypeLegalizer::ExpandIntRes_SADDSUBO(SDNode *Node, // Compute the overflow. // - // LHSSign -> LHS >= 0 - // RHSSign -> RHS >= 0 - // SumSign -> Sum >= 0 + // LHSSign -> LHS < 0 + // RHSSign -> RHS < 0 + // SumSign -> Sum < 0 // // Add: // Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign) // Sub: // Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign) // + // To get better codegen we can rewrite this by doing bitwise math on + // the integers and extract the final sign bit at the end. So the + // above becomes: + // + // Add: + // Overflow -> (~(LHS ^ RHS) & (LHS ^ Sum)) < 0 + // Sub: + // Overflow -> ((LHS ^ RHS) & (LHS ^ Sum)) < 0 + // + // NOTE: This is different than the expansion we do in expandSADDSUBO + // because it is more costly to determine the RHS is > 0 for SSUBO with the + // integers split. + EVT VT = LHS.getValueType(); + SDValue SignsMatch = DAG.getNode(ISD::XOR, dl, VT, LHS, RHS); + if (IsAdd) + SignsMatch = DAG.getNOT(dl, SignsMatch, VT); + + SDValue SumSignNE = DAG.getNode(ISD::XOR, dl, VT, LHS, Sum); + Ovf = DAG.getNode(ISD::AND, dl, VT, SignsMatch, SumSignNE); EVT OType = Node->getValueType(1); - SDValue Zero = DAG.getConstant(0, dl, LHS.getValueType()); - - SDValue LHSSign = DAG.getSetCC(dl, OType, LHS, Zero, ISD::SETGE); - SDValue RHSSign = DAG.getSetCC(dl, OType, RHS, Zero, ISD::SETGE); - SDValue SignsMatch = DAG.getSetCC(dl, OType, LHSSign, RHSSign, - Node->getOpcode() == ISD::SADDO ? - ISD::SETEQ : ISD::SETNE); - - SDValue SumSign = DAG.getSetCC(dl, OType, Sum, Zero, ISD::SETGE); - SDValue SumSignNE = DAG.getSetCC(dl, OType, LHSSign, SumSign, ISD::SETNE); - - Ovf = DAG.getNode(ISD::AND, dl, OType, SignsMatch, SumSignNE); + Ovf = DAG.getSetCC(dl, OType, Ovf, DAG.getConstant(0, dl, VT), ISD::SETLT); } // Use the calculated overflow everywhere. @@ -3909,33 +3979,32 @@ void DAGTypeLegalizer::ExpandIntRes_XMULO(SDNode *N, // %1 = { iNh, i1 } @umul.with.overflow.iNh(iNh %LHS.HI, iNh %RHS.LO) // %2 = { iNh, i1 } @umul.with.overflow.iNh(iNh %RHS.HI, iNh %LHS.LO) // %3 = mul nuw iN (%LHS.LOW as iN), (%RHS.LOW as iN) - // %4 = add iN (%1.0 as iN) << Nh, (%2.0 as iN) << Nh - // %5 = { iN, i1 } @uadd.with.overflow.iN( %4, %3 ) + // %4 = add iNh %1.0, %2.0 as iN + // %5 = { iNh, i1 } @uadd.with.overflow.iNh(iNh %4, iNh %3.HIGH) // - // %res = { %5.0, %0 || %1.1 || %2.1 || %5.1 } + // %lo = %3.LO + // %hi = %5.0 + // %ovf = %0 || %1.1 || %2.1 || %5.1 SDValue LHS = N->getOperand(0), RHS = N->getOperand(1); SDValue LHSHigh, LHSLow, RHSHigh, RHSLow; - SplitInteger(LHS, LHSLow, LHSHigh); - SplitInteger(RHS, RHSLow, RHSHigh); - EVT HalfVT = LHSLow.getValueType() - , BitVT = N->getValueType(1); - SDVTList VTHalfMulO = DAG.getVTList(HalfVT, BitVT); - SDVTList VTFullAddO = DAG.getVTList(VT, BitVT); + GetExpandedInteger(LHS, LHSLow, LHSHigh); + GetExpandedInteger(RHS, RHSLow, RHSHigh); + EVT HalfVT = LHSLow.getValueType(); + EVT BitVT = N->getValueType(1); + SDVTList VTHalfWithO = DAG.getVTList(HalfVT, BitVT); SDValue HalfZero = DAG.getConstant(0, dl, HalfVT); SDValue Overflow = DAG.getNode(ISD::AND, dl, BitVT, DAG.getSetCC(dl, BitVT, LHSHigh, HalfZero, ISD::SETNE), DAG.getSetCC(dl, BitVT, RHSHigh, HalfZero, ISD::SETNE)); - SDValue One = DAG.getNode(ISD::UMULO, dl, VTHalfMulO, LHSHigh, RHSLow); + SDValue One = DAG.getNode(ISD::UMULO, dl, VTHalfWithO, LHSHigh, RHSLow); Overflow = DAG.getNode(ISD::OR, dl, BitVT, Overflow, One.getValue(1)); - SDValue OneInHigh = DAG.getNode(ISD::BUILD_PAIR, dl, VT, HalfZero, - One.getValue(0)); - SDValue Two = DAG.getNode(ISD::UMULO, dl, VTHalfMulO, RHSHigh, LHSLow); + SDValue Two = DAG.getNode(ISD::UMULO, dl, VTHalfWithO, RHSHigh, LHSLow); Overflow = DAG.getNode(ISD::OR, dl, BitVT, Overflow, Two.getValue(1)); - SDValue TwoInHigh = DAG.getNode(ISD::BUILD_PAIR, dl, VT, HalfZero, - Two.getValue(0)); + + SDValue HighSum = DAG.getNode(ISD::ADD, dl, HalfVT, One, Two); // Cannot use `UMUL_LOHI` directly, because some 32-bit targets (ARM) do not // know how to expand `i64,i64 = umul_lohi a, b` and abort (why isn’t this @@ -3946,10 +4015,10 @@ void DAGTypeLegalizer::ExpandIntRes_XMULO(SDNode *N, SDValue Three = DAG.getNode(ISD::MUL, dl, VT, DAG.getNode(ISD::ZERO_EXTEND, dl, VT, LHSLow), DAG.getNode(ISD::ZERO_EXTEND, dl, VT, RHSLow)); - SDValue Four = DAG.getNode(ISD::ADD, dl, VT, OneInHigh, TwoInHigh); - SDValue Five = DAG.getNode(ISD::UADDO, dl, VTFullAddO, Three, Four); - Overflow = DAG.getNode(ISD::OR, dl, BitVT, Overflow, Five.getValue(1)); - SplitInteger(Five, Lo, Hi); + SplitInteger(Three, Lo, Hi); + + Hi = DAG.getNode(ISD::UADDO, dl, VTHalfWithO, Hi, HighSum); + Overflow = DAG.getNode(ISD::OR, dl, BitVT, Overflow, Hi.getValue(1)); ReplaceValueWith(SDValue(N, 1), Overflow); return; } @@ -4133,6 +4202,21 @@ void DAGTypeLegalizer::ExpandIntRes_FunnelShift(SDNode *N, SplitInteger(Res, Lo, Hi); } +void DAGTypeLegalizer::ExpandIntRes_VSCALE(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT VT = N->getValueType(0); + EVT HalfVT = + EVT::getIntegerVT(*DAG.getContext(), N->getValueSizeInBits(0) / 2); + SDLoc dl(N); + + // We assume VSCALE(1) fits into a legal integer. + APInt One(HalfVT.getSizeInBits(), 1); + SDValue VScaleBase = DAG.getVScale(dl, HalfVT, One); + VScaleBase = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, VScaleBase); + SDValue Res = DAG.getNode(ISD::MUL, dl, VT, VScaleBase, N->getOperand(0)); + SplitInteger(Res, Lo, Hi); +} + //===----------------------------------------------------------------------===// // Integer Operand Expansion //===----------------------------------------------------------------------===// @@ -4163,6 +4247,7 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; case ISD::INSERT_VECTOR_ELT: Res = ExpandOp_INSERT_VECTOR_ELT(N); break; case ISD::SCALAR_TO_VECTOR: Res = ExpandOp_SCALAR_TO_VECTOR(N); break; + case ISD::SPLAT_VECTOR: Res = ExpandIntOp_SPLAT_VECTOR(N); break; case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break; case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; case ISD::SETCCCARRY: Res = ExpandIntOp_SETCCCARRY(N); break; @@ -4418,6 +4503,14 @@ SDValue DAGTypeLegalizer::ExpandIntOp_SETCCCARRY(SDNode *N) { LowCmp.getValue(1), Cond); } +SDValue DAGTypeLegalizer::ExpandIntOp_SPLAT_VECTOR(SDNode *N) { + // Split the operand and replace with SPLAT_VECTOR_PARTS. + SDValue Lo, Hi; + GetExpandedInteger(N->getOperand(0), Lo, Hi); + return DAG.getNode(ISD::SPLAT_VECTOR_PARTS, SDLoc(N), N->getValueType(0), Lo, + Hi); +} + SDValue DAGTypeLegalizer::ExpandIntOp_Shift(SDNode *N) { // The value being shifted is legal, but the shift amount is too big. // It follows that either the result of the shift is undefined, or the @@ -4587,6 +4680,15 @@ SDValue DAGTypeLegalizer::ExpandIntOp_ATOMIC_STORE(SDNode *N) { return Swap.getValue(1); } +SDValue DAGTypeLegalizer::PromoteIntRes_VECTOR_SPLICE(SDNode *N) { + SDLoc dl(N); + + SDValue V0 = GetPromotedInteger(N->getOperand(0)); + SDValue V1 = GetPromotedInteger(N->getOperand(1)); + EVT OutVT = V0.getValueType(); + + return DAG.getNode(ISD::VECTOR_SPLICE, dl, OutVT, V0, V1, N->getOperand(2)); +} SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_SUBVECTOR(SDNode *N) { @@ -4648,6 +4750,35 @@ SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_SUBVECTOR(SDNode *N) { return DAG.getBuildVector(NOutVT, dl, Ops); } +SDValue DAGTypeLegalizer::PromoteIntRes_INSERT_SUBVECTOR(SDNode *N) { + EVT OutVT = N->getValueType(0); + EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT); + assert(NOutVT.isVector() && "This type must be promoted to a vector type"); + + SDLoc dl(N); + SDValue Vec = N->getOperand(0); + SDValue SubVec = N->getOperand(1); + SDValue Idx = N->getOperand(2); + + EVT SubVecVT = SubVec.getValueType(); + EVT NSubVT = + EVT::getVectorVT(*DAG.getContext(), NOutVT.getVectorElementType(), + SubVecVT.getVectorElementCount()); + + Vec = GetPromotedInteger(Vec); + SubVec = DAG.getNode(ISD::ANY_EXTEND, dl, NSubVT, SubVec); + + return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, NOutVT, Vec, SubVec, Idx); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_VECTOR_REVERSE(SDNode *N) { + SDLoc dl(N); + + SDValue V0 = GetPromotedInteger(N->getOperand(0)); + EVT OutVT = V0.getValueType(); + + return DAG.getNode(ISD::VECTOR_REVERSE, dl, OutVT, V0); +} SDValue DAGTypeLegalizer::PromoteIntRes_VECTOR_SHUFFLE(SDNode *N) { ShuffleVectorSDNode *SV = cast<ShuffleVectorSDNode>(N); @@ -4725,6 +4856,16 @@ SDValue DAGTypeLegalizer::PromoteIntRes_SPLAT_VECTOR(SDNode *N) { return DAG.getNode(ISD::SPLAT_VECTOR, dl, NOutVT, Op); } +SDValue DAGTypeLegalizer::PromoteIntRes_STEP_VECTOR(SDNode *N) { + SDLoc dl(N); + EVT OutVT = N->getValueType(0); + EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT); + assert(NOutVT.isVector() && "Type must be promoted to a vector type"); + APInt StepVal = cast<ConstantSDNode>(N->getOperand(0))->getAPIntValue(); + return DAG.getStepVector(dl, NOutVT, + StepVal.sext(NOutVT.getScalarSizeInBits())); +} + SDValue DAGTypeLegalizer::PromoteIntRes_CONCAT_VECTORS(SDNode *N) { SDLoc dl(N); |