diff options
author | Chris Lattner <sabre@nondot.org> | 2006-04-04 17:25:31 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2006-04-04 17:25:31 +0000 |
commit | 7ff7e674580adad7a5bccdbd74cf9c9f05e46d0f (patch) | |
tree | 3ae6c61ce0b9328b0abe8a2a07b562a2c1ee1122 /lib/Target/PowerPC/PPCISelLowering.cpp | |
parent | 4352cc9e217e4482ad53f5a7b92c3543f569eb6e (diff) |
Ask legalize to promote all vector shuffles to be v16i8 instead of having to
handle all 4 PPC vector types. This simplifies the matching code and allows
us to eliminate a bunch of patterns. This also adds cases we were missing,
such as CodeGen/PowerPC/vec_splat.ll:splat_h.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27400 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.cpp | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 1c3f4fdcef..b27f5959db 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -181,8 +181,9 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) setOperationAction(ISD::OR , (MVT::ValueType)VT, Legal); setOperationAction(ISD::XOR , (MVT::ValueType)VT, Legal); - // We can custom expand all VECTOR_SHUFFLEs to VPERM. - setOperationAction(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, Custom); + // We promote all shuffles to v16i8. + setOperationAction(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, Promote); + AddPromotedToType(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, MVT::v16i8); setOperationAction(ISD::MUL , (MVT::ValueType)VT, Expand); setOperationAction(ISD::SDIV, (MVT::ValueType)VT, Expand); @@ -196,6 +197,10 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) setOperationAction(ISD::SCALAR_TO_VECTOR, (MVT::ValueType)VT, Expand); } + // We can custom expand all VECTOR_SHUFFLEs to VPERM, others we can handle + // with merges, splats, etc. + setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v16i8, Custom); + addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass); addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass); addRegisterClass(MVT::v8i16, PPC::VRRCRegisterClass); @@ -266,33 +271,47 @@ static bool isFloatingPointZero(SDOperand Op) { /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element that is suitable for input to /// VSPLTB/VSPLTH/VSPLTW. -bool PPC::isSplatShuffleMask(SDNode *N) { - assert(N->getOpcode() == ISD::BUILD_VECTOR); - - // We can only splat 8-bit, 16-bit, and 32-bit quantities. - if (N->getNumOperands() != 4 && N->getNumOperands() != 8 && - N->getNumOperands() != 16) - return false; +bool PPC::isSplatShuffleMask(SDNode *N, unsigned EltSize) { + assert(N->getOpcode() == ISD::BUILD_VECTOR && + N->getNumOperands() == 16 && + (EltSize == 1 || EltSize == 2 || EltSize == 4)); // This is a splat operation if each element of the permute is the same, and // if the value doesn't reference the second vector. + unsigned ElementBase = 0; SDOperand Elt = N->getOperand(0); + if (ConstantSDNode *EltV = dyn_cast<ConstantSDNode>(Elt)) + ElementBase = EltV->getValue(); + else + return false; // FIXME: Handle UNDEF elements too! + + if (cast<ConstantSDNode>(Elt)->getValue() >= 16) + return false; + + // Check that they are consequtive. + for (unsigned i = 1; i != EltSize; ++i) { + if (!isa<ConstantSDNode>(N->getOperand(i)) || + cast<ConstantSDNode>(N->getOperand(i))->getValue() != i+ElementBase) + return false; + } + assert(isa<ConstantSDNode>(Elt) && "Invalid VECTOR_SHUFFLE mask!"); - for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i) { + for (unsigned i = EltSize, e = 16; i != e; i += EltSize) { assert(isa<ConstantSDNode>(N->getOperand(i)) && "Invalid VECTOR_SHUFFLE mask!"); - if (N->getOperand(i) != Elt) return false; + for (unsigned j = 0; j != EltSize; ++j) + if (N->getOperand(i+j) != N->getOperand(j)) + return false; } - // Make sure it is a splat of the first vector operand. - return cast<ConstantSDNode>(Elt)->getValue() < N->getNumOperands(); + return true; } /// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the /// specified isSplatShuffleMask VECTOR_SHUFFLE mask. -unsigned PPC::getVSPLTImmediate(SDNode *N) { - assert(isSplatShuffleMask(N)); - return cast<ConstantSDNode>(N->getOperand(0))->getValue(); +unsigned PPC::getVSPLTImmediate(SDNode *N, unsigned EltSize) { + assert(isSplatShuffleMask(N, EltSize)); + return cast<ConstantSDNode>(N->getOperand(0))->getValue() / EltSize; } /// isVecSplatImm - Return true if this is a build_vector of constants which @@ -734,7 +753,10 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { // 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 (PPC::isSplatShuffleMask(PermMask.Val) && V2.getOpcode() == ISD::UNDEF) + if (V2.getOpcode() == ISD::UNDEF && + (PPC::isSplatShuffleMask(PermMask.Val, 1) || + PPC::isSplatShuffleMask(PermMask.Val, 2) || + PPC::isSplatShuffleMask(PermMask.Val, 4))) break; // TODO: Handle more cases, and also handle cases that are cheaper to do as |