[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Chris Lattner
lattner at cs.uiuc.edu
Thu Apr 13 22:19:30 PDT 2006
Changes in directory llvm/lib/Target/PowerPC:
PPCISelLowering.cpp updated: 1.148 -> 1.149
---
Log message:
Pull the VECTOR_SHUFFLE and BUILD_VECTOR lowering code out into separate
functions, which makes the code much cleaner :)
---
Diffs of the changes: (+155 -147)
PPCISelLowering.cpp | 302 ++++++++++++++++++++++++++--------------------------
1 files changed, 155 insertions(+), 147 deletions(-)
Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
diff -u llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.148 llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.149
--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.148 Thu Apr 13 12:10:48 2006
+++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp Fri Apr 14 00:19:18 2006
@@ -587,11 +587,166 @@
return false;
}
+// If this is a case we can't handle, return null and let the default
+// expansion code take care of it. If we CAN select this case, and if it
+// selects to a single instruction, return Op. Otherwise, if we can codegen
+// this case more efficiently than a constant pool load, lower it to the
+// sequence of ops that should be used.
+static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
+ // If this is a vector of constants or undefs, get the bits. A bit in
+ // UndefBits is set if the corresponding element of the vector is an
+ // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
+ // zero.
+ uint64_t VectorBits[2];
+ uint64_t UndefBits[2];
+ if (GetConstantBuildVectorBits(Op.Val, VectorBits, UndefBits))
+ return SDOperand(); // Not a constant vector.
+
+ // See if this is all zeros.
+ if ((VectorBits[0] | VectorBits[1]) == 0) {
+ // Canonicalize all zero vectors to be v4i32.
+ if (Op.getValueType() != MVT::v4i32) {
+ SDOperand Z = DAG.getConstant(0, MVT::i32);
+ Z = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Z, Z, Z, Z);
+ Op = DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Z);
+ }
+ return Op;
+ }
+
+ // Check to see if this is something we can use VSPLTI* to form.
+ MVT::ValueType CanonicalVT = MVT::Other;
+ SDNode *CST = 0;
+
+ if ((CST = PPC::get_VSPLTI_elt(Op.Val, 4, DAG).Val)) // vspltisw
+ CanonicalVT = MVT::v4i32;
+ else if ((CST = PPC::get_VSPLTI_elt(Op.Val, 2, DAG).Val)) // vspltish
+ CanonicalVT = MVT::v8i16;
+ else if ((CST = PPC::get_VSPLTI_elt(Op.Val, 1, DAG).Val)) // vspltisb
+ CanonicalVT = MVT::v16i8;
+
+ // If this matches one of the vsplti* patterns, force it to the canonical
+ // type for the pattern.
+ if (CST) {
+ if (Op.getValueType() != CanonicalVT) {
+ // Convert the splatted element to the right element type.
+ SDOperand Elt = DAG.getNode(ISD::TRUNCATE,
+ MVT::getVectorBaseType(CanonicalVT),
+ SDOperand(CST, 0));
+ std::vector<SDOperand> Ops(MVT::getVectorNumElements(CanonicalVT), Elt);
+ SDOperand Res = DAG.getNode(ISD::BUILD_VECTOR, CanonicalVT, Ops);
+ Op = DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
+ }
+ return Op;
+ }
+
+ // If this is some other splat of 4-byte elements, see if we can handle it
+ // in another way.
+ // FIXME: Make this more undef happy and work with other widths (1,2 bytes).
+ if (VectorBits[0] == VectorBits[1] &&
+ unsigned(VectorBits[0]) == unsigned(VectorBits[0] >> 32)) {
+ unsigned Bits = unsigned(VectorBits[0]);
+
+ // If this is 0x8000_0000 x 4, turn into vspltisw + vslw. If it is
+ // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000). These are important
+ // for fneg/fabs.
+ if (Bits == 0x80000000 || Bits == 0x7FFFFFFF) {
+ // Make -1 and vspltisw -1:
+ SDOperand OnesI = DAG.getConstant(~0U, MVT::i32);
+ SDOperand OnesV = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
+ OnesI, OnesI, OnesI, OnesI);
+
+ // Make the VSLW intrinsic, computing 0x8000_0000.
+ SDOperand Res
+ = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, MVT::v4i32,
+ DAG.getConstant(Intrinsic::ppc_altivec_vslw, MVT::i32),
+ OnesV, OnesV);
+
+ // If this is 0x7FFF_FFFF, xor by OnesV to invert it.
+ if (Bits == 0x7FFFFFFF)
+ Res = DAG.getNode(ISD::XOR, MVT::v4i32, Res, OnesV);
+
+ return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
+ }
+ }
+
+ return SDOperand();
+}
+
+/// LowerVECTOR_SHUFFLE - Return the code we lower for VECTOR_SHUFFLE. If this
+/// is a shuffle we can handle in a single instruction, return it. Otherwise,
+/// return the code it can be lowered into. Worst case, it can always be
+/// lowered into a vperm.
+static SDOperand LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
+ SDOperand V1 = Op.getOperand(0);
+ SDOperand V2 = Op.getOperand(1);
+ SDOperand PermMask = Op.getOperand(2);
+
+ // Cases that are handled by instructions that take permute immediates
+ // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be
+ // selected by the instruction selector.
+ if (V2.getOpcode() == ISD::UNDEF) {
+ if (PPC::isSplatShuffleMask(PermMask.Val, 1) ||
+ PPC::isSplatShuffleMask(PermMask.Val, 2) ||
+ PPC::isSplatShuffleMask(PermMask.Val, 4) ||
+ PPC::isVPKUWUMShuffleMask(PermMask.Val, true) ||
+ PPC::isVPKUHUMShuffleMask(PermMask.Val, true) ||
+ PPC::isVSLDOIShuffleMask(PermMask.Val, true) != -1 ||
+ PPC::isVMRGLShuffleMask(PermMask.Val, 1, true) ||
+ PPC::isVMRGLShuffleMask(PermMask.Val, 2, true) ||
+ PPC::isVMRGLShuffleMask(PermMask.Val, 4, true) ||
+ PPC::isVMRGHShuffleMask(PermMask.Val, 1, true) ||
+ PPC::isVMRGHShuffleMask(PermMask.Val, 2, true) ||
+ PPC::isVMRGHShuffleMask(PermMask.Val, 4, true)) {
+ return Op;
+ }
+ }
+
+ // Altivec has a variety of "shuffle immediates" that take two vector inputs
+ // and produce a fixed permutation. If any of these match, do not lower to
+ // VPERM.
+ if (PPC::isVPKUWUMShuffleMask(PermMask.Val, false) ||
+ PPC::isVPKUHUMShuffleMask(PermMask.Val, false) ||
+ PPC::isVSLDOIShuffleMask(PermMask.Val, false) != -1 ||
+ PPC::isVMRGLShuffleMask(PermMask.Val, 1, false) ||
+ PPC::isVMRGLShuffleMask(PermMask.Val, 2, false) ||
+ PPC::isVMRGLShuffleMask(PermMask.Val, 4, false) ||
+ PPC::isVMRGHShuffleMask(PermMask.Val, 1, false) ||
+ PPC::isVMRGHShuffleMask(PermMask.Val, 2, false) ||
+ PPC::isVMRGHShuffleMask(PermMask.Val, 4, false))
+ return Op;
+
+ // TODO: Handle more cases, and also handle cases that are cheaper to do as
+ // multiple such instructions than as a constant pool load/vperm pair.
+
+ // Lower this to a VPERM(V1, V2, V3) expression, where V3 is a constant
+ // vector that will get spilled to the constant pool.
+ if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
+
+ // The SHUFFLE_VECTOR mask is almost exactly what we want for vperm, except
+ // that it is in input element units, not in bytes. Convert now.
+ MVT::ValueType EltVT = MVT::getVectorBaseType(V1.getValueType());
+ unsigned BytesPerElement = MVT::getSizeInBits(EltVT)/8;
+
+ std::vector<SDOperand> ResultMask;
+ for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
+ unsigned SrcElt =cast<ConstantSDNode>(PermMask.getOperand(i))->getValue();
+
+ for (unsigned j = 0; j != BytesPerElement; ++j)
+ ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
+ MVT::i8));
+ }
+
+ SDOperand VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8, ResultMask);
+ return DAG.getNode(PPCISD::VPERM, V1.getValueType(), V1, V2, VPermMask);
+}
+
/// LowerOperation - Provide custom lowering hooks for some operations.
///
SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) {
default: assert(0 && "Wasn't expecting to be able to lower this!");
+ case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
+ case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
case ISD::FP_TO_SINT: {
assert(MVT::isFloatingPoint(Op.getOperand(0).getValueType()));
SDOperand Src = Op.getOperand(0);
@@ -963,153 +1118,6 @@
// Load it out.
return DAG.getLoad(Op.getValueType(), Store, FIdx, DAG.getSrcValue(NULL));
}
- case ISD::BUILD_VECTOR: {
- // If this is a case we can't handle, return null and let the default
- // expansion code take care of it. If we CAN select this case, return Op
- // or something simpler.
-
- // If this is a vector of constants or undefs, get the bits. A bit in
- // UndefBits is set if the corresponding element of the vector is an
- // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
- // zero.
- uint64_t VectorBits[2];
- uint64_t UndefBits[2];
- if (GetConstantBuildVectorBits(Op.Val, VectorBits, UndefBits))
- return SDOperand(); // Not a constant vector.
-
- // See if this is all zeros.
- if ((VectorBits[0] | VectorBits[1]) == 0) {
- // Canonicalize all zero vectors to be v4i32.
- if (Op.getValueType() != MVT::v4i32) {
- SDOperand Z = DAG.getConstant(0, MVT::i32);
- Z = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Z, Z, Z, Z);
- Op = DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Z);
- }
- return Op;
- }
-
- // Check to see if this is something we can use VSPLTI* to form.
- MVT::ValueType CanonicalVT = MVT::Other;
- SDNode *CST = 0;
-
- if ((CST = PPC::get_VSPLTI_elt(Op.Val, 4, DAG).Val)) // vspltisw
- CanonicalVT = MVT::v4i32;
- else if ((CST = PPC::get_VSPLTI_elt(Op.Val, 2, DAG).Val)) // vspltish
- CanonicalVT = MVT::v8i16;
- else if ((CST = PPC::get_VSPLTI_elt(Op.Val, 1, DAG).Val)) // vspltisb
- CanonicalVT = MVT::v16i8;
-
- // If this matches one of the vsplti* patterns, force it to the canonical
- // type for the pattern.
- if (CST) {
- if (Op.getValueType() != CanonicalVT) {
- // Convert the splatted element to the right element type.
- SDOperand Elt = DAG.getNode(ISD::TRUNCATE,
- MVT::getVectorBaseType(CanonicalVT),
- SDOperand(CST, 0));
- std::vector<SDOperand> Ops(MVT::getVectorNumElements(CanonicalVT), Elt);
- SDOperand Res = DAG.getNode(ISD::BUILD_VECTOR, CanonicalVT, Ops);
- Op = DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
- }
- return Op;
- }
-
- // If this is some other splat of 4-byte elements, see if we can handle it
- // in another way.
- // FIXME: Make this more undef happy and work with other widths (1,2 bytes).
- if (VectorBits[0] == VectorBits[1] &&
- unsigned(VectorBits[0]) == unsigned(VectorBits[0] >> 32)) {
- unsigned Bits = unsigned(VectorBits[0]);
-
- // If this is 0x8000_0000 x 4, turn into vspltisw + vslw. If it is
- // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000). These are important
- // for fneg/fabs.
- if (Bits == 0x80000000 || Bits == 0x7FFFFFFF) {
- // Make -1 and vspltisw -1:
- SDOperand OnesI = DAG.getConstant(~0U, MVT::i32);
- SDOperand OnesV = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32,
- OnesI, OnesI, OnesI, OnesI);
-
- // Make the VSLW intrinsic, computing 0x8000_0000.
- SDOperand Res
- = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, MVT::v4i32,
- DAG.getConstant(Intrinsic::ppc_altivec_vslw, MVT::i32),
- OnesV, OnesV);
-
- // If this is 0x7FFF_FFFF, xor by OnesV to invert it.
- if (Bits == 0x7FFFFFFF)
- Res = DAG.getNode(ISD::XOR, MVT::v4i32, Res, OnesV);
-
- return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
- }
- }
-
-
- return SDOperand();
- }
- case ISD::VECTOR_SHUFFLE: {
- SDOperand V1 = Op.getOperand(0);
- SDOperand V2 = Op.getOperand(1);
- SDOperand PermMask = Op.getOperand(2);
-
- // Cases that are handled by instructions that take permute immediates
- // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be
- // selected by the instruction selector.
- if (V2.getOpcode() == ISD::UNDEF) {
- if (PPC::isSplatShuffleMask(PermMask.Val, 1) ||
- PPC::isSplatShuffleMask(PermMask.Val, 2) ||
- PPC::isSplatShuffleMask(PermMask.Val, 4) ||
- PPC::isVPKUWUMShuffleMask(PermMask.Val, true) ||
- PPC::isVPKUHUMShuffleMask(PermMask.Val, true) ||
- PPC::isVSLDOIShuffleMask(PermMask.Val, true) != -1 ||
- PPC::isVMRGLShuffleMask(PermMask.Val, 1, true) ||
- PPC::isVMRGLShuffleMask(PermMask.Val, 2, true) ||
- PPC::isVMRGLShuffleMask(PermMask.Val, 4, true) ||
- PPC::isVMRGHShuffleMask(PermMask.Val, 1, true) ||
- PPC::isVMRGHShuffleMask(PermMask.Val, 2, true) ||
- PPC::isVMRGHShuffleMask(PermMask.Val, 4, true)) {
- return Op;
- }
- }
-
- // Altivec has a variety of "shuffle immediates" that take two vector inputs
- // and produce a fixed permutation. If any of these match, do not lower to
- // VPERM.
- if (PPC::isVPKUWUMShuffleMask(PermMask.Val, false) ||
- PPC::isVPKUHUMShuffleMask(PermMask.Val, false) ||
- PPC::isVSLDOIShuffleMask(PermMask.Val, false) != -1 ||
- PPC::isVMRGLShuffleMask(PermMask.Val, 1, false) ||
- PPC::isVMRGLShuffleMask(PermMask.Val, 2, false) ||
- PPC::isVMRGLShuffleMask(PermMask.Val, 4, false) ||
- PPC::isVMRGHShuffleMask(PermMask.Val, 1, false) ||
- PPC::isVMRGHShuffleMask(PermMask.Val, 2, false) ||
- PPC::isVMRGHShuffleMask(PermMask.Val, 4, false))
- return Op;
-
- // TODO: Handle more cases, and also handle cases that are cheaper to do as
- // multiple such instructions than as a constant pool load/vperm pair.
-
- // Lower this to a VPERM(V1, V2, V3) expression, where V3 is a constant
- // vector that will get spilled to the constant pool.
- if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
-
- // The SHUFFLE_VECTOR mask is almost exactly what we want for vperm, except
- // that it is in input element units, not in bytes. Convert now.
- MVT::ValueType EltVT = MVT::getVectorBaseType(V1.getValueType());
- unsigned BytesPerElement = MVT::getSizeInBits(EltVT)/8;
-
- std::vector<SDOperand> ResultMask;
- for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) {
- unsigned SrcElt =cast<ConstantSDNode>(PermMask.getOperand(i))->getValue();
-
- for (unsigned j = 0; j != BytesPerElement; ++j)
- ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,
- MVT::i8));
- }
-
- SDOperand VPermMask =DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8, ResultMask);
- return DAG.getNode(PPCISD::VPERM, V1.getValueType(), V1, V2, VPermMask);
- }
case ISD::INTRINSIC_WO_CHAIN: {
unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getValue();
More information about the llvm-commits
mailing list