[PowerPC] Swap arguments and adjust shift count for vsldoi on little endian

Commits r213915 and r214718 fix recognition of shuffle masks for vmrg*
and vpku*um instructions for a little-endian target, by swapping the
input arguments.  The vsldoi instruction requires similar treatment,
and also needs its shift count adjusted for little endian.

Reviewed by Ulrich Weigand.

This is a bug fix candidate for release 3.5 (and hopefully the last of
those for PowerPC).

llvm-svn: 214923
This commit is contained in:
Bill Schmidt 2014-08-05 20:47:25 +00:00
parent 6e496338e6
commit 42a6936c78
4 changed files with 44 additions and 17 deletions

View File

@ -989,7 +989,12 @@ bool PPC::isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize,
/// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift
/// amount, otherwise return -1. /// amount, otherwise return -1.
int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary, SelectionDAG &DAG) { /// The ShuffleKind distinguishes between big-endian operations with two
/// different inputs (0), either-endian operations with two identical inputs
/// (1), and little-endian operations with two different inputs (2). For the
/// latter, the input operands are swapped (see PPCInstrAltivec.td).
int PPC::isVSLDOIShuffleMask(SDNode *N, unsigned ShuffleKind,
SelectionDAG &DAG) {
if (N->getValueType(0) != MVT::v16i8) if (N->getValueType(0) != MVT::v16i8)
return -1; return -1;
@ -1008,18 +1013,24 @@ int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary, SelectionDAG &DAG) {
if (ShiftAmt < i) return -1; if (ShiftAmt < i) return -1;
ShiftAmt -= i; ShiftAmt -= i;
bool isLE = DAG.getTarget().getSubtargetImpl()->getDataLayout()->
isLittleEndian();
if (!isUnary) { if ((ShuffleKind == 0 && !isLE) || (ShuffleKind == 2 && isLE)) {
// Check the rest of the elements to see if they are consecutive. // Check the rest of the elements to see if they are consecutive.
for (++i; i != 16; ++i) for (++i; i != 16; ++i)
if (!isConstantOrUndef(SVOp->getMaskElt(i), ShiftAmt+i)) if (!isConstantOrUndef(SVOp->getMaskElt(i), ShiftAmt+i))
return -1; return -1;
} else { } else if (ShuffleKind == 1) {
// Check the rest of the elements to see if they are consecutive. // Check the rest of the elements to see if they are consecutive.
for (++i; i != 16; ++i) for (++i; i != 16; ++i)
if (!isConstantOrUndef(SVOp->getMaskElt(i), (ShiftAmt+i) & 15)) if (!isConstantOrUndef(SVOp->getMaskElt(i), (ShiftAmt+i) & 15))
return -1; return -1;
} } else
return -1;
if (ShuffleKind == 2 && isLE)
ShiftAmt = 16 - ShiftAmt;
return ShiftAmt; return ShiftAmt;
} }
@ -6050,7 +6061,7 @@ SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
PPC::isSplatShuffleMask(SVOp, 4) || PPC::isSplatShuffleMask(SVOp, 4) ||
PPC::isVPKUWUMShuffleMask(SVOp, 1, DAG) || PPC::isVPKUWUMShuffleMask(SVOp, 1, DAG) ||
PPC::isVPKUHUMShuffleMask(SVOp, 1, DAG) || PPC::isVPKUHUMShuffleMask(SVOp, 1, DAG) ||
PPC::isVSLDOIShuffleMask(SVOp, true, DAG) != -1 || PPC::isVSLDOIShuffleMask(SVOp, 1, DAG) != -1 ||
PPC::isVMRGLShuffleMask(SVOp, 1, 1, DAG) || PPC::isVMRGLShuffleMask(SVOp, 1, 1, DAG) ||
PPC::isVMRGLShuffleMask(SVOp, 2, 1, DAG) || PPC::isVMRGLShuffleMask(SVOp, 2, 1, DAG) ||
PPC::isVMRGLShuffleMask(SVOp, 4, 1, DAG) || PPC::isVMRGLShuffleMask(SVOp, 4, 1, DAG) ||
@ -6067,7 +6078,7 @@ SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
unsigned int ShuffleKind = isLittleEndian ? 2 : 0; unsigned int ShuffleKind = isLittleEndian ? 2 : 0;
if (PPC::isVPKUWUMShuffleMask(SVOp, ShuffleKind, DAG) || if (PPC::isVPKUWUMShuffleMask(SVOp, ShuffleKind, DAG) ||
PPC::isVPKUHUMShuffleMask(SVOp, ShuffleKind, DAG) || PPC::isVPKUHUMShuffleMask(SVOp, ShuffleKind, DAG) ||
PPC::isVSLDOIShuffleMask(SVOp, false, DAG) != -1 || PPC::isVSLDOIShuffleMask(SVOp, ShuffleKind, DAG) != -1 ||
PPC::isVMRGLShuffleMask(SVOp, 1, ShuffleKind, DAG) || PPC::isVMRGLShuffleMask(SVOp, 1, ShuffleKind, DAG) ||
PPC::isVMRGLShuffleMask(SVOp, 2, ShuffleKind, DAG) || PPC::isVMRGLShuffleMask(SVOp, 2, ShuffleKind, DAG) ||
PPC::isVMRGLShuffleMask(SVOp, 4, ShuffleKind, DAG) || PPC::isVMRGLShuffleMask(SVOp, 4, ShuffleKind, DAG) ||

View File

@ -319,9 +319,10 @@ namespace llvm {
bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize,
unsigned ShuffleKind, SelectionDAG &DAG); unsigned ShuffleKind, SelectionDAG &DAG);
/// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the
/// amount, otherwise return -1. /// shift amount, otherwise return -1.
int isVSLDOIShuffleMask(SDNode *N, bool isUnary, SelectionDAG &DAG); int isVSLDOIShuffleMask(SDNode *N, unsigned ShuffleKind,
SelectionDAG &DAG);
/// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand
/// specifies a splat of a single element that is suitable for input to /// specifies a splat of a single element that is suitable for input to

View File

@ -129,25 +129,36 @@ def vmrghw_swapped_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
def VSLDOI_get_imm : SDNodeXForm<vector_shuffle, [{ def VSLDOI_get_imm : SDNodeXForm<vector_shuffle, [{
return getI32Imm(PPC::isVSLDOIShuffleMask(N, false, *CurDAG)); return getI32Imm(PPC::isVSLDOIShuffleMask(N, 0, *CurDAG));
}]>; }]>;
def vsldoi_shuffle : PatFrag<(ops node:$lhs, node:$rhs), def vsldoi_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
(vector_shuffle node:$lhs, node:$rhs), [{ (vector_shuffle node:$lhs, node:$rhs), [{
return PPC::isVSLDOIShuffleMask(N, false, *CurDAG) != -1; return PPC::isVSLDOIShuffleMask(N, 0, *CurDAG) != -1;
}], VSLDOI_get_imm>; }], VSLDOI_get_imm>;
/// VSLDOI_unary* - These are used to match vsldoi(X,X), which is turned into /// VSLDOI_unary* - These are used to match vsldoi(X,X), which is turned into
/// vector_shuffle(X,undef,mask) by the dag combiner. /// vector_shuffle(X,undef,mask) by the dag combiner.
def VSLDOI_unary_get_imm : SDNodeXForm<vector_shuffle, [{ def VSLDOI_unary_get_imm : SDNodeXForm<vector_shuffle, [{
return getI32Imm(PPC::isVSLDOIShuffleMask(N, true, *CurDAG)); return getI32Imm(PPC::isVSLDOIShuffleMask(N, 1, *CurDAG));
}]>; }]>;
def vsldoi_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs), def vsldoi_unary_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
(vector_shuffle node:$lhs, node:$rhs), [{ (vector_shuffle node:$lhs, node:$rhs), [{
return PPC::isVSLDOIShuffleMask(N, true, *CurDAG) != -1; return PPC::isVSLDOIShuffleMask(N, 1, *CurDAG) != -1;
}], VSLDOI_unary_get_imm>; }], VSLDOI_unary_get_imm>;
/// VSLDOI_swapped* - These fragments are provided for little-endian, where
/// the inputs must be swapped for correct semantics.
def VSLDOI_swapped_get_imm : SDNodeXForm<vector_shuffle, [{
return getI32Imm(PPC::isVSLDOIShuffleMask(N, 2, *CurDAG));
}]>;
def vsldoi_swapped_shuffle : PatFrag<(ops node:$lhs, node:$rhs),
(vector_shuffle node:$lhs, node:$rhs), [{
return PPC::isVSLDOIShuffleMask(N, 2, *CurDAG) != -1;
}], VSLDOI_get_imm>;
// VSPLT*_get_imm xform function: convert vector_shuffle mask to VSPLT* imm. // VSPLT*_get_imm xform function: convert vector_shuffle mask to VSPLT* imm.
def VSPLTB_get_imm : SDNodeXForm<vector_shuffle, [{ def VSPLTB_get_imm : SDNodeXForm<vector_shuffle, [{
return getI32Imm(PPC::getVSPLTImmediate(N, 1, *CurDAG)); return getI32Imm(PPC::getVSPLTImmediate(N, 1, *CurDAG));
@ -803,9 +814,11 @@ def:Pat<(vpkuwum_unary_shuffle v16i8:$vA, undef),
def:Pat<(vpkuhum_unary_shuffle v16i8:$vA, undef), def:Pat<(vpkuhum_unary_shuffle v16i8:$vA, undef),
(VPKUHUM $vA, $vA)>; (VPKUHUM $vA, $vA)>;
// Match vpkuwum(y,x), vpkuhum(y,x), i.e., swapped operands. // Match vsldoi(y,x), vpkuwum(y,x), vpkuhum(y,x), i.e., swapped operands.
// These fragments are matched for little-endian, where the // These fragments are matched for little-endian, where the inputs must
// inputs must be swapped for correct semantics. // be swapped for correct semantics.
def:Pat<(vsldoi_swapped_shuffle:$in v16i8:$vA, v16i8:$vB),
(VSLDOI $vB, $vA, (VSLDOI_swapped_get_imm $in))>;
def:Pat<(vpkuwum_swapped_shuffle v16i8:$vA, v16i8:$vB), def:Pat<(vpkuwum_swapped_shuffle v16i8:$vA, v16i8:$vB),
(VPKUWUM $vB, $vA)>; (VPKUWUM $vB, $vA)>;
def:Pat<(vpkuhum_swapped_shuffle v16i8:$vA, v16i8:$vB), def:Pat<(vpkuhum_swapped_shuffle v16i8:$vA, v16i8:$vB),

View File

@ -190,7 +190,9 @@ entry:
%tmp = load <16 x i8>* %A %tmp = load <16 x i8>* %A
%tmp2 = load <16 x i8>* %B %tmp2 = load <16 x i8>* %B
%tmp3 = shufflevector <16 x i8> %tmp, <16 x i8> %tmp2, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27> %tmp3 = shufflevector <16 x i8> %tmp, <16 x i8> %tmp2, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27>
; CHECK: vsldoi ; CHECK: lvx [[REG1:[0-9]+]]
; CHECK: lvx [[REG2:[0-9]+]]
; CHECK: vsldoi [[REG3:[0-9]+]], [[REG2]], [[REG1]], 4
store <16 x i8> %tmp3, <16 x i8>* %A store <16 x i8> %tmp3, <16 x i8>* %A
ret void ret void
} }