mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-03 17:31:50 +00:00
Support pattern matching vsldoi(x,y) and vsldoi(x,x), which allows the f.e. to
lower it and LLVM to have one fewer intrinsic. This implements CodeGen/PowerPC/vec_shuffle.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27450 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eb2285b7ff
commit
d0608e191f
@ -277,46 +277,73 @@ static bool isConstantOrUndef(SDOperand Op, unsigned Val) {
|
|||||||
/// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a
|
/// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a
|
||||||
/// VPKUHUM instruction.
|
/// VPKUHUM instruction.
|
||||||
bool PPC::isVPKUHUMShuffleMask(SDNode *N) {
|
bool PPC::isVPKUHUMShuffleMask(SDNode *N) {
|
||||||
return isConstantOrUndef(N->getOperand( 0), 1) &&
|
for (unsigned i = 0; i != 16; ++i)
|
||||||
isConstantOrUndef(N->getOperand( 1), 3) &&
|
if (!isConstantOrUndef(N->getOperand(i), i*2+1))
|
||||||
isConstantOrUndef(N->getOperand( 2), 5) &&
|
return false;
|
||||||
isConstantOrUndef(N->getOperand( 3), 7) &&
|
return true;
|
||||||
isConstantOrUndef(N->getOperand( 4), 9) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 5), 11) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 6), 13) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 7), 15) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 8), 17) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 9), 19) &&
|
|
||||||
isConstantOrUndef(N->getOperand(10), 21) &&
|
|
||||||
isConstantOrUndef(N->getOperand(11), 23) &&
|
|
||||||
isConstantOrUndef(N->getOperand(12), 25) &&
|
|
||||||
isConstantOrUndef(N->getOperand(13), 27) &&
|
|
||||||
isConstantOrUndef(N->getOperand(14), 29) &&
|
|
||||||
isConstantOrUndef(N->getOperand(15), 31);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a
|
/// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a
|
||||||
/// VPKUWUM instruction.
|
/// VPKUWUM instruction.
|
||||||
bool PPC::isVPKUWUMShuffleMask(SDNode *N) {
|
bool PPC::isVPKUWUMShuffleMask(SDNode *N) {
|
||||||
return isConstantOrUndef(N->getOperand( 0), 2) &&
|
for (unsigned i = 0; i != 16; i += 2)
|
||||||
isConstantOrUndef(N->getOperand( 1), 3) &&
|
if (!isConstantOrUndef(N->getOperand(i ), i*2+2) ||
|
||||||
isConstantOrUndef(N->getOperand( 2), 6) &&
|
!isConstantOrUndef(N->getOperand(i+1), i*2+3))
|
||||||
isConstantOrUndef(N->getOperand( 3), 7) &&
|
return false;
|
||||||
isConstantOrUndef(N->getOperand( 4), 10) &&
|
return true;
|
||||||
isConstantOrUndef(N->getOperand( 5), 11) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 6), 14) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 7), 15) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 8), 18) &&
|
|
||||||
isConstantOrUndef(N->getOperand( 9), 19) &&
|
|
||||||
isConstantOrUndef(N->getOperand(10), 22) &&
|
|
||||||
isConstantOrUndef(N->getOperand(11), 23) &&
|
|
||||||
isConstantOrUndef(N->getOperand(12), 26) &&
|
|
||||||
isConstantOrUndef(N->getOperand(13), 27) &&
|
|
||||||
isConstantOrUndef(N->getOperand(14), 30) &&
|
|
||||||
isConstantOrUndef(N->getOperand(15), 31);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift
|
||||||
|
/// amount, otherwise return -1.
|
||||||
|
int PPC::isVSLDOIShuffleMask(SDNode *N) {
|
||||||
|
assert(N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!");
|
||||||
|
// Find the first non-undef value in the shuffle mask.
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i != 16 && N->getOperand(i).getOpcode() == ISD::UNDEF; ++i)
|
||||||
|
/*search*/;
|
||||||
|
|
||||||
|
if (i == 16) return -1; // all undef.
|
||||||
|
|
||||||
|
// Otherwise, check to see if the rest of the elements are consequtively
|
||||||
|
// numbered from this value.
|
||||||
|
unsigned ShiftAmt = cast<ConstantSDNode>(N->getOperand(i))->getValue();
|
||||||
|
if (ShiftAmt < i) return -1;
|
||||||
|
ShiftAmt -= i;
|
||||||
|
|
||||||
|
// Check the rest of the elements to see if they are consequtive.
|
||||||
|
for (++i; i != 16; ++i)
|
||||||
|
if (!isConstantOrUndef(N->getOperand(i), ShiftAmt+i))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ShiftAmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isVSLDOIRotateShuffleMask - If this is a vsldoi rotate shuffle mask,
|
||||||
|
/// return the shift amount, otherwise return -1. Note that vlsdoi(x,x) will
|
||||||
|
/// result in the shuffle being changed to shuffle(x,undef, ...) with
|
||||||
|
/// transformed byte numbers.
|
||||||
|
int PPC::isVSLDOIRotateShuffleMask(SDNode *N) {
|
||||||
|
assert(N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!");
|
||||||
|
// Find the first non-undef value in the shuffle mask.
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i != 16 && N->getOperand(i).getOpcode() == ISD::UNDEF; ++i)
|
||||||
|
/*search*/;
|
||||||
|
|
||||||
|
if (i == 16) return -1; // all undef.
|
||||||
|
|
||||||
|
// Otherwise, check to see if the rest of the elements are consequtively
|
||||||
|
// numbered from this value.
|
||||||
|
unsigned ShiftAmt = cast<ConstantSDNode>(N->getOperand(i))->getValue();
|
||||||
|
if (ShiftAmt < i) return -1;
|
||||||
|
ShiftAmt -= i;
|
||||||
|
|
||||||
|
// Check the rest of the elements to see if they are consequtive.
|
||||||
|
for (++i; i != 16; ++i)
|
||||||
|
if (!isConstantOrUndef(N->getOperand(i), (ShiftAmt+i) & 15))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ShiftAmt;
|
||||||
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
@ -810,7 +837,9 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
return Op;
|
return Op;
|
||||||
|
|
||||||
if (PPC::isVPKUWUMShuffleMask(PermMask.Val) ||
|
if (PPC::isVPKUWUMShuffleMask(PermMask.Val) ||
|
||||||
PPC::isVPKUHUMShuffleMask(PermMask.Val))
|
PPC::isVPKUHUMShuffleMask(PermMask.Val) ||
|
||||||
|
PPC::isVSLDOIShuffleMask(PermMask.Val) != -1 ||
|
||||||
|
PPC::isVSLDOIRotateShuffleMask(PermMask.Val) != -1)
|
||||||
return Op;
|
return Op;
|
||||||
|
|
||||||
// TODO: Handle more cases, and also handle cases that are cheaper to do as
|
// TODO: Handle more cases, and also handle cases that are cheaper to do as
|
||||||
|
@ -110,6 +110,14 @@ namespace llvm {
|
|||||||
/// VPKUWUM instruction.
|
/// VPKUWUM instruction.
|
||||||
bool isVPKUWUMShuffleMask(SDNode *N);
|
bool isVPKUWUMShuffleMask(SDNode *N);
|
||||||
|
|
||||||
|
/// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift
|
||||||
|
/// amount, otherwise return -1.
|
||||||
|
int isVSLDOIShuffleMask(SDNode *N);
|
||||||
|
|
||||||
|
/// isVSLDOIRotateShuffleMask - If this is a vsldoi rotate shuffle mask,
|
||||||
|
/// return the shift amount, otherwise return -1. This matches vsldoi(x,x).
|
||||||
|
int isVSLDOIRotateShuffleMask(SDNode *N);
|
||||||
|
|
||||||
/// 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
|
||||||
/// VSPLTB/VSPLTH/VSPLTW.
|
/// VSPLTB/VSPLTH/VSPLTW.
|
||||||
|
@ -24,6 +24,23 @@ def VPKUWUM_shuffle_mask : PatLeaf<(build_vector), [{
|
|||||||
return PPC::isVPKUWUMShuffleMask(N);
|
return PPC::isVPKUWUMShuffleMask(N);
|
||||||
}]>;
|
}]>;
|
||||||
|
|
||||||
|
def VSLDOI_get_imm : SDNodeXForm<build_vector, [{
|
||||||
|
return getI32Imm(PPC::isVSLDOIShuffleMask(N));
|
||||||
|
}]>;
|
||||||
|
def VSLDOI_shuffle_mask : PatLeaf<(build_vector), [{
|
||||||
|
return PPC::isVSLDOIShuffleMask(N) != -1;
|
||||||
|
}], VSLDOI_get_imm>;
|
||||||
|
|
||||||
|
/// VSLDOI_rotate* - These are used to match vsldoi(X,X), which is turned into
|
||||||
|
/// vector_shuffle(X,undef,mask) by the dag combiner.
|
||||||
|
def VSLDOI_rotate_get_imm : SDNodeXForm<build_vector, [{
|
||||||
|
return getI32Imm(PPC::isVSLDOIRotateShuffleMask(N));
|
||||||
|
}]>;
|
||||||
|
def VSLDOI_rotate_shuffle_mask : PatLeaf<(build_vector), [{
|
||||||
|
return PPC::isVSLDOIRotateShuffleMask(N) != -1;
|
||||||
|
}], VSLDOI_rotate_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<build_vector, [{
|
def VSPLTB_get_imm : SDNodeXForm<build_vector, [{
|
||||||
return getI32Imm(PPC::getVSPLTImmediate(N, 1));
|
return getI32Imm(PPC::getVSPLTImmediate(N, 1));
|
||||||
@ -182,11 +199,12 @@ def VMLADDUHM : VA1a_Int<34, "vmladduhm", int_ppc_altivec_vmladduhm>;
|
|||||||
def VPERM : VA1a_Int<43, "vperm", int_ppc_altivec_vperm>;
|
def VPERM : VA1a_Int<43, "vperm", int_ppc_altivec_vperm>;
|
||||||
def VSEL : VA1a_Int<42, "vsel", int_ppc_altivec_vsel>;
|
def VSEL : VA1a_Int<42, "vsel", int_ppc_altivec_vsel>;
|
||||||
|
|
||||||
|
// Shuffles.
|
||||||
def VSLDOI : VAForm_2<44, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB, u5imm:$SH),
|
def VSLDOI : VAForm_2<44, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB, u5imm:$SH),
|
||||||
"vsldoi $vD, $vA, $vB, $SH", VecFP,
|
"vsldoi $vD, $vA, $vB, $SH", VecFP,
|
||||||
[(set VRRC:$vD,
|
[(set VRRC:$vD,
|
||||||
(int_ppc_altivec_vsldoi VRRC:$vA, VRRC:$vB,
|
(vector_shuffle (v16i8 VRRC:$vA), VRRC:$vB,
|
||||||
imm:$SH))]>;
|
VSLDOI_shuffle_mask:$SH))]>;
|
||||||
|
|
||||||
// VX-Form instructions. AltiVec arithmetic ops.
|
// VX-Form instructions. AltiVec arithmetic ops.
|
||||||
def VADDFP : VXForm_1<10, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
def VADDFP : VXForm_1<10, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||||
@ -504,6 +522,12 @@ def : Pat<(v4f32 (bitconvert (v16i8 VRRC:$src))), (v4f32 VRRC:$src)>;
|
|||||||
def : Pat<(v4f32 (bitconvert (v8i16 VRRC:$src))), (v4f32 VRRC:$src)>;
|
def : Pat<(v4f32 (bitconvert (v8i16 VRRC:$src))), (v4f32 VRRC:$src)>;
|
||||||
def : Pat<(v4f32 (bitconvert (v4i32 VRRC:$src))), (v4f32 VRRC:$src)>;
|
def : Pat<(v4f32 (bitconvert (v4i32 VRRC:$src))), (v4f32 VRRC:$src)>;
|
||||||
|
|
||||||
|
// Shuffles.
|
||||||
|
|
||||||
|
// Match vsldoi(x,x)
|
||||||
|
def:Pat<(vector_shuffle (v16i8 VRRC:$vA),undef, VSLDOI_rotate_shuffle_mask:$in),
|
||||||
|
(VSLDOI VRRC:$vA, VRRC:$vA, VSLDOI_rotate_shuffle_mask:$in)>;
|
||||||
|
|
||||||
// Immediate vector formation with vsplti*.
|
// Immediate vector formation with vsplti*.
|
||||||
def : Pat<(v16i8 vecspltisb:$invec), (v16i8 (VSPLTISB vecspltisb:$invec))>;
|
def : Pat<(v16i8 vecspltisb:$invec), (v16i8 (VSPLTISB vecspltisb:$invec))>;
|
||||||
def : Pat<(v16i8 vecspltish:$invec), (v16i8 (VSPLTISH vecspltish:$invec))>;
|
def : Pat<(v16i8 vecspltish:$invec), (v16i8 (VSPLTISH vecspltish:$invec))>;
|
||||||
|
@ -130,11 +130,6 @@ Instcombine llvm.ppc.altivec.vperm with an immediate into a shuffle operation.
|
|||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
Handle VECTOR_SHUFFLE nodes with the appropriate shuffle mask with vsldoi,
|
|
||||||
vpkuhum and vpkuwum.
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
Implement multiply for vector integer types, to avoid the horrible scalarized
|
Implement multiply for vector integer types, to avoid the horrible scalarized
|
||||||
code produced by legalize.
|
code produced by legalize.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user