From: Evan Cheng Date: Wed, 22 Mar 2006 18:59:22 +0000 (+0000) Subject: - Implement X86ISelLowering::isShuffleMaskLegal(). We currently only support X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0188ecba85c7139f237baa4ce5612fdfc83e1b84;p=oota-llvm.git - Implement X86ISelLowering::isShuffleMaskLegal(). We currently only support splat and PSHUFD cases. - Clean up shuffle / splat matching code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26954 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index fafaf00ed1c..d26d7879a45 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1368,6 +1368,26 @@ static bool DarwinGVRequiresExtraLoad(GlobalValue *GV) { (GV->isExternal() && !GV->hasNotBeenReadFromBytecode())); } +/// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand +/// specifies a shuffle of elements that is suitable for input to PSHUFD. +bool X86::isPSHUFDMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + if (N->getNumOperands() != 4) + return false; + + // Check if the value doesn't reference the second vector. + SDOperand Elt = N->getOperand(0); + assert(isa(Elt) && "Invalid VECTOR_SHUFFLE mask!"); + for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i) { + assert(isa(N->getOperand(i)) && + "Invalid VECTOR_SHUFFLE mask!"); + if (cast(N->getOperand(i))->getValue() >= 4) return false; + } + + return true; +} + /// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies /// a splat of a single element. bool X86::isSplatMask(SDNode *N) { @@ -2211,17 +2231,26 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { SDOperand PermMask = Op.getOperand(2); MVT::ValueType VT = Op.getValueType(); - if (V2.getOpcode() == ISD::UNDEF) { - // Handle splat cases. - if (X86::isSplatMask(PermMask.Val)) { - if (VT == MVT::v2f64 || VT == MVT::v2i64) - // Use unpcklpd - return DAG.getNode(X86ISD::UNPCKLP, VT, V1, V1); + // Handle splat cases. + if (X86::isSplatMask(PermMask.Val)) { + if (V2.getOpcode() == ISD::UNDEF) // Leave the VECTOR_SHUFFLE alone. It matches SHUFP*. return SDOperand(); - } else if (VT == MVT::v4f32) + else + // Make it match SHUFP* or UNPCKLPD. Second vector is undef since it's + // not needed. + return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, + DAG.getNode(ISD::UNDEF, V1.getValueType()), + PermMask); + } else if (X86::isPSHUFDMask(PermMask.Val)) { + if (V2.getOpcode() == ISD::UNDEF) // Leave the VECTOR_SHUFFLE alone. It matches PSHUFD. return SDOperand(); + else + // Make it match PSHUFD. Second vector is undef since it's not needed. + return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, + DAG.getNode(ISD::UNDEF, V1.getValueType()), + PermMask); } // TODO. @@ -2262,7 +2291,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::GlobalBaseReg: return "X86ISD::GlobalBaseReg"; case X86ISD::Wrapper: return "X86ISD::Wrapper"; case X86ISD::SCALAR_TO_VECTOR: return "X86ISD::SCALAR_TO_VECTOR"; - case X86ISD::UNPCKLP: return "X86ISD::UNPCKLP"; } } @@ -2341,3 +2369,11 @@ bool X86TargetLowering::isLegalAddressImmediate(GlobalValue *GV) const { } else return true; } + +/// isShuffleMaskLegal - Targets can use this to indicate that they only +/// support *some* VECTOR_SHUFFLE operations, those with specific masks. +/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values +/// are assumed to be legal. +bool X86TargetLowering::isShuffleMaskLegal(SDOperand Mask) const { + return (X86::isSplatMask(Mask.Val) || X86::isPSHUFDMask(Mask.Val)); +} diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index b89445796a8..e9ff015b5af 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -179,6 +179,10 @@ namespace llvm { /// Define some predicates that are used for node matching. namespace X86 { + /// isPSHUFDMask - Return true if the specified VECTOR_SHUFFLE operand + /// specifies a shuffle of elements that is suitable for input to PSHUFD. + bool isPSHUFDMask(SDNode *N); + /// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element. bool isSplatMask(SDNode *N); @@ -259,6 +263,11 @@ namespace llvm { virtual bool isLegalAddressImmediate(int64_t V) const; virtual bool isLegalAddressImmediate(GlobalValue *GV) const; + /// isShuffleMaskLegal - Targets can use this to indicate that they only + /// support *some* VECTOR_SHUFFLE operations, those with specific masks. + /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values + /// are assumed to be legal. + virtual bool isShuffleMaskLegal(SDOperand Mask) const; private: // C Calling Convention implementation. std::vector LowerCCCArguments(Function &F, SelectionDAG &DAG); diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index aa82c297794..fe8bc946132 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -55,7 +55,15 @@ def SHUFP_splat_mask : PatLeaf<(build_vector), [{ return X86::isSplatMask(N); }], SHUFFLE_get_shuf_imm>; -def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{}], SHUFFLE_get_pshufd_imm>; +def UNPCKLP_splat_mask : PatLeaf<(build_vector), [{ + return X86::isSplatMask(N); +}]>; + +// Only use PSHUF if it is not a splat. +def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{ + return !X86::isSplatMask(N) && X86::isPSHUFDMask(N); +}], SHUFFLE_get_pshufd_imm>; + //===----------------------------------------------------------------------===// // SSE scalar FP Instructions @@ -691,9 +699,7 @@ def PSHUFWrm : PSIi8<0x70, MRMSrcMem, "pshufw {$src2, $src1, $dst|$dst, $src1, $src2}", []>; def PSHUFDrr : PDIi8<0x70, MRMDestReg, (ops VR128:$dst, VR128:$src1, i8imm:$src2), - "pshufd {$src2, $src1, $dst|$dst, $src1, $src2}", - [(set VR128:$dst, (vector_shuffle (v4f32 VR128:$src1), (undef), - PSHUFD_shuffle_mask:$src2))]>; + "pshufd {$src2, $src1, $dst|$dst, $src1, $src2}", []>; def PSHUFDrm : PDIi8<0x70, MRMSrcMem, (ops VR128:$dst, i128mem:$src1, i8imm:$src2), "pshufd {$src2, $src1, $dst|$dst, $src1, $src2}", []>; @@ -809,12 +815,13 @@ def : Pat<(vector_shuffle (v4i32 VR128:$src), (undef), SHUFP_splat_mask:$sm), (v4i32 (SHUFPSrr VR128:$src, VR128:$src, SHUFP_splat_mask:$sm))>; // Splat v2f64 / v2i64 -def : Pat<(X86unpcklp (v2f64 VR128:$src1), VR128:$src2), - (v2f64 (UNPCKLPDrr VR128:$src1, VR128:$src2))>; -def : Pat<(X86unpcklp (v2i64 VR128:$src1), VR128:$src2), - (v2i64 (UNPCKLPDrr VR128:$src1, VR128:$src2))>; - -// Shuffle v4i32, undef -def : Pat<(vector_shuffle (v4i32 VR128:$src1), (undef), - PSHUFD_shuffle_mask:$src2), - (v4i32 (PSHUFDrr VR128:$src1, PSHUFD_shuffle_mask:$src2))>; +def : Pat<(vector_shuffle (v2f64 VR128:$src), (undef), UNPCKLP_splat_mask:$sm), + (v2f64 (UNPCKLPDrr VR128:$src, VR128:$src))>; +def : Pat<(vector_shuffle (v2i64 VR128:$src), (undef), UNPCKLP_splat_mask:$sm), + (v2i64 (UNPCKLPDrr VR128:$src, VR128:$src))>; + +// Shuffle v4f32 / v4i32, undef. These should only match if splat cases do not. +def : Pat<(vector_shuffle (v4f32 VR128:$src), (undef), PSHUFD_shuffle_mask:$sm), + (v4f32 (PSHUFDrr VR128:$src, PSHUFD_shuffle_mask:$sm))>; +def : Pat<(vector_shuffle (v4i32 VR128:$src), (undef), PSHUFD_shuffle_mask:$sm), + (v4i32 (PSHUFDrr VR128:$src, PSHUFD_shuffle_mask:$sm))>;