mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-06 20:33:54 +00:00
Codegen things like:
<int -1, int -1, int -1, int -1> and <int 65537, int 65537, int 65537, int 65537> Using things like: vspltisb v0, -1 and: vspltish v0, 1 instead of using constant pool loads. This implements CodeGen/PowerPC/vec_splat.ll:splat_imm_i{32|16}. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27106 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b45854fff5
commit
9c61dcf1aa
@ -102,6 +102,11 @@ namespace {
|
|||||||
unsigned AsmVariant, const char *ExtraCode);
|
unsigned AsmVariant, const char *ExtraCode);
|
||||||
|
|
||||||
|
|
||||||
|
void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo) {
|
||||||
|
char value = MI->getOperand(OpNo).getImmedValue();
|
||||||
|
value = (value << (32-5)) >> (32-5);
|
||||||
|
O << (int)value;
|
||||||
|
}
|
||||||
void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) {
|
void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) {
|
||||||
unsigned char value = MI->getOperand(OpNo).getImmedValue();
|
unsigned char value = MI->getOperand(OpNo).getImmedValue();
|
||||||
assert(value <= 31 && "Invalid u5imm argument!");
|
assert(value <= 31 && "Invalid u5imm argument!");
|
||||||
|
@ -301,6 +301,63 @@ bool PPC::isZeroVector(SDNode *N) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isVecSplatImm - Return true if this is a build_vector of constants which
|
||||||
|
/// can be formed by using a vspltis[bhw] instruction. The ByteSize field
|
||||||
|
/// indicates the number of bytes of each element [124] -> [bhw].
|
||||||
|
bool PPC::isVecSplatImm(SDNode *N, unsigned ByteSize, char *Val) {
|
||||||
|
SDOperand OpVal(0, 0);
|
||||||
|
// Check to see if this buildvec has a single non-undef value in its elements.
|
||||||
|
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
|
||||||
|
if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
|
||||||
|
if (OpVal.Val == 0)
|
||||||
|
OpVal = N->getOperand(i);
|
||||||
|
else if (OpVal != N->getOperand(i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OpVal.Val == 0) return false; // All UNDEF: use implicit def.
|
||||||
|
|
||||||
|
unsigned ValSizeInBytes;
|
||||||
|
uint64_t Value;
|
||||||
|
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
|
||||||
|
Value = CN->getValue();
|
||||||
|
ValSizeInBytes = MVT::getSizeInBits(CN->getValueType(0))/8;
|
||||||
|
} else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) {
|
||||||
|
assert(CN->getValueType(0) == MVT::f32 && "Only one legal FP vector type!");
|
||||||
|
Value = FloatToBits(CN->getValue());
|
||||||
|
ValSizeInBytes = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the splat value is larger than the element value, then we can never do
|
||||||
|
// this splat. The only case that we could fit the replicated bits into our
|
||||||
|
// immediate field for would be zero, and we prefer to use vxor for it.
|
||||||
|
if (ValSizeInBytes < ByteSize) return false;
|
||||||
|
|
||||||
|
// If the element value is larger than the splat value, cut it in half and
|
||||||
|
// check to see if the two halves are equal. Continue doing this until we
|
||||||
|
// get to ByteSize. This allows us to handle 0x01010101 as 0x01.
|
||||||
|
while (ValSizeInBytes > ByteSize) {
|
||||||
|
ValSizeInBytes >>= 1;
|
||||||
|
|
||||||
|
// If the top half equals the bottom half, we're still ok.
|
||||||
|
if (((Value >> (ValSizeInBytes*8)) & ((8 << ValSizeInBytes)-1)) !=
|
||||||
|
(Value & ((8 << ValSizeInBytes)-1)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properly sign extend the value.
|
||||||
|
int ShAmt = (4-ByteSize)*8;
|
||||||
|
int MaskVal = ((int)Value << ShAmt) >> ShAmt;
|
||||||
|
|
||||||
|
// If this is zero, don't match, zero matches isZeroVector.
|
||||||
|
if (MaskVal == 0) return false;
|
||||||
|
|
||||||
|
if (Val) *Val = MaskVal;
|
||||||
|
|
||||||
|
// Finally, if this value fits in a 5 bit sext field, return true.
|
||||||
|
return ((MaskVal << (32-5)) >> (32-5)) == MaskVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||||
///
|
///
|
||||||
@ -668,6 +725,12 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
// FIXME: We should handle splat(-0.0), and other cases here.
|
// FIXME: We should handle splat(-0.0), and other cases here.
|
||||||
if (PPC::isZeroVector(Op.Val))
|
if (PPC::isZeroVector(Op.Val))
|
||||||
return Op;
|
return Op;
|
||||||
|
|
||||||
|
if (PPC::isVecSplatImm(Op.Val, 1) || // vspltisb
|
||||||
|
PPC::isVecSplatImm(Op.Val, 2) || // vspltish
|
||||||
|
PPC::isVecSplatImm(Op.Val, 4)) // vspltisw
|
||||||
|
return Op;
|
||||||
|
|
||||||
return SDOperand();
|
return SDOperand();
|
||||||
|
|
||||||
case ISD::VECTOR_SHUFFLE: {
|
case ISD::VECTOR_SHUFFLE: {
|
||||||
|
@ -105,6 +105,11 @@ namespace llvm {
|
|||||||
/// isZeroVector - Return true if this build_vector is an all-zero vector.
|
/// isZeroVector - Return true if this build_vector is an all-zero vector.
|
||||||
///
|
///
|
||||||
bool isZeroVector(SDNode *N);
|
bool isZeroVector(SDNode *N);
|
||||||
|
|
||||||
|
/// isVecSplatImm - Return true if this is a build_vector of constants which
|
||||||
|
/// can be formed by using a vspltis[bhw] instruction. The ByteSize field
|
||||||
|
/// indicates the number of bytes of each element [124] -> [bhw].
|
||||||
|
bool isVecSplatImm(SDNode *N, unsigned ByteSize, char *Val = 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
class PPCTargetLowering : public TargetLowering {
|
class PPCTargetLowering : public TargetLowering {
|
||||||
|
@ -140,6 +140,37 @@ def vecimm0 : PatLeaf<(build_vector), [{
|
|||||||
}]>;
|
}]>;
|
||||||
|
|
||||||
|
|
||||||
|
// VSPLTISB_get_imm xform function: convert build_vector to VSPLTISB imm.
|
||||||
|
def VSPLTISB_get_imm : SDNodeXForm<build_vector, [{
|
||||||
|
char Val;
|
||||||
|
PPC::isVecSplatImm(N, 1, &Val);
|
||||||
|
return getI32Imm(Val);
|
||||||
|
}]>;
|
||||||
|
def vecspltisb : PatLeaf<(build_vector), [{
|
||||||
|
return PPC::isVecSplatImm(N, 1);
|
||||||
|
}], VSPLTISB_get_imm>;
|
||||||
|
|
||||||
|
// VSPLTISH_get_imm xform function: convert build_vector to VSPLTISH imm.
|
||||||
|
def VSPLTISH_get_imm : SDNodeXForm<build_vector, [{
|
||||||
|
char Val;
|
||||||
|
PPC::isVecSplatImm(N, 2, &Val);
|
||||||
|
return getI32Imm(Val);
|
||||||
|
}]>;
|
||||||
|
def vecspltish : PatLeaf<(build_vector), [{
|
||||||
|
return PPC::isVecSplatImm(N, 2);
|
||||||
|
}], VSPLTISH_get_imm>;
|
||||||
|
|
||||||
|
// VSPLTISW_get_imm xform function: convert build_vector to VSPLTISW imm.
|
||||||
|
def VSPLTISW_get_imm : SDNodeXForm<build_vector, [{
|
||||||
|
char Val;
|
||||||
|
PPC::isVecSplatImm(N, 4, &Val);
|
||||||
|
return getI32Imm(Val);
|
||||||
|
}]>;
|
||||||
|
def vecspltisw : PatLeaf<(build_vector), [{
|
||||||
|
return PPC::isVecSplatImm(N, 4);
|
||||||
|
}], VSPLTISW_get_imm>;
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// PowerPC Flag Definitions.
|
// PowerPC Flag Definitions.
|
||||||
|
|
||||||
@ -155,6 +186,9 @@ class isDOT {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// PowerPC Operand Definitions.
|
// PowerPC Operand Definitions.
|
||||||
|
|
||||||
|
def s5imm : Operand<i32> {
|
||||||
|
let PrintMethod = "printS5ImmOperand";
|
||||||
|
}
|
||||||
def u5imm : Operand<i32> {
|
def u5imm : Operand<i32> {
|
||||||
let PrintMethod = "printU5ImmOperand";
|
let PrintMethod = "printU5ImmOperand";
|
||||||
}
|
}
|
||||||
@ -1055,12 +1089,21 @@ def VSPLTB : VXForm_1<524, (ops VRRC:$vD, u5imm:$UIMM, VRRC:$vB),
|
|||||||
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,
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
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 (v4f32 VRRC:$vB), (undef),
|
||||||
VSPLT_shuffle_mask:$UIMM))]>;
|
VSPLT_shuffle_mask:$UIMM))]>;
|
||||||
// FIXME: ALSO ADD SUPPORT FOR v4i32!
|
|
||||||
|
def VSPLTISB : VXForm_1<780, (ops VRRC:$vD, s5imm:$SIMM),
|
||||||
|
"vspltisb $vD, $SIMM", VecPerm,
|
||||||
|
[(set VRRC:$vD, (v4f32 vecspltisb:$SIMM))]>;
|
||||||
|
def VSPLTISH : VXForm_1<844, (ops VRRC:$vD, s5imm:$SIMM),
|
||||||
|
"vspltish $vD, $SIMM", VecPerm,
|
||||||
|
[(set VRRC:$vD, (v4f32 vecspltish:$SIMM))]>;
|
||||||
|
def VSPLTISW : VXForm_1<908, (ops VRRC:$vD, s5imm:$SIMM),
|
||||||
|
"vspltisw $vD, $SIMM", VecPerm,
|
||||||
|
[(set VRRC:$vD, (v4f32 vecspltisw:$SIMM))]>;
|
||||||
|
|
||||||
|
|
||||||
// VX-Form Pseudo Instructions
|
// VX-Form Pseudo Instructions
|
||||||
|
|
||||||
@ -1216,6 +1259,11 @@ def : Pat<(v4i32 (PPClve_x xoaddr:$src)),
|
|||||||
def : Pat<(v4i32 (undef)), (v4i32 (IMPLICIT_DEF_VRRC))>;
|
def : Pat<(v4i32 (undef)), (v4i32 (IMPLICIT_DEF_VRRC))>;
|
||||||
def : Pat<(v4i32 vecimm0), (v4i32 (V_SET0))>;
|
def : Pat<(v4i32 vecimm0), (v4i32 (V_SET0))>;
|
||||||
|
|
||||||
|
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))>;
|
||||||
|
|
||||||
|
|
||||||
// bit_convert
|
// bit_convert
|
||||||
def : Pat<(v4i32 (bitconvert (v4f32 VRRC:$src))), (v4i32 VRRC:$src)>;
|
def : Pat<(v4i32 (bitconvert (v4f32 VRRC:$src))), (v4i32 VRRC:$src)>;
|
||||||
def : Pat<(v4f32 (bitconvert (v4i32 VRRC:$src))), (v4f32 VRRC:$src)>;
|
def : Pat<(v4f32 (bitconvert (v4i32 VRRC:$src))), (v4f32 VRRC:$src)>;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user