Skip to content

Commit

Permalink
- VECTOR_SHUFFLE of v4i32 / v4f32 with undef second vector always mat…
Browse files Browse the repository at this point in the history
…ches

  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
  • Loading branch information
Evan Cheng committed Mar 22, 2006
1 parent c04b423 commit 63d3300
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 45 deletions.
52 changes: 27 additions & 25 deletions lib/Target/X86/X86ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<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) {
Expand All @@ -1412,9 +1391,10 @@ bool X86::isSplatMask(SDNode *N) {
return cast<ConstantSDNode>(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;
Expand All @@ -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<ConstantSDNode>(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) {
Expand Down Expand Up @@ -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();
}
Expand Down
15 changes: 8 additions & 7 deletions lib/Target/X86/X86ISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

//===----------------------------------------------------------------------===//
Expand Down
33 changes: 20 additions & 13 deletions lib/Target/X86/X86InstrSSE.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<build_vector, [{
return getI8Imm(X86::getShuffleImmediate(N));
// SHUFFLE_get_shuf_imm xform function: convert vector_shuffle mask to PSHUF*,
// SHUFP* etc. imm.
def SHUFFLE_get_shuf_imm : SDNodeXForm<build_vector, [{
return getI8Imm(X86::getShuffleSHUFImmediate(N));
}]>;

def SHUFFLE_splat_mask : PatLeaf<(build_vector), [{
def SHUFFLE_get_pshufd_imm : SDNodeXForm<build_vector, [{
return getI8Imm(X86::getShufflePSHUFDImmediate(N));
}]>;

def SHUFP_splat_mask : PatLeaf<(build_vector), [{
return X86::isSplatMask(N);
}], SHUFFLE_get_imm>;
}], SHUFFLE_get_shuf_imm>;

def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{
return X86::isPSHUFDMask(N);
}], SHUFFLE_get_imm>;
def PSHUFD_shuffle_mask : PatLeaf<(build_vector), [{}], SHUFFLE_get_pshufd_imm>;

//===----------------------------------------------------------------------===//
// SSE scalar FP Instructions
Expand Down Expand Up @@ -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))>;

0 comments on commit 63d3300

Please sign in to comment.