forked from OSchip/llvm-project
* Add supprot for SCALAR_TO_VECTOR operations where the input needs to be
promoted/expanded (e.g. SCALAR_TO_VECTOR from i8/i16 on PPC). * Add support for targets to request that VECTOR_SHUFFLE nodes be promoted to a canonical type, for example, we only want v16i8 shuffles on PPC. * Move isShuffleLegal out of TLI into Legalize. * Teach isShuffleLegal to allow shuffles that need to be promoted. llvm-svn: 27399
This commit is contained in:
parent
299ecf2a78
commit
6be79823e7
|
@ -165,6 +165,17 @@ private:
|
|||
/// we know that this type is legal for the target.
|
||||
SDOperand PackVectorOp(SDOperand O, MVT::ValueType PackedVT);
|
||||
|
||||
/// isShuffleLegal - Return true if a vector shuffle is legal with the
|
||||
/// specified mask and type. Targets can specify exactly which masks they
|
||||
/// support and the code generator is tasked with not creating illegal masks.
|
||||
///
|
||||
/// Note that this will also return true for shuffles that are promoted to a
|
||||
/// different type.
|
||||
///
|
||||
/// If this is a legal shuffle, this method returns the (possibly promoted)
|
||||
/// build_vector Mask. If it's not a legal shuffle, it returns null.
|
||||
SDNode *isShuffleLegal(MVT::ValueType VT, SDOperand Mask) const;
|
||||
|
||||
bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest);
|
||||
|
||||
void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC);
|
||||
|
@ -178,6 +189,7 @@ private:
|
|||
|
||||
SDOperand ExpandBIT_CONVERT(MVT::ValueType DestVT, SDOperand SrcOp);
|
||||
SDOperand ExpandBUILD_VECTOR(SDNode *Node);
|
||||
SDOperand ExpandSCALAR_TO_VECTOR(SDNode *Node);
|
||||
SDOperand ExpandLegalINT_TO_FP(bool isSigned,
|
||||
SDOperand LegalOp,
|
||||
MVT::ValueType DestVT);
|
||||
|
@ -202,6 +214,51 @@ private:
|
|||
};
|
||||
}
|
||||
|
||||
/// isVectorShuffleLegal - Return true if a vector shuffle is legal with the
|
||||
/// specified mask and type. Targets can specify exactly which masks they
|
||||
/// support and the code generator is tasked with not creating illegal masks.
|
||||
///
|
||||
/// Note that this will also return true for shuffles that are promoted to a
|
||||
/// different type.
|
||||
SDNode *SelectionDAGLegalize::isShuffleLegal(MVT::ValueType VT,
|
||||
SDOperand Mask) const {
|
||||
switch (TLI.getOperationAction(ISD::VECTOR_SHUFFLE, VT)) {
|
||||
default: return 0;
|
||||
case TargetLowering::Legal:
|
||||
case TargetLowering::Custom:
|
||||
break;
|
||||
case TargetLowering::Promote: {
|
||||
// If this is promoted to a different type, convert the shuffle mask and
|
||||
// ask if it is legal in the promoted type!
|
||||
MVT::ValueType NVT = TLI.getTypeToPromoteTo(ISD::VECTOR_SHUFFLE, VT);
|
||||
|
||||
// If we changed # elements, change the shuffle mask.
|
||||
unsigned NumEltsGrowth =
|
||||
MVT::getVectorNumElements(NVT) / MVT::getVectorNumElements(VT);
|
||||
assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!");
|
||||
if (NumEltsGrowth > 1) {
|
||||
// Renumber the elements.
|
||||
std::vector<SDOperand> Ops;
|
||||
for (unsigned i = 0, e = Mask.getNumOperands(); i != e; ++i) {
|
||||
SDOperand InOp = Mask.getOperand(i);
|
||||
for (unsigned j = 0; j != NumEltsGrowth; ++j) {
|
||||
if (InOp.getOpcode() == ISD::UNDEF)
|
||||
Ops.push_back(DAG.getNode(ISD::UNDEF, MVT::i32));
|
||||
else {
|
||||
unsigned InEltNo = cast<ConstantSDNode>(InOp)->getValue();
|
||||
Ops.push_back(DAG.getConstant(InEltNo*NumEltsGrowth+j, MVT::i32));
|
||||
}
|
||||
}
|
||||
}
|
||||
Mask = DAG.getNode(ISD::BUILD_VECTOR, NVT, Ops);
|
||||
}
|
||||
VT = NVT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TLI.isShuffleMaskLegal(Mask, VT) ? Mask.Val : 0;
|
||||
}
|
||||
|
||||
/// getScalarizedOpcode - Return the scalar opcode that corresponds to the
|
||||
/// specified vector opcode.
|
||||
static unsigned getScalarizedOpcode(unsigned VecOp, MVT::ValueType VT) {
|
||||
|
@ -839,6 +896,11 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||
}
|
||||
break;
|
||||
case ISD::SCALAR_TO_VECTOR:
|
||||
if (!TLI.isTypeLegal(Node->getOperand(0).getValueType())) {
|
||||
Result = LegalizeOp(ExpandSCALAR_TO_VECTOR(Node));
|
||||
break;
|
||||
}
|
||||
|
||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // InVal
|
||||
Result = DAG.UpdateNodeOperands(Result, Tmp1);
|
||||
switch (TLI.getOperationAction(ISD::SCALAR_TO_VECTOR,
|
||||
|
@ -853,35 +915,43 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||
break;
|
||||
}
|
||||
// FALLTHROUGH
|
||||
case TargetLowering::Expand: {
|
||||
// If the target doesn't support this, store the value to a temporary
|
||||
// stack slot, then EXTLOAD the vector back out.
|
||||
// TODO: If a target doesn't support this, create a stack slot for the
|
||||
// whole vector, then store into it, then load the whole vector.
|
||||
SDOperand StackPtr =
|
||||
CreateStackTemporary(Node->getOperand(0).getValueType());
|
||||
SDOperand Ch = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
||||
Node->getOperand(0), StackPtr,
|
||||
DAG.getSrcValue(NULL));
|
||||
Result = DAG.getExtLoad(ISD::EXTLOAD, Node->getValueType(0), Ch, StackPtr,
|
||||
DAG.getSrcValue(NULL),
|
||||
Node->getOperand(0).getValueType());
|
||||
case TargetLowering::Expand:
|
||||
Result = LegalizeOp(ExpandSCALAR_TO_VECTOR(Node));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ISD::VECTOR_SHUFFLE:
|
||||
assert(TLI.isShuffleLegal(Result.getValueType(), Node->getOperand(2)) &&
|
||||
"vector shuffle should not be created if not legal!");
|
||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the input vectors,
|
||||
Tmp2 = LegalizeOp(Node->getOperand(1)); // but not the shuffle mask.
|
||||
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2));
|
||||
|
||||
// Allow targets to custom lower the SHUFFLEs they support.
|
||||
if (TLI.getOperationAction(ISD::VECTOR_SHUFFLE, Result.getValueType())
|
||||
== TargetLowering::Custom) {
|
||||
switch (TLI.getOperationAction(ISD::VECTOR_SHUFFLE,Result.getValueType())) {
|
||||
default: assert(0 && "Unknown operation action!");
|
||||
case TargetLowering::Legal:
|
||||
assert(isShuffleLegal(Result.getValueType(), Node->getOperand(2)) &&
|
||||
"vector shuffle should not be created if not legal!");
|
||||
break;
|
||||
case TargetLowering::Custom:
|
||||
Tmp1 = TLI.LowerOperation(Result, DAG);
|
||||
if (Tmp1.Val) Result = Tmp1;
|
||||
break;
|
||||
case TargetLowering::Promote: {
|
||||
// Change base type to a different vector type.
|
||||
MVT::ValueType OVT = Node->getValueType(0);
|
||||
MVT::ValueType NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OVT);
|
||||
|
||||
// Cast the two input vectors.
|
||||
Tmp1 = DAG.getNode(ISD::BIT_CONVERT, NVT, Tmp1);
|
||||
Tmp2 = DAG.getNode(ISD::BIT_CONVERT, NVT, Tmp2);
|
||||
|
||||
// Convert the shuffle mask to the right # elements.
|
||||
Tmp3 = SDOperand(isShuffleLegal(OVT, Node->getOperand(2)), 0);
|
||||
assert(Tmp3.Val && "Shuffle not legal?");
|
||||
Result = DAG.getNode(ISD::VECTOR_SHUFFLE, NVT, Tmp1, Tmp2, Tmp3);
|
||||
Result = DAG.getNode(ISD::BIT_CONVERT, OVT, Result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -3197,6 +3267,17 @@ SDOperand SelectionDAGLegalize::ExpandBIT_CONVERT(MVT::ValueType DestVT,
|
|||
return DAG.getLoad(DestVT, Store, FIPtr, DAG.getSrcValue(0));
|
||||
}
|
||||
|
||||
SDOperand SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) {
|
||||
// Create a vector sized/aligned stack slot, store the value to element #0,
|
||||
// then load the whole vector back out.
|
||||
SDOperand StackPtr = CreateStackTemporary(Node->getValueType(0));
|
||||
SDOperand Ch = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
||||
Node->getOperand(0), StackPtr,
|
||||
DAG.getSrcValue(NULL));
|
||||
return DAG.getLoad(Node->getValueType(0), Ch, StackPtr,DAG.getSrcValue(NULL));
|
||||
}
|
||||
|
||||
|
||||
/// ExpandBUILD_VECTOR - Expand a BUILD_VECTOR node on targets that don't
|
||||
/// support the operation, but do support the resultant packed vector type.
|
||||
SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
|
||||
|
@ -3274,7 +3355,7 @@ SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
|
|||
SDOperand SplatMask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT, ZeroVec);
|
||||
|
||||
// If the target supports VECTOR_SHUFFLE and this shuffle mask, use it.
|
||||
if (TLI.isShuffleLegal(Node->getValueType(0), SplatMask)) {
|
||||
if (isShuffleLegal(Node->getValueType(0), SplatMask)) {
|
||||
// Get the splatted value into the low element of a vector register.
|
||||
SDOperand LowValVec =
|
||||
DAG.getNode(ISD::SCALAR_TO_VECTOR, Node->getValueType(0), SplatValue);
|
||||
|
@ -3304,8 +3385,8 @@ SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
|
|||
SDOperand ShuffleMask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec);
|
||||
|
||||
// If the target supports VECTOR_SHUFFLE and this shuffle mask, use it.
|
||||
if (TLI.isShuffleLegal(Node->getValueType(0), ShuffleMask) &&
|
||||
TLI.isOperationLegal(ISD::SCALAR_TO_VECTOR, Node->getValueType(0))) {
|
||||
if (TLI.isOperationLegal(ISD::SCALAR_TO_VECTOR, Node->getValueType(0)) &&
|
||||
isShuffleLegal(Node->getValueType(0), ShuffleMask)) {
|
||||
std::vector<SDOperand> Ops;
|
||||
for(std::map<SDOperand,std::vector<unsigned> >::iterator I=Values.begin(),
|
||||
E = Values.end(); I != E; ++I) {
|
||||
|
|
Loading…
Reference in New Issue