mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-01 07:30:31 +00:00
Add support for NEON VMVN immediate instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108324 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
046afdb50b
commit
7e3f0d2690
@ -625,6 +625,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case ARMISD::VGETLANEu: return "ARMISD::VGETLANEu";
|
case ARMISD::VGETLANEu: return "ARMISD::VGETLANEu";
|
||||||
case ARMISD::VGETLANEs: return "ARMISD::VGETLANEs";
|
case ARMISD::VGETLANEs: return "ARMISD::VGETLANEs";
|
||||||
case ARMISD::VMOVIMM: return "ARMISD::VMOVIMM";
|
case ARMISD::VMOVIMM: return "ARMISD::VMOVIMM";
|
||||||
|
case ARMISD::VMVNIMM: return "ARMISD::VMVNIMM";
|
||||||
case ARMISD::VDUP: return "ARMISD::VDUP";
|
case ARMISD::VDUP: return "ARMISD::VDUP";
|
||||||
case ARMISD::VDUPLANE: return "ARMISD::VDUPLANE";
|
case ARMISD::VDUPLANE: return "ARMISD::VDUPLANE";
|
||||||
case ARMISD::VEXT: return "ARMISD::VEXT";
|
case ARMISD::VEXT: return "ARMISD::VEXT";
|
||||||
@ -2925,6 +2926,8 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
|
|||||||
|
|
||||||
switch (SplatBitSize) {
|
switch (SplatBitSize) {
|
||||||
case 8:
|
case 8:
|
||||||
|
if (!isVMOV)
|
||||||
|
return SDValue();
|
||||||
// Any 1-byte value is OK. Op=0, Cmode=1110.
|
// Any 1-byte value is OK. Op=0, Cmode=1110.
|
||||||
assert((SplatBits & ~0xff) == 0 && "one byte splat value is too big");
|
assert((SplatBits & ~0xff) == 0 && "one byte splat value is too big");
|
||||||
OpCmode = 0xe;
|
OpCmode = 0xe;
|
||||||
@ -3006,9 +3009,9 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
|
|||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
case 64: {
|
case 64: {
|
||||||
// NEON has a 64-bit VMOV splat where each byte is either 0 or 0xff.
|
|
||||||
if (!isVMOV)
|
if (!isVMOV)
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
// NEON has a 64-bit VMOV splat where each byte is either 0 or 0xff.
|
||||||
uint64_t BitMask = 0xff;
|
uint64_t BitMask = 0xff;
|
||||||
uint64_t Val = 0;
|
uint64_t Val = 0;
|
||||||
unsigned ImmMask = 1;
|
unsigned ImmMask = 1;
|
||||||
@ -3248,6 +3251,17 @@ static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
|||||||
SDValue Vmov = DAG.getNode(ARMISD::VMOVIMM, dl, VmovVT, Val);
|
SDValue Vmov = DAG.getNode(ARMISD::VMOVIMM, dl, VmovVT, Val);
|
||||||
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vmov);
|
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vmov);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try an immediate VMVN.
|
||||||
|
uint64_t NegatedImm = (SplatBits.getZExtValue() ^
|
||||||
|
((1LL << SplatBitSize) - 1));
|
||||||
|
Val = isNEONModifiedImm(NegatedImm,
|
||||||
|
SplatUndef.getZExtValue(), SplatBitSize,
|
||||||
|
DAG, VmovVT, VT.is128BitVector(), false);
|
||||||
|
if (Val.getNode()) {
|
||||||
|
SDValue Vmov = DAG.getNode(ARMISD::VMVNIMM, dl, VmovVT, Val);
|
||||||
|
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vmov);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4232,14 +4246,15 @@ static SDValue PerformVMOVRRDCombine(SDNode *N,
|
|||||||
/// ARMISD::VDUPLANE.
|
/// ARMISD::VDUPLANE.
|
||||||
static SDValue PerformVDUPLANECombine(SDNode *N,
|
static SDValue PerformVDUPLANECombine(SDNode *N,
|
||||||
TargetLowering::DAGCombinerInfo &DCI) {
|
TargetLowering::DAGCombinerInfo &DCI) {
|
||||||
// If the source is already a VMOVIMM splat, the VDUPLANE is redundant.
|
// If the source is already a VMOVIMM or VMVNIMM splat, the VDUPLANE is
|
||||||
|
// redundant.
|
||||||
SDValue Op = N->getOperand(0);
|
SDValue Op = N->getOperand(0);
|
||||||
EVT VT = N->getValueType(0);
|
EVT VT = N->getValueType(0);
|
||||||
|
|
||||||
// Ignore bit_converts.
|
// Ignore bit_converts.
|
||||||
while (Op.getOpcode() == ISD::BIT_CONVERT)
|
while (Op.getOpcode() == ISD::BIT_CONVERT)
|
||||||
Op = Op.getOperand(0);
|
Op = Op.getOperand(0);
|
||||||
if (Op.getOpcode() != ARMISD::VMOVIMM)
|
if (Op.getOpcode() != ARMISD::VMOVIMM && Op.getOpcode() != ARMISD::VMVNIMM)
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
// Make sure the VMOV element size is not bigger than the VDUPLANE elements.
|
// Make sure the VMOV element size is not bigger than the VDUPLANE elements.
|
||||||
|
@ -124,8 +124,11 @@ namespace llvm {
|
|||||||
VGETLANEu, // zero-extend vector extract element
|
VGETLANEu, // zero-extend vector extract element
|
||||||
VGETLANEs, // sign-extend vector extract element
|
VGETLANEs, // sign-extend vector extract element
|
||||||
|
|
||||||
// Vector duplicate:
|
// Vector move immediate and move negated immediate:
|
||||||
VMOVIMM,
|
VMOVIMM,
|
||||||
|
VMVNIMM,
|
||||||
|
|
||||||
|
// Vector duplicate:
|
||||||
VDUP,
|
VDUP,
|
||||||
VDUPLANE,
|
VDUPLANE,
|
||||||
|
|
||||||
|
@ -65,9 +65,10 @@ def SDTARMVGETLN : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisInt<1>,
|
|||||||
def NEONvgetlaneu : SDNode<"ARMISD::VGETLANEu", SDTARMVGETLN>;
|
def NEONvgetlaneu : SDNode<"ARMISD::VGETLANEu", SDTARMVGETLN>;
|
||||||
def NEONvgetlanes : SDNode<"ARMISD::VGETLANEs", SDTARMVGETLN>;
|
def NEONvgetlanes : SDNode<"ARMISD::VGETLANEs", SDTARMVGETLN>;
|
||||||
|
|
||||||
def NEONvmovImm : SDNode<"ARMISD::VMOVIMM",
|
def SDTARMVMOVIMM : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVT<1, i32>]>;
|
||||||
SDTypeProfile<1, 1, [SDTCisVec<0>,
|
def NEONvmovImm : SDNode<"ARMISD::VMOVIMM", SDTARMVMOVIMM>;
|
||||||
SDTCisVT<1, i32>]>>;
|
def NEONvmvnImm : SDNode<"ARMISD::VMVNIMM", SDTARMVMOVIMM>;
|
||||||
|
|
||||||
def NEONvdup : SDNode<"ARMISD::VDUP", SDTypeProfile<1, 1, [SDTCisVec<0>]>>;
|
def NEONvdup : SDNode<"ARMISD::VDUP", SDTypeProfile<1, 1, [SDTCisVec<0>]>>;
|
||||||
|
|
||||||
// VDUPLANE can produce a quad-register result from a double-register source,
|
// VDUPLANE can produce a quad-register result from a double-register source,
|
||||||
@ -2383,6 +2384,28 @@ def VORNq : N3VX<0, 0, 0b11, 0b0001, 1, 1, (outs QPR:$dst),
|
|||||||
[(set QPR:$dst, (v4i32 (or QPR:$src1,
|
[(set QPR:$dst, (v4i32 (or QPR:$src1,
|
||||||
(vnotq QPR:$src2))))]>;
|
(vnotq QPR:$src2))))]>;
|
||||||
|
|
||||||
|
// VMVN : Vector Bitwise NOT (Immediate)
|
||||||
|
|
||||||
|
let isReMaterializable = 1 in {
|
||||||
|
def VMVNv4i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 0, 1, 1, (outs DPR:$dst),
|
||||||
|
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||||
|
"vmvn", "i16", "$dst, $SIMM", "",
|
||||||
|
[(set DPR:$dst, (v4i16 (NEONvmvnImm timm:$SIMM)))]>;
|
||||||
|
def VMVNv8i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 1, 1, 1, (outs QPR:$dst),
|
||||||
|
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||||
|
"vmvn", "i16", "$dst, $SIMM", "",
|
||||||
|
[(set QPR:$dst, (v8i16 (NEONvmvnImm timm:$SIMM)))]>;
|
||||||
|
|
||||||
|
def VMVNv2i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 0, 1, 1, (outs DPR:$dst),
|
||||||
|
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||||
|
"vmvn", "i32", "$dst, $SIMM", "",
|
||||||
|
[(set DPR:$dst, (v2i32 (NEONvmvnImm timm:$SIMM)))]>;
|
||||||
|
def VMVNv4i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 1, 1, 1, (outs QPR:$dst),
|
||||||
|
(ins nModImm:$SIMM), IIC_VMOVImm,
|
||||||
|
"vmvn", "i32", "$dst, $SIMM", "",
|
||||||
|
[(set QPR:$dst, (v4i32 (NEONvmvnImm timm:$SIMM)))]>;
|
||||||
|
}
|
||||||
|
|
||||||
// VMVN : Vector Bitwise NOT
|
// VMVN : Vector Bitwise NOT
|
||||||
def VMVNd : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 0, 0,
|
def VMVNd : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 0, 0,
|
||||||
(outs DPR:$dst), (ins DPR:$src), IIC_VSUBiD,
|
(outs DPR:$dst), (ins DPR:$src), IIC_VSUBiD,
|
||||||
|
@ -18,6 +18,18 @@ define <4 x i16> @v_movi16b() nounwind {
|
|||||||
ret <4 x i16> < i16 4096, i16 4096, i16 4096, i16 4096 >
|
ret <4 x i16> < i16 4096, i16 4096, i16 4096, i16 4096 >
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define <4 x i16> @v_mvni16a() nounwind {
|
||||||
|
;CHECK: v_mvni16a:
|
||||||
|
;CHECK: vmvn.i16 d0, #0x10
|
||||||
|
ret <4 x i16> < i16 65519, i16 65519, i16 65519, i16 65519 >
|
||||||
|
}
|
||||||
|
|
||||||
|
define <4 x i16> @v_mvni16b() nounwind {
|
||||||
|
;CHECK: v_mvni16b:
|
||||||
|
;CHECK: vmvn.i16 d0, #0x1000
|
||||||
|
ret <4 x i16> < i16 61439, i16 61439, i16 61439, i16 61439 >
|
||||||
|
}
|
||||||
|
|
||||||
define <2 x i32> @v_movi32a() nounwind {
|
define <2 x i32> @v_movi32a() nounwind {
|
||||||
;CHECK: v_movi32a:
|
;CHECK: v_movi32a:
|
||||||
;CHECK: vmov.i32 d0, #0x20
|
;CHECK: vmov.i32 d0, #0x20
|
||||||
@ -54,6 +66,42 @@ define <2 x i32> @v_movi32f() nounwind {
|
|||||||
ret <2 x i32> < i32 2162687, i32 2162687 >
|
ret <2 x i32> < i32 2162687, i32 2162687 >
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define <2 x i32> @v_mvni32a() nounwind {
|
||||||
|
;CHECK: v_mvni32a:
|
||||||
|
;CHECK: vmvn.i32 d0, #0x20
|
||||||
|
ret <2 x i32> < i32 4294967263, i32 4294967263 >
|
||||||
|
}
|
||||||
|
|
||||||
|
define <2 x i32> @v_mvni32b() nounwind {
|
||||||
|
;CHECK: v_mvni32b:
|
||||||
|
;CHECK: vmvn.i32 d0, #0x2000
|
||||||
|
ret <2 x i32> < i32 4294959103, i32 4294959103 >
|
||||||
|
}
|
||||||
|
|
||||||
|
define <2 x i32> @v_mvni32c() nounwind {
|
||||||
|
;CHECK: v_mvni32c:
|
||||||
|
;CHECK: vmvn.i32 d0, #0x200000
|
||||||
|
ret <2 x i32> < i32 4292870143, i32 4292870143 >
|
||||||
|
}
|
||||||
|
|
||||||
|
define <2 x i32> @v_mvni32d() nounwind {
|
||||||
|
;CHECK: v_mvni32d:
|
||||||
|
;CHECK: vmvn.i32 d0, #0x20000000
|
||||||
|
ret <2 x i32> < i32 3758096383, i32 3758096383 >
|
||||||
|
}
|
||||||
|
|
||||||
|
define <2 x i32> @v_mvni32e() nounwind {
|
||||||
|
;CHECK: v_mvni32e:
|
||||||
|
;CHECK: vmvn.i32 d0, #0x20FF
|
||||||
|
ret <2 x i32> < i32 4294958848, i32 4294958848 >
|
||||||
|
}
|
||||||
|
|
||||||
|
define <2 x i32> @v_mvni32f() nounwind {
|
||||||
|
;CHECK: v_mvni32f:
|
||||||
|
;CHECK: vmvn.i32 d0, #0x20FFFF
|
||||||
|
ret <2 x i32> < i32 4292804608, i32 4292804608 >
|
||||||
|
}
|
||||||
|
|
||||||
define <1 x i64> @v_movi64() nounwind {
|
define <1 x i64> @v_movi64() nounwind {
|
||||||
;CHECK: v_movi64:
|
;CHECK: v_movi64:
|
||||||
;CHECK: vmov.i64 d0, #0xFF0000FF0000FFFF
|
;CHECK: vmov.i64 d0, #0xFF0000FF0000FFFF
|
||||||
|
Loading…
Reference in New Issue
Block a user