From 63d3300da1ec6403fbf11f62d6404c7f87bffdba Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 22 Mar 2006 08:01:21 +0000 Subject: [PATCH] - VECTOR_SHUFFLE of v4i32 / v4f32 with undef second vector always matches PSHUFD. We can make permutes entries which point to the undef pointing anything we want. - Change some names to appease Chris. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26951 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 52 ++++++++++++++++-------------- lib/Target/X86/X86ISelLowering.h | 15 +++++---- lib/Target/X86/X86InstrSSE.td | 35 ++++++++++++-------- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index e7ce462de59..fafaf00ed1c 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1368,27 +1368,6 @@ 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; - - // This is a splat operation if each element of the permute is the same, and - // 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) { @@ -1412,9 +1391,10 @@ bool X86::isSplatMask(SDNode *N) { return cast(Elt)->getValue() < N->getNumOperands(); } -/// getShuffleImmediate - Return the appropriate immediate to shuffle -/// the specified isShuffleMask VECTOR_SHUFFLE mask. -unsigned X86::getShuffleImmediate(SDNode *N) { +/// getShuffleSHUFImmediate - Return the appropriate immediate to shuffle +/// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUF* and SHUFP* +/// instructions. +unsigned X86::getShuffleSHUFImmediate(SDNode *N) { unsigned NumOperands = N->getNumOperands(); unsigned Shift = (NumOperands == 4) ? 2 : 1; unsigned Mask = 0; @@ -1428,6 +1408,28 @@ unsigned X86::getShuffleImmediate(SDNode *N) { return Mask; } +/// getShufflePSHUFDImmediate - Return the appropriate immediate to shuffle +/// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUFD instruction. +unsigned X86::getShufflePSHUFDImmediate(SDNode *N) { + unsigned NumOperands = N->getNumOperands(); + unsigned Mask = 0; + + assert(NumOperands == 4 && "Expect v4f32 / v4i32 vector operand"); + + unsigned i = NumOperands - 1; + do { + uint64_t Val = cast(N->getOperand(i))->getValue(); + // Second vector operand must be undef. We can have it point to anything + // we want. + if (Val >= NumOperands) Val = 0; + Mask |= Val; + Mask <<= 2; + --i; + } while (i != 0); + + return Mask; +} + /// LowerOperation - Provide custom lowering hooks for some operations. /// SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { @@ -2217,7 +2219,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(X86ISD::UNPCKLP, VT, V1, V1); // Leave the VECTOR_SHUFFLE alone. It matches SHUFP*. return SDOperand(); - } else if (VT == MVT::v4f32 && X86::isPSHUFDMask(PermMask.Val)) + } else if (VT == MVT::v4f32) // Leave the VECTOR_SHUFFLE alone. It matches PSHUFD. return SDOperand(); } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index ecfc8a237de..b89445796a8 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -179,17 +179,18 @@ 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); - /// getShuffleImmediate - Return the appropriate immediate to shuffle - /// the specified isShuffleMask VECTOR_SHUFFLE mask. - unsigned getShuffleImmediate(SDNode *N); + /// getShuffleSHUFImmediate - Return the appropriate immediate to shuffle + /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUF* and SHUFP* + /// instructions. + unsigned getShuffleSHUFImmediate(SDNode *N); + + /// getShufflePSHUFDImmediate - Return the appropriate immediate to shuffle + /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUFD instruction. + unsigned getShufflePSHUFDImmediate(SDNode *N); } //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 856a8000493..aa82c297794 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -41,19 +41,21 @@ def X86loadpf64 : PatFrag<(ops node:$ptr), (f64 (X86loadp node:$ptr))>; def loadv4f32 : PatFrag<(ops node:$ptr), (v4f32 (load node:$ptr))>; def loadv2f64 : PatFrag<(ops node:$ptr), (v2f64 (load node:$ptr))>; -// SHUFFLE_get_imm xform function: convert vector_shuffle mask to PSHUF*, -// SHUF* etc. imm. -def SHUFFLE_get_imm : SDNodeXForm; -def SHUFFLE_splat_mask : PatLeaf<(build_vector), [{ - return X86::isSplatMask(N); -}], SHUFFLE_get_imm>; +def SHUFFLE_get_pshufd_imm : SDNodeXForm; -def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{ - return X86::isPSHUFDMask(N); -}], SHUFFLE_get_imm>; +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>; //===----------------------------------------------------------------------===// // SSE scalar FP Instructions @@ -801,13 +803,18 @@ def : Pat<(v16i8 (X86s2vec R32:$src)), (MOVD128rr R32:$src)>, // Splat v4f32 / v4i32 -def : Pat<(vector_shuffle (v4f32 VR128:$src), (undef), SHUFFLE_splat_mask:$sm), - (v4f32 (SHUFPSrr VR128:$src, VR128:$src, SHUFFLE_splat_mask:$sm))>; -def : Pat<(vector_shuffle (v4i32 VR128:$src), (undef), SHUFFLE_splat_mask:$sm), - (v4i32 (SHUFPSrr VR128:$src, VR128:$src, SHUFFLE_splat_mask:$sm))>; +def : Pat<(vector_shuffle (v4f32 VR128:$src), (undef), SHUFP_splat_mask:$sm), + (v4f32 (SHUFPSrr VR128:$src, VR128:$src, SHUFP_splat_mask:$sm))>; +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))>;