return cast<ConstantSDNode>(N->getOperand(0))->getValue() / EltSize;
}
-/// get_VSPLI_elt - If this is a build_vector of constants which can be formed
+/// get_VSPLTI_elt - If this is a build_vector of constants which can be formed
/// by using a vspltis[bhw] instruction of the specified element size, return
/// the constant being splatted. The ByteSize field indicates the number of
/// bytes of each element [124] -> [bhw].
-SDOperand PPC::get_VSPLI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) {
+SDOperand PPC::get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) {
SDOperand OpVal(0, 0);
// If ByteSize of the splat is bigger than the element size of the
// Load it out.
return DAG.getLoad(Op.getValueType(), Store, FIdx, DAG.getSrcValue(NULL));
}
- case ISD::BUILD_VECTOR:
+ case ISD::BUILD_VECTOR: {
// If this is a case we can't handle, return null and let the default
// expansion code take care of it. If we CAN select this case, return Op.
return Op;
}
- if (PPC::get_VSPLI_elt(Op.Val, 1, DAG).Val || // vspltisb
- PPC::get_VSPLI_elt(Op.Val, 2, DAG).Val || // vspltish
- PPC::get_VSPLI_elt(Op.Val, 4, DAG).Val) // vspltisw
+ // Check to see if this is something we can use VSPLTI* to form.
+ MVT::ValueType CanonicalVT = MVT::Other;
+ SDNode *CST = 0;
+
+ if ((CST = PPC::get_VSPLTI_elt(Op.Val, 4, DAG).Val)) // vspltisw
+ CanonicalVT = MVT::v4i32;
+ else if ((CST = PPC::get_VSPLTI_elt(Op.Val, 2, DAG).Val)) // vspltish
+ CanonicalVT = MVT::v8i16;
+ else if ((CST = PPC::get_VSPLTI_elt(Op.Val, 1, DAG).Val)) // vspltisb
+ CanonicalVT = MVT::v16i8;
+
+ // If this matches one of the vsplti* patterns, force it to the canonical
+ // type for the pattern.
+ if (CST) {
+ if (Op.getValueType() != CanonicalVT) {
+ // Convert the splatted element to the right element type.
+ SDOperand Elt = DAG.getNode(ISD::TRUNCATE,
+ MVT::getVectorBaseType(CanonicalVT),
+ SDOperand(CST, 0));
+ std::vector<SDOperand> Ops(MVT::getVectorNumElements(CanonicalVT), Elt);
+ SDOperand Res = DAG.getNode(ISD::BUILD_VECTOR, CanonicalVT, Ops);
+ Op = DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
+ }
return Op;
+ }
return SDOperand();
-
+ }
case ISD::VECTOR_SHUFFLE: {
SDOperand V1 = Op.getOperand(0);
SDOperand V2 = Op.getOperand(1);
// VSPLTISB_get_imm xform function: convert build_vector to VSPLTISB imm.
def VSPLTISB_get_imm : SDNodeXForm<build_vector, [{
- return PPC::get_VSPLI_elt(N, 1, *CurDAG);
+ return PPC::get_VSPLTI_elt(N, 1, *CurDAG);
}]>;
def vecspltisb : PatLeaf<(build_vector), [{
- return PPC::get_VSPLI_elt(N, 1, *CurDAG).Val != 0;
+ return PPC::get_VSPLTI_elt(N, 1, *CurDAG).Val != 0;
}], VSPLTISB_get_imm>;
// VSPLTISH_get_imm xform function: convert build_vector to VSPLTISH imm.
def VSPLTISH_get_imm : SDNodeXForm<build_vector, [{
- return PPC::get_VSPLI_elt(N, 2, *CurDAG);
+ return PPC::get_VSPLTI_elt(N, 2, *CurDAG);
}]>;
def vecspltish : PatLeaf<(build_vector), [{
- return PPC::get_VSPLI_elt(N, 2, *CurDAG).Val != 0;
+ return PPC::get_VSPLTI_elt(N, 2, *CurDAG).Val != 0;
}], VSPLTISH_get_imm>;
// VSPLTISW_get_imm xform function: convert build_vector to VSPLTISW imm.
def VSPLTISW_get_imm : SDNodeXForm<build_vector, [{
- return PPC::get_VSPLI_elt(N, 4, *CurDAG);
+ return PPC::get_VSPLTI_elt(N, 4, *CurDAG);
}]>;
def vecspltisw : PatLeaf<(build_vector), [{
- return PPC::get_VSPLI_elt(N, 4, *CurDAG).Val != 0;
+ return PPC::get_VSPLTI_elt(N, 4, *CurDAG).Val != 0;
}], VSPLTISW_get_imm>;
//===----------------------------------------------------------------------===//
def VSPLTISB : VXForm_3<780, (ops VRRC:$vD, s5imm:$SIMM),
"vspltisb $vD, $SIMM", VecPerm,
- [(set VRRC:$vD, (v4f32 vecspltisb:$SIMM))]>;
+ [(set VRRC:$vD, (v16i8 vecspltisb:$SIMM))]>;
def VSPLTISH : VXForm_3<844, (ops VRRC:$vD, s5imm:$SIMM),
"vspltish $vD, $SIMM", VecPerm,
- [(set VRRC:$vD, (v4f32 vecspltish:$SIMM))]>;
+ [(set VRRC:$vD, (v8i16 vecspltish:$SIMM))]>;
def VSPLTISW : VXForm_3<908, (ops VRRC:$vD, s5imm:$SIMM),
"vspltisw $vD, $SIMM", VecPerm,
- [(set VRRC:$vD, (v4f32 vecspltisw:$SIMM))]>;
+ [(set VRRC:$vD, (v4i32 vecspltisw:$SIMM))]>;
// Vector Pack.
def VPKPX : VX1_Int<782, "vpkpx", int_ppc_altivec_vpkpx>;
def : Pat<(int_ppc_altivec_dststt GPRC:$rA, GPRC:$rB, imm:$STRM),
(DSTST 1, imm:$STRM, GPRC:$rA, GPRC:$rB)>;
-// Undef/Zero.
+// Undef.
def : Pat<(v16i8 (undef)), (v16i8 (IMPLICIT_DEF_VRRC))>;
def : Pat<(v8i16 (undef)), (v8i16 (IMPLICIT_DEF_VRRC))>;
def : Pat<(v4i32 (undef)), (v4i32 (IMPLICIT_DEF_VRRC))>;
def:Pat<(vector_shuffle (v16i8 VRRC:$vA), undef, VMRGHW_unary_shuffle_mask:$in),
(VMRGHW VRRC:$vA, VRRC:$vA)>;
-// Immediate vector formation with vsplti*.
-def : Pat<(v16i8 vecspltisb:$invec), (v16i8 (VSPLTISB vecspltisb:$invec))>;
-def : Pat<(v16i8 vecspltish:$invec), (v16i8 (VSPLTISH vecspltish:$invec))>;
-def : Pat<(v16i8 vecspltisw:$invec), (v16i8 (VSPLTISW vecspltisw:$invec))>;
-
-def : Pat<(v8i16 vecspltisb:$invec), (v8i16 (VSPLTISB vecspltisb:$invec))>;
-def : Pat<(v8i16 vecspltish:$invec), (v8i16 (VSPLTISH vecspltish:$invec))>;
-def : Pat<(v8i16 vecspltisw:$invec), (v8i16 (VSPLTISW vecspltisw:$invec))>;
-
-def : Pat<(v4i32 vecspltisb:$invec), (v4i32 (VSPLTISB vecspltisb:$invec))>;
-def : Pat<(v4i32 vecspltish:$invec), (v4i32 (VSPLTISH vecspltish:$invec))>;
-def : Pat<(v4i32 vecspltisw:$invec), (v4i32 (VSPLTISW vecspltisw:$invec))>;
-
// Logical Operations
def : Pat<(v16i8 (vnot VRRC:$vA)), (v16i8 (VNOR VRRC:$vA, VRRC:$vA))>;
def : Pat<(v8i16 (vnot VRRC:$vA)), (v8i16 (VNOR VRRC:$vA, VRRC:$vA))>;