mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-08 19:25:47 +00:00
Further changes for Neon vector shuffles:
- change isShuffleMaskLegal to show that all shuffles with 32-bit and 64-bit elements are legal - the Neon shuffle instructions do not support 64-bit elements, but we were not checking for that before lowering shuffles to use them - remove some 64-bit element vduplane patterns that are no longer needed git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105586 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -3171,7 +3171,9 @@ ARMTargetLowering::isShuffleMaskLegal(const SmallVectorImpl<int> &M,
|
|||||||
bool ReverseVEXT;
|
bool ReverseVEXT;
|
||||||
unsigned Imm, WhichResult;
|
unsigned Imm, WhichResult;
|
||||||
|
|
||||||
return (ShuffleVectorSDNode::isSplatMask(&M[0], VT) ||
|
unsigned EltSize = VT.getVectorElementType().getSizeInBits();
|
||||||
|
return (EltSize >= 32 ||
|
||||||
|
ShuffleVectorSDNode::isSplatMask(&M[0], VT) ||
|
||||||
isVREVMask(M, VT, 64) ||
|
isVREVMask(M, VT, 64) ||
|
||||||
isVREVMask(M, VT, 32) ||
|
isVREVMask(M, VT, 32) ||
|
||||||
isVREVMask(M, VT, 16) ||
|
isVREVMask(M, VT, 16) ||
|
||||||
@@ -3269,60 +3271,63 @@ static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
|
|||||||
// of the same time so that they get CSEd properly.
|
// of the same time so that they get CSEd properly.
|
||||||
SVN->getMask(ShuffleMask);
|
SVN->getMask(ShuffleMask);
|
||||||
|
|
||||||
if (ShuffleVectorSDNode::isSplatMask(&ShuffleMask[0], VT)) {
|
unsigned EltSize = VT.getVectorElementType().getSizeInBits();
|
||||||
int Lane = SVN->getSplatIndex();
|
if (EltSize <= 32) {
|
||||||
// If this is undef splat, generate it via "just" vdup, if possible.
|
if (ShuffleVectorSDNode::isSplatMask(&ShuffleMask[0], VT)) {
|
||||||
if (Lane == -1) Lane = 0;
|
int Lane = SVN->getSplatIndex();
|
||||||
|
// If this is undef splat, generate it via "just" vdup, if possible.
|
||||||
|
if (Lane == -1) Lane = 0;
|
||||||
|
|
||||||
if (Lane == 0 && V1.getOpcode() == ISD::SCALAR_TO_VECTOR) {
|
if (Lane == 0 && V1.getOpcode() == ISD::SCALAR_TO_VECTOR) {
|
||||||
return DAG.getNode(ARMISD::VDUP, dl, VT, V1.getOperand(0));
|
return DAG.getNode(ARMISD::VDUP, dl, VT, V1.getOperand(0));
|
||||||
|
}
|
||||||
|
return DAG.getNode(ARMISD::VDUPLANE, dl, VT, V1,
|
||||||
|
DAG.getConstant(Lane, MVT::i32));
|
||||||
}
|
}
|
||||||
return DAG.getNode(ARMISD::VDUPLANE, dl, VT, V1,
|
|
||||||
DAG.getConstant(Lane, MVT::i32));
|
bool ReverseVEXT;
|
||||||
|
unsigned Imm;
|
||||||
|
if (isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
|
||||||
|
if (ReverseVEXT)
|
||||||
|
std::swap(V1, V2);
|
||||||
|
return DAG.getNode(ARMISD::VEXT, dl, VT, V1, V2,
|
||||||
|
DAG.getConstant(Imm, MVT::i32));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVREVMask(ShuffleMask, VT, 64))
|
||||||
|
return DAG.getNode(ARMISD::VREV64, dl, VT, V1);
|
||||||
|
if (isVREVMask(ShuffleMask, VT, 32))
|
||||||
|
return DAG.getNode(ARMISD::VREV32, dl, VT, V1);
|
||||||
|
if (isVREVMask(ShuffleMask, VT, 16))
|
||||||
|
return DAG.getNode(ARMISD::VREV16, dl, VT, V1);
|
||||||
|
|
||||||
|
// Check for Neon shuffles that modify both input vectors in place.
|
||||||
|
// If both results are used, i.e., if there are two shuffles with the same
|
||||||
|
// source operands and with masks corresponding to both results of one of
|
||||||
|
// these operations, DAG memoization will ensure that a single node is
|
||||||
|
// used for both shuffles.
|
||||||
|
unsigned WhichResult;
|
||||||
|
if (isVTRNMask(ShuffleMask, VT, WhichResult))
|
||||||
|
return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT),
|
||||||
|
V1, V2).getValue(WhichResult);
|
||||||
|
if (isVUZPMask(ShuffleMask, VT, WhichResult))
|
||||||
|
return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT),
|
||||||
|
V1, V2).getValue(WhichResult);
|
||||||
|
if (isVZIPMask(ShuffleMask, VT, WhichResult))
|
||||||
|
return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT),
|
||||||
|
V1, V2).getValue(WhichResult);
|
||||||
|
|
||||||
|
if (isVTRN_v_undef_Mask(ShuffleMask, VT, WhichResult))
|
||||||
|
return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT),
|
||||||
|
V1, V1).getValue(WhichResult);
|
||||||
|
if (isVUZP_v_undef_Mask(ShuffleMask, VT, WhichResult))
|
||||||
|
return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT),
|
||||||
|
V1, V1).getValue(WhichResult);
|
||||||
|
if (isVZIP_v_undef_Mask(ShuffleMask, VT, WhichResult))
|
||||||
|
return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT),
|
||||||
|
V1, V1).getValue(WhichResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReverseVEXT;
|
|
||||||
unsigned Imm;
|
|
||||||
if (isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
|
|
||||||
if (ReverseVEXT)
|
|
||||||
std::swap(V1, V2);
|
|
||||||
return DAG.getNode(ARMISD::VEXT, dl, VT, V1, V2,
|
|
||||||
DAG.getConstant(Imm, MVT::i32));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isVREVMask(ShuffleMask, VT, 64))
|
|
||||||
return DAG.getNode(ARMISD::VREV64, dl, VT, V1);
|
|
||||||
if (isVREVMask(ShuffleMask, VT, 32))
|
|
||||||
return DAG.getNode(ARMISD::VREV32, dl, VT, V1);
|
|
||||||
if (isVREVMask(ShuffleMask, VT, 16))
|
|
||||||
return DAG.getNode(ARMISD::VREV16, dl, VT, V1);
|
|
||||||
|
|
||||||
// Check for Neon shuffles that modify both input vectors in place.
|
|
||||||
// If both results are used, i.e., if there are two shuffles with the same
|
|
||||||
// source operands and with masks corresponding to both results of one of
|
|
||||||
// these operations, DAG memoization will ensure that a single node is
|
|
||||||
// used for both shuffles.
|
|
||||||
unsigned WhichResult;
|
|
||||||
if (isVTRNMask(ShuffleMask, VT, WhichResult))
|
|
||||||
return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT),
|
|
||||||
V1, V2).getValue(WhichResult);
|
|
||||||
if (isVUZPMask(ShuffleMask, VT, WhichResult))
|
|
||||||
return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT),
|
|
||||||
V1, V2).getValue(WhichResult);
|
|
||||||
if (isVZIPMask(ShuffleMask, VT, WhichResult))
|
|
||||||
return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT),
|
|
||||||
V1, V2).getValue(WhichResult);
|
|
||||||
|
|
||||||
if (isVTRN_v_undef_Mask(ShuffleMask, VT, WhichResult))
|
|
||||||
return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT),
|
|
||||||
V1, V1).getValue(WhichResult);
|
|
||||||
if (isVUZP_v_undef_Mask(ShuffleMask, VT, WhichResult))
|
|
||||||
return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT),
|
|
||||||
V1, V1).getValue(WhichResult);
|
|
||||||
if (isVZIP_v_undef_Mask(ShuffleMask, VT, WhichResult))
|
|
||||||
return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT),
|
|
||||||
V1, V1).getValue(WhichResult);
|
|
||||||
|
|
||||||
// If the shuffle is not directly supported and it has 4 elements, use
|
// If the shuffle is not directly supported and it has 4 elements, use
|
||||||
// the PerfectShuffle-generated table to synthesize it from other shuffles.
|
// the PerfectShuffle-generated table to synthesize it from other shuffles.
|
||||||
unsigned NumElts = VT.getVectorNumElements();
|
unsigned NumElts = VT.getVectorNumElements();
|
||||||
@@ -3346,7 +3351,6 @@ static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implement shuffles with 32- or 64-bit elements as ARMISD::BUILD_VECTORs.
|
// Implement shuffles with 32- or 64-bit elements as ARMISD::BUILD_VECTORs.
|
||||||
unsigned EltSize = VT.getVectorElementType().getSizeInBits();
|
|
||||||
if (EltSize >= 32) {
|
if (EltSize >= 32) {
|
||||||
// Do the expansion with floating-point types, since that is what the VFP
|
// Do the expansion with floating-point types, since that is what the VFP
|
||||||
// registers are defined to use, and since i64 is not legal.
|
// registers are defined to use, and since i64 is not legal.
|
||||||
|
@@ -812,11 +812,6 @@ def DSubReg_f64_reg : SDNodeXForm<imm, [{
|
|||||||
assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
|
assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
|
||||||
return CurDAG->getTargetConstant(ARM::dsub_0 + N->getZExtValue(), MVT::i32);
|
return CurDAG->getTargetConstant(ARM::dsub_0 + N->getZExtValue(), MVT::i32);
|
||||||
}]>;
|
}]>;
|
||||||
def DSubReg_f64_other_reg : SDNodeXForm<imm, [{
|
|
||||||
assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering");
|
|
||||||
return CurDAG->getTargetConstant(ARM::dsub_0 + (1 - N->getZExtValue()),
|
|
||||||
MVT::i32);
|
|
||||||
}]>;
|
|
||||||
|
|
||||||
// Extract S sub-registers of Q/D registers.
|
// Extract S sub-registers of Q/D registers.
|
||||||
def SSubReg_f32_reg : SDNodeXForm<imm, [{
|
def SSubReg_f32_reg : SDNodeXForm<imm, [{
|
||||||
@@ -3122,17 +3117,6 @@ def VDUPfqf : N2V<0b11, 0b11, {?,1}, {0,0}, 0b11000, 1, 0,
|
|||||||
IIC_VMOVD, "vdup", "32", "$dst, ${src:lane}", "",
|
IIC_VMOVD, "vdup", "32", "$dst, ${src:lane}", "",
|
||||||
[(set QPR:$dst, (v4f32 (NEONvdup (f32 SPR:$src))))]>;
|
[(set QPR:$dst, (v4f32 (NEONvdup (f32 SPR:$src))))]>;
|
||||||
|
|
||||||
def : Pat<(v2i64 (NEONvduplane (v2i64 QPR:$src), imm:$lane)),
|
|
||||||
(INSERT_SUBREG QPR:$src,
|
|
||||||
(i64 (EXTRACT_SUBREG QPR:$src,
|
|
||||||
(DSubReg_f64_reg imm:$lane))),
|
|
||||||
(DSubReg_f64_other_reg imm:$lane))>;
|
|
||||||
def : Pat<(v2f64 (NEONvduplane (v2f64 QPR:$src), imm:$lane)),
|
|
||||||
(INSERT_SUBREG QPR:$src,
|
|
||||||
(f64 (EXTRACT_SUBREG QPR:$src,
|
|
||||||
(DSubReg_f64_reg imm:$lane))),
|
|
||||||
(DSubReg_f64_other_reg imm:$lane))>;
|
|
||||||
|
|
||||||
// VMOVN : Vector Narrowing Move
|
// VMOVN : Vector Narrowing Move
|
||||||
defm VMOVN : N2VNInt_HSD<0b11,0b11,0b10,0b00100,0,0, IIC_VMOVD,
|
defm VMOVN : N2VNInt_HSD<0b11,0b11,0b10,0b00100,0,0, IIC_VMOVD,
|
||||||
"vmovn", "i", int_arm_neon_vmovn>;
|
"vmovn", "i", int_arm_neon_vmovn>;
|
||||||
|
Reference in New Issue
Block a user