aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp293
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);