mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Use a target-specific VMOVIMM DAG node instead of BUILD_VECTOR to represent
NEON VMOV-immediate instructions. This simplifies some things. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108275 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
87a85c7ef0
commit
cba270d042
@ -624,6 +624,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case ARMISD::VQRSHRNsu: return "ARMISD::VQRSHRNsu";
|
||||
case ARMISD::VGETLANEu: return "ARMISD::VGETLANEu";
|
||||
case ARMISD::VGETLANEs: return "ARMISD::VGETLANEs";
|
||||
case ARMISD::VMOVIMM: return "ARMISD::VMOVIMM";
|
||||
case ARMISD::VDUP: return "ARMISD::VDUP";
|
||||
case ARMISD::VDUPLANE: return "ARMISD::VDUPLANE";
|
||||
case ARMISD::VEXT: return "ARMISD::VEXT";
|
||||
@ -2644,51 +2645,18 @@ static SDValue ExpandBIT_CONVERT(SDNode *N, SelectionDAG &DAG) {
|
||||
}
|
||||
|
||||
/// getZeroVector - Returns a vector of specified type with all zero elements.
|
||||
///
|
||||
/// Zero vectors are used to represent vector negation and in those cases
|
||||
/// will be implemented with the NEON VNEG instruction. However, VNEG does
|
||||
/// not support i64 elements, so sometimes the zero vectors will need to be
|
||||
/// explicitly constructed. Regardless, use a canonical VMOV to create the
|
||||
/// zero vector.
|
||||
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) {
|
||||
assert(VT.isVector() && "Expected a vector type");
|
||||
|
||||
// Zero vectors are used to represent vector negation and in those cases
|
||||
// will be implemented with the NEON VNEG instruction. However, VNEG does
|
||||
// not support i64 elements, so sometimes the zero vectors will need to be
|
||||
// explicitly constructed. For those cases, and potentially other uses in
|
||||
// the future, always build zero vectors as <16 x i8> or <8 x i8> bitcasted
|
||||
// to their dest type. This ensures they get CSE'd.
|
||||
SDValue Vec;
|
||||
SDValue Cst = DAG.getTargetConstant(0, MVT::i8);
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
MVT TVT;
|
||||
|
||||
if (VT.getSizeInBits() == 64) {
|
||||
Ops.assign(8, Cst); TVT = MVT::v8i8;
|
||||
} else {
|
||||
Ops.assign(16, Cst); TVT = MVT::v16i8;
|
||||
}
|
||||
Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, TVT, &Ops[0], Ops.size());
|
||||
|
||||
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec);
|
||||
}
|
||||
|
||||
/// getOnesVector - Returns a vector of specified type with all bits set.
|
||||
///
|
||||
static SDValue getOnesVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) {
|
||||
assert(VT.isVector() && "Expected a vector type");
|
||||
|
||||
// Always build ones vectors as <16 x i8> or <8 x i8> bitcasted to their
|
||||
// dest type. This ensures they get CSE'd.
|
||||
SDValue Vec;
|
||||
SDValue Cst = DAG.getTargetConstant(0xFF, MVT::i8);
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
MVT TVT;
|
||||
|
||||
if (VT.getSizeInBits() == 64) {
|
||||
Ops.assign(8, Cst); TVT = MVT::v8i8;
|
||||
} else {
|
||||
Ops.assign(16, Cst); TVT = MVT::v16i8;
|
||||
}
|
||||
Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, TVT, &Ops[0], Ops.size());
|
||||
|
||||
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec);
|
||||
// The canonical modified immediate encoding of a zero vector is....0!
|
||||
SDValue EncodedVal = DAG.getTargetConstant(0, MVT::i32);
|
||||
EVT VmovVT = VT.is128BitVector() ? MVT::v4i32 : MVT::v2i32;
|
||||
SDValue Vmov = DAG.getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
|
||||
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vmov);
|
||||
}
|
||||
|
||||
/// LowerShiftRightParts - Lower SRA_PARTS, which returns two
|
||||
@ -2941,13 +2909,11 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
|
||||
|
||||
/// isNEONModifiedImm - Check if the specified splat value corresponds to a
|
||||
/// valid vector constant for a NEON instruction with a "modified immediate"
|
||||
/// operand (e.g., VMOV). If so, return either the constant being
|
||||
/// splatted or the encoded value, depending on the DoEncode parameter.
|
||||
/// operand (e.g., VMOV). If so, return the encoded value.
|
||||
static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
|
||||
unsigned SplatBitSize, SelectionDAG &DAG,
|
||||
bool isVMOV, bool DoEncode) {
|
||||
EVT &VT, bool is128Bits, bool isVMOV) {
|
||||
unsigned OpCmode, Imm;
|
||||
EVT VT;
|
||||
|
||||
// SplatBitSize is set to the smallest size that splats the vector, so a
|
||||
// zero vector will always have SplatBitSize == 8. However, NEON modified
|
||||
@ -2963,12 +2929,12 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
|
||||
assert((SplatBits & ~0xff) == 0 && "one byte splat value is too big");
|
||||
OpCmode = 0xe;
|
||||
Imm = SplatBits;
|
||||
VT = MVT::i8;
|
||||
VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
// NEON's 16-bit VMOV supports splat values where only one byte is nonzero.
|
||||
VT = MVT::i16;
|
||||
VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
|
||||
if ((SplatBits & ~0xff) == 0) {
|
||||
// Value = 0x00nn: Op=x, Cmode=100x.
|
||||
OpCmode = 0x8;
|
||||
@ -2988,7 +2954,7 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
|
||||
// * only one byte is nonzero, or
|
||||
// * the least significant byte is 0xff and the second byte is nonzero, or
|
||||
// * the least significant 2 bytes are 0xff and the third is nonzero.
|
||||
VT = MVT::i32;
|
||||
VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
|
||||
if ((SplatBits & ~0xff) == 0) {
|
||||
// Value = 0x000000nn: Op=x, Cmode=000x.
|
||||
OpCmode = 0;
|
||||
@ -3060,7 +3026,7 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
|
||||
// Op=1, Cmode=1110.
|
||||
OpCmode = 0x1e;
|
||||
SplatBits = Val;
|
||||
VT = MVT::i64;
|
||||
VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3069,32 +3035,8 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
if (DoEncode) {
|
||||
unsigned EncodedVal = ARM_AM::createNEONModImm(OpCmode, Imm);
|
||||
return DAG.getTargetConstant(EncodedVal, MVT::i32);
|
||||
}
|
||||
return DAG.getTargetConstant(SplatBits, VT);
|
||||
}
|
||||
|
||||
/// getNEONModImm - If this is a valid vector constant for a NEON instruction
|
||||
/// with a "modified immediate" operand (e.g., VMOV) of the specified element
|
||||
/// size, return the encoded value for that immediate. The ByteSize field
|
||||
/// indicates the number of bytes of each element [1248].
|
||||
SDValue ARM::getNEONModImm(SDNode *N, unsigned ByteSize, bool isVMOV,
|
||||
SelectionDAG &DAG) {
|
||||
BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(N);
|
||||
APInt SplatBits, SplatUndef;
|
||||
unsigned SplatBitSize;
|
||||
bool HasAnyUndefs;
|
||||
if (! BVN || ! BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize,
|
||||
HasAnyUndefs, ByteSize * 8))
|
||||
return SDValue();
|
||||
|
||||
if (SplatBitSize > ByteSize * 8)
|
||||
return SDValue();
|
||||
|
||||
return isNEONModifiedImm(SplatBits.getZExtValue(), SplatUndef.getZExtValue(),
|
||||
SplatBitSize, DAG, isVMOV, true);
|
||||
unsigned EncodedVal = ARM_AM::createNEONModImm(OpCmode, Imm);
|
||||
return DAG.getTargetConstant(EncodedVal, MVT::i32);
|
||||
}
|
||||
|
||||
static bool isVEXTMask(const SmallVectorImpl<int> &M, EVT VT,
|
||||
@ -3285,43 +3227,6 @@ static bool isVZIP_v_undef_Mask(const SmallVectorImpl<int> &M, EVT VT,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static SDValue BuildSplat(SDValue Val, EVT VT, SelectionDAG &DAG, DebugLoc dl) {
|
||||
// Canonicalize all-zeros and all-ones vectors.
|
||||
ConstantSDNode *ConstVal = cast<ConstantSDNode>(Val.getNode());
|
||||
if (ConstVal->isNullValue())
|
||||
return getZeroVector(VT, DAG, dl);
|
||||
if (ConstVal->isAllOnesValue())
|
||||
return getOnesVector(VT, DAG, dl);
|
||||
|
||||
EVT CanonicalVT;
|
||||
if (VT.is64BitVector()) {
|
||||
switch (Val.getValueType().getSizeInBits()) {
|
||||
case 8: CanonicalVT = MVT::v8i8; break;
|
||||
case 16: CanonicalVT = MVT::v4i16; break;
|
||||
case 32: CanonicalVT = MVT::v2i32; break;
|
||||
case 64: CanonicalVT = MVT::v1i64; break;
|
||||
default: llvm_unreachable("unexpected splat element type"); break;
|
||||
}
|
||||
} else {
|
||||
assert(VT.is128BitVector() && "unknown splat vector size");
|
||||
switch (Val.getValueType().getSizeInBits()) {
|
||||
case 8: CanonicalVT = MVT::v16i8; break;
|
||||
case 16: CanonicalVT = MVT::v8i16; break;
|
||||
case 32: CanonicalVT = MVT::v4i32; break;
|
||||
case 64: CanonicalVT = MVT::v2i64; break;
|
||||
default: llvm_unreachable("unexpected splat element type"); break;
|
||||
}
|
||||
}
|
||||
|
||||
// Build a canonical splat for this value.
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
Ops.assign(CanonicalVT.getVectorNumElements(), Val);
|
||||
SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, CanonicalVT, &Ops[0],
|
||||
Ops.size());
|
||||
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Res);
|
||||
}
|
||||
|
||||
// If this is a case we can't handle, return null and let the default
|
||||
// expansion code take care of it.
|
||||
static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
||||
@ -3335,11 +3240,14 @@ static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
||||
if (BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
|
||||
if (SplatBitSize <= 64) {
|
||||
// Check if an immediate VMOV works.
|
||||
EVT VmovVT;
|
||||
SDValue Val = isNEONModifiedImm(SplatBits.getZExtValue(),
|
||||
SplatUndef.getZExtValue(),
|
||||
SplatBitSize, DAG, true, false);
|
||||
if (Val.getNode())
|
||||
return BuildSplat(Val, VT, DAG, dl);
|
||||
SplatUndef.getZExtValue(), SplatBitSize,
|
||||
DAG, VmovVT, VT.is128BitVector(), true);
|
||||
if (Val.getNode()) {
|
||||
SDValue Vmov = DAG.getNode(ARMISD::VMOVIMM, dl, VmovVT, Val);
|
||||
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vmov);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,7 @@ namespace llvm {
|
||||
VGETLANEs, // sign-extend vector extract element
|
||||
|
||||
// Vector duplicate:
|
||||
VMOVIMM,
|
||||
VDUP,
|
||||
VDUPLANE,
|
||||
|
||||
@ -152,13 +153,6 @@ namespace llvm {
|
||||
|
||||
/// Define some predicates that are used for node matching.
|
||||
namespace ARM {
|
||||
/// getNEONModImm - If this is a valid vector constant for a NEON
|
||||
/// instruction with a "modified immediate" operand (e.g., VMOV) of the
|
||||
/// specified element size, return the encoded value for that immediate.
|
||||
/// The ByteSize field indicates the number of bytes of each element [1248].
|
||||
SDValue getNEONModImm(SDNode *N, unsigned ByteSize, bool isVMOV,
|
||||
SelectionDAG &DAG);
|
||||
|
||||
/// getVFPf32Imm / getVFPf64Imm - If the given fp immediate can be
|
||||
/// materialized with a VMOV.f32 / VMOV.f64 (i.e. fconsts / fconstd)
|
||||
/// instruction, returns its 8-bit integer representation. Otherwise,
|
||||
|
@ -65,6 +65,9 @@ def SDTARMVGETLN : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisInt<1>,
|
||||
def NEONvgetlaneu : SDNode<"ARMISD::VGETLANEu", SDTARMVGETLN>;
|
||||
def NEONvgetlanes : SDNode<"ARMISD::VGETLANEs", SDTARMVGETLN>;
|
||||
|
||||
def NEONvmovImm : SDNode<"ARMISD::VMOVIMM",
|
||||
SDTypeProfile<1, 1, [SDTCisVec<0>,
|
||||
SDTCisVT<1, i32>]>>;
|
||||
def NEONvdup : SDNode<"ARMISD::VDUP", SDTypeProfile<1, 1, [SDTCisVec<0>]>>;
|
||||
|
||||
// VDUPLANE can produce a quad-register result from a double-register source,
|
||||
@ -94,6 +97,20 @@ def SDTARMFMAX : SDTypeProfile<1, 2, [SDTCisVT<0, f32>, SDTCisSameAs<0, 1>,
|
||||
def NEONfmax : SDNode<"ARMISD::FMAX", SDTARMFMAX>;
|
||||
def NEONfmin : SDNode<"ARMISD::FMIN", SDTARMFMAX>;
|
||||
|
||||
def NEONimmAllZerosV: PatLeaf<(NEONvmovImm (i32 timm)), [{
|
||||
ConstantSDNode *ConstVal = cast<ConstantSDNode>(N->getOperand(0));
|
||||
unsigned EltBits;
|
||||
uint64_t EltVal = ARM_AM::decodeNEONModImm(ConstVal->getZExtValue(), EltBits);
|
||||
return (EltBits == 32 && EltVal == 0);
|
||||
}]>;
|
||||
|
||||
def NEONimmAllOnesV: PatLeaf<(NEONvmovImm (i32 timm)), [{
|
||||
ConstantSDNode *ConstVal = cast<ConstantSDNode>(N->getOperand(0));
|
||||
unsigned EltBits;
|
||||
uint64_t EltVal = ARM_AM::decodeNEONModImm(ConstVal->getZExtValue(), EltBits);
|
||||
return (EltBits == 8 && EltVal == 0xff);
|
||||
}]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// NEON operand definitions
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -2318,10 +2335,10 @@ defm VTST : N3V_QHS<0, 0, 0b1000, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q,
|
||||
|
||||
// Vector Bitwise Operations.
|
||||
|
||||
def vnot8 : PatFrag<(ops node:$in),
|
||||
(xor node:$in, (bitconvert (v8i8 immAllOnesV)))>;
|
||||
def vnot16 : PatFrag<(ops node:$in),
|
||||
(xor node:$in, (bitconvert (v16i8 immAllOnesV)))>;
|
||||
def vnotd : PatFrag<(ops node:$in),
|
||||
(xor node:$in, (bitconvert (v8i8 NEONimmAllOnesV)))>;
|
||||
def vnotq : PatFrag<(ops node:$in),
|
||||
(xor node:$in, (bitconvert (v16i8 NEONimmAllOnesV)))>;
|
||||
|
||||
|
||||
// VAND : Vector Bitwise AND
|
||||
@ -2347,36 +2364,36 @@ def VBICd : N3VX<0, 0, 0b01, 0b0001, 0, 1, (outs DPR:$dst),
|
||||
(ins DPR:$src1, DPR:$src2), N3RegFrm, IIC_VBINiD,
|
||||
"vbic", "$dst, $src1, $src2", "",
|
||||
[(set DPR:$dst, (v2i32 (and DPR:$src1,
|
||||
(vnot8 DPR:$src2))))]>;
|
||||
(vnotd DPR:$src2))))]>;
|
||||
def VBICq : N3VX<0, 0, 0b01, 0b0001, 1, 1, (outs QPR:$dst),
|
||||
(ins QPR:$src1, QPR:$src2), N3RegFrm, IIC_VBINiQ,
|
||||
"vbic", "$dst, $src1, $src2", "",
|
||||
[(set QPR:$dst, (v4i32 (and QPR:$src1,
|
||||
(vnot16 QPR:$src2))))]>;
|
||||
(vnotq QPR:$src2))))]>;
|
||||
|
||||
// VORN : Vector Bitwise OR NOT
|
||||
def VORNd : N3VX<0, 0, 0b11, 0b0001, 0, 1, (outs DPR:$dst),
|
||||
(ins DPR:$src1, DPR:$src2), N3RegFrm, IIC_VBINiD,
|
||||
"vorn", "$dst, $src1, $src2", "",
|
||||
[(set DPR:$dst, (v2i32 (or DPR:$src1,
|
||||
(vnot8 DPR:$src2))))]>;
|
||||
(vnotd DPR:$src2))))]>;
|
||||
def VORNq : N3VX<0, 0, 0b11, 0b0001, 1, 1, (outs QPR:$dst),
|
||||
(ins QPR:$src1, QPR:$src2), N3RegFrm, IIC_VBINiQ,
|
||||
"vorn", "$dst, $src1, $src2", "",
|
||||
[(set QPR:$dst, (v4i32 (or QPR:$src1,
|
||||
(vnot16 QPR:$src2))))]>;
|
||||
(vnotq QPR:$src2))))]>;
|
||||
|
||||
// VMVN : Vector Bitwise NOT
|
||||
def VMVNd : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 0, 0,
|
||||
(outs DPR:$dst), (ins DPR:$src), IIC_VSUBiD,
|
||||
"vmvn", "$dst, $src", "",
|
||||
[(set DPR:$dst, (v2i32 (vnot8 DPR:$src)))]>;
|
||||
[(set DPR:$dst, (v2i32 (vnotd DPR:$src)))]>;
|
||||
def VMVNq : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 1, 0,
|
||||
(outs QPR:$dst), (ins QPR:$src), IIC_VSUBiD,
|
||||
"vmvn", "$dst, $src", "",
|
||||
[(set QPR:$dst, (v4i32 (vnot16 QPR:$src)))]>;
|
||||
def : Pat<(v2i32 (vnot8 DPR:$src)), (VMVNd DPR:$src)>;
|
||||
def : Pat<(v4i32 (vnot16 QPR:$src)), (VMVNq QPR:$src)>;
|
||||
[(set QPR:$dst, (v4i32 (vnotq QPR:$src)))]>;
|
||||
def : Pat<(v2i32 (vnotd DPR:$src)), (VMVNd DPR:$src)>;
|
||||
def : Pat<(v4i32 (vnotq QPR:$src)), (VMVNq QPR:$src)>;
|
||||
|
||||
// VBSL : Vector Bitwise Select
|
||||
def VBSLd : N3VX<1, 0, 0b01, 0b0001, 0, 1, (outs DPR:$dst),
|
||||
@ -2385,14 +2402,14 @@ def VBSLd : N3VX<1, 0, 0b01, 0b0001, 0, 1, (outs DPR:$dst),
|
||||
"vbsl", "$dst, $src2, $src3", "$src1 = $dst",
|
||||
[(set DPR:$dst,
|
||||
(v2i32 (or (and DPR:$src2, DPR:$src1),
|
||||
(and DPR:$src3, (vnot8 DPR:$src1)))))]>;
|
||||
(and DPR:$src3, (vnotd DPR:$src1)))))]>;
|
||||
def VBSLq : N3VX<1, 0, 0b01, 0b0001, 1, 1, (outs QPR:$dst),
|
||||
(ins QPR:$src1, QPR:$src2, QPR:$src3),
|
||||
N3RegFrm, IIC_VCNTiQ,
|
||||
"vbsl", "$dst, $src2, $src3", "$src1 = $dst",
|
||||
[(set QPR:$dst,
|
||||
(v4i32 (or (and QPR:$src2, QPR:$src1),
|
||||
(and QPR:$src3, (vnot16 QPR:$src1)))))]>;
|
||||
(and QPR:$src3, (vnotq QPR:$src1)))))]>;
|
||||
|
||||
// VBIF : Vector Bitwise Insert if False
|
||||
// like VBSL but with: "vbif $dst, $src3, $src1", "$src2 = $dst",
|
||||
@ -2726,20 +2743,19 @@ defm VQABS : N2VInt_QHS<0b11, 0b11, 0b00, 0b01110, 0,
|
||||
|
||||
// Vector Negate.
|
||||
|
||||
def vneg : PatFrag<(ops node:$in), (sub immAllZerosV, node:$in)>;
|
||||
def vneg8 : PatFrag<(ops node:$in),
|
||||
(sub (bitconvert (v8i8 immAllZerosV)), node:$in)>;
|
||||
def vneg16 : PatFrag<(ops node:$in),
|
||||
(sub (bitconvert (v16i8 immAllZerosV)), node:$in)>;
|
||||
def vnegd : PatFrag<(ops node:$in),
|
||||
(sub (bitconvert (v2i32 NEONimmAllZerosV)), node:$in)>;
|
||||
def vnegq : PatFrag<(ops node:$in),
|
||||
(sub (bitconvert (v4i32 NEONimmAllZerosV)), node:$in)>;
|
||||
|
||||
class VNEGD<bits<2> size, string OpcodeStr, string Dt, ValueType Ty>
|
||||
: N2V<0b11, 0b11, size, 0b01, 0b00111, 0, 0, (outs DPR:$dst), (ins DPR:$src),
|
||||
IIC_VSHLiD, OpcodeStr, Dt, "$dst, $src", "",
|
||||
[(set DPR:$dst, (Ty (vneg8 DPR:$src)))]>;
|
||||
[(set DPR:$dst, (Ty (vnegd DPR:$src)))]>;
|
||||
class VNEGQ<bits<2> size, string OpcodeStr, string Dt, ValueType Ty>
|
||||
: N2V<0b11, 0b11, size, 0b01, 0b00111, 1, 0, (outs QPR:$dst), (ins QPR:$src),
|
||||
IIC_VSHLiD, OpcodeStr, Dt, "$dst, $src", "",
|
||||
[(set QPR:$dst, (Ty (vneg16 QPR:$src)))]>;
|
||||
[(set QPR:$dst, (Ty (vnegq QPR:$src)))]>;
|
||||
|
||||
// VNEG : Vector Negate (integer)
|
||||
def VNEGs8d : VNEGD<0b00, "vneg", "s8", v8i8>;
|
||||
@ -2759,12 +2775,12 @@ def VNEGf32q : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 1, 0,
|
||||
"vneg", "f32", "$dst, $src", "",
|
||||
[(set QPR:$dst, (v4f32 (fneg QPR:$src)))]>;
|
||||
|
||||
def : Pat<(v8i8 (vneg8 DPR:$src)), (VNEGs8d DPR:$src)>;
|
||||
def : Pat<(v4i16 (vneg8 DPR:$src)), (VNEGs16d DPR:$src)>;
|
||||
def : Pat<(v2i32 (vneg8 DPR:$src)), (VNEGs32d DPR:$src)>;
|
||||
def : Pat<(v16i8 (vneg16 QPR:$src)), (VNEGs8q QPR:$src)>;
|
||||
def : Pat<(v8i16 (vneg16 QPR:$src)), (VNEGs16q QPR:$src)>;
|
||||
def : Pat<(v4i32 (vneg16 QPR:$src)), (VNEGs32q QPR:$src)>;
|
||||
def : Pat<(v8i8 (vnegd DPR:$src)), (VNEGs8d DPR:$src)>;
|
||||
def : Pat<(v4i16 (vnegd DPR:$src)), (VNEGs16d DPR:$src)>;
|
||||
def : Pat<(v2i32 (vnegd DPR:$src)), (VNEGs32d DPR:$src)>;
|
||||
def : Pat<(v16i8 (vnegq QPR:$src)), (VNEGs8q QPR:$src)>;
|
||||
def : Pat<(v8i16 (vnegq QPR:$src)), (VNEGs16q QPR:$src)>;
|
||||
def : Pat<(v4i32 (vnegq QPR:$src)), (VNEGs32q QPR:$src)>;
|
||||
|
||||
// VQNEG : Vector Saturating Negate
|
||||
defm VQNEG : N2VInt_QHS<0b11, 0b11, 0b00, 0b01111, 0,
|
||||
@ -2818,74 +2834,42 @@ def VMOVQQQQ : PseudoInst<(outs QQQQPR:$dst), (ins QQQQPR:$src),
|
||||
|
||||
// VMOV : Vector Move (Immediate)
|
||||
|
||||
// VMOV_get_imm8 xform function: convert build_vector to VMOV.i8 imm.
|
||||
def VMOV_get_imm8 : SDNodeXForm<build_vector, [{
|
||||
return ARM::getNEONModImm(N, 1, true, *CurDAG);
|
||||
}]>;
|
||||
def vmovImm8 : PatLeaf<(build_vector), [{
|
||||
return ARM::getNEONModImm(N, 1, true, *CurDAG).getNode() != 0;
|
||||
}], VMOV_get_imm8>;
|
||||
|
||||
// VMOV_get_imm16 xform function: convert build_vector to VMOV.i16 imm.
|
||||
def VMOV_get_imm16 : SDNodeXForm<build_vector, [{
|
||||
return ARM::getNEONModImm(N, 2, true, *CurDAG);
|
||||
}]>;
|
||||
def vmovImm16 : PatLeaf<(build_vector), [{
|
||||
return ARM::getNEONModImm(N, 2, true, *CurDAG).getNode() != 0;
|
||||
}], VMOV_get_imm16>;
|
||||
|
||||
// VMOV_get_imm32 xform function: convert build_vector to VMOV.i32 imm.
|
||||
def VMOV_get_imm32 : SDNodeXForm<build_vector, [{
|
||||
return ARM::getNEONModImm(N, 4, true, *CurDAG);
|
||||
}]>;
|
||||
def vmovImm32 : PatLeaf<(build_vector), [{
|
||||
return ARM::getNEONModImm(N, 4, true, *CurDAG).getNode() != 0;
|
||||
}], VMOV_get_imm32>;
|
||||
|
||||
// VMOV_get_imm64 xform function: convert build_vector to VMOV.i64 imm.
|
||||
def VMOV_get_imm64 : SDNodeXForm<build_vector, [{
|
||||
return ARM::getNEONModImm(N, 8, true, *CurDAG);
|
||||
}]>;
|
||||
def vmovImm64 : PatLeaf<(build_vector), [{
|
||||
return ARM::getNEONModImm(N, 8, true, *CurDAG).getNode() != 0;
|
||||
}], VMOV_get_imm64>;
|
||||
|
||||
let isReMaterializable = 1 in {
|
||||
def VMOVv8i8 : N1ModImm<1, 0b000, 0b1110, 0, 0, 0, 1, (outs DPR:$dst),
|
||||
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||
"vmov", "i8", "$dst, $SIMM", "",
|
||||
[(set DPR:$dst, (v8i8 vmovImm8:$SIMM))]>;
|
||||
[(set DPR:$dst, (v8i8 (NEONvmovImm timm:$SIMM)))]>;
|
||||
def VMOVv16i8 : N1ModImm<1, 0b000, 0b1110, 0, 1, 0, 1, (outs QPR:$dst),
|
||||
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||
"vmov", "i8", "$dst, $SIMM", "",
|
||||
[(set QPR:$dst, (v16i8 vmovImm8:$SIMM))]>;
|
||||
[(set QPR:$dst, (v16i8 (NEONvmovImm timm:$SIMM)))]>;
|
||||
|
||||
def VMOVv4i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 0, 0, 1, (outs DPR:$dst),
|
||||
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||
"vmov", "i16", "$dst, $SIMM", "",
|
||||
[(set DPR:$dst, (v4i16 vmovImm16:$SIMM))]>;
|
||||
[(set DPR:$dst, (v4i16 (NEONvmovImm timm:$SIMM)))]>;
|
||||
def VMOVv8i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 1, 0, 1, (outs QPR:$dst),
|
||||
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||
"vmov", "i16", "$dst, $SIMM", "",
|
||||
[(set QPR:$dst, (v8i16 vmovImm16:$SIMM))]>;
|
||||
[(set QPR:$dst, (v8i16 (NEONvmovImm timm:$SIMM)))]>;
|
||||
|
||||
def VMOVv2i32 : N1ModImm<1, 0b000, {0,?,?,0}, 0, 0, 0, 1, (outs DPR:$dst),
|
||||
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||
"vmov", "i32", "$dst, $SIMM", "",
|
||||
[(set DPR:$dst, (v2i32 vmovImm32:$SIMM))]>;
|
||||
[(set DPR:$dst, (v2i32 (NEONvmovImm timm:$SIMM)))]>;
|
||||
def VMOVv4i32 : N1ModImm<1, 0b000, {0,?,?,0}, 0, 1, 0, 1, (outs QPR:$dst),
|
||||
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||
"vmov", "i32", "$dst, $SIMM", "",
|
||||
[(set QPR:$dst, (v4i32 vmovImm32:$SIMM))]>;
|
||||
[(set QPR:$dst, (v4i32 (NEONvmovImm timm:$SIMM)))]>;
|
||||
|
||||
def VMOVv1i64 : N1ModImm<1, 0b000, 0b1110, 0, 0, 1, 1, (outs DPR:$dst),
|
||||
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||
"vmov", "i64", "$dst, $SIMM", "",
|
||||
[(set DPR:$dst, (v1i64 vmovImm64:$SIMM))]>;
|
||||
[(set DPR:$dst, (v1i64 (NEONvmovImm timm:$SIMM)))]>;
|
||||
def VMOVv2i64 : N1ModImm<1, 0b000, 0b1110, 0, 1, 1, 1, (outs QPR:$dst),
|
||||
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||
"vmov", "i64", "$dst, $SIMM", "",
|
||||
[(set QPR:$dst, (v2i64 vmovImm64:$SIMM))]>;
|
||||
[(set QPR:$dst, (v2i64 (NEONvmovImm timm:$SIMM)))]>;
|
||||
} // isReMaterializable
|
||||
|
||||
// VMOV : Vector Get Lane (move scalar to ARM core register)
|
||||
|
@ -239,7 +239,7 @@ define arm_aapcs_vfpcc float @t9(%0* nocapture, %3* nocapture) nounwind {
|
||||
; CHECK: t9:
|
||||
; CHECK: vldr.64
|
||||
; CHECK-NOT: vmov d{{.*}}, d0
|
||||
; CHECK: vmov.i8 d1
|
||||
; CHECK: vmov.i32 d1
|
||||
; CHECK-NEXT: vstmia r0, {d0, d1}
|
||||
; CHECK-NEXT: vstmia r0, {d0, d1}
|
||||
%3 = bitcast double 0.000000e+00 to <2 x float> ; <<2 x float>> [#uses=2]
|
||||
|
Loading…
Reference in New Issue
Block a user