mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
Ask legalize to promote all vector shuffles to be v16i8 instead of having to
handle all 4 PPC vector types. This simplifies the matching code and allows us to eliminate a bunch of patterns. This also adds cases we were missing, such as CodeGen/PowerPC/vec_splat.ll:splat_h. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27400 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4352cc9e21
commit
7ff7e67458
@ -181,8 +181,9 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
|
|||||||
setOperationAction(ISD::OR , (MVT::ValueType)VT, Legal);
|
setOperationAction(ISD::OR , (MVT::ValueType)VT, Legal);
|
||||||
setOperationAction(ISD::XOR , (MVT::ValueType)VT, Legal);
|
setOperationAction(ISD::XOR , (MVT::ValueType)VT, Legal);
|
||||||
|
|
||||||
// We can custom expand all VECTOR_SHUFFLEs to VPERM.
|
// We promote all shuffles to v16i8.
|
||||||
setOperationAction(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, Custom);
|
setOperationAction(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, Promote);
|
||||||
|
AddPromotedToType(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, MVT::v16i8);
|
||||||
|
|
||||||
setOperationAction(ISD::MUL , (MVT::ValueType)VT, Expand);
|
setOperationAction(ISD::MUL , (MVT::ValueType)VT, Expand);
|
||||||
setOperationAction(ISD::SDIV, (MVT::ValueType)VT, Expand);
|
setOperationAction(ISD::SDIV, (MVT::ValueType)VT, Expand);
|
||||||
@ -196,6 +197,10 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
|
|||||||
setOperationAction(ISD::SCALAR_TO_VECTOR, (MVT::ValueType)VT, Expand);
|
setOperationAction(ISD::SCALAR_TO_VECTOR, (MVT::ValueType)VT, Expand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We can custom expand all VECTOR_SHUFFLEs to VPERM, others we can handle
|
||||||
|
// with merges, splats, etc.
|
||||||
|
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v16i8, Custom);
|
||||||
|
|
||||||
addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass);
|
addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass);
|
||||||
addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass);
|
addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass);
|
||||||
addRegisterClass(MVT::v8i16, PPC::VRRCRegisterClass);
|
addRegisterClass(MVT::v8i16, PPC::VRRCRegisterClass);
|
||||||
@ -266,33 +271,47 @@ static bool isFloatingPointZero(SDOperand Op) {
|
|||||||
/// 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.
|
||||||
bool PPC::isSplatShuffleMask(SDNode *N) {
|
bool PPC::isSplatShuffleMask(SDNode *N, unsigned EltSize) {
|
||||||
assert(N->getOpcode() == ISD::BUILD_VECTOR);
|
assert(N->getOpcode() == ISD::BUILD_VECTOR &&
|
||||||
|
N->getNumOperands() == 16 &&
|
||||||
// We can only splat 8-bit, 16-bit, and 32-bit quantities.
|
(EltSize == 1 || EltSize == 2 || EltSize == 4));
|
||||||
if (N->getNumOperands() != 4 && N->getNumOperands() != 8 &&
|
|
||||||
N->getNumOperands() != 16)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// This is a splat operation if each element of the permute is the same, and
|
// This is a splat operation if each element of the permute is the same, and
|
||||||
// if the value doesn't reference the second vector.
|
// if the value doesn't reference the second vector.
|
||||||
|
unsigned ElementBase = 0;
|
||||||
SDOperand Elt = N->getOperand(0);
|
SDOperand Elt = N->getOperand(0);
|
||||||
assert(isa<ConstantSDNode>(Elt) && "Invalid VECTOR_SHUFFLE mask!");
|
if (ConstantSDNode *EltV = dyn_cast<ConstantSDNode>(Elt))
|
||||||
for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i) {
|
ElementBase = EltV->getValue();
|
||||||
assert(isa<ConstantSDNode>(N->getOperand(i)) &&
|
else
|
||||||
"Invalid VECTOR_SHUFFLE mask!");
|
return false; // FIXME: Handle UNDEF elements too!
|
||||||
if (N->getOperand(i) != Elt) return false;
|
|
||||||
|
if (cast<ConstantSDNode>(Elt)->getValue() >= 16)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check that they are consequtive.
|
||||||
|
for (unsigned i = 1; i != EltSize; ++i) {
|
||||||
|
if (!isa<ConstantSDNode>(N->getOperand(i)) ||
|
||||||
|
cast<ConstantSDNode>(N->getOperand(i))->getValue() != i+ElementBase)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure it is a splat of the first vector operand.
|
assert(isa<ConstantSDNode>(Elt) && "Invalid VECTOR_SHUFFLE mask!");
|
||||||
return cast<ConstantSDNode>(Elt)->getValue() < N->getNumOperands();
|
for (unsigned i = EltSize, e = 16; i != e; i += EltSize) {
|
||||||
|
assert(isa<ConstantSDNode>(N->getOperand(i)) &&
|
||||||
|
"Invalid VECTOR_SHUFFLE mask!");
|
||||||
|
for (unsigned j = 0; j != EltSize; ++j)
|
||||||
|
if (N->getOperand(i+j) != N->getOperand(j))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the
|
/// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the
|
||||||
/// specified isSplatShuffleMask VECTOR_SHUFFLE mask.
|
/// specified isSplatShuffleMask VECTOR_SHUFFLE mask.
|
||||||
unsigned PPC::getVSPLTImmediate(SDNode *N) {
|
unsigned PPC::getVSPLTImmediate(SDNode *N, unsigned EltSize) {
|
||||||
assert(isSplatShuffleMask(N));
|
assert(isSplatShuffleMask(N, EltSize));
|
||||||
return cast<ConstantSDNode>(N->getOperand(0))->getValue();
|
return cast<ConstantSDNode>(N->getOperand(0))->getValue() / EltSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isVecSplatImm - Return true if this is a build_vector of constants which
|
/// isVecSplatImm - Return true if this is a build_vector of constants which
|
||||||
@ -734,7 +753,10 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
// Cases that are handled by instructions that take permute immediates
|
// Cases that are handled by instructions that take permute immediates
|
||||||
// (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be
|
// (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be
|
||||||
// selected by the instruction selector.
|
// selected by the instruction selector.
|
||||||
if (PPC::isSplatShuffleMask(PermMask.Val) && V2.getOpcode() == ISD::UNDEF)
|
if (V2.getOpcode() == ISD::UNDEF &&
|
||||||
|
(PPC::isSplatShuffleMask(PermMask.Val, 1) ||
|
||||||
|
PPC::isSplatShuffleMask(PermMask.Val, 2) ||
|
||||||
|
PPC::isSplatShuffleMask(PermMask.Val, 4)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -105,11 +105,11 @@ namespace llvm {
|
|||||||
/// 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.
|
||||||
bool isSplatShuffleMask(SDNode *N);
|
bool isSplatShuffleMask(SDNode *N, unsigned EltSize);
|
||||||
|
|
||||||
/// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the
|
/// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the
|
||||||
/// specified isSplatShuffleMask VECTOR_SHUFFLE mask.
|
/// specified isSplatShuffleMask VECTOR_SHUFFLE mask.
|
||||||
unsigned getVSPLTImmediate(SDNode *N);
|
unsigned getVSPLTImmediate(SDNode *N, unsigned EltSize);
|
||||||
|
|
||||||
/// isVecSplatImm - Return true if this is a build_vector of constants which
|
/// isVecSplatImm - Return true if this is a build_vector of constants which
|
||||||
/// can be formed by using a vspltis[bhw] instruction. The ByteSize field
|
/// can be formed by using a vspltis[bhw] instruction. The ByteSize field
|
||||||
|
@ -15,14 +15,25 @@
|
|||||||
// Altivec transformation functions and pattern fragments.
|
// Altivec transformation functions and pattern fragments.
|
||||||
//
|
//
|
||||||
|
|
||||||
// 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 VSPLT_get_imm : SDNodeXForm<build_vector, [{
|
def VSPLTB_get_imm : SDNodeXForm<build_vector, [{
|
||||||
return getI32Imm(PPC::getVSPLTImmediate(N));
|
return getI32Imm(PPC::getVSPLTImmediate(N, 1));
|
||||||
}]>;
|
}]>;
|
||||||
|
def VSPLTB_shuffle_mask : PatLeaf<(build_vector), [{
|
||||||
def VSPLT_shuffle_mask : PatLeaf<(build_vector), [{
|
return PPC::isSplatShuffleMask(N, 1);
|
||||||
return PPC::isSplatShuffleMask(N);
|
}], VSPLTB_get_imm>;
|
||||||
}], VSPLT_get_imm>;
|
def VSPLTH_get_imm : SDNodeXForm<build_vector, [{
|
||||||
|
return getI32Imm(PPC::getVSPLTImmediate(N, 2));
|
||||||
|
}]>;
|
||||||
|
def VSPLTH_shuffle_mask : PatLeaf<(build_vector), [{
|
||||||
|
return PPC::isSplatShuffleMask(N, 2);
|
||||||
|
}], VSPLTH_get_imm>;
|
||||||
|
def VSPLTW_get_imm : SDNodeXForm<build_vector, [{
|
||||||
|
return getI32Imm(PPC::getVSPLTImmediate(N, 4));
|
||||||
|
}]>;
|
||||||
|
def VSPLTW_shuffle_mask : PatLeaf<(build_vector), [{
|
||||||
|
return PPC::isSplatShuffleMask(N, 4);
|
||||||
|
}], VSPLTW_get_imm>;
|
||||||
|
|
||||||
|
|
||||||
// VSPLTISB_get_imm xform function: convert build_vector to VSPLTISB imm.
|
// VSPLTISB_get_imm xform function: convert build_vector to VSPLTISB imm.
|
||||||
@ -55,11 +66,6 @@ def vecspltisw : PatLeaf<(build_vector), [{
|
|||||||
return PPC::isVecSplatImm(N, 4);
|
return PPC::isVecSplatImm(N, 4);
|
||||||
}], VSPLTISW_get_imm>;
|
}], VSPLTISW_get_imm>;
|
||||||
|
|
||||||
class isVDOT { // vector dot instruction.
|
|
||||||
list<Register> Defs = [CR6];
|
|
||||||
bit RC = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Helpers for defining instructions that directly correspond to intrinsics.
|
// Helpers for defining instructions that directly correspond to intrinsics.
|
||||||
|
|
||||||
@ -294,15 +300,15 @@ def VSLW : VX1_Int< 388, "vslw", int_ppc_altivec_vslw>;
|
|||||||
def VSPLTB : VXForm_1<524, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
|
def VSPLTB : VXForm_1<524, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
|
||||||
"vspltb $vD, $vB, $UIMM", VecPerm,
|
"vspltb $vD, $vB, $UIMM", VecPerm,
|
||||||
[(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef),
|
[(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef),
|
||||||
VSPLT_shuffle_mask:$UIMM))]>;
|
VSPLTB_shuffle_mask:$UIMM))]>;
|
||||||
def VSPLTH : VXForm_1<588, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
|
def VSPLTH : VXForm_1<588, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
|
||||||
"vsplth $vD, $vB, $UIMM", VecPerm,
|
"vsplth $vD, $vB, $UIMM", VecPerm,
|
||||||
[(set VRRC:$vD, (vector_shuffle (v8i16 VRRC:$vB), (undef),
|
[(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef),
|
||||||
VSPLT_shuffle_mask:$UIMM))]>;
|
VSPLTH_shuffle_mask:$UIMM))]>;
|
||||||
def VSPLTW : VXForm_1<652, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
|
def VSPLTW : VXForm_1<652, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
|
||||||
"vspltw $vD, $vB, $UIMM", VecPerm,
|
"vspltw $vD, $vB, $UIMM", VecPerm,
|
||||||
[(set VRRC:$vD, (vector_shuffle (v4f32 VRRC:$vB), (undef),
|
[(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vB), (undef),
|
||||||
VSPLT_shuffle_mask:$UIMM))]>;
|
VSPLTW_shuffle_mask:$UIMM))]>;
|
||||||
|
|
||||||
def VSR : VX1_Int< 708, "vsr" , int_ppc_altivec_vsr>;
|
def VSR : VX1_Int< 708, "vsr" , int_ppc_altivec_vsr>;
|
||||||
def VSRO : VX1_Int<1100, "vsro" , int_ppc_altivec_vsro>;
|
def VSRO : VX1_Int<1100, "vsro" , int_ppc_altivec_vsro>;
|
||||||
@ -355,7 +361,10 @@ class VCMP<bits<10> xo, string asmstr, ValueType Ty>
|
|||||||
[(set VRRC:$vD, (Ty (PPCvcmp VRRC:$vA, VRRC:$vB, xo)))]>;
|
[(set VRRC:$vD, (Ty (PPCvcmp VRRC:$vA, VRRC:$vB, xo)))]>;
|
||||||
class VCMPo<bits<10> xo, string asmstr, ValueType Ty>
|
class VCMPo<bits<10> xo, string asmstr, ValueType Ty>
|
||||||
: VXRForm_1<xo, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), asmstr, VecFPCompare,
|
: VXRForm_1<xo, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), asmstr, VecFPCompare,
|
||||||
[(set VRRC:$vD, (Ty (PPCvcmp_o VRRC:$vA, VRRC:$vB, xo)))]>,isVDOT;
|
[(set VRRC:$vD, (Ty (PPCvcmp_o VRRC:$vA, VRRC:$vB, xo)))]> {
|
||||||
|
let Defs = [CR6];
|
||||||
|
let RC = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// f32 element comparisons.0
|
// f32 element comparisons.0
|
||||||
def VCMPBFP : VCMP <966, "vcmpbfp $vD, $vA, $vB" , v4f32>;
|
def VCMPBFP : VCMP <966, "vcmpbfp $vD, $vA, $vB" , v4f32>;
|
||||||
@ -487,14 +496,6 @@ def : Pat<(int_ppc_altivec_vmaddfp VRRC:$A, VRRC:$B, VRRC:$C),
|
|||||||
(VMADDFP VRRC:$A, VRRC:$B, VRRC:$C)>;
|
(VMADDFP VRRC:$A, VRRC:$B, VRRC:$C)>;
|
||||||
def : Pat<(int_ppc_altivec_vnmsubfp VRRC:$A, VRRC:$B, VRRC:$C),
|
def : Pat<(int_ppc_altivec_vnmsubfp VRRC:$A, VRRC:$B, VRRC:$C),
|
||||||
(VNMSUBFP VRRC:$A, VRRC:$B, VRRC:$C)>;
|
(VNMSUBFP VRRC:$A, VRRC:$B, VRRC:$C)>;
|
||||||
def : Pat<(vector_shuffle (v4i32 VRRC:$vB), (undef), VSPLT_shuffle_mask:$UIMM),
|
|
||||||
(v4i32 (VSPLTW VSPLT_shuffle_mask:$UIMM, VRRC:$vB))>;
|
|
||||||
|
|
||||||
def : Pat<(PPCvperm (v4i32 VRRC:$vA), VRRC:$vB, VRRC:$vC),
|
|
||||||
(v4i32 (VPERM VRRC:$vA, VRRC:$vB, VRRC:$vC))>;
|
|
||||||
def : Pat<(PPCvperm (v4f32 VRRC:$vA), VRRC:$vB, VRRC:$vC),
|
|
||||||
(v4f32 (VPERM VRRC:$vA, VRRC:$vB, VRRC:$vC))>;
|
|
||||||
def : Pat<(PPCvperm (v8i16 VRRC:$vA), VRRC:$vB, VRRC:$vC),
|
|
||||||
(v8i16 (VPERM VRRC:$vA, VRRC:$vB, VRRC:$vC))>;
|
|
||||||
def : Pat<(PPCvperm (v16i8 VRRC:$vA), VRRC:$vB, VRRC:$vC),
|
def : Pat<(PPCvperm (v16i8 VRRC:$vA), VRRC:$vB, VRRC:$vC),
|
||||||
(v16i8 (VPERM VRRC:$vA, VRRC:$vB, VRRC:$vC))>;
|
(v16i8 (VPERM VRRC:$vA, VRRC:$vB, VRRC:$vC))>;
|
||||||
|
Loading…
Reference in New Issue
Block a user