case ARMISD::VST2D: return "ARMISD::VST2D";
case ARMISD::VST3D: return "ARMISD::VST3D";
case ARMISD::VST4D: return "ARMISD::VST4D";
+ case ARMISD::VREV64: return "ARMISD::VREV64";
+ case ARMISD::VREV32: return "ARMISD::VREV32";
+ case ARMISD::VREV16: return "ARMISD::VREV16";
}
}
/// isVREVMask - Check if a vector shuffle corresponds to a VREV
/// instruction with the specified blocksize. (The order of the elements
/// within each block of the vector is reversed.)
-bool ARM::isVREVMask(ShuffleVectorSDNode *N, unsigned BlockSize) {
+static bool isVREVMask(ShuffleVectorSDNode *N, unsigned BlockSize) {
assert((BlockSize==16 || BlockSize==32 || BlockSize==64) &&
"Only possible block sizes for VREV are: 16, 32, 64");
}
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
+ ShuffleVectorSDNode *SVN = dyn_cast<ShuffleVectorSDNode>(Op.getNode());
+ assert(SVN != 0 && "Expected a ShuffleVectorSDNode in LowerVECTOR_SHUFFLE");
+ DebugLoc dl = Op.getDebugLoc();
+ EVT VT = Op.getValueType();
+
+ if (isVREVMask(SVN, 64))
+ return DAG.getNode(ARMISD::VREV64, dl, VT, SVN->getOperand(0));
+ if (isVREVMask(SVN, 32))
+ return DAG.getNode(ARMISD::VREV32, dl, VT, SVN->getOperand(0));
+ if (isVREVMask(SVN, 16))
+ return DAG.getNode(ARMISD::VREV16, dl, VT, SVN->getOperand(0));
+
return Op;
}
def NEONvst4d : SDNode<"ARMISD::VST4D", SDTARMVST4,
[SDNPHasChain, SDNPMayStore]>;
+def SDTARMVSHUF : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0, 1>]>;
+def NEONvrev64 : SDNode<"ARMISD::VREV64", SDTARMVSHUF>;
+def NEONvrev32 : SDNode<"ARMISD::VREV32", SDTARMVSHUF>;
+def NEONvrev16 : SDNode<"ARMISD::VREV16", SDTARMVSHUF>;
+
//===----------------------------------------------------------------------===//
// NEON operand definitions
//===----------------------------------------------------------------------===//
def VCVTxu2fq : N2VCvtQ<1, 1, 0b000000, 0b1110, 0, 1, "vcvt.f32.u32",
v4f32, v4i32, int_arm_neon_vcvtfxu2fp>;
-// VREV : Vector Reverse
-
-def vrev64_shuffle : PatFrag<(ops node:$in),
- (vector_shuffle node:$in, undef), [{
- ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
- return ARM::isVREVMask(SVOp, 64);
-}]>;
-
-def vrev32_shuffle : PatFrag<(ops node:$in),
- (vector_shuffle node:$in, undef), [{
- ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
- return ARM::isVREVMask(SVOp, 32);
-}]>;
-
-def vrev16_shuffle : PatFrag<(ops node:$in),
- (vector_shuffle node:$in, undef), [{
- ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N);
- return ARM::isVREVMask(SVOp, 16);
-}]>;
+// Vector Reverse.
// VREV64 : Vector Reverse elements within 64-bit doublewords
: N2V<0b11, 0b11, op19_18, 0b00, 0b00000, 0, 0, (outs DPR:$dst),
(ins DPR:$src), NoItinerary,
!strconcat(OpcodeStr, "\t$dst, $src"), "",
- [(set DPR:$dst, (Ty (vrev64_shuffle (Ty DPR:$src))))]>;
+ [(set DPR:$dst, (Ty (NEONvrev64 (Ty DPR:$src))))]>;
class VREV64Q<bits<2> op19_18, string OpcodeStr, ValueType Ty>
: N2V<0b11, 0b11, op19_18, 0b00, 0b00000, 1, 0, (outs QPR:$dst),
(ins QPR:$src), NoItinerary,
!strconcat(OpcodeStr, "\t$dst, $src"), "",
- [(set QPR:$dst, (Ty (vrev64_shuffle (Ty QPR:$src))))]>;
+ [(set QPR:$dst, (Ty (NEONvrev64 (Ty QPR:$src))))]>;
def VREV64d8 : VREV64D<0b00, "vrev64.8", v8i8>;
def VREV64d16 : VREV64D<0b01, "vrev64.16", v4i16>;
: N2V<0b11, 0b11, op19_18, 0b00, 0b00001, 0, 0, (outs DPR:$dst),
(ins DPR:$src), NoItinerary,
!strconcat(OpcodeStr, "\t$dst, $src"), "",
- [(set DPR:$dst, (Ty (vrev32_shuffle (Ty DPR:$src))))]>;
+ [(set DPR:$dst, (Ty (NEONvrev32 (Ty DPR:$src))))]>;
class VREV32Q<bits<2> op19_18, string OpcodeStr, ValueType Ty>
: N2V<0b11, 0b11, op19_18, 0b00, 0b00001, 1, 0, (outs QPR:$dst),
(ins QPR:$src), NoItinerary,
!strconcat(OpcodeStr, "\t$dst, $src"), "",
- [(set QPR:$dst, (Ty (vrev32_shuffle (Ty QPR:$src))))]>;
+ [(set QPR:$dst, (Ty (NEONvrev32 (Ty QPR:$src))))]>;
def VREV32d8 : VREV32D<0b00, "vrev32.8", v8i8>;
def VREV32d16 : VREV32D<0b01, "vrev32.16", v4i16>;
: N2V<0b11, 0b11, op19_18, 0b00, 0b00010, 0, 0, (outs DPR:$dst),
(ins DPR:$src), NoItinerary,
!strconcat(OpcodeStr, "\t$dst, $src"), "",
- [(set DPR:$dst, (Ty (vrev16_shuffle (Ty DPR:$src))))]>;
+ [(set DPR:$dst, (Ty (NEONvrev16 (Ty DPR:$src))))]>;
class VREV16Q<bits<2> op19_18, string OpcodeStr, ValueType Ty>
: N2V<0b11, 0b11, op19_18, 0b00, 0b00010, 1, 0, (outs QPR:$dst),
(ins QPR:$src), NoItinerary,
!strconcat(OpcodeStr, "\t$dst, $src"), "",
- [(set QPR:$dst, (Ty (vrev16_shuffle (Ty QPR:$src))))]>;
+ [(set QPR:$dst, (Ty (NEONvrev16 (Ty QPR:$src))))]>;
def VREV16d8 : VREV16D<0b00, "vrev16.8", v8i8>;
def VREV16q8 : VREV16Q<0b00, "vrev16.8", v16i8>;