mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-15 07:59:33 +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 llvm-svn: 105586
This commit is contained in:
parent
ff11696889
commit
9cf6656d4b
@ -3171,7 +3171,9 @@ ARMTargetLowering::isShuffleMaskLegal(const SmallVectorImpl<int> &M,
|
||||
bool ReverseVEXT;
|
||||
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, 32) ||
|
||||
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.
|
||||
SVN->getMask(ShuffleMask);
|
||||
|
||||
if (ShuffleVectorSDNode::isSplatMask(&ShuffleMask[0], VT)) {
|
||||
int Lane = SVN->getSplatIndex();
|
||||
// If this is undef splat, generate it via "just" vdup, if possible.
|
||||
if (Lane == -1) Lane = 0;
|
||||
unsigned EltSize = VT.getVectorElementType().getSizeInBits();
|
||||
if (EltSize <= 32) {
|
||||
if (ShuffleVectorSDNode::isSplatMask(&ShuffleMask[0], VT)) {
|
||||
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) {
|
||||
return DAG.getNode(ARMISD::VDUP, dl, VT, V1.getOperand(0));
|
||||
if (Lane == 0 && V1.getOpcode() == ISD::SCALAR_TO_VECTOR) {
|
||||
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
|
||||
// the PerfectShuffle-generated table to synthesize it from other shuffles.
|
||||
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.
|
||||
unsigned EltSize = VT.getVectorElementType().getSizeInBits();
|
||||
if (EltSize >= 32) {
|
||||
// Do the expansion with floating-point types, since that is what the VFP
|
||||
// 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");
|
||||
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.
|
||||
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}", "",
|
||||
[(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
|
||||
defm VMOVN : N2VNInt_HSD<0b11,0b11,0b10,0b00100,0,0, IIC_VMOVD,
|
||||
"vmovn", "i", int_arm_neon_vmovn>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user