From: Bob Wilson Date: Wed, 12 Aug 2009 22:31:50 +0000 (+0000) Subject: Recognize Neon VREV shuffles during legalization instead of selection. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=d8e1757eacbcbae6657558f40fdada4279a9d1ed;p=oota-llvm.git Recognize Neon VREV shuffles during legalization instead of selection. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78850 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 0d2d7d2ad40..f348fe20210 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -484,6 +484,9 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { 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"; } } @@ -2336,7 +2339,7 @@ SDValue ARM::getVMOVImm(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) { /// 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"); @@ -2432,6 +2435,18 @@ static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) { } static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { + ShuffleVectorSDNode *SVN = dyn_cast(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; } diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 648d388037a..328959a24d9 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -124,7 +124,12 @@ namespace llvm { VLD4D, VST2D, VST3D, - VST4D + VST4D, + + // Vector shuffles: + VREV64, // reverse elements within 64-bit doublewords + VREV32, // reverse elements within 32-bit words + VREV16 // reverse elements within 16-bit halfwords }; } @@ -135,11 +140,6 @@ namespace llvm { /// return the constant being splatted. The ByteSize field indicates the /// number of bytes of each element [1248]. SDValue getVMOVImm(SDNode *N, unsigned ByteSize, SelectionDAG &DAG); - - /// 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 isVREVMask(ShuffleVectorSDNode *N, unsigned blocksize); } //===--------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 9eb11603b50..7654be7b3fd 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -95,6 +95,11 @@ def NEONvst3d : SDNode<"ARMISD::VST3D", SDTARMVST3, 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 //===----------------------------------------------------------------------===// @@ -1881,25 +1886,7 @@ def VCVTxs2fq : N2VCvtQ<0, 1, 0b000000, 0b1110, 0, 1, "vcvt.f32.s32", 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(N); - return ARM::isVREVMask(SVOp, 64); -}]>; - -def vrev32_shuffle : PatFrag<(ops node:$in), - (vector_shuffle node:$in, undef), [{ - ShuffleVectorSDNode *SVOp = cast(N); - return ARM::isVREVMask(SVOp, 32); -}]>; - -def vrev16_shuffle : PatFrag<(ops node:$in), - (vector_shuffle node:$in, undef), [{ - ShuffleVectorSDNode *SVOp = cast(N); - return ARM::isVREVMask(SVOp, 16); -}]>; +// Vector Reverse. // VREV64 : Vector Reverse elements within 64-bit doublewords @@ -1907,12 +1894,12 @@ class VREV64D op19_18, string OpcodeStr, ValueType Ty> : 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 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>; @@ -1930,12 +1917,12 @@ class VREV32D op19_18, string OpcodeStr, ValueType Ty> : 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 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>; @@ -1949,12 +1936,12 @@ class VREV16D op19_18, string OpcodeStr, ValueType Ty> : 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 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>;