Commute vector_shuffle to match more movlhps, movlp{s|d} cases.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27840 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2006-04-19 20:35:22 +00:00
parent 3a00a3e573
commit 533a0aa9ba
2 changed files with 59 additions and 63 deletions

View File

@ -1555,21 +1555,6 @@ bool X86::isMOVHLPSMask(SDNode *N) {
isUndefOrEqual(N->getOperand(3), 3);
}
/// isMOVLHPSMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVHLPS.
bool X86::isMOVLHPSMask(SDNode *N) {
assert(N->getOpcode() == ISD::BUILD_VECTOR);
if (N->getNumOperands() != 4)
return false;
// Expect bit0 == 0, bit1 == 1, bit2 == 4, bit3 == 5
return isUndefOrEqual(N->getOperand(0), 0) &&
isUndefOrEqual(N->getOperand(1), 1) &&
isUndefOrEqual(N->getOperand(2), 4) &&
isUndefOrEqual(N->getOperand(3), 5);
}
/// isMOVLPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVLP{S|D}.
bool X86::isMOVLPMask(SDNode *N) {
@ -1591,7 +1576,8 @@ bool X86::isMOVLPMask(SDNode *N) {
}
/// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVHP{S|D}.
/// specifies a shuffle of elements that is suitable for input to MOVHP{S|D}
/// and MOVLHPS.
bool X86::isMOVHPMask(SDNode *N) {
assert(N->getOpcode() == ISD::BUILD_VECTOR);
@ -1909,35 +1895,52 @@ static SDOperand CommuteVectorShuffle(SDOperand Op, SelectionDAG &DAG) {
return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V2, V1, Mask);
}
/// ShouldXformToMOVHLPS - Return true if the node should be transformed to
/// match movhlps. The lower half elements should come from upper half of
/// V1 (and in order), and the upper half elements should come from the upper
/// half of V2 (and in order).
static bool ShouldXformToMOVHLPS(SDNode *Mask) {
unsigned NumElems = Mask->getNumOperands();
if (NumElems != 4)
return false;
for (unsigned i = 0, e = 2; i != e; ++i)
if (!isUndefOrEqual(Mask->getOperand(i), i+2))
return false;
for (unsigned i = 2; i != 4; ++i)
if (!isUndefOrEqual(Mask->getOperand(i), i+4))
return false;
return true;
}
/// isScalarLoadToVector - Returns true if the node is a scalar load that
/// is promoted to a vector.
static inline bool isScalarLoadToVector(SDOperand Op) {
if (Op.getOpcode() == ISD::SCALAR_TO_VECTOR) {
Op = Op.getOperand(0);
return (Op.getOpcode() == ISD::LOAD);
static inline bool isScalarLoadToVector(SDNode *N) {
if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
N = N->getOperand(0).Val;
return (N->getOpcode() == ISD::LOAD);
}
return false;
}
/// ShouldXformedToMOVLP - Return true if the node should be transformed to
/// match movlp{d|s}. The lower half elements should come from V1 (and in
/// order), and the upper half elements should come from the upper half of
/// V2 (not necessarily in order). And since V1 will become the source of
/// the MOVLP, it must be a scalar load.
static bool ShouldXformedToMOVLP(SDOperand V1, SDOperand V2, SDOperand Mask) {
if (isScalarLoadToVector(V1)) {
unsigned NumElems = Mask.getNumOperands();
for (unsigned i = 0, e = NumElems/2; i != e; ++i)
if (!isUndefOrEqual(Mask.getOperand(i), i))
return false;
for (unsigned i = NumElems/2; i != NumElems; ++i)
if (!isUndefOrInRange(Mask.getOperand(i),
NumElems+NumElems/2, NumElems*2))
return false;
return true;
}
/// ShouldXformToMOVLP{S|D} - Return true if the node should be transformed to
/// match movlp{s|d}. The lower half elements should come from lower half of
/// V1 (and in order), and the upper half elements should come from the upper
/// half of V2 (and in order). And since V1 will become the source of the
/// MOVLP, it must be either a vector load or a scalar load to vector.
static bool ShouldXformToMOVLP(SDNode *V1, SDNode *Mask) {
if (V1->getOpcode() != ISD::LOAD && !isScalarLoadToVector(V1))
return false;
return false;
unsigned NumElems = Mask->getNumOperands();
if (NumElems != 2 && NumElems != 4)
return false;
for (unsigned i = 0, e = NumElems/2; i != e; ++i)
if (!isUndefOrEqual(Mask->getOperand(i), i))
return false;
for (unsigned i = NumElems/2; i != NumElems; ++i)
if (!isUndefOrEqual(Mask->getOperand(i), i+NumElems))
return false;
return true;
}
/// isLowerFromV2UpperFromV1 - Returns true if the shuffle mask is except
@ -2806,29 +2809,16 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
return PromoteSplat(Op, DAG);
}
// Normalize the node to match x86 shuffle ops if needed
if (V2.getOpcode() != ISD::UNDEF) {
bool DoSwap = false;
if (ShouldXformedToMOVLP(V1, V2, PermMask))
DoSwap = true;
else if (isLowerFromV2UpperFromV1(PermMask))
DoSwap = true;
if (DoSwap) {
Op = CommuteVectorShuffle(Op, DAG);
V1 = Op.getOperand(0);
V2 = Op.getOperand(1);
PermMask = Op.getOperand(2);
}
}
if (NumElems == 2)
return Op;
if (ShouldXformToMOVHLPS(PermMask.Val) ||
ShouldXformToMOVLP(V1.Val, PermMask.Val))
return CommuteVectorShuffle(Op, DAG);
if (X86::isMOVSMask(PermMask.Val) ||
X86::isMOVSHDUPMask(PermMask.Val) ||
X86::isMOVSLDUPMask(PermMask.Val))
X86::isMOVSLDUPMask(PermMask.Val) ||
X86::isMOVHLPSMask(PermMask.Val) ||
X86::isMOVHPMask(PermMask.Val) ||
X86::isMOVLPMask(PermMask.Val))
return Op;
if (X86::isUNPCKLMask(PermMask.Val) ||
@ -2837,6 +2827,15 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
// Leave the VECTOR_SHUFFLE alone. It matches {P}UNPCKL*.
return Op;
// Normalize the node to match x86 shuffle ops if needed
if (V2.getOpcode() != ISD::UNDEF)
if (isLowerFromV2UpperFromV1(PermMask)) {
Op = CommuteVectorShuffle(Op, DAG);
V1 = Op.getOperand(0);
V2 = Op.getOperand(1);
PermMask = Op.getOperand(2);
}
// If VT is integer, try PSHUF* first, then SHUFP*.
if (MVT::isInteger(VT)) {
if (X86::isPSHUFDMask(PermMask.Val) ||

View File

@ -204,10 +204,6 @@ namespace llvm {
/// specifies a shuffle of elements that is suitable for input to SHUFP*.
bool isSHUFPMask(SDNode *N);
/// isMOVLHPSMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVHLPS.
bool isMOVLHPSMask(SDNode *N);
/// isMOVHLPSMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVHLPS.
bool isMOVHLPSMask(SDNode *N);
@ -217,7 +213,8 @@ namespace llvm {
bool isMOVLPMask(SDNode *N);
/// isMOVHPMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a shuffle of elements that is suitable for input to MOVHP{S|D}.
/// specifies a shuffle of elements that is suitable for input to MOVHP{S|D}
/// as well as MOVLHPS.
bool isMOVHPMask(SDNode *N);
/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand