mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-23 16:19:52 +00:00
Use early exit to reduce indentation. No functional change.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@65962 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -3171,152 +3171,152 @@ SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
|||||||
APInt APSplatBits, APSplatUndef;
|
APInt APSplatBits, APSplatUndef;
|
||||||
unsigned SplatBitSize;
|
unsigned SplatBitSize;
|
||||||
bool HasAnyUndefs;
|
bool HasAnyUndefs;
|
||||||
if (BVN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
|
if (! BVN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
|
||||||
HasAnyUndefs) &&
|
HasAnyUndefs) || SplatBitSize > 32)
|
||||||
SplatBitSize <= 32) {
|
return SDValue();
|
||||||
unsigned SplatBits = APSplatBits.getZExtValue();
|
|
||||||
unsigned SplatUndef = APSplatUndef.getZExtValue();
|
|
||||||
unsigned SplatSize = SplatBitSize / 8;
|
|
||||||
|
|
||||||
// First, handle single instruction cases.
|
unsigned SplatBits = APSplatBits.getZExtValue();
|
||||||
|
unsigned SplatUndef = APSplatUndef.getZExtValue();
|
||||||
|
unsigned SplatSize = SplatBitSize / 8;
|
||||||
|
|
||||||
// All zeros?
|
// First, handle single instruction cases.
|
||||||
if (SplatBits == 0) {
|
|
||||||
// Canonicalize all zero vectors to be v4i32.
|
// All zeros?
|
||||||
if (Op.getValueType() != MVT::v4i32 || HasAnyUndefs) {
|
if (SplatBits == 0) {
|
||||||
SDValue Z = DAG.getConstant(0, MVT::i32);
|
// Canonicalize all zero vectors to be v4i32.
|
||||||
Z = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Z, Z, Z, Z);
|
if (Op.getValueType() != MVT::v4i32 || HasAnyUndefs) {
|
||||||
Op = DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Z);
|
SDValue Z = DAG.getConstant(0, MVT::i32);
|
||||||
}
|
Z = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Z, Z, Z, Z);
|
||||||
return Op;
|
Op = DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Z);
|
||||||
}
|
}
|
||||||
|
return Op;
|
||||||
|
}
|
||||||
|
|
||||||
// If the sign extended value is in the range [-16,15], use VSPLTI[bhw].
|
// If the sign extended value is in the range [-16,15], use VSPLTI[bhw].
|
||||||
int32_t SextVal= (int32_t(SplatBits << (32-SplatBitSize)) >>
|
int32_t SextVal= (int32_t(SplatBits << (32-SplatBitSize)) >>
|
||||||
(32-SplatBitSize));
|
(32-SplatBitSize));
|
||||||
if (SextVal >= -16 && SextVal <= 15)
|
if (SextVal >= -16 && SextVal <= 15)
|
||||||
return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG, dl);
|
return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG, dl);
|
||||||
|
|
||||||
|
|
||||||
// Two instruction sequences.
|
// Two instruction sequences.
|
||||||
|
|
||||||
// If this value is in the range [-32,30] and is even, use:
|
// If this value is in the range [-32,30] and is even, use:
|
||||||
// tmp = VSPLTI[bhw], result = add tmp, tmp
|
// tmp = VSPLTI[bhw], result = add tmp, tmp
|
||||||
if (SextVal >= -32 && SextVal <= 30 && (SextVal & 1) == 0) {
|
if (SextVal >= -32 && SextVal <= 30 && (SextVal & 1) == 0) {
|
||||||
SDValue Res = BuildSplatI(SextVal >> 1, SplatSize, MVT::Other, DAG, dl);
|
SDValue Res = BuildSplatI(SextVal >> 1, SplatSize, MVT::Other, DAG, dl);
|
||||||
Res = DAG.getNode(ISD::ADD, dl, Res.getValueType(), Res, Res);
|
Res = DAG.getNode(ISD::ADD, dl, Res.getValueType(), Res, Res);
|
||||||
|
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is 0x8000_0000 x 4, turn into vspltisw + vslw. If it is
|
||||||
|
// 0x7FFF_FFFF x 4, turn it into not(0x8000_0000). This is important
|
||||||
|
// for fneg/fabs.
|
||||||
|
if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) {
|
||||||
|
// Make -1 and vspltisw -1:
|
||||||
|
SDValue OnesV = BuildSplatI(-1, 4, MVT::v4i32, DAG, dl);
|
||||||
|
|
||||||
|
// Make the VSLW intrinsic, computing 0x8000_0000.
|
||||||
|
SDValue Res = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, OnesV,
|
||||||
|
OnesV, DAG, dl);
|
||||||
|
|
||||||
|
// xor by OnesV to invert it.
|
||||||
|
Res = DAG.getNode(ISD::XOR, dl, MVT::v4i32, Res, OnesV);
|
||||||
|
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if this is a wide variety of vsplti*, binop self cases.
|
||||||
|
static const signed char SplatCsts[] = {
|
||||||
|
-1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
|
||||||
|
-8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned idx = 0; idx < array_lengthof(SplatCsts); ++idx) {
|
||||||
|
// Indirect through the SplatCsts array so that we favor 'vsplti -1' for
|
||||||
|
// cases which are ambiguous (e.g. formation of 0x8000_0000). 'vsplti -1'
|
||||||
|
int i = SplatCsts[idx];
|
||||||
|
|
||||||
|
// Figure out what shift amount will be used by altivec if shifted by i in
|
||||||
|
// this splat size.
|
||||||
|
unsigned TypeShiftAmt = i & (SplatBitSize-1);
|
||||||
|
|
||||||
|
// vsplti + shl self.
|
||||||
|
if (SextVal == (i << (int)TypeShiftAmt)) {
|
||||||
|
SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl);
|
||||||
|
static const unsigned IIDs[] = { // Intrinsic to use for each size.
|
||||||
|
Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
|
||||||
|
Intrinsic::ppc_altivec_vslw
|
||||||
|
};
|
||||||
|
Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl);
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is 0x8000_0000 x 4, turn into vspltisw + vslw. If it is
|
// vsplti + srl self.
|
||||||
// 0x7FFF_FFFF x 4, turn it into not(0x8000_0000). This is important
|
if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) {
|
||||||
// for fneg/fabs.
|
SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl);
|
||||||
if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) {
|
static const unsigned IIDs[] = { // Intrinsic to use for each size.
|
||||||
// Make -1 and vspltisw -1:
|
Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
|
||||||
SDValue OnesV = BuildSplatI(-1, 4, MVT::v4i32, DAG, dl);
|
Intrinsic::ppc_altivec_vsrw
|
||||||
|
};
|
||||||
// Make the VSLW intrinsic, computing 0x8000_0000.
|
Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl);
|
||||||
SDValue Res = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, OnesV,
|
|
||||||
OnesV, DAG, dl);
|
|
||||||
|
|
||||||
// xor by OnesV to invert it.
|
|
||||||
Res = DAG.getNode(ISD::XOR, dl, MVT::v4i32, Res, OnesV);
|
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if this is a wide variety of vsplti*, binop self cases.
|
// vsplti + sra self.
|
||||||
static const signed char SplatCsts[] = {
|
if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) {
|
||||||
-1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
|
SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl);
|
||||||
-8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
|
static const unsigned IIDs[] = { // Intrinsic to use for each size.
|
||||||
};
|
Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0,
|
||||||
|
Intrinsic::ppc_altivec_vsraw
|
||||||
for (unsigned idx = 0; idx < array_lengthof(SplatCsts); ++idx) {
|
};
|
||||||
// Indirect through the SplatCsts array so that we favor 'vsplti -1' for
|
Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl);
|
||||||
// cases which are ambiguous (e.g. formation of 0x8000_0000). 'vsplti -1'
|
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
||||||
int i = SplatCsts[idx];
|
|
||||||
|
|
||||||
// Figure out what shift amount will be used by altivec if shifted by i in
|
|
||||||
// this splat size.
|
|
||||||
unsigned TypeShiftAmt = i & (SplatBitSize-1);
|
|
||||||
|
|
||||||
// vsplti + shl self.
|
|
||||||
if (SextVal == (i << (int)TypeShiftAmt)) {
|
|
||||||
SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl);
|
|
||||||
static const unsigned IIDs[] = { // Intrinsic to use for each size.
|
|
||||||
Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
|
|
||||||
Intrinsic::ppc_altivec_vslw
|
|
||||||
};
|
|
||||||
Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl);
|
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// vsplti + srl self.
|
|
||||||
if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) {
|
|
||||||
SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl);
|
|
||||||
static const unsigned IIDs[] = { // Intrinsic to use for each size.
|
|
||||||
Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
|
|
||||||
Intrinsic::ppc_altivec_vsrw
|
|
||||||
};
|
|
||||||
Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl);
|
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// vsplti + sra self.
|
|
||||||
if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) {
|
|
||||||
SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl);
|
|
||||||
static const unsigned IIDs[] = { // Intrinsic to use for each size.
|
|
||||||
Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0,
|
|
||||||
Intrinsic::ppc_altivec_vsraw
|
|
||||||
};
|
|
||||||
Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl);
|
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// vsplti + rol self.
|
|
||||||
if (SextVal == (int)(((unsigned)i << TypeShiftAmt) |
|
|
||||||
((unsigned)i >> (SplatBitSize-TypeShiftAmt)))) {
|
|
||||||
SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl);
|
|
||||||
static const unsigned IIDs[] = { // Intrinsic to use for each size.
|
|
||||||
Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0,
|
|
||||||
Intrinsic::ppc_altivec_vrlw
|
|
||||||
};
|
|
||||||
Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl);
|
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// t = vsplti c, result = vsldoi t, t, 1
|
|
||||||
if (SextVal == ((i << 8) | (i >> (TypeShiftAmt-8)))) {
|
|
||||||
SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl);
|
|
||||||
return BuildVSLDOI(T, T, 1, Op.getValueType(), DAG, dl);
|
|
||||||
}
|
|
||||||
// t = vsplti c, result = vsldoi t, t, 2
|
|
||||||
if (SextVal == ((i << 16) | (i >> (TypeShiftAmt-16)))) {
|
|
||||||
SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl);
|
|
||||||
return BuildVSLDOI(T, T, 2, Op.getValueType(), DAG, dl);
|
|
||||||
}
|
|
||||||
// t = vsplti c, result = vsldoi t, t, 3
|
|
||||||
if (SextVal == ((i << 24) | (i >> (TypeShiftAmt-24)))) {
|
|
||||||
SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl);
|
|
||||||
return BuildVSLDOI(T, T, 3, Op.getValueType(), DAG, dl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Three instruction sequences.
|
// vsplti + rol self.
|
||||||
|
if (SextVal == (int)(((unsigned)i << TypeShiftAmt) |
|
||||||
|
((unsigned)i >> (SplatBitSize-TypeShiftAmt)))) {
|
||||||
|
SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl);
|
||||||
|
static const unsigned IIDs[] = { // Intrinsic to use for each size.
|
||||||
|
Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0,
|
||||||
|
Intrinsic::ppc_altivec_vrlw
|
||||||
|
};
|
||||||
|
Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl);
|
||||||
|
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res);
|
||||||
|
}
|
||||||
|
|
||||||
// Odd, in range [17,31]: (vsplti C)-(vsplti -16).
|
// t = vsplti c, result = vsldoi t, t, 1
|
||||||
if (SextVal >= 0 && SextVal <= 31) {
|
if (SextVal == ((i << 8) | (i >> (TypeShiftAmt-8)))) {
|
||||||
SDValue LHS = BuildSplatI(SextVal-16, SplatSize, MVT::Other, DAG, dl);
|
SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl);
|
||||||
SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl);
|
return BuildVSLDOI(T, T, 1, Op.getValueType(), DAG, dl);
|
||||||
LHS = DAG.getNode(ISD::SUB, dl, LHS.getValueType(), LHS, RHS);
|
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), LHS);
|
|
||||||
}
|
}
|
||||||
// Odd, in range [-31,-17]: (vsplti C)+(vsplti -16).
|
// t = vsplti c, result = vsldoi t, t, 2
|
||||||
if (SextVal >= -31 && SextVal <= 0) {
|
if (SextVal == ((i << 16) | (i >> (TypeShiftAmt-16)))) {
|
||||||
SDValue LHS = BuildSplatI(SextVal+16, SplatSize, MVT::Other, DAG, dl);
|
SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl);
|
||||||
SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl);
|
return BuildVSLDOI(T, T, 2, Op.getValueType(), DAG, dl);
|
||||||
LHS = DAG.getNode(ISD::ADD, dl, LHS.getValueType(), LHS, RHS);
|
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), LHS);
|
|
||||||
}
|
}
|
||||||
|
// t = vsplti c, result = vsldoi t, t, 3
|
||||||
|
if (SextVal == ((i << 24) | (i >> (TypeShiftAmt-24)))) {
|
||||||
|
SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl);
|
||||||
|
return BuildVSLDOI(T, T, 3, Op.getValueType(), DAG, dl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Three instruction sequences.
|
||||||
|
|
||||||
|
// Odd, in range [17,31]: (vsplti C)-(vsplti -16).
|
||||||
|
if (SextVal >= 0 && SextVal <= 31) {
|
||||||
|
SDValue LHS = BuildSplatI(SextVal-16, SplatSize, MVT::Other, DAG, dl);
|
||||||
|
SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl);
|
||||||
|
LHS = DAG.getNode(ISD::SUB, dl, LHS.getValueType(), LHS, RHS);
|
||||||
|
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), LHS);
|
||||||
|
}
|
||||||
|
// Odd, in range [-31,-17]: (vsplti C)+(vsplti -16).
|
||||||
|
if (SextVal >= -31 && SextVal <= 0) {
|
||||||
|
SDValue LHS = BuildSplatI(SextVal+16, SplatSize, MVT::Other, DAG, dl);
|
||||||
|
SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl);
|
||||||
|
LHS = DAG.getNode(ISD::ADD, dl, LHS.getValueType(), LHS, RHS);
|
||||||
|
return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), LHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|||||||
Reference in New Issue
Block a user