Changes in directory llvm/lib/Target/X86:
X86ISelLowering.cpp updated: 1.118 -> 1.119 X86ISelLowering.h updated: 1.36 -> 1.37 X86InstrSSE.td updated: 1.15 -> 1.16 --- Log message: - Implement X86ISelLowering::isShuffleMaskLegal(). We currently only support splat and PSHUFD cases. - Clean up shuffle / splat matching code. --- Diffs of the changes: (+73 -21) X86ISelLowering.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++-------- X86ISelLowering.h | 9 +++++++++ X86InstrSSE.td | 33 ++++++++++++++++++++------------- 3 files changed, 73 insertions(+), 21 deletions(-) Index: llvm/lib/Target/X86/X86ISelLowering.cpp diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.118 llvm/lib/Target/X86/X86ISelLowering.cpp:1.119 --- llvm/lib/Target/X86/X86ISelLowering.cpp:1.118 Wed Mar 22 02:01:21 2006 +++ llvm/lib/Target/X86/X86ISelLowering.cpp Wed Mar 22 12:59:22 2006 @@ -1368,6 +1368,26 @@ (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<ConstantSDNode>(Elt) && "Invalid VECTOR_SHUFFLE mask!"); + for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i) { + assert(isa<ConstantSDNode>(N->getOperand(i)) && + "Invalid VECTOR_SHUFFLE mask!"); + if (cast<ConstantSDNode>(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 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 @@ 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 @@ } 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)); +} Index: llvm/lib/Target/X86/X86ISelLowering.h diff -u llvm/lib/Target/X86/X86ISelLowering.h:1.36 llvm/lib/Target/X86/X86ISelLowering.h:1.37 --- llvm/lib/Target/X86/X86ISelLowering.h:1.36 Wed Mar 22 02:01:21 2006 +++ llvm/lib/Target/X86/X86ISelLowering.h Wed Mar 22 12:59:22 2006 @@ -179,6 +179,10 @@ /// 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 @@ 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<SDOperand> LowerCCCArguments(Function &F, SelectionDAG &DAG); Index: llvm/lib/Target/X86/X86InstrSSE.td diff -u llvm/lib/Target/X86/X86InstrSSE.td:1.15 llvm/lib/Target/X86/X86InstrSSE.td:1.16 --- llvm/lib/Target/X86/X86InstrSSE.td:1.15 Wed Mar 22 02:01:21 2006 +++ llvm/lib/Target/X86/X86InstrSSE.td Wed Mar 22 12:59:22 2006 @@ -55,7 +55,15 @@ 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 @@ "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 @@ (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))>; _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits