/// processed to the result.
std::map<SDValue, SDValue> ScalarizedNodes;
- /// WidenNodes - For nodes that need to be widen from one vector type to
- /// another, this contains the mapping of ones we have already widen. This
- /// allows us to avoid widening more than once.
+ /// WidenNodes - For nodes that need to be widened from one vector type to
+ /// another, this contains the mapping of those that we have already widen.
+ /// This allows us to avoid widening more than once.
std::map<SDValue, SDValue> WidenNodes;
void AddLegalizedOperand(SDValue From, SDValue To) {
// If someone requests legalization of the new node, return itself.
LegalizedNodes.insert(std::make_pair(To, To));
}
- void AddWidenOperand(SDValue From, SDValue To) {
+ void AddWidenedOperand(SDValue From, SDValue To) {
bool isNew = WidenNodes.insert(std::make_pair(From, To)).second;
assert(isNew && "Got into the map somehow?");
// If someone requests legalization of the new node, return itself.
/// types.
void ExpandOp(SDValue O, SDValue &Lo, SDValue &Hi);
- /// WidenVectorOp - Widen a vector operation in order to do the computation
- /// in a wider type given to a wider type given by WidenVT (e.g., v3i32 to
- /// v4i32). The produced value will have the correct value for the existing
- /// elements but no guarantee is made about the new elements at the end of
- /// the vector: it may be zero, sign-extended, or garbage. This is useful
- /// when we have instruction operating on an illegal vector type and we want
- /// to widen it to do the computation on a legal wider vector type.
+ /// WidenVectorOp - Widen a vector operation to a wider type given by WidenVT
+ /// (e.g., v3i32 to v4i32). The produced value will have the correct value
+ /// for the existing elements but no guarantee is made about the new elements
+ /// at the end of the vector: it may be zero, ones, or garbage. This is useful
+ /// when we have an instruction operating on an illegal vector type and we
+ /// want to widen it to do the computation on a legal wider vector type.
SDValue WidenVectorOp(SDValue Op, MVT WidenVT);
/// SplitVectorOp - Given an operand of vector type, break it down into
/// scalar (e.g. f32) value.
SDValue ScalarizeVectorOp(SDValue O);
- /// Useful 16 element vector used to pass operands for widening
+ /// Useful 16 element vector type that is used to pass operands for widening.
typedef SmallVector<SDValue, 16> SDValueVector;
/// LoadWidenVectorOp - Load a vector for a wider type. Returns true if
Tmp3 = Node->getOperand(3); // RHS
Tmp4 = Node->getOperand(1); // CC
- LegalizeSetCC(Node->getValueType(0), Tmp2, Tmp3, Tmp4);
+ LegalizeSetCC(TLI.getSetCCResultType(Tmp2), Tmp2, Tmp3, Tmp4);
LastCALLSEQ_END = DAG.getEntryNode();
// If we didn't get both a LHS and RHS back from LegalizeSetCC,
Tmp4 = LegalizeOp(Node->getOperand(3)); // False
SDValue CC = Node->getOperand(4);
- LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, CC);
+ LegalizeSetCC(TLI.getSetCCResultType(Tmp1), Tmp1, Tmp2, CC);
// If we didn't get both a LHS and RHS back from LegalizeSetCC,
// the LHS is a legal SETCC itself. In this case, we need to compare
}
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
-
+
switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
default: assert(0 && "BinOp legalize operation not supported");
case TargetLowering::Legal: break;
}
}
break;
-
+ case ISD::CONVERT_RNDSAT: {
+ ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(Node)->getCvtCode();
+ switch (CvtCode) {
+ default: assert(0 && "Unknown cvt code!");
+ case ISD::CVT_SF:
+ case ISD::CVT_UF:
+ break;
+ case ISD::CVT_FF:
+ case ISD::CVT_FS:
+ case ISD::CVT_FU:
+ case ISD::CVT_SS:
+ case ISD::CVT_SU:
+ case ISD::CVT_US:
+ case ISD::CVT_UU: {
+ SDValue DTyOp = Node->getOperand(1);
+ SDValue STyOp = Node->getOperand(2);
+ SDValue RndOp = Node->getOperand(3);
+ SDValue SatOp = Node->getOperand(4);
+ switch (getTypeAction(Node->getOperand(0).getValueType())) {
+ case Expand: assert(0 && "Shouldn't need to expand other operators here!");
+ case Legal:
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, DTyOp, STyOp,
+ RndOp, SatOp);
+ if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
+ TargetLowering::Custom) {
+ Tmp1 = TLI.LowerOperation(Result, DAG);
+ if (Tmp1.getNode()) Result = Tmp1;
+ }
+ break;
+ case Promote:
+ Result = PromoteOp(Node->getOperand(0));
+ // For FP, make Op1 a i32
+
+ Result = DAG.getConvertRndSat(Result.getValueType(), Result,
+ DTyOp, STyOp, RndOp, SatOp, CvtCode);
+ break;
+ }
+ break;
+ }
+ } // end switch CvtCode
+ break;
+ }
// Conversion operators. The source and destination have different types.
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP: {
break;
}
break;
+ case ISD::CONVERT_RNDSAT: {
+ ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(Node)->getCvtCode();
+ assert ((CvtCode == ISD::CVT_SS || CvtCode == ISD::CVT_SU ||
+ CvtCode == ISD::CVT_US || CvtCode == ISD::CVT_UU ||
+ CvtCode == ISD::CVT_SF || CvtCode == ISD::CVT_UF) &&
+ "can only promote integers");
+ Result = DAG.getConvertRndSat(NVT, Node->getOperand(0),
+ Node->getOperand(1), Node->getOperand(2),
+ Node->getOperand(3), Node->getOperand(4),
+ CvtCode);
+ break;
+
+ }
case ISD::BIT_CONVERT:
Result = EmitStackConvert(Node->getOperand(0), Node->getValueType(0),
Node->getValueType(0));
Lo = Node->getOperand(0);
Hi = Node->getOperand(1);
} else {
- SmallVector<SDValue, 8> LoOps(Node->op_begin(),
- Node->op_begin()+NewNumSubvectors);
+ SmallVector<SDValue, 8> LoOps(Node->op_begin(),
+ Node->op_begin()+NewNumSubvectors);
Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Lo, &LoOps[0], LoOps.size());
- SmallVector<SDValue, 8> HiOps(Node->op_begin()+NewNumSubvectors,
+ SmallVector<SDValue, 8> HiOps(Node->op_begin()+NewNumSubvectors,
Node->op_end());
Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Hi, &HiOps[0], HiOps.size());
}
break;
}
+ case ISD::EXTRACT_SUBVECTOR: {
+ SDValue Vec = Op.getOperand(0);
+ SDValue Idx = Op.getOperand(1);
+ MVT IdxVT = Idx.getValueType();
+
+ Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Lo, Vec, Idx);
+ ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx);
+ if (CIdx) {
+ Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Hi, Vec,
+ DAG.getConstant(CIdx->getZExtValue() + NewNumElts_Lo,
+ IdxVT));
+ } else {
+ Idx = DAG.getNode(ISD::ADD, IdxVT, Idx,
+ DAG.getConstant(NewNumElts_Lo, IdxVT));
+ Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Hi, Vec, Idx);
+ }
+ break;
+ }
case ISD::SELECT: {
SDValue Cond = Node->getOperand(0);
Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, H);
break;
}
+ case ISD::CONVERT_RNDSAT: {
+ ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(Node)->getCvtCode();
+ SDValue L, H;
+ SplitVectorOp(Node->getOperand(0), L, H);
+ SDValue DTyOpL = DAG.getValueType(NewVT_Lo);
+ SDValue DTyOpH = DAG.getValueType(NewVT_Hi);
+ SDValue STyOpL = DAG.getValueType(L.getValueType());
+ SDValue STyOpH = DAG.getValueType(H.getValueType());
+
+ SDValue RndOp = Node->getOperand(3);
+ SDValue SatOp = Node->getOperand(4);
+
+ Lo = DAG.getConvertRndSat(NewVT_Lo, L, DTyOpL, STyOpL,
+ RndOp, SatOp, CvtCode);
+ Hi = DAG.getConvertRndSat(NewVT_Hi, H, DTyOpH, STyOpH,
+ RndOp, SatOp, CvtCode);
+ break;
+ }
case ISD::LOAD: {
LoadSDNode *LD = cast<LoadSDNode>(Node);
SDValue Ch = LD->getChain();
NewVT,
ScalarizeVectorOp(Node->getOperand(0)));
break;
+ case ISD::CONVERT_RNDSAT: {
+ SDValue Op0 = ScalarizeVectorOp(Node->getOperand(0));
+ Result = DAG.getConvertRndSat(NewVT, Op0,
+ DAG.getValueType(NewVT),
+ DAG.getValueType(Op0.getValueType()),
+ Node->getOperand(3),
+ Node->getOperand(4),
+ cast<CvtRndSatSDNode>(Node)->getCvtCode());
+ break;
+ }
case ISD::FPOWI:
case ISD::FP_ROUND:
Result = DAG.getNode(Node->getOpcode(),
break;
}
case ISD::EXTRACT_SUBVECTOR:
- Result = Node->getOperand(0);
- assert(Result.getValueType() == NewVT);
+ Result = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, Node->getOperand(0),
+ Node->getOperand(1));
break;
case ISD::BIT_CONVERT: {
SDValue Op0 = Op.getOperand(0);
// the legal type, the resulting code will be more efficient. If this is not
// the case, the resulting code will preform badly as we end up generating
// code to pack/unpack the results. It is the function that calls widen
- // that is responsible for seeing this doesn't happen. For some cases, we
- // have decided that it is not worth widening so we just split the operation.
+ // that is responsible for seeing this doesn't happen.
switch (Node->getOpcode()) {
default:
#ifndef NDEBUG
assert(0 && "Unexpected operation in WidenVectorOp!");
break;
case ISD::CopyFromReg:
- assert(0 && "CopyFromReg must be legal!");
- case ISD::UNDEF:
+ assert(0 && "CopyFromReg doesn't need widening!");
case ISD::Constant:
case ISD::ConstantFP:
// To build a vector of these elements, clients should call BuildVector
// Variable Arguments with vector types doesn't make any sense to me
assert(0 && "Unexpected operation in WidenVectorOp!");
break;
+ case ISD::UNDEF:
+ Result = DAG.getNode(ISD::UNDEF, WidenVT);
+ break;
case ISD::BUILD_VECTOR: {
// Build a vector with undefined for the new nodes
SDValueVector NewOps(Node->op_begin(), Node->op_end());
case ISD::FNEG:
case ISD::FSQRT:
case ISD::FSIN:
- case ISD::FCOS: {
+ case ISD::FCOS:
+ case ISD::CTPOP:
+ case ISD::CTTZ:
+ case ISD::CTLZ: {
// Unary op widening
SDValue Tmp1;
TargetLowering::LegalizeAction action =
}
break;
}
+ case ISD::CONVERT_RNDSAT: {
+ SDValue RndOp = Node->getOperand(3);
+ SDValue SatOp = Node->getOperand(4);
+
+ TargetLowering::LegalizeAction action =
+ TLI.getOperationAction(Node->getOpcode(), WidenVT);
+
+ SDValue SrcOp = Node->getOperand(0);
+
+ // Converts between two different types so we need to determine
+ // the correct widen type for the input operand.
+ MVT SVT = SrcOp.getValueType();
+ assert(SVT.isVector() && "can not widen non vector type");
+ MVT SEVT = SVT.getVectorElementType();
+ MVT SWidenVT = MVT::getVectorVT(SEVT, NewNumElts);
+
+ SrcOp = WidenVectorOp(SrcOp, SWidenVT);
+ assert(SrcOp.getValueType() == WidenVT);
+ SDValue DTyOp = DAG.getValueType(WidenVT);
+ SDValue STyOp = DAG.getValueType(SrcOp.getValueType());
+ ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(Node)->getCvtCode();
+
+ Result = DAG.getConvertRndSat(WidenVT, SrcOp, DTyOp, STyOp,
+ RndOp, SatOp, CvtCode);
+ switch (action) {
+ default: assert(0 && "action not supported");
+ case TargetLowering::Legal:
+ break;
+ case TargetLowering::Promote:
+ // We defer the promotion to when we legalize the op
+ break;
+ case TargetLowering::Expand:
+ // Expand the operation into a bunch of nasty scalar code.
+ Result = LegalizeOp(UnrollVectorOp(Result));
+ break;
+ }
+ break;
+ }
case ISD::FPOW:
case ISD::FPOWI:
case ISD::ADD:
break;
}
case ISD::EXTRACT_SUBVECTOR: {
- SDValue Tmp1;
-
- // The incoming vector might already be the proper type
- if (Node->getOperand(0).getValueType() != WidenVT)
- Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT);
- else
- Tmp1 = Node->getOperand(0);
- assert(Tmp1.getValueType() == WidenVT);
- Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1, Node->getOperand(1));
+ SDValue Tmp1 = Node->getOperand(0);
+ SDValue Idx = Node->getOperand(1);
+ ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx);
+ if (CIdx && CIdx->getZExtValue() == 0) {
+ // Since we are access the start of the vector, the incoming
+ // vector type might be the proper.
+ MVT Tmp1VT = Tmp1.getValueType();
+ if (Tmp1VT == WidenVT)
+ return Tmp1;
+ else {
+ unsigned Tmp1VTNumElts = Tmp1VT.getVectorNumElements();
+ if (Tmp1VTNumElts < NewNumElts)
+ Result = WidenVectorOp(Tmp1, WidenVT);
+ else
+ Result = DAG.getNode(ISD::EXTRACT_SUBVECTOR, WidenVT, Tmp1, Idx);
+ }
+ } else if (NewNumElts % NumElts == 0) {
+ // Widen the extracted subvector.
+ unsigned NumConcat = NewNumElts / NumElts;
+ SDValue UndefVal = DAG.getNode(ISD::UNDEF, VT);
+ SmallVector<SDValue, 8> MOps;
+ MOps.push_back(Op);
+ for (unsigned i = 1; i != NumConcat; ++i) {
+ MOps.push_back(UndefVal);
+ }
+ Result = LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, WidenVT,
+ &MOps[0], MOps.size()));
+ } else {
+ assert(0 && "can not widen extract subvector");
+ // This could be implemented using insert and build vector but I would
+ // like to see when this happens.
+ }
break;
}
if (Result != Op)
Result = LegalizeOp(Result);
- AddWidenOperand(Op, Result);
+ AddWidenedOperand(Op, Result);
return Result;
}
FindWidenVecType(TLI, LdWidth, ResType, EVT, VecEVT);
EVTWidth = EVT.getSizeInBits();
// Readjust position and vector position based on new load type
- Idx = Idx * (oEVTWidth/EVTWidth)+1;
+ Idx = Idx * (oEVTWidth/EVTWidth);
VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, VecOp);
}
int SVOffset,
unsigned Alignment,
bool isVolatile,
- SDValue ValOp,
+ SDValue ValOp,
unsigned StWidth) {
// Breaks the stores into a series of power of 2 width stores. For any
// width, we convert the vector to the vector of element size that we
SDValue VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, ValOp);
SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EVT, VecOp,
- DAG.getIntPtrConstant(0));
+ DAG.getIntPtrConstant(0));
SDValue StOp = DAG.getStore(Chain, EOp, BasePtr, SV, SVOffset,
isVolatile, Alignment);
StChain.push_back(StOp);
FindWidenVecType(TLI, StWidth, VVT, EVT, VecEVT);
EVTWidth = EVT.getSizeInBits();
// Readjust position and vector position based on new load type
- Idx = Idx * (oEVTWidth/EVTWidth)+1;
+ Idx = Idx * (oEVTWidth/EVTWidth);
VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, VecOp);
}
EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EVT, VecOp,
- DAG.getIntPtrConstant(Idx));
+ DAG.getIntPtrConstant(Idx++));
StChain.push_back(DAG.getStore(Chain, EOp, BasePtr, SV,
SVOffset + Offset, isVolatile,
MinAlign(Alignment, Offset)));