[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Chris Lattner
lattner at cs.uiuc.edu
Tue Apr 4 10:23:39 PDT 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
LegalizeDAG.cpp updated: 1.351 -> 1.352
---
Log message:
* 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.
---
Diffs of the changes: (+102 -21)
LegalizeDAG.cpp | 123 ++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 102 insertions(+), 21 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.351 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.352
--- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.351 Sat Apr 1 23:06:04 2006
+++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Tue Apr 4 12:23:26 2006
@@ -165,6 +165,17 @@
/// 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 @@
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 @@
};
}
+/// 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 @@
}
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 @@
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 @@
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 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 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) {
More information about the llvm-commits
mailing list