From 86b4972a7026ac350fe1066ef2b6495bb2a6fbcc Mon Sep 17 00:00:00 2001 From: David Green Date: Mon, 15 Jul 2019 11:22:05 +0000 Subject: [PATCH] [ARM] Move Shifts after Bits. NFC This just moves the shift instruction definitions further down the ARMInstrMVE.td file, to make positioning patterns slightly more natural. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366054 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrMVE.td | 2249 +++++++++++++++++---------------- 1 file changed, 1125 insertions(+), 1124 deletions(-) diff --git a/lib/Target/ARM/ARMInstrMVE.td b/lib/Target/ARM/ARMInstrMVE.td index 10ed876f484..9eec9a6f096 100644 --- a/lib/Target/ARM/ARMInstrMVE.td +++ b/lib/Target/ARM/ARMInstrMVE.td @@ -939,30 +939,11 @@ let Predicates = [HasMVEInt] in { // end of mve_comp instructions -// start of mve_imm_shift instructions - -def MVE_VSHLC : MVE_p<(outs rGPR:$RdmDest, MQPR:$Qd), - (ins MQPR:$QdSrc, rGPR:$RdmSrc, long_shift:$imm), - NoItinerary, "vshlc", "", "$QdSrc, $RdmSrc, $imm", - vpred_n, "$RdmDest = $RdmSrc,$Qd = $QdSrc"> { - bits<5> imm; - bits<4> Qd; - bits<4> RdmDest; - - let Inst{28} = 0b0; - let Inst{25-23} = 0b101; - let Inst{22} = Qd{3}; - let Inst{21} = 0b1; - let Inst{20-16} = imm{4-0}; - let Inst{15-13} = Qd{2-0}; - let Inst{12-4} = 0b011111100; - let Inst{3-0} = RdmDest{3-0}; -} +// start of mve_bit instructions -class MVE_shift_imm pattern=[]> - : MVE_p { +class MVE_bit_arith pattern=[]> + : MVE_p { bits<4> Qd; bits<4> Qm; @@ -972,1378 +953,1398 @@ class MVE_shift_imm sz, bit U, - list pattern=[]> - : MVE_shift_imm<(outs MQPR:$Qd), (ins MQPR:$Qm), - iname, suffix, "$Qd, $Qm", vpred_r, "", - pattern> { - let Inst{28} = U; - let Inst{25-23} = 0b101; - let Inst{21} = 0b1; - let Inst{20-19} = sz{1-0}; - let Inst{18-16} = 0b000; - let Inst{11-6} = 0b111101; - let Inst{4} = 0b0; +def MVE_VBIC : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), + "vbic", "", "$Qd, $Qn, $Qm", ""> { + bits<4> Qn; + + let Inst{28} = 0b0; + let Inst{25-23} = 0b110; + let Inst{21-20} = 0b01; + let Inst{19-17} = Qn{2-0}; + let Inst{16} = 0b0; + let Inst{12-8} = 0b00001; + let Inst{7} = Qn{3}; + let Inst{6} = 0b1; + let Inst{4} = 0b1; let Inst{0} = 0b0; } -multiclass MVE_VMOVL_shift_half sz, bit U, - list pattern=[]> { - def bh : MVE_VMOVL { - let Inst{12} = 0b0; - } - def th : MVE_VMOVL { - let Inst{12} = 0b1; - } +class MVE_VREV size, bits<2> bit_8_7> + : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qm), iname, + suffix, "$Qd, $Qm", ""> { + + let Inst{28} = 0b1; + let Inst{25-23} = 0b111; + let Inst{21-20} = 0b11; + let Inst{19-18} = size; + let Inst{17-16} = 0b00; + let Inst{12-9} = 0b0000; + let Inst{8-7} = bit_8_7; + let Inst{6} = 0b1; + let Inst{4} = 0b0; + let Inst{0} = 0b0; } -defm MVE_VMOVLs8 : MVE_VMOVL_shift_half<"vmovl", "s8", 0b01, 0b0>; -defm MVE_VMOVLu8 : MVE_VMOVL_shift_half<"vmovl", "u8", 0b01, 0b1>; -defm MVE_VMOVLs16 : MVE_VMOVL_shift_half<"vmovl", "s16", 0b10, 0b0>; -defm MVE_VMOVLu16 : MVE_VMOVL_shift_half<"vmovl", "u16", 0b10, 0b1>; +def MVE_VREV64_8 : MVE_VREV<"vrev64", "8", 0b00, 0b00>; +def MVE_VREV64_16 : MVE_VREV<"vrev64", "16", 0b01, 0b00>; +def MVE_VREV64_32 : MVE_VREV<"vrev64", "32", 0b10, 0b00>; + +def MVE_VREV32_8 : MVE_VREV<"vrev32", "8", 0b00, 0b01>; +def MVE_VREV32_16 : MVE_VREV<"vrev32", "16", 0b01, 0b01>; + +def MVE_VREV16_8 : MVE_VREV<"vrev16", "8", 0b00, 0b10>; let Predicates = [HasMVEInt] in { - def : Pat<(sext_inreg (v4i32 MQPR:$src), v4i16), - (MVE_VMOVLs16bh MQPR:$src)>; - def : Pat<(sext_inreg (v8i16 MQPR:$src), v8i8), - (MVE_VMOVLs8bh MQPR:$src)>; - def : Pat<(sext_inreg (v4i32 MQPR:$src), v4i8), - (MVE_VMOVLs16bh (MVE_VMOVLs8bh MQPR:$src))>; +def : Pat<(v4i32 (ARMvrev64 (v4i32 MQPR:$src))), + (v4i32 (MVE_VREV64_32 (v4i32 MQPR:$src)))>; +def : Pat<(v8i16 (ARMvrev64 (v8i16 MQPR:$src))), + (v8i16 (MVE_VREV64_16 (v8i16 MQPR:$src)))>; +def : Pat<(v16i8 (ARMvrev64 (v16i8 MQPR:$src))), + (v16i8 (MVE_VREV64_8 (v16i8 MQPR:$src)))>; - // zext_inreg 16 -> 32 - def : Pat<(and (v4i32 MQPR:$src), (v4i32 (ARMvmovImm (i32 0xCFF)))), - (MVE_VMOVLu16bh MQPR:$src)>; - // zext_inreg 8 -> 16 - def : Pat<(and (v8i16 MQPR:$src), (v8i16 (ARMvmovImm (i32 0x8FF)))), - (MVE_VMOVLu8bh MQPR:$src)>; -} +def : Pat<(v8i16 (ARMvrev32 (v8i16 MQPR:$src))), + (v8i16 (MVE_VREV32_16 (v8i16 MQPR:$src)))>; +def : Pat<(v16i8 (ARMvrev32 (v16i8 MQPR:$src))), + (v16i8 (MVE_VREV32_8 (v16i8 MQPR:$src)))>; +def : Pat<(v16i8 (ARMvrev16 (v16i8 MQPR:$src))), + (v16i8 (MVE_VREV16_8 (v16i8 MQPR:$src)))>; -class MVE_VSHLL_imm pattern=[]> - : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$Qm), immops), - iname, suffix, "$Qd, $Qm, $imm", vpred_r, "", pattern> { - let Inst{28} = U; - let Inst{25-23} = 0b101; - let Inst{21} = 0b1; - let Inst{12} = th; - let Inst{11-6} = 0b111101; +def : Pat<(v4f32 (ARMvrev64 (v4f32 MQPR:$src))), + (v4f32 (MVE_VREV64_32 (v4f32 MQPR:$src)))>; +def : Pat<(v8f16 (ARMvrev64 (v8f16 MQPR:$src))), + (v8f16 (MVE_VREV64_16 (v8f16 MQPR:$src)))>; +def : Pat<(v8f16 (ARMvrev32 (v8f16 MQPR:$src))), + (v8f16 (MVE_VREV32_16 (v8f16 MQPR:$src)))>; +} + +def MVE_VMVN : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qm), + "vmvn", "", "$Qd, $Qm", ""> { + let Inst{28} = 0b1; + let Inst{25-23} = 0b111; + let Inst{21-16} = 0b110000; + let Inst{12-6} = 0b0010111; let Inst{4} = 0b0; let Inst{0} = 0b0; } -// The immediate VSHLL instructions accept shift counts from 1 up to -// the lane width (8 or 16), but the full-width shifts have an -// entirely separate encoding, given below with 'lw' in the name. - -class MVE_VSHLL_imm8 pattern=[]> - : MVE_VSHLL_imm { - bits<3> imm; - let Inst{20-19} = 0b01; - let Inst{18-16} = imm; +let Predicates = [HasMVEInt] in { + def : Pat<(v16i8 (vnotq (v16i8 MQPR:$val1))), + (v16i8 (MVE_VMVN (v16i8 MQPR:$val1)))>; + def : Pat<(v8i16 (vnotq (v8i16 MQPR:$val1))), + (v8i16 (MVE_VMVN (v8i16 MQPR:$val1)))>; + def : Pat<(v4i32 (vnotq (v4i32 MQPR:$val1))), + (v4i32 (MVE_VMVN (v4i32 MQPR:$val1)))>; } -class MVE_VSHLL_imm16 pattern=[]> - : MVE_VSHLL_imm { - bits<4> imm; - let Inst{20} = 0b1; - let Inst{19-16} = imm; +class MVE_bit_ops bit_21_20, bit bit_28> + : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), + iname, "", "$Qd, $Qn, $Qm", ""> { + bits<4> Qn; + + let Inst{28} = bit_28; + let Inst{25-23} = 0b110; + let Inst{21-20} = bit_21_20; + let Inst{19-17} = Qn{2-0}; + let Inst{16} = 0b0; + let Inst{12-8} = 0b00001; + let Inst{7} = Qn{3}; + let Inst{6} = 0b1; + let Inst{4} = 0b1; + let Inst{0} = 0b0; } -def MVE_VSHLL_imms8bh : MVE_VSHLL_imm8 <"vshllb", "s8", 0b0, 0b0>; -def MVE_VSHLL_imms8th : MVE_VSHLL_imm8 <"vshllt", "s8", 0b0, 0b1>; -def MVE_VSHLL_immu8bh : MVE_VSHLL_imm8 <"vshllb", "u8", 0b1, 0b0>; -def MVE_VSHLL_immu8th : MVE_VSHLL_imm8 <"vshllt", "u8", 0b1, 0b1>; -def MVE_VSHLL_imms16bh : MVE_VSHLL_imm16<"vshllb", "s16", 0b0, 0b0>; -def MVE_VSHLL_imms16th : MVE_VSHLL_imm16<"vshllt", "s16", 0b0, 0b1>; -def MVE_VSHLL_immu16bh : MVE_VSHLL_imm16<"vshllb", "u16", 0b1, 0b0>; -def MVE_VSHLL_immu16th : MVE_VSHLL_imm16<"vshllt", "u16", 0b1, 0b1>; +def MVE_VEOR : MVE_bit_ops<"veor", 0b00, 0b1>; +def MVE_VORN : MVE_bit_ops<"vorn", 0b11, 0b0>; +def MVE_VORR : MVE_bit_ops<"vorr", 0b10, 0b0>; +def MVE_VAND : MVE_bit_ops<"vand", 0b00, 0b0>; -class MVE_VSHLL_by_lane_width size, - bit U, string ops, list pattern=[]> - : MVE_shift_imm<(outs MQPR:$Qd), (ins MQPR:$Qm), - iname, suffix, ops, vpred_r, "", pattern> { - let Inst{28} = U; - let Inst{25-23} = 0b100; - let Inst{21-20} = 0b11; - let Inst{19-18} = size{1-0}; - let Inst{17-16} = 0b01; - let Inst{11-6} = 0b111000; - let Inst{4} = 0b0; - let Inst{0} = 0b1; -} +// add ignored suffixes as aliases -multiclass MVE_VSHLL_lw sz, bit U, - string ops, list pattern=[]> { - def bh : MVE_VSHLL_by_lane_width { - let Inst{12} = 0b0; - } - def th : MVE_VSHLL_by_lane_width { - let Inst{12} = 0b1; - } +foreach s=["s8", "s16", "s32", "u8", "u16", "u32", "i8", "i16", "i32", "f16", "f32"] in { + def : MVEInstAlias<"vbic${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", + (MVE_VBIC MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; + def : MVEInstAlias<"veor${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", + (MVE_VEOR MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; + def : MVEInstAlias<"vorn${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", + (MVE_VORN MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; + def : MVEInstAlias<"vorr${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", + (MVE_VORR MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; + def : MVEInstAlias<"vand${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", + (MVE_VAND MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; } -defm MVE_VSHLL_lws8 : MVE_VSHLL_lw<"vshll", "s8", 0b00, 0b0, "$Qd, $Qm, #8">; -defm MVE_VSHLL_lws16 : MVE_VSHLL_lw<"vshll", "s16", 0b01, 0b0, "$Qd, $Qm, #16">; -defm MVE_VSHLL_lwu8 : MVE_VSHLL_lw<"vshll", "u8", 0b00, 0b1, "$Qd, $Qm, #8">; -defm MVE_VSHLL_lwu16 : MVE_VSHLL_lw<"vshll", "u16", 0b01, 0b1, "$Qd, $Qm, #16">; +let Predicates = [HasMVEInt] in { + def : Pat<(v16i8 (and (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), + (v16i8 (MVE_VAND (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; + def : Pat<(v8i16 (and (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), + (v8i16 (MVE_VAND (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; + def : Pat<(v4i32 (and (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), + (v4i32 (MVE_VAND (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; -class MVE_VxSHRN pattern=[]> - : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops), - iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc", - pattern> { - bits<5> imm; + def : Pat<(v16i8 (or (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), + (v16i8 (MVE_VORR (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; + def : Pat<(v8i16 (or (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), + (v8i16 (MVE_VORR (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; + def : Pat<(v4i32 (or (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), + (v4i32 (MVE_VORR (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; - let Inst{28} = bit_28; - let Inst{25-23} = 0b101; - let Inst{21} = 0b0; - let Inst{20-16} = imm{4-0}; - let Inst{12} = bit_12; - let Inst{11-6} = 0b111111; - let Inst{4} = 0b0; - let Inst{0} = 0b1; -} + def : Pat<(v16i8 (xor (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), + (v16i8 (MVE_VEOR (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; + def : Pat<(v8i16 (xor (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), + (v8i16 (MVE_VEOR (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; + def : Pat<(v4i32 (xor (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), + (v4i32 (MVE_VEOR (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; -def MVE_VRSHRNi16bh : MVE_VxSHRN< - "vrshrnb", "i16", 0b0, 0b1, (ins shr_imm8:$imm)> { - let Inst{20-19} = 0b01; -} -def MVE_VRSHRNi16th : MVE_VxSHRN< - "vrshrnt", "i16", 0b1, 0b1,(ins shr_imm8:$imm)> { - let Inst{20-19} = 0b01; -} -def MVE_VRSHRNi32bh : MVE_VxSHRN< - "vrshrnb", "i32", 0b0, 0b1, (ins shr_imm16:$imm)> { - let Inst{20} = 0b1; -} -def MVE_VRSHRNi32th : MVE_VxSHRN< - "vrshrnt", "i32", 0b1, 0b1, (ins shr_imm16:$imm)> { - let Inst{20} = 0b1; -} + def : Pat<(v16i8 (and (v16i8 MQPR:$val1), (vnotq MQPR:$val2))), + (v16i8 (MVE_VBIC (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; + def : Pat<(v8i16 (and (v8i16 MQPR:$val1), (vnotq MQPR:$val2))), + (v8i16 (MVE_VBIC (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; + def : Pat<(v4i32 (and (v4i32 MQPR:$val1), (vnotq MQPR:$val2))), + (v4i32 (MVE_VBIC (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; -def MVE_VSHRNi16bh : MVE_VxSHRN< - "vshrnb", "i16", 0b0, 0b0, (ins shr_imm8:$imm)> { - let Inst{20-19} = 0b01; -} -def MVE_VSHRNi16th : MVE_VxSHRN< - "vshrnt", "i16", 0b1, 0b0, (ins shr_imm8:$imm)> { - let Inst{20-19} = 0b01; + def : Pat<(v16i8 (or (v16i8 MQPR:$val1), (vnotq (v16i8 MQPR:$val2)))), + (v16i8 (MVE_VORN (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; + def : Pat<(v8i16 (or (v8i16 MQPR:$val1), (vnotq MQPR:$val2))), + (v8i16 (MVE_VORN (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; + def : Pat<(v4i32 (or (v4i32 MQPR:$val1), (vnotq MQPR:$val2))), + (v4i32 (MVE_VORN (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; } -def MVE_VSHRNi32bh : MVE_VxSHRN< - "vshrnb", "i32", 0b0, 0b0, (ins shr_imm16:$imm)> { - let Inst{20} = 0b1; + +class MVE_bit_cmode cmode, dag inOps> + : MVE_p<(outs MQPR:$Qd), inOps, NoItinerary, + iname, suffix, "$Qd, $imm", vpred_n, "$Qd = $Qd_src"> { + bits<8> imm; + bits<4> Qd; + + let Inst{28} = imm{7}; + let Inst{27-23} = 0b11111; + let Inst{22} = Qd{3}; + let Inst{21-19} = 0b000; + let Inst{18-16} = imm{6-4}; + let Inst{15-13} = Qd{2-0}; + let Inst{12} = 0b0; + let Inst{11-8} = cmode; + let Inst{7-6} = 0b01; + let Inst{4} = 0b1; + let Inst{3-0} = imm{3-0}; } -def MVE_VSHRNi32th : MVE_VxSHRN< - "vshrnt", "i32", 0b1, 0b0, (ins shr_imm16:$imm)> { - let Inst{20} = 0b1; + +class MVE_VORR cmode, ExpandImm imm_type> + : MVE_bit_cmode<"vorr", suffix, cmode, (ins MQPR:$Qd_src, imm_type:$imm)> { + let Inst{5} = 0b0; } -class MVE_VxQRSHRUN pattern=[]> - : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops), - iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc", - pattern> { - bits<5> imm; +def MVE_VORRIZ0v4i32 : MVE_VORR<"i32", 0b0001, expzero00>; +def MVE_VORRIZ0v8i16 : MVE_VORR<"i16", 0b1001, expzero00>; +def MVE_VORRIZ8v4i32 : MVE_VORR<"i32", 0b0011, expzero08>; +def MVE_VORRIZ8v8i16 : MVE_VORR<"i16", 0b1011, expzero08>; +def MVE_VORRIZ16v4i32 : MVE_VORR<"i32", 0b0101, expzero16>; +def MVE_VORRIZ24v4i32 : MVE_VORR<"i32", 0b0111, expzero24>; - let Inst{28} = bit_28; - let Inst{25-23} = 0b101; - let Inst{21} = 0b0; - let Inst{20-16} = imm{4-0}; - let Inst{12} = bit_12; - let Inst{11-6} = 0b111111; - let Inst{4} = 0b0; - let Inst{0} = 0b0; -} +def MVE_VORNIZ0v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm", + (ins MQPR:$Qd_src, expzero00inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; +def MVE_VORNIZ0v8i16 : MVEAsmPseudo<"vorn${vp}.i16\t$Qd, $imm", + (ins MQPR:$Qd_src, expzero00inv16:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; +def MVE_VORNIZ8v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm", + (ins MQPR:$Qd_src, expzero08inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; +def MVE_VORNIZ8v8i16 : MVEAsmPseudo<"vorn${vp}.i16\t$Qd, $imm", + (ins MQPR:$Qd_src, expzero08inv16:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; +def MVE_VORNIZ16v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm", + (ins MQPR:$Qd_src, expzero16inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; +def MVE_VORNIZ24v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm", + (ins MQPR:$Qd_src, expzero24inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; -def MVE_VQRSHRUNs16bh : MVE_VxQRSHRUN< - "vqrshrunb", "s16", 0b1, 0b0, (ins shr_imm8:$imm)> { - let Inst{20-19} = 0b01; +def MVE_VMOV : MVEInstAlias<"vmov${vp}\t$Qd, $Qm", + (MVE_VORR MQPR:$Qd, MQPR:$Qm, MQPR:$Qm, vpred_r:$vp)>; + +class MVE_VBIC cmode, ExpandImm imm_type> + : MVE_bit_cmode<"vbic", suffix, cmode, (ins MQPR:$Qd_src, imm_type:$imm)> { + let Inst{5} = 0b1; } -def MVE_VQRSHRUNs16th : MVE_VxQRSHRUN< - "vqrshrunt", "s16", 0b1, 0b1, (ins shr_imm8:$imm)> { - let Inst{20-19} = 0b01; + +def MVE_VBICIZ0v4i32 : MVE_VBIC<"i32", 0b0001, expzero00>; +def MVE_VBICIZ0v8i16 : MVE_VBIC<"i16", 0b1001, expzero00>; +def MVE_VBICIZ8v4i32 : MVE_VBIC<"i32", 0b0011, expzero08>; +def MVE_VBICIZ8v8i16 : MVE_VBIC<"i16", 0b1011, expzero08>; +def MVE_VBICIZ16v4i32 : MVE_VBIC<"i32", 0b0101, expzero16>; +def MVE_VBICIZ24v4i32 : MVE_VBIC<"i32", 0b0111, expzero24>; + +def MVE_VANDIZ0v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm", + (ins MQPR:$Qda_src, expzero00inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; +def MVE_VANDIZ0v8i16 : MVEAsmPseudo<"vand${vp}.i16\t$Qda, $imm", + (ins MQPR:$Qda_src, expzero00inv16:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; +def MVE_VANDIZ8v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm", + (ins MQPR:$Qda_src, expzero08inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; +def MVE_VANDIZ8v8i16 : MVEAsmPseudo<"vand${vp}.i16\t$Qda, $imm", + (ins MQPR:$Qda_src, expzero08inv16:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; +def MVE_VANDIZ16v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm", + (ins MQPR:$Qda_src, expzero16inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; +def MVE_VANDIZ24v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm", + (ins MQPR:$Qda_src, expzero24inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; + +class MVE_VMOV_lane_direction { + bit bit_20; + dag oops; + dag iops; + string ops; + string cstr; } -def MVE_VQRSHRUNs32bh : MVE_VxQRSHRUN< - "vqrshrunb", "s32", 0b1, 0b0, (ins shr_imm16:$imm)> { - let Inst{20} = 0b1; +def MVE_VMOV_from_lane : MVE_VMOV_lane_direction { + let bit_20 = 0b1; + let oops = (outs rGPR:$Rt); + let iops = (ins MQPR:$Qd); + let ops = "$Rt, $Qd$Idx"; + let cstr = ""; } -def MVE_VQRSHRUNs32th : MVE_VxQRSHRUN< - "vqrshrunt", "s32", 0b1, 0b1, (ins shr_imm16:$imm)> { - let Inst{20} = 0b1; +def MVE_VMOV_to_lane : MVE_VMOV_lane_direction { + let bit_20 = 0b0; + let oops = (outs MQPR:$Qd); + let iops = (ins MQPR:$Qd_src, rGPR:$Rt); + let ops = "$Qd$Idx, $Rt"; + let cstr = "$Qd = $Qd_src"; } -def MVE_VQSHRUNs16bh : MVE_VxQRSHRUN< - "vqshrunb", "s16", 0b0, 0b0, (ins shr_imm8:$imm)> { - let Inst{20-19} = 0b01; +class MVE_VMOV_lane + : MVE_VMOV_lane_base { + bits<4> Qd; + bits<4> Rt; + + let Inst{31-24} = 0b11101110; + let Inst{23} = U; + let Inst{20} = dir.bit_20; + let Inst{19-17} = Qd{2-0}; + let Inst{15-12} = Rt{3-0}; + let Inst{11-8} = 0b1011; + let Inst{7} = Qd{3}; + let Inst{4-0} = 0b10000; } -def MVE_VQSHRUNs16th : MVE_VxQRSHRUN< - "vqshrunt", "s16", 0b0, 0b1, (ins shr_imm8:$imm)> { - let Inst{20-19} = 0b01; + +class MVE_VMOV_lane_32 + : MVE_VMOV_lane<"32", 0b0, (ins MVEVectorIndex<4>:$Idx), dir> { + bits<2> Idx; + let Inst{22} = 0b0; + let Inst{6-5} = 0b00; + let Inst{16} = Idx{1}; + let Inst{21} = Idx{0}; + + let Predicates = [HasFPRegsV8_1M]; } -def MVE_VQSHRUNs32bh : MVE_VxQRSHRUN< - "vqshrunb", "s32", 0b0, 0b0, (ins shr_imm16:$imm)> { - let Inst{20} = 0b1; + +class MVE_VMOV_lane_16 + : MVE_VMOV_lane:$Idx), dir> { + bits<3> Idx; + let Inst{22} = 0b0; + let Inst{5} = 0b1; + let Inst{16} = Idx{2}; + let Inst{21} = Idx{1}; + let Inst{6} = Idx{0}; } -def MVE_VQSHRUNs32th : MVE_VxQRSHRUN< - "vqshrunt", "s32", 0b0, 0b1, (ins shr_imm16:$imm)> { - let Inst{20} = 0b1; + +class MVE_VMOV_lane_8 + : MVE_VMOV_lane:$Idx), dir> { + bits<4> Idx; + let Inst{22} = 0b1; + let Inst{16} = Idx{3}; + let Inst{21} = Idx{2}; + let Inst{6} = Idx{1}; + let Inst{5} = Idx{0}; } -class MVE_VxQRSHRN pattern=[]> - : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops), - iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc", - pattern> { - bits<5> imm; +def MVE_VMOV_from_lane_32 : MVE_VMOV_lane_32< MVE_VMOV_from_lane>; +def MVE_VMOV_to_lane_32 : MVE_VMOV_lane_32< MVE_VMOV_to_lane>; +def MVE_VMOV_from_lane_s16 : MVE_VMOV_lane_16<"s16", 0b0, MVE_VMOV_from_lane>; +def MVE_VMOV_from_lane_u16 : MVE_VMOV_lane_16<"u16", 0b1, MVE_VMOV_from_lane>; +def MVE_VMOV_to_lane_16 : MVE_VMOV_lane_16< "16", 0b0, MVE_VMOV_to_lane>; +def MVE_VMOV_from_lane_s8 : MVE_VMOV_lane_8 < "s8", 0b0, MVE_VMOV_from_lane>; +def MVE_VMOV_from_lane_u8 : MVE_VMOV_lane_8 < "u8", 0b1, MVE_VMOV_from_lane>; +def MVE_VMOV_to_lane_8 : MVE_VMOV_lane_8 < "8", 0b0, MVE_VMOV_to_lane>; - let Inst{25-23} = 0b101; - let Inst{21} = 0b0; - let Inst{20-16} = imm{4-0}; - let Inst{12} = bit_12; - let Inst{11-6} = 0b111101; - let Inst{4} = 0b0; - let Inst{0} = bit_0; -} +let Predicates = [HasMVEInt] in { + def : Pat<(extractelt (v2f64 MQPR:$src), imm:$lane), + (f64 (EXTRACT_SUBREG MQPR:$src, (DSubReg_f64_reg imm:$lane)))>; + def : Pat<(insertelt (v2f64 MQPR:$src1), DPR:$src2, imm:$lane), + (INSERT_SUBREG (v2f64 (COPY_TO_REGCLASS MQPR:$src1, MQPR)), DPR:$src2, (DSubReg_f64_reg imm:$lane))>; -multiclass MVE_VxQRSHRN_types { - def s16 : MVE_VxQRSHRN { - let Inst{28} = 0b0; - let Inst{20-19} = 0b01; - } - def u16 : MVE_VxQRSHRN { - let Inst{28} = 0b1; - let Inst{20-19} = 0b01; - } - def s32 : MVE_VxQRSHRN { - let Inst{28} = 0b0; - let Inst{20} = 0b1; - } - def u32 : MVE_VxQRSHRN { - let Inst{28} = 0b1; - let Inst{20} = 0b1; - } -} + def : Pat<(extractelt (v4i32 MQPR:$src), imm:$lane), + (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG MQPR:$src, (SSubReg_f32_reg imm:$lane))), rGPR)>; + def : Pat<(insertelt (v4i32 MQPR:$src1), rGPR:$src2, imm:$lane), + (MVE_VMOV_to_lane_32 MQPR:$src1, rGPR:$src2, imm:$lane)>; -defm MVE_VQRSHRNbh : MVE_VxQRSHRN_types<"vqrshrnb", 0b1, 0b0>; -defm MVE_VQRSHRNth : MVE_VxQRSHRN_types<"vqrshrnt", 0b1, 0b1>; -defm MVE_VQSHRNbh : MVE_VxQRSHRN_types<"vqshrnb", 0b0, 0b0>; -defm MVE_VQSHRNth : MVE_VxQRSHRN_types<"vqshrnt", 0b0, 0b1>; + def : Pat<(vector_insert (v16i8 MQPR:$src1), rGPR:$src2, imm:$lane), + (MVE_VMOV_to_lane_8 MQPR:$src1, rGPR:$src2, imm:$lane)>; + def : Pat<(vector_insert (v8i16 MQPR:$src1), rGPR:$src2, imm:$lane), + (MVE_VMOV_to_lane_16 MQPR:$src1, rGPR:$src2, imm:$lane)>; -// end of mve_imm_shift instructions + def : Pat<(ARMvgetlanes (v16i8 MQPR:$src), imm:$lane), + (MVE_VMOV_from_lane_s8 MQPR:$src, imm:$lane)>; + def : Pat<(ARMvgetlanes (v8i16 MQPR:$src), imm:$lane), + (MVE_VMOV_from_lane_s16 MQPR:$src, imm:$lane)>; + def : Pat<(ARMvgetlaneu (v16i8 MQPR:$src), imm:$lane), + (MVE_VMOV_from_lane_u8 MQPR:$src, imm:$lane)>; + def : Pat<(ARMvgetlaneu (v8i16 MQPR:$src), imm:$lane), + (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane)>; -// start of mve_shift instructions + def : Pat<(v16i8 (scalar_to_vector GPR:$src)), + (MVE_VMOV_to_lane_8 (v16i8 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; + def : Pat<(v8i16 (scalar_to_vector GPR:$src)), + (MVE_VMOV_to_lane_16 (v8i16 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; + def : Pat<(v4i32 (scalar_to_vector GPR:$src)), + (MVE_VMOV_to_lane_32 (v4i32 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; -class MVE_shift_by_vec size, bit bit_4, bit bit_8> - : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qm, MQPR:$Qn), NoItinerary, - iname, suffix, "$Qd, $Qm, $Qn", vpred_r, "", []> { - // Shift instructions which take a vector of shift counts + // Floating point patterns, still enabled under HasMVEInt + def : Pat<(extractelt (v4f32 MQPR:$src), imm:$lane), + (COPY_TO_REGCLASS (f32 (EXTRACT_SUBREG MQPR:$src, (SSubReg_f32_reg imm:$lane))), SPR)>; + def : Pat<(insertelt (v4f32 MQPR:$src1), (f32 SPR:$src2), imm:$lane), + (INSERT_SUBREG (v4f32 (COPY_TO_REGCLASS MQPR:$src1, MQPR)), SPR:$src2, (SSubReg_f32_reg imm:$lane))>; + + def : Pat<(insertelt (v8f16 MQPR:$src1), HPR:$src2, imm:$lane), + (MVE_VMOV_to_lane_16 MQPR:$src1, (COPY_TO_REGCLASS HPR:$src2, rGPR), imm:$lane)>; + def : Pat<(extractelt (v8f16 MQPR:$src), imm:$lane), + (COPY_TO_REGCLASS (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane), HPR)>; + + def : Pat<(v4f32 (scalar_to_vector SPR:$src)), + (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), SPR:$src, ssub_0)>; + def : Pat<(v4f32 (scalar_to_vector GPR:$src)), + (MVE_VMOV_to_lane_32 (v4f32 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; + def : Pat<(v8f16 (scalar_to_vector HPR:$src)), + (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), HPR:$src, ssub_0)>; + def : Pat<(v8f16 (scalar_to_vector GPR:$src)), + (MVE_VMOV_to_lane_16 (v8f16 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; +} + +// end of mve_bit instructions + +// start of MVE Integer instructions + +class MVE_int size, list pattern=[]> + : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), NoItinerary, + iname, suffix, "$Qd, $Qn, $Qm", vpred_r, "", pattern> { bits<4> Qd; - bits<4> Qm; bits<4> Qn; + bits<4> Qm; - let Inst{28} = U; - let Inst{25-24} = 0b11; - let Inst{23} = 0b0; let Inst{22} = Qd{3}; let Inst{21-20} = size; let Inst{19-17} = Qn{2-0}; - let Inst{16} = 0b0; let Inst{15-13} = Qd{2-0}; - let Inst{12-9} = 0b0010; - let Inst{8} = bit_8; let Inst{7} = Qn{3}; let Inst{6} = 0b1; let Inst{5} = Qm{3}; - let Inst{4} = bit_4; let Inst{3-1} = Qm{2-0}; - let Inst{0} = 0b0; -} - -multiclass mve_shift_by_vec_multi { - def s8 : MVE_shift_by_vec; - def s16 : MVE_shift_by_vec; - def s32 : MVE_shift_by_vec; - def u8 : MVE_shift_by_vec; - def u16 : MVE_shift_by_vec; - def u32 : MVE_shift_by_vec; } -defm MVE_VSHL_by_vec : mve_shift_by_vec_multi<"vshl", 0b0, 0b0>; -defm MVE_VQSHL_by_vec : mve_shift_by_vec_multi<"vqshl", 0b1, 0b0>; -defm MVE_VQRSHL_by_vec : mve_shift_by_vec_multi<"vqrshl", 0b1, 0b1>; -defm MVE_VRSHL_by_vec : mve_shift_by_vec_multi<"vrshl", 0b0, 0b1>; - -class MVE_shift_with_imm pattern=[]> - : MVE_p { - bits<4> Qd; - bits<4> Qm; +class MVE_VMULt1 size, list pattern=[]> + : MVE_int<"vmul", suffix, size, pattern> { - let Inst{23} = 0b1; - let Inst{22} = Qd{3}; - let Inst{15-13} = Qd{2-0}; - let Inst{12-11} = 0b00; - let Inst{7-6} = 0b01; - let Inst{5} = Qm{3}; + let Inst{28} = 0b0; + let Inst{25-23} = 0b110; + let Inst{16} = 0b0; + let Inst{12-8} = 0b01001; let Inst{4} = 0b1; - let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; } -class MVE_VSxI_imm - : MVE_shift_with_imm { - bits<6> imm; - let Inst{28} = 0b1; - let Inst{25-24} = 0b11; - let Inst{21-16} = imm; - let Inst{10-9} = 0b10; - let Inst{8} = bit_8; -} - -def MVE_VSRIimm8 : MVE_VSxI_imm<"vsri", "8", 0b0, (ins shr_imm8:$imm)> { - let Inst{21-19} = 0b001; -} - -def MVE_VSRIimm16 : MVE_VSxI_imm<"vsri", "16", 0b0, (ins shr_imm16:$imm)> { - let Inst{21-20} = 0b01; -} - -def MVE_VSRIimm32 : MVE_VSxI_imm<"vsri", "32", 0b0, (ins shr_imm32:$imm)> { - let Inst{21} = 0b1; -} - -def MVE_VSLIimm8 : MVE_VSxI_imm<"vsli", "8", 0b1, (ins imm0_7:$imm)> { - let Inst{21-19} = 0b001; -} - -def MVE_VSLIimm16 : MVE_VSxI_imm<"vsli", "16", 0b1, (ins imm0_15:$imm)> { - let Inst{21-20} = 0b01; -} +def MVE_VMULt1i8 : MVE_VMULt1<"i8", 0b00>; +def MVE_VMULt1i16 : MVE_VMULt1<"i16", 0b01>; +def MVE_VMULt1i32 : MVE_VMULt1<"i32", 0b10>; -def MVE_VSLIimm32 : MVE_VSxI_imm<"vsli", "32", 0b1,(ins imm0_31:$imm)> { - let Inst{21} = 0b1; +let Predicates = [HasMVEInt] in { + def : Pat<(v16i8 (mul (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), + (v16i8 (MVE_VMULt1i8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; + def : Pat<(v8i16 (mul (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), + (v8i16 (MVE_VMULt1i16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; + def : Pat<(v4i32 (mul (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), + (v4i32 (MVE_VMULt1i32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; } -class MVE_VQSHL_imm - : MVE_shift_with_imm<"vqshl", suffix, (outs MQPR:$Qd), - !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", - vpred_r, ""> { - bits<6> imm; - - let Inst{25-24} = 0b11; - let Inst{21-16} = imm; - let Inst{10-8} = 0b111; -} +class MVE_VQxDMULH size, bit rounding, + list pattern=[]> + : MVE_int { -def MVE_VSLIimms8 : MVE_VQSHL_imm<"s8", (ins imm0_7:$imm)> { - let Inst{28} = 0b0; - let Inst{21-19} = 0b001; + let Inst{28} = rounding; + let Inst{25-23} = 0b110; + let Inst{16} = 0b0; + let Inst{12-8} = 0b01011; + let Inst{4} = 0b0; + let Inst{0} = 0b0; } -def MVE_VSLIimmu8 : MVE_VQSHL_imm<"u8", (ins imm0_7:$imm)> { - let Inst{28} = 0b1; - let Inst{21-19} = 0b001; -} +class MVE_VQDMULH size, list pattern=[]> + : MVE_VQxDMULH<"vqdmulh", suffix, size, 0b0, pattern>; +class MVE_VQRDMULH size, list pattern=[]> + : MVE_VQxDMULH<"vqrdmulh", suffix, size, 0b1, pattern>; -def MVE_VSLIimms16 : MVE_VQSHL_imm<"s16", (ins imm0_15:$imm)> { - let Inst{28} = 0b0; - let Inst{21-20} = 0b01; -} +def MVE_VQDMULHi8 : MVE_VQDMULH<"s8", 0b00>; +def MVE_VQDMULHi16 : MVE_VQDMULH<"s16", 0b01>; +def MVE_VQDMULHi32 : MVE_VQDMULH<"s32", 0b10>; -def MVE_VSLIimmu16 : MVE_VQSHL_imm<"u16", (ins imm0_15:$imm)> { - let Inst{28} = 0b1; - let Inst{21-20} = 0b01; -} +def MVE_VQRDMULHi8 : MVE_VQRDMULH<"s8", 0b00>; +def MVE_VQRDMULHi16 : MVE_VQRDMULH<"s16", 0b01>; +def MVE_VQRDMULHi32 : MVE_VQRDMULH<"s32", 0b10>; -def MVE_VSLIimms32 : MVE_VQSHL_imm<"s32", (ins imm0_31:$imm)> { - let Inst{28} = 0b0; - let Inst{21} = 0b1; -} +class MVE_VADDSUB size, bit subtract, + list pattern=[]> + : MVE_int { -def MVE_VSLIimmu32 : MVE_VQSHL_imm<"u32", (ins imm0_31:$imm)> { - let Inst{28} = 0b1; - let Inst{21} = 0b1; + let Inst{28} = subtract; + let Inst{25-23} = 0b110; + let Inst{16} = 0b0; + let Inst{12-8} = 0b01000; + let Inst{4} = 0b0; + let Inst{0} = 0b0; } -class MVE_VQSHLU_imm - : MVE_shift_with_imm<"vqshlu", suffix, (outs MQPR:$Qd), - !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", - vpred_r, ""> { - bits<6> imm; +class MVE_VADD size, list pattern=[]> + : MVE_VADDSUB<"vadd", suffix, size, 0b0, pattern>; +class MVE_VSUB size, list pattern=[]> + : MVE_VADDSUB<"vsub", suffix, size, 0b1, pattern>; - let Inst{28} = 0b1; - let Inst{25-24} = 0b11; - let Inst{21-16} = imm; - let Inst{10-8} = 0b110; -} +def MVE_VADDi8 : MVE_VADD<"i8", 0b00>; +def MVE_VADDi16 : MVE_VADD<"i16", 0b01>; +def MVE_VADDi32 : MVE_VADD<"i32", 0b10>; -def MVE_VQSHLU_imms8 : MVE_VQSHLU_imm<"s8", (ins imm0_7:$imm)> { - let Inst{21-19} = 0b001; +let Predicates = [HasMVEInt] in { + def : Pat<(v16i8 (add (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), + (v16i8 (MVE_VADDi8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; + def : Pat<(v8i16 (add (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), + (v8i16 (MVE_VADDi16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; + def : Pat<(v4i32 (add (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), + (v4i32 (MVE_VADDi32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; } -def MVE_VQSHLU_imms16 : MVE_VQSHLU_imm<"s16", (ins imm0_15:$imm)> { - let Inst{21-20} = 0b01; -} +def MVE_VSUBi8 : MVE_VSUB<"i8", 0b00>; +def MVE_VSUBi16 : MVE_VSUB<"i16", 0b01>; +def MVE_VSUBi32 : MVE_VSUB<"i32", 0b10>; -def MVE_VQSHLU_imms32 : MVE_VQSHLU_imm<"s32", (ins imm0_31:$imm)> { - let Inst{21} = 0b1; +let Predicates = [HasMVEInt] in { + def : Pat<(v16i8 (sub (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), + (v16i8 (MVE_VSUBi8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; + def : Pat<(v8i16 (sub (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), + (v8i16 (MVE_VSUBi16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; + def : Pat<(v4i32 (sub (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), + (v4i32 (MVE_VSUBi32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; } -class MVE_VRSHR_imm - : MVE_shift_with_imm<"vrshr", suffix, (outs MQPR:$Qd), - !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", - vpred_r, ""> { - bits<6> imm; +class MVE_VQADDSUB size, list pattern=[]> + : MVE_int { - let Inst{25-24} = 0b11; - let Inst{21-16} = imm; - let Inst{10-8} = 0b010; + let Inst{28} = U; + let Inst{25-23} = 0b110; + let Inst{16} = 0b0; + let Inst{12-10} = 0b000; + let Inst{9} = subtract; + let Inst{8} = 0b0; + let Inst{4} = 0b1; + let Inst{0} = 0b0; } -def MVE_VRSHR_imms8 : MVE_VRSHR_imm<"s8", (ins shr_imm8:$imm)> { - let Inst{28} = 0b0; - let Inst{21-19} = 0b001; -} +class MVE_VQADD size, list pattern=[]> + : MVE_VQADDSUB<"vqadd", suffix, U, 0b0, size, pattern>; +class MVE_VQSUB size, list pattern=[]> + : MVE_VQADDSUB<"vqsub", suffix, U, 0b1, size, pattern>; -def MVE_VRSHR_immu8 : MVE_VRSHR_imm<"u8", (ins shr_imm8:$imm)> { - let Inst{28} = 0b1; - let Inst{21-19} = 0b001; -} +def MVE_VQADDs8 : MVE_VQADD<"s8", 0b0, 0b00>; +def MVE_VQADDs16 : MVE_VQADD<"s16", 0b0, 0b01>; +def MVE_VQADDs32 : MVE_VQADD<"s32", 0b0, 0b10>; +def MVE_VQADDu8 : MVE_VQADD<"u8", 0b1, 0b00>; +def MVE_VQADDu16 : MVE_VQADD<"u16", 0b1, 0b01>; +def MVE_VQADDu32 : MVE_VQADD<"u32", 0b1, 0b10>; -def MVE_VRSHR_imms16 : MVE_VRSHR_imm<"s16", (ins shr_imm16:$imm)> { - let Inst{28} = 0b0; - let Inst{21-20} = 0b01; -} +def MVE_VQSUBs8 : MVE_VQSUB<"s8", 0b0, 0b00>; +def MVE_VQSUBs16 : MVE_VQSUB<"s16", 0b0, 0b01>; +def MVE_VQSUBs32 : MVE_VQSUB<"s32", 0b0, 0b10>; +def MVE_VQSUBu8 : MVE_VQSUB<"u8", 0b1, 0b00>; +def MVE_VQSUBu16 : MVE_VQSUB<"u16", 0b1, 0b01>; +def MVE_VQSUBu32 : MVE_VQSUB<"u32", 0b1, 0b10>; -def MVE_VRSHR_immu16 : MVE_VRSHR_imm<"u16", (ins shr_imm16:$imm)> { - let Inst{28} = 0b1; - let Inst{21-20} = 0b01; -} +class MVE_VABD_int size, list pattern=[]> + : MVE_int<"vabd", suffix, size, pattern> { -def MVE_VRSHR_imms32 : MVE_VRSHR_imm<"s32", (ins shr_imm32:$imm)> { - let Inst{28} = 0b0; - let Inst{21} = 0b1; + let Inst{28} = U; + let Inst{25-23} = 0b110; + let Inst{16} = 0b0; + let Inst{12-8} = 0b00111; + let Inst{4} = 0b0; + let Inst{0} = 0b0; } -def MVE_VRSHR_immu32 : MVE_VRSHR_imm<"u32", (ins shr_imm32:$imm)> { - let Inst{28} = 0b1; - let Inst{21} = 0b1; -} +def MVE_VABDs8 : MVE_VABD_int<"s8", 0b0, 0b00>; +def MVE_VABDs16 : MVE_VABD_int<"s16", 0b0, 0b01>; +def MVE_VABDs32 : MVE_VABD_int<"s32", 0b0, 0b10>; +def MVE_VABDu8 : MVE_VABD_int<"u8", 0b1, 0b00>; +def MVE_VABDu16 : MVE_VABD_int<"u16", 0b1, 0b01>; +def MVE_VABDu32 : MVE_VABD_int<"u32", 0b1, 0b10>; -class MVE_VSHR_imm - : MVE_shift_with_imm<"vshr", suffix, (outs MQPR:$Qd), - !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", - vpred_r, ""> { - bits<6> imm; +class MVE_VRHADD size, list pattern=[]> + : MVE_int<"vrhadd", suffix, size, pattern> { - let Inst{25-24} = 0b11; - let Inst{21-16} = imm; - let Inst{10-8} = 0b000; + let Inst{28} = U; + let Inst{25-23} = 0b110; + let Inst{16} = 0b0; + let Inst{12-8} = 0b00001; + let Inst{4} = 0b0; + let Inst{0} = 0b0; } -def MVE_VSHR_imms8 : MVE_VSHR_imm<"s8", (ins shr_imm8:$imm)> { - let Inst{28} = 0b0; - let Inst{21-19} = 0b001; -} +def MVE_VRHADDs8 : MVE_VRHADD<"s8", 0b0, 0b00>; +def MVE_VRHADDs16 : MVE_VRHADD<"s16", 0b0, 0b01>; +def MVE_VRHADDs32 : MVE_VRHADD<"s32", 0b0, 0b10>; +def MVE_VRHADDu8 : MVE_VRHADD<"u8", 0b1, 0b00>; +def MVE_VRHADDu16 : MVE_VRHADD<"u16", 0b1, 0b01>; +def MVE_VRHADDu32 : MVE_VRHADD<"u32", 0b1, 0b10>; -def MVE_VSHR_immu8 : MVE_VSHR_imm<"u8", (ins shr_imm8:$imm)> { - let Inst{28} = 0b1; - let Inst{21-19} = 0b001; -} +class MVE_VHADDSUB size, list pattern=[]> + : MVE_int { -def MVE_VSHR_imms16 : MVE_VSHR_imm<"s16", (ins shr_imm16:$imm)> { - let Inst{28} = 0b0; - let Inst{21-20} = 0b01; + let Inst{28} = U; + let Inst{25-23} = 0b110; + let Inst{16} = 0b0; + let Inst{12-10} = 0b000; + let Inst{9} = subtract; + let Inst{8} = 0b0; + let Inst{4} = 0b0; + let Inst{0} = 0b0; } -def MVE_VSHR_immu16 : MVE_VSHR_imm<"u16", (ins shr_imm16:$imm)> { - let Inst{28} = 0b1; - let Inst{21-20} = 0b01; -} +class MVE_VHADD size, + list pattern=[]> + : MVE_VHADDSUB<"vhadd", suffix, U, 0b0, size, pattern>; +class MVE_VHSUB size, + list pattern=[]> + : MVE_VHADDSUB<"vhsub", suffix, U, 0b1, size, pattern>; -def MVE_VSHR_imms32 : MVE_VSHR_imm<"s32", (ins shr_imm32:$imm)> { - let Inst{28} = 0b0; - let Inst{21} = 0b1; -} +def MVE_VHADDs8 : MVE_VHADD<"s8", 0b0, 0b00>; +def MVE_VHADDs16 : MVE_VHADD<"s16", 0b0, 0b01>; +def MVE_VHADDs32 : MVE_VHADD<"s32", 0b0, 0b10>; +def MVE_VHADDu8 : MVE_VHADD<"u8", 0b1, 0b00>; +def MVE_VHADDu16 : MVE_VHADD<"u16", 0b1, 0b01>; +def MVE_VHADDu32 : MVE_VHADD<"u32", 0b1, 0b10>; -def MVE_VSHR_immu32 : MVE_VSHR_imm<"u32", (ins shr_imm32:$imm)> { - let Inst{28} = 0b1; - let Inst{21} = 0b1; -} +def MVE_VHSUBs8 : MVE_VHSUB<"s8", 0b0, 0b00>; +def MVE_VHSUBs16 : MVE_VHSUB<"s16", 0b0, 0b01>; +def MVE_VHSUBs32 : MVE_VHSUB<"s32", 0b0, 0b10>; +def MVE_VHSUBu8 : MVE_VHSUB<"u8", 0b1, 0b00>; +def MVE_VHSUBu16 : MVE_VHSUB<"u16", 0b1, 0b01>; +def MVE_VHSUBu32 : MVE_VHSUB<"u32", 0b1, 0b10>; -class MVE_VSHL_imm - : MVE_shift_with_imm<"vshl", suffix, (outs MQPR:$Qd), - !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", - vpred_r, ""> { - bits<6> imm; +class MVE_VDUP pattern=[]> + : MVE_p<(outs MQPR:$Qd), (ins rGPR:$Rt), NoItinerary, + "vdup", suffix, "$Qd, $Rt", vpred_r, "", pattern> { + bits<4> Qd; + bits<4> Rt; let Inst{28} = 0b0; - let Inst{25-24} = 0b11; - let Inst{21-16} = imm; - let Inst{10-8} = 0b101; + let Inst{25-23} = 0b101; + let Inst{22} = B; + let Inst{21-20} = 0b10; + let Inst{19-17} = Qd{2-0}; + let Inst{16} = 0b0; + let Inst{15-12} = Rt; + let Inst{11-8} = 0b1011; + let Inst{7} = Qd{3}; + let Inst{6} = 0b0; + let Inst{5} = E; + let Inst{4-0} = 0b10000; } -def MVE_VSHL_immi8 : MVE_VSHL_imm<"i8", (ins imm0_7:$imm)> { - let Inst{21-19} = 0b001; -} +def MVE_VDUP32 : MVE_VDUP<"32", 0b0, 0b0>; +def MVE_VDUP16 : MVE_VDUP<"16", 0b0, 0b1>; +def MVE_VDUP8 : MVE_VDUP<"8", 0b1, 0b0>; -def MVE_VSHL_immi16 : MVE_VSHL_imm<"i16", (ins imm0_15:$imm)> { - let Inst{21-20} = 0b01; -} +let Predicates = [HasMVEInt] in { + def : Pat<(v16i8 (ARMvdup (i32 rGPR:$elem))), + (MVE_VDUP8 rGPR:$elem)>; + def : Pat<(v8i16 (ARMvdup (i32 rGPR:$elem))), + (MVE_VDUP16 rGPR:$elem)>; + def : Pat<(v4i32 (ARMvdup (i32 rGPR:$elem))), + (MVE_VDUP32 rGPR:$elem)>; -def MVE_VSHL_immi32 : MVE_VSHL_imm<"i32", (ins imm0_31:$imm)> { - let Inst{21} = 0b1; -} -// end of mve_shift instructions + def : Pat<(v4i32 (ARMvduplane (v4i32 MQPR:$src), imm:$lane)), + (MVE_VDUP32 (MVE_VMOV_from_lane_32 MQPR:$src, imm:$lane))>; + // For the 16-bit and 8-bit vduplanes we don't care about the signedness + // of the lane move operation as we only want the lowest 8/16 bits anyway. + def : Pat<(v8i16 (ARMvduplane (v8i16 MQPR:$src), imm:$lane)), + (MVE_VDUP16 (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane))>; + def : Pat<(v16i8 (ARMvduplane (v16i8 MQPR:$src), imm:$lane)), + (MVE_VDUP8 (MVE_VMOV_from_lane_u8 MQPR:$src, imm:$lane))>; -// start of mve_bit instructions + def : Pat<(v4f32 (ARMvdup (f32 SPR:$elem))), + (v4f32 (MVE_VDUP32 (i32 (COPY_TO_REGCLASS (f32 SPR:$elem), rGPR))))>; + def : Pat<(v8f16 (ARMvdup (f16 HPR:$elem))), + (v8f16 (MVE_VDUP16 (i32 (COPY_TO_REGCLASS (f16 HPR:$elem), rGPR))))>; -class MVE_bit_arith pattern=[]> - : MVE_p { + def : Pat<(v4f32 (ARMvduplane (v4f32 MQPR:$src), imm:$lane)), + (MVE_VDUP32 (MVE_VMOV_from_lane_32 MQPR:$src, imm:$lane))>; + def : Pat<(v8f16 (ARMvduplane (v8f16 MQPR:$src), imm:$lane)), + (MVE_VDUP16 (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane))>; +} + + +class MVEIntSingleSrc size, + list pattern=[]> + : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qm), NoItinerary, + iname, suffix, "$Qd, $Qm", vpred_r, "", pattern> { bits<4> Qd; bits<4> Qm; let Inst{22} = Qd{3}; + let Inst{19-18} = size{1-0}; let Inst{15-13} = Qd{2-0}; let Inst{5} = Qm{3}; let Inst{3-1} = Qm{2-0}; } -def MVE_VBIC : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), - "vbic", "", "$Qd, $Qn, $Qm", ""> { - bits<4> Qn; - - let Inst{28} = 0b0; - let Inst{25-23} = 0b110; - let Inst{21-20} = 0b01; - let Inst{19-17} = Qn{2-0}; - let Inst{16} = 0b0; - let Inst{12-8} = 0b00001; - let Inst{7} = Qn{3}; - let Inst{6} = 0b1; - let Inst{4} = 0b1; - let Inst{0} = 0b0; -} - -class MVE_VREV size, bits<2> bit_8_7> - : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qm), iname, - suffix, "$Qd, $Qm", ""> { +class MVE_VCLSCLZ size, + bit count_zeroes, list pattern=[]> + : MVEIntSingleSrc { let Inst{28} = 0b1; let Inst{25-23} = 0b111; let Inst{21-20} = 0b11; - let Inst{19-18} = size; let Inst{17-16} = 0b00; - let Inst{12-9} = 0b0000; - let Inst{8-7} = bit_8_7; + let Inst{12-8} = 0b00100; + let Inst{7} = count_zeroes; let Inst{6} = 0b1; let Inst{4} = 0b0; let Inst{0} = 0b0; } -def MVE_VREV64_8 : MVE_VREV<"vrev64", "8", 0b00, 0b00>; -def MVE_VREV64_16 : MVE_VREV<"vrev64", "16", 0b01, 0b00>; -def MVE_VREV64_32 : MVE_VREV<"vrev64", "32", 0b10, 0b00>; - -def MVE_VREV32_8 : MVE_VREV<"vrev32", "8", 0b00, 0b01>; -def MVE_VREV32_16 : MVE_VREV<"vrev32", "16", 0b01, 0b01>; - -def MVE_VREV16_8 : MVE_VREV<"vrev16", "8", 0b00, 0b10>; - -let Predicates = [HasMVEInt] in { -def : Pat<(v4i32 (ARMvrev64 (v4i32 MQPR:$src))), - (v4i32 (MVE_VREV64_32 (v4i32 MQPR:$src)))>; -def : Pat<(v8i16 (ARMvrev64 (v8i16 MQPR:$src))), - (v8i16 (MVE_VREV64_16 (v8i16 MQPR:$src)))>; -def : Pat<(v16i8 (ARMvrev64 (v16i8 MQPR:$src))), - (v16i8 (MVE_VREV64_8 (v16i8 MQPR:$src)))>; - -def : Pat<(v8i16 (ARMvrev32 (v8i16 MQPR:$src))), - (v8i16 (MVE_VREV32_16 (v8i16 MQPR:$src)))>; -def : Pat<(v16i8 (ARMvrev32 (v16i8 MQPR:$src))), - (v16i8 (MVE_VREV32_8 (v16i8 MQPR:$src)))>; +def MVE_VCLSs8 : MVE_VCLSCLZ<"vcls", "s8", 0b00, 0b0>; +def MVE_VCLSs16 : MVE_VCLSCLZ<"vcls", "s16", 0b01, 0b0>; +def MVE_VCLSs32 : MVE_VCLSCLZ<"vcls", "s32", 0b10, 0b0>; -def : Pat<(v16i8 (ARMvrev16 (v16i8 MQPR:$src))), - (v16i8 (MVE_VREV16_8 (v16i8 MQPR:$src)))>; +def MVE_VCLZs8 : MVE_VCLSCLZ<"vclz", "i8", 0b00, 0b1>; +def MVE_VCLZs16 : MVE_VCLSCLZ<"vclz", "i16", 0b01, 0b1>; +def MVE_VCLZs32 : MVE_VCLSCLZ<"vclz", "i32", 0b10, 0b1>; -def : Pat<(v4f32 (ARMvrev64 (v4f32 MQPR:$src))), - (v4f32 (MVE_VREV64_32 (v4f32 MQPR:$src)))>; -def : Pat<(v8f16 (ARMvrev64 (v8f16 MQPR:$src))), - (v8f16 (MVE_VREV64_16 (v8f16 MQPR:$src)))>; -def : Pat<(v8f16 (ARMvrev32 (v8f16 MQPR:$src))), - (v8f16 (MVE_VREV32_16 (v8f16 MQPR:$src)))>; -} +class MVE_VABSNEG_int size, bit negate, + list pattern=[]> + : MVEIntSingleSrc { -def MVE_VMVN : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qm), - "vmvn", "", "$Qd, $Qm", ""> { let Inst{28} = 0b1; let Inst{25-23} = 0b111; - let Inst{21-16} = 0b110000; - let Inst{12-6} = 0b0010111; - let Inst{4} = 0b0; - let Inst{0} = 0b0; -} - -let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (vnotq (v16i8 MQPR:$val1))), - (v16i8 (MVE_VMVN (v16i8 MQPR:$val1)))>; - def : Pat<(v8i16 (vnotq (v8i16 MQPR:$val1))), - (v8i16 (MVE_VMVN (v8i16 MQPR:$val1)))>; - def : Pat<(v4i32 (vnotq (v4i32 MQPR:$val1))), - (v4i32 (MVE_VMVN (v4i32 MQPR:$val1)))>; -} - -class MVE_bit_ops bit_21_20, bit bit_28> - : MVE_bit_arith<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), - iname, "", "$Qd, $Qn, $Qm", ""> { - bits<4> Qn; - - let Inst{28} = bit_28; - let Inst{25-23} = 0b110; - let Inst{21-20} = bit_21_20; - let Inst{19-17} = Qn{2-0}; - let Inst{16} = 0b0; - let Inst{12-8} = 0b00001; - let Inst{7} = Qn{3}; + let Inst{21-20} = 0b11; + let Inst{17-16} = 0b01; + let Inst{12-8} = 0b00011; + let Inst{7} = negate; let Inst{6} = 0b1; - let Inst{4} = 0b1; + let Inst{4} = 0b0; let Inst{0} = 0b0; } -def MVE_VEOR : MVE_bit_ops<"veor", 0b00, 0b1>; -def MVE_VORN : MVE_bit_ops<"vorn", 0b11, 0b0>; -def MVE_VORR : MVE_bit_ops<"vorr", 0b10, 0b0>; -def MVE_VAND : MVE_bit_ops<"vand", 0b00, 0b0>; - -// add ignored suffixes as aliases - -foreach s=["s8", "s16", "s32", "u8", "u16", "u32", "i8", "i16", "i32", "f16", "f32"] in { - def : MVEInstAlias<"vbic${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", - (MVE_VBIC MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; - def : MVEInstAlias<"veor${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", - (MVE_VEOR MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; - def : MVEInstAlias<"vorn${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", - (MVE_VORN MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; - def : MVEInstAlias<"vorr${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", - (MVE_VORR MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; - def : MVEInstAlias<"vand${vp}." # s # "\t$QdSrc, $QnSrc, $QmSrc", - (MVE_VAND MQPR:$QdSrc, MQPR:$QnSrc, MQPR:$QmSrc, vpred_r:$vp)>; -} +def MVE_VABSs8 : MVE_VABSNEG_int<"vabs", "s8", 0b00, 0b0>; +def MVE_VABSs16 : MVE_VABSNEG_int<"vabs", "s16", 0b01, 0b0>; +def MVE_VABSs32 : MVE_VABSNEG_int<"vabs", "s32", 0b10, 0b0>; let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (and (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), - (v16i8 (MVE_VAND (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; - def : Pat<(v8i16 (and (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), - (v8i16 (MVE_VAND (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; - def : Pat<(v4i32 (and (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), - (v4i32 (MVE_VAND (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; - - def : Pat<(v16i8 (or (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), - (v16i8 (MVE_VORR (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; - def : Pat<(v8i16 (or (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), - (v8i16 (MVE_VORR (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; - def : Pat<(v4i32 (or (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), - (v4i32 (MVE_VORR (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; - - def : Pat<(v16i8 (xor (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), - (v16i8 (MVE_VEOR (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; - def : Pat<(v8i16 (xor (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), - (v8i16 (MVE_VEOR (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; - def : Pat<(v4i32 (xor (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), - (v4i32 (MVE_VEOR (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; - - def : Pat<(v16i8 (and (v16i8 MQPR:$val1), (vnotq MQPR:$val2))), - (v16i8 (MVE_VBIC (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; - def : Pat<(v8i16 (and (v8i16 MQPR:$val1), (vnotq MQPR:$val2))), - (v8i16 (MVE_VBIC (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; - def : Pat<(v4i32 (and (v4i32 MQPR:$val1), (vnotq MQPR:$val2))), - (v4i32 (MVE_VBIC (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; - - def : Pat<(v16i8 (or (v16i8 MQPR:$val1), (vnotq (v16i8 MQPR:$val2)))), - (v16i8 (MVE_VORN (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; - def : Pat<(v8i16 (or (v8i16 MQPR:$val1), (vnotq MQPR:$val2))), - (v8i16 (MVE_VORN (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; - def : Pat<(v4i32 (or (v4i32 MQPR:$val1), (vnotq MQPR:$val2))), - (v4i32 (MVE_VORN (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; -} - -class MVE_bit_cmode cmode, dag inOps> - : MVE_p<(outs MQPR:$Qd), inOps, NoItinerary, - iname, suffix, "$Qd, $imm", vpred_n, "$Qd = $Qd_src"> { - bits<8> imm; - bits<4> Qd; - - let Inst{28} = imm{7}; - let Inst{27-23} = 0b11111; - let Inst{22} = Qd{3}; - let Inst{21-19} = 0b000; - let Inst{18-16} = imm{6-4}; - let Inst{15-13} = Qd{2-0}; - let Inst{12} = 0b0; - let Inst{11-8} = cmode; - let Inst{7-6} = 0b01; - let Inst{4} = 0b1; - let Inst{3-0} = imm{3-0}; -} - -class MVE_VORR cmode, ExpandImm imm_type> - : MVE_bit_cmode<"vorr", suffix, cmode, (ins MQPR:$Qd_src, imm_type:$imm)> { - let Inst{5} = 0b0; -} - -def MVE_VORRIZ0v4i32 : MVE_VORR<"i32", 0b0001, expzero00>; -def MVE_VORRIZ0v8i16 : MVE_VORR<"i16", 0b1001, expzero00>; -def MVE_VORRIZ8v4i32 : MVE_VORR<"i32", 0b0011, expzero08>; -def MVE_VORRIZ8v8i16 : MVE_VORR<"i16", 0b1011, expzero08>; -def MVE_VORRIZ16v4i32 : MVE_VORR<"i32", 0b0101, expzero16>; -def MVE_VORRIZ24v4i32 : MVE_VORR<"i32", 0b0111, expzero24>; - -def MVE_VORNIZ0v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm", - (ins MQPR:$Qd_src, expzero00inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; -def MVE_VORNIZ0v8i16 : MVEAsmPseudo<"vorn${vp}.i16\t$Qd, $imm", - (ins MQPR:$Qd_src, expzero00inv16:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; -def MVE_VORNIZ8v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm", - (ins MQPR:$Qd_src, expzero08inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; -def MVE_VORNIZ8v8i16 : MVEAsmPseudo<"vorn${vp}.i16\t$Qd, $imm", - (ins MQPR:$Qd_src, expzero08inv16:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; -def MVE_VORNIZ16v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm", - (ins MQPR:$Qd_src, expzero16inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; -def MVE_VORNIZ24v4i32 : MVEAsmPseudo<"vorn${vp}.i32\t$Qd, $imm", - (ins MQPR:$Qd_src, expzero24inv32:$imm, vpred_n:$vp), (outs MQPR:$Qd)>; - -def MVE_VMOV : MVEInstAlias<"vmov${vp}\t$Qd, $Qm", - (MVE_VORR MQPR:$Qd, MQPR:$Qm, MQPR:$Qm, vpred_r:$vp)>; - -class MVE_VBIC cmode, ExpandImm imm_type> - : MVE_bit_cmode<"vbic", suffix, cmode, (ins MQPR:$Qd_src, imm_type:$imm)> { - let Inst{5} = 0b1; + def : Pat<(v16i8 (abs (v16i8 MQPR:$v))), + (v16i8 (MVE_VABSs8 $v))>; + def : Pat<(v8i16 (abs (v8i16 MQPR:$v))), + (v8i16 (MVE_VABSs16 $v))>; + def : Pat<(v4i32 (abs (v4i32 MQPR:$v))), + (v4i32 (MVE_VABSs32 $v))>; } -def MVE_VBICIZ0v4i32 : MVE_VBIC<"i32", 0b0001, expzero00>; -def MVE_VBICIZ0v8i16 : MVE_VBIC<"i16", 0b1001, expzero00>; -def MVE_VBICIZ8v4i32 : MVE_VBIC<"i32", 0b0011, expzero08>; -def MVE_VBICIZ8v8i16 : MVE_VBIC<"i16", 0b1011, expzero08>; -def MVE_VBICIZ16v4i32 : MVE_VBIC<"i32", 0b0101, expzero16>; -def MVE_VBICIZ24v4i32 : MVE_VBIC<"i32", 0b0111, expzero24>; - -def MVE_VANDIZ0v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm", - (ins MQPR:$Qda_src, expzero00inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; -def MVE_VANDIZ0v8i16 : MVEAsmPseudo<"vand${vp}.i16\t$Qda, $imm", - (ins MQPR:$Qda_src, expzero00inv16:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; -def MVE_VANDIZ8v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm", - (ins MQPR:$Qda_src, expzero08inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; -def MVE_VANDIZ8v8i16 : MVEAsmPseudo<"vand${vp}.i16\t$Qda, $imm", - (ins MQPR:$Qda_src, expzero08inv16:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; -def MVE_VANDIZ16v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm", - (ins MQPR:$Qda_src, expzero16inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; -def MVE_VANDIZ24v4i32 : MVEAsmPseudo<"vand${vp}.i32\t$Qda, $imm", - (ins MQPR:$Qda_src, expzero24inv32:$imm, vpred_n:$vp), (outs MQPR:$Qda)>; +def MVE_VNEGs8 : MVE_VABSNEG_int<"vneg", "s8", 0b00, 0b1>; +def MVE_VNEGs16 : MVE_VABSNEG_int<"vneg", "s16", 0b01, 0b1>; +def MVE_VNEGs32 : MVE_VABSNEG_int<"vneg", "s32", 0b10, 0b1>; -class MVE_VMOV_lane_direction { - bit bit_20; - dag oops; - dag iops; - string ops; - string cstr; -} -def MVE_VMOV_from_lane : MVE_VMOV_lane_direction { - let bit_20 = 0b1; - let oops = (outs rGPR:$Rt); - let iops = (ins MQPR:$Qd); - let ops = "$Rt, $Qd$Idx"; - let cstr = ""; +let Predicates = [HasMVEInt] in { + def : Pat<(v16i8 (vnegq (v16i8 MQPR:$v))), + (v16i8 (MVE_VNEGs8 $v))>; + def : Pat<(v8i16 (vnegq (v8i16 MQPR:$v))), + (v8i16 (MVE_VNEGs16 $v))>; + def : Pat<(v4i32 (vnegq (v4i32 MQPR:$v))), + (v4i32 (MVE_VNEGs32 $v))>; } -def MVE_VMOV_to_lane : MVE_VMOV_lane_direction { - let bit_20 = 0b0; - let oops = (outs MQPR:$Qd); - let iops = (ins MQPR:$Qd_src, rGPR:$Rt); - let ops = "$Qd$Idx, $Rt"; - let cstr = "$Qd = $Qd_src"; + +class MVE_VQABSNEG size, + bit negate, list pattern=[]> + : MVEIntSingleSrc { + + let Inst{28} = 0b1; + let Inst{25-23} = 0b111; + let Inst{21-20} = 0b11; + let Inst{17-16} = 0b00; + let Inst{12-8} = 0b00111; + let Inst{7} = negate; + let Inst{6} = 0b1; + let Inst{4} = 0b0; + let Inst{0} = 0b0; } -class MVE_VMOV_lane - : MVE_VMOV_lane_base { +def MVE_VQABSs8 : MVE_VQABSNEG<"vqabs", "s8", 0b00, 0b0>; +def MVE_VQABSs16 : MVE_VQABSNEG<"vqabs", "s16", 0b01, 0b0>; +def MVE_VQABSs32 : MVE_VQABSNEG<"vqabs", "s32", 0b10, 0b0>; + +def MVE_VQNEGs8 : MVE_VQABSNEG<"vqneg", "s8", 0b00, 0b1>; +def MVE_VQNEGs16 : MVE_VQABSNEG<"vqneg", "s16", 0b01, 0b1>; +def MVE_VQNEGs32 : MVE_VQABSNEG<"vqneg", "s32", 0b10, 0b1>; + +class MVE_mod_imm cmode, bit op, + dag iops, list pattern=[]> + : MVE_p<(outs MQPR:$Qd), iops, NoItinerary, iname, suffix, "$Qd, $imm", + vpred_r, "", pattern> { + bits<13> imm; bits<4> Qd; - bits<4> Rt; - let Inst{31-24} = 0b11101110; - let Inst{23} = U; - let Inst{20} = dir.bit_20; - let Inst{19-17} = Qd{2-0}; - let Inst{15-12} = Rt{3-0}; - let Inst{11-8} = 0b1011; - let Inst{7} = Qd{3}; - let Inst{4-0} = 0b10000; + let Inst{28} = imm{7}; + let Inst{25-23} = 0b111; + let Inst{22} = Qd{3}; + let Inst{21-19} = 0b000; + let Inst{18-16} = imm{6-4}; + let Inst{15-13} = Qd{2-0}; + let Inst{12} = 0b0; + let Inst{11-8} = cmode{3-0}; + let Inst{7-6} = 0b01; + let Inst{5} = op; + let Inst{4} = 0b1; + let Inst{3-0} = imm{3-0}; + + let DecoderMethod = "DecodeMVEModImmInstruction"; } -class MVE_VMOV_lane_32 - : MVE_VMOV_lane<"32", 0b0, (ins MVEVectorIndex<4>:$Idx), dir> { - bits<2> Idx; - let Inst{22} = 0b0; - let Inst{6-5} = 0b00; - let Inst{16} = Idx{1}; - let Inst{21} = Idx{0}; +let isReMaterializable = 1 in { +let isAsCheapAsAMove = 1 in { +def MVE_VMOVimmi8 : MVE_mod_imm<"vmov", "i8", {1,1,1,0}, 0b0, (ins nImmSplatI8:$imm)>; +def MVE_VMOVimmi16 : MVE_mod_imm<"vmov", "i16", {1,0,?,0}, 0b0, (ins nImmSplatI16:$imm)> { + let Inst{9} = imm{9}; +} +def MVE_VMOVimmi32 : MVE_mod_imm<"vmov", "i32", {?,?,?,?}, 0b0, (ins nImmVMOVI32:$imm)> { + let Inst{11-8} = imm{11-8}; +} +def MVE_VMOVimmi64 : MVE_mod_imm<"vmov", "i64", {1,1,1,0}, 0b1, (ins nImmSplatI64:$imm)>; +def MVE_VMOVimmf32 : MVE_mod_imm<"vmov", "f32", {1,1,1,1}, 0b0, (ins nImmVMOVF32:$imm)>; +} // let isAsCheapAsAMove = 1 - let Predicates = [HasFPRegsV8_1M]; +def MVE_VMVNimmi16 : MVE_mod_imm<"vmvn", "i16", {1,0,?,0}, 0b1, (ins nImmSplatI16:$imm)> { + let Inst{9} = imm{9}; +} +def MVE_VMVNimmi32 : MVE_mod_imm<"vmvn", "i32", {?,?,?,?}, 0b1, (ins nImmVMOVI32:$imm)> { + let Inst{11-8} = imm{11-8}; } +} // let isReMaterializable = 1 -class MVE_VMOV_lane_16 - : MVE_VMOV_lane:$Idx), dir> { - bits<3> Idx; - let Inst{22} = 0b0; - let Inst{5} = 0b1; - let Inst{16} = Idx{2}; - let Inst{21} = Idx{1}; - let Inst{6} = Idx{0}; +let Predicates = [HasMVEInt] in { + def : Pat<(v16i8 (ARMvmovImm timm:$simm)), + (v16i8 (MVE_VMOVimmi8 nImmSplatI8:$simm))>; + def : Pat<(v8i16 (ARMvmovImm timm:$simm)), + (v8i16 (MVE_VMOVimmi16 nImmSplatI16:$simm))>; + def : Pat<(v4i32 (ARMvmovImm timm:$simm)), + (v4i32 (MVE_VMOVimmi32 nImmVMOVI32:$simm))>; + + def : Pat<(v8i16 (ARMvmvnImm timm:$simm)), + (v8i16 (MVE_VMVNimmi16 nImmSplatI16:$simm))>; + def : Pat<(v4i32 (ARMvmvnImm timm:$simm)), + (v4i32 (MVE_VMVNimmi32 nImmVMOVI32:$simm))>; + + def : Pat<(v4f32 (ARMvmovFPImm timm:$simm)), + (v4f32 (MVE_VMOVimmf32 nImmVMOVF32:$simm))>; } -class MVE_VMOV_lane_8 - : MVE_VMOV_lane:$Idx), dir> { - bits<4> Idx; - let Inst{22} = 0b1; - let Inst{16} = Idx{3}; - let Inst{21} = Idx{2}; - let Inst{6} = Idx{1}; - let Inst{5} = Idx{0}; +class MVE_VMINMAXA size, + bit bit_12, list pattern=[]> + : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qd_src, MQPR:$Qm), + NoItinerary, iname, suffix, "$Qd, $Qm", vpred_n, "$Qd = $Qd_src", + pattern> { + bits<4> Qd; + bits<4> Qm; + + let Inst{28} = 0b0; + let Inst{25-23} = 0b100; + let Inst{22} = Qd{3}; + let Inst{21-20} = 0b11; + let Inst{19-18} = size; + let Inst{17-16} = 0b11; + let Inst{15-13} = Qd{2-0}; + let Inst{12} = bit_12; + let Inst{11-6} = 0b111010; + let Inst{5} = Qm{3}; + let Inst{4} = 0b0; + let Inst{3-1} = Qm{2-0}; + let Inst{0} = 0b1; } -def MVE_VMOV_from_lane_32 : MVE_VMOV_lane_32< MVE_VMOV_from_lane>; -def MVE_VMOV_to_lane_32 : MVE_VMOV_lane_32< MVE_VMOV_to_lane>; -def MVE_VMOV_from_lane_s16 : MVE_VMOV_lane_16<"s16", 0b0, MVE_VMOV_from_lane>; -def MVE_VMOV_from_lane_u16 : MVE_VMOV_lane_16<"u16", 0b1, MVE_VMOV_from_lane>; -def MVE_VMOV_to_lane_16 : MVE_VMOV_lane_16< "16", 0b0, MVE_VMOV_to_lane>; -def MVE_VMOV_from_lane_s8 : MVE_VMOV_lane_8 < "s8", 0b0, MVE_VMOV_from_lane>; -def MVE_VMOV_from_lane_u8 : MVE_VMOV_lane_8 < "u8", 0b1, MVE_VMOV_from_lane>; -def MVE_VMOV_to_lane_8 : MVE_VMOV_lane_8 < "8", 0b0, MVE_VMOV_to_lane>; +def MVE_VMAXAs8 : MVE_VMINMAXA<"vmaxa", "s8", 0b00, 0b0>; +def MVE_VMAXAs16 : MVE_VMINMAXA<"vmaxa", "s16", 0b01, 0b0>; +def MVE_VMAXAs32 : MVE_VMINMAXA<"vmaxa", "s32", 0b10, 0b0>; -let Predicates = [HasMVEInt] in { - def : Pat<(extractelt (v2f64 MQPR:$src), imm:$lane), - (f64 (EXTRACT_SUBREG MQPR:$src, (DSubReg_f64_reg imm:$lane)))>; - def : Pat<(insertelt (v2f64 MQPR:$src1), DPR:$src2, imm:$lane), - (INSERT_SUBREG (v2f64 (COPY_TO_REGCLASS MQPR:$src1, MQPR)), DPR:$src2, (DSubReg_f64_reg imm:$lane))>; +def MVE_VMINAs8 : MVE_VMINMAXA<"vmina", "s8", 0b00, 0b1>; +def MVE_VMINAs16 : MVE_VMINMAXA<"vmina", "s16", 0b01, 0b1>; +def MVE_VMINAs32 : MVE_VMINMAXA<"vmina", "s32", 0b10, 0b1>; - def : Pat<(extractelt (v4i32 MQPR:$src), imm:$lane), - (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG MQPR:$src, (SSubReg_f32_reg imm:$lane))), rGPR)>; - def : Pat<(insertelt (v4i32 MQPR:$src1), rGPR:$src2, imm:$lane), - (MVE_VMOV_to_lane_32 MQPR:$src1, rGPR:$src2, imm:$lane)>; +// end of MVE Integer instructions - def : Pat<(vector_insert (v16i8 MQPR:$src1), rGPR:$src2, imm:$lane), - (MVE_VMOV_to_lane_8 MQPR:$src1, rGPR:$src2, imm:$lane)>; - def : Pat<(vector_insert (v8i16 MQPR:$src1), rGPR:$src2, imm:$lane), - (MVE_VMOV_to_lane_16 MQPR:$src1, rGPR:$src2, imm:$lane)>; +// start of mve_imm_shift instructions - def : Pat<(ARMvgetlanes (v16i8 MQPR:$src), imm:$lane), - (MVE_VMOV_from_lane_s8 MQPR:$src, imm:$lane)>; - def : Pat<(ARMvgetlanes (v8i16 MQPR:$src), imm:$lane), - (MVE_VMOV_from_lane_s16 MQPR:$src, imm:$lane)>; - def : Pat<(ARMvgetlaneu (v16i8 MQPR:$src), imm:$lane), - (MVE_VMOV_from_lane_u8 MQPR:$src, imm:$lane)>; - def : Pat<(ARMvgetlaneu (v8i16 MQPR:$src), imm:$lane), - (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane)>; +def MVE_VSHLC : MVE_p<(outs rGPR:$RdmDest, MQPR:$Qd), + (ins MQPR:$QdSrc, rGPR:$RdmSrc, long_shift:$imm), + NoItinerary, "vshlc", "", "$QdSrc, $RdmSrc, $imm", + vpred_n, "$RdmDest = $RdmSrc,$Qd = $QdSrc"> { + bits<5> imm; + bits<4> Qd; + bits<4> RdmDest; - def : Pat<(v16i8 (scalar_to_vector GPR:$src)), - (MVE_VMOV_to_lane_8 (v16i8 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; - def : Pat<(v8i16 (scalar_to_vector GPR:$src)), - (MVE_VMOV_to_lane_16 (v8i16 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; - def : Pat<(v4i32 (scalar_to_vector GPR:$src)), - (MVE_VMOV_to_lane_32 (v4i32 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; + let Inst{28} = 0b0; + let Inst{25-23} = 0b101; + let Inst{22} = Qd{3}; + let Inst{21} = 0b1; + let Inst{20-16} = imm{4-0}; + let Inst{15-13} = Qd{2-0}; + let Inst{12-4} = 0b011111100; + let Inst{3-0} = RdmDest{3-0}; +} - // Floating point patterns, still enabled under HasMVEInt - def : Pat<(extractelt (v4f32 MQPR:$src), imm:$lane), - (COPY_TO_REGCLASS (f32 (EXTRACT_SUBREG MQPR:$src, (SSubReg_f32_reg imm:$lane))), SPR)>; - def : Pat<(insertelt (v4f32 MQPR:$src1), (f32 SPR:$src2), imm:$lane), - (INSERT_SUBREG (v4f32 (COPY_TO_REGCLASS MQPR:$src1, MQPR)), SPR:$src2, (SSubReg_f32_reg imm:$lane))>; +class MVE_shift_imm pattern=[]> + : MVE_p { + bits<4> Qd; + bits<4> Qm; - def : Pat<(insertelt (v8f16 MQPR:$src1), HPR:$src2, imm:$lane), - (MVE_VMOV_to_lane_16 MQPR:$src1, (COPY_TO_REGCLASS HPR:$src2, rGPR), imm:$lane)>; - def : Pat<(extractelt (v8f16 MQPR:$src), imm:$lane), - (COPY_TO_REGCLASS (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane), HPR)>; + let Inst{22} = Qd{3}; + let Inst{15-13} = Qd{2-0}; + let Inst{5} = Qm{3}; + let Inst{3-1} = Qm{2-0}; +} - def : Pat<(v4f32 (scalar_to_vector SPR:$src)), - (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), SPR:$src, ssub_0)>; - def : Pat<(v4f32 (scalar_to_vector GPR:$src)), - (MVE_VMOV_to_lane_32 (v4f32 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; - def : Pat<(v8f16 (scalar_to_vector HPR:$src)), - (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), HPR:$src, ssub_0)>; - def : Pat<(v8f16 (scalar_to_vector GPR:$src)), - (MVE_VMOV_to_lane_16 (v8f16 (IMPLICIT_DEF)), rGPR:$src, (i32 0))>; +class MVE_VMOVL sz, bit U, + list pattern=[]> + : MVE_shift_imm<(outs MQPR:$Qd), (ins MQPR:$Qm), + iname, suffix, "$Qd, $Qm", vpred_r, "", + pattern> { + let Inst{28} = U; + let Inst{25-23} = 0b101; + let Inst{21} = 0b1; + let Inst{20-19} = sz{1-0}; + let Inst{18-16} = 0b000; + let Inst{11-6} = 0b111101; + let Inst{4} = 0b0; + let Inst{0} = 0b0; +} + +multiclass MVE_VMOVL_shift_half sz, bit U, + list pattern=[]> { + def bh : MVE_VMOVL { + let Inst{12} = 0b0; + } + def th : MVE_VMOVL { + let Inst{12} = 0b1; + } } -// end of mve_bit instructions - -// start of MVE Integer instructions +defm MVE_VMOVLs8 : MVE_VMOVL_shift_half<"vmovl", "s8", 0b01, 0b0>; +defm MVE_VMOVLu8 : MVE_VMOVL_shift_half<"vmovl", "u8", 0b01, 0b1>; +defm MVE_VMOVLs16 : MVE_VMOVL_shift_half<"vmovl", "s16", 0b10, 0b0>; +defm MVE_VMOVLu16 : MVE_VMOVL_shift_half<"vmovl", "u16", 0b10, 0b1>; -class MVE_int size, list pattern=[]> - : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qn, MQPR:$Qm), NoItinerary, - iname, suffix, "$Qd, $Qn, $Qm", vpred_r, "", pattern> { - bits<4> Qd; - bits<4> Qn; - bits<4> Qm; +let Predicates = [HasMVEInt] in { + def : Pat<(sext_inreg (v4i32 MQPR:$src), v4i16), + (MVE_VMOVLs16bh MQPR:$src)>; + def : Pat<(sext_inreg (v8i16 MQPR:$src), v8i8), + (MVE_VMOVLs8bh MQPR:$src)>; + def : Pat<(sext_inreg (v4i32 MQPR:$src), v4i8), + (MVE_VMOVLs16bh (MVE_VMOVLs8bh MQPR:$src))>; - let Inst{22} = Qd{3}; - let Inst{21-20} = size; - let Inst{19-17} = Qn{2-0}; - let Inst{15-13} = Qd{2-0}; - let Inst{7} = Qn{3}; - let Inst{6} = 0b1; - let Inst{5} = Qm{3}; - let Inst{3-1} = Qm{2-0}; + // zext_inreg 16 -> 32 + def : Pat<(and (v4i32 MQPR:$src), (v4i32 (ARMvmovImm (i32 0xCFF)))), + (MVE_VMOVLu16bh MQPR:$src)>; + // zext_inreg 8 -> 16 + def : Pat<(and (v8i16 MQPR:$src), (v8i16 (ARMvmovImm (i32 0x8FF)))), + (MVE_VMOVLu8bh MQPR:$src)>; } -class MVE_VMULt1 size, list pattern=[]> - : MVE_int<"vmul", suffix, size, pattern> { - let Inst{28} = 0b0; - let Inst{25-23} = 0b110; - let Inst{16} = 0b0; - let Inst{12-8} = 0b01001; - let Inst{4} = 0b1; +class MVE_VSHLL_imm pattern=[]> + : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$Qm), immops), + iname, suffix, "$Qd, $Qm, $imm", vpred_r, "", pattern> { + let Inst{28} = U; + let Inst{25-23} = 0b101; + let Inst{21} = 0b1; + let Inst{12} = th; + let Inst{11-6} = 0b111101; + let Inst{4} = 0b0; let Inst{0} = 0b0; } -def MVE_VMULt1i8 : MVE_VMULt1<"i8", 0b00>; -def MVE_VMULt1i16 : MVE_VMULt1<"i16", 0b01>; -def MVE_VMULt1i32 : MVE_VMULt1<"i32", 0b10>; +// The immediate VSHLL instructions accept shift counts from 1 up to +// the lane width (8 or 16), but the full-width shifts have an +// entirely separate encoding, given below with 'lw' in the name. -let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (mul (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), - (v16i8 (MVE_VMULt1i8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; - def : Pat<(v8i16 (mul (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), - (v8i16 (MVE_VMULt1i16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; - def : Pat<(v4i32 (mul (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), - (v4i32 (MVE_VMULt1i32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; +class MVE_VSHLL_imm8 pattern=[]> + : MVE_VSHLL_imm { + bits<3> imm; + let Inst{20-19} = 0b01; + let Inst{18-16} = imm; } -class MVE_VQxDMULH size, bit rounding, - list pattern=[]> - : MVE_int { +class MVE_VSHLL_imm16 pattern=[]> + : MVE_VSHLL_imm { + bits<4> imm; + let Inst{20} = 0b1; + let Inst{19-16} = imm; +} - let Inst{28} = rounding; - let Inst{25-23} = 0b110; - let Inst{16} = 0b0; - let Inst{12-8} = 0b01011; +def MVE_VSHLL_imms8bh : MVE_VSHLL_imm8 <"vshllb", "s8", 0b0, 0b0>; +def MVE_VSHLL_imms8th : MVE_VSHLL_imm8 <"vshllt", "s8", 0b0, 0b1>; +def MVE_VSHLL_immu8bh : MVE_VSHLL_imm8 <"vshllb", "u8", 0b1, 0b0>; +def MVE_VSHLL_immu8th : MVE_VSHLL_imm8 <"vshllt", "u8", 0b1, 0b1>; +def MVE_VSHLL_imms16bh : MVE_VSHLL_imm16<"vshllb", "s16", 0b0, 0b0>; +def MVE_VSHLL_imms16th : MVE_VSHLL_imm16<"vshllt", "s16", 0b0, 0b1>; +def MVE_VSHLL_immu16bh : MVE_VSHLL_imm16<"vshllb", "u16", 0b1, 0b0>; +def MVE_VSHLL_immu16th : MVE_VSHLL_imm16<"vshllt", "u16", 0b1, 0b1>; + +class MVE_VSHLL_by_lane_width size, + bit U, string ops, list pattern=[]> + : MVE_shift_imm<(outs MQPR:$Qd), (ins MQPR:$Qm), + iname, suffix, ops, vpred_r, "", pattern> { + let Inst{28} = U; + let Inst{25-23} = 0b100; + let Inst{21-20} = 0b11; + let Inst{19-18} = size{1-0}; + let Inst{17-16} = 0b01; + let Inst{11-6} = 0b111000; let Inst{4} = 0b0; - let Inst{0} = 0b0; + let Inst{0} = 0b1; } -class MVE_VQDMULH size, list pattern=[]> - : MVE_VQxDMULH<"vqdmulh", suffix, size, 0b0, pattern>; -class MVE_VQRDMULH size, list pattern=[]> - : MVE_VQxDMULH<"vqrdmulh", suffix, size, 0b1, pattern>; - -def MVE_VQDMULHi8 : MVE_VQDMULH<"s8", 0b00>; -def MVE_VQDMULHi16 : MVE_VQDMULH<"s16", 0b01>; -def MVE_VQDMULHi32 : MVE_VQDMULH<"s32", 0b10>; +multiclass MVE_VSHLL_lw sz, bit U, + string ops, list pattern=[]> { + def bh : MVE_VSHLL_by_lane_width { + let Inst{12} = 0b0; + } + def th : MVE_VSHLL_by_lane_width { + let Inst{12} = 0b1; + } +} -def MVE_VQRDMULHi8 : MVE_VQRDMULH<"s8", 0b00>; -def MVE_VQRDMULHi16 : MVE_VQRDMULH<"s16", 0b01>; -def MVE_VQRDMULHi32 : MVE_VQRDMULH<"s32", 0b10>; +defm MVE_VSHLL_lws8 : MVE_VSHLL_lw<"vshll", "s8", 0b00, 0b0, "$Qd, $Qm, #8">; +defm MVE_VSHLL_lws16 : MVE_VSHLL_lw<"vshll", "s16", 0b01, 0b0, "$Qd, $Qm, #16">; +defm MVE_VSHLL_lwu8 : MVE_VSHLL_lw<"vshll", "u8", 0b00, 0b1, "$Qd, $Qm, #8">; +defm MVE_VSHLL_lwu16 : MVE_VSHLL_lw<"vshll", "u16", 0b01, 0b1, "$Qd, $Qm, #16">; -class MVE_VADDSUB size, bit subtract, - list pattern=[]> - : MVE_int { +class MVE_VxSHRN pattern=[]> + : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops), + iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc", + pattern> { + bits<5> imm; - let Inst{28} = subtract; - let Inst{25-23} = 0b110; - let Inst{16} = 0b0; - let Inst{12-8} = 0b01000; + let Inst{28} = bit_28; + let Inst{25-23} = 0b101; + let Inst{21} = 0b0; + let Inst{20-16} = imm{4-0}; + let Inst{12} = bit_12; + let Inst{11-6} = 0b111111; let Inst{4} = 0b0; - let Inst{0} = 0b0; + let Inst{0} = 0b1; } -class MVE_VADD size, list pattern=[]> - : MVE_VADDSUB<"vadd", suffix, size, 0b0, pattern>; -class MVE_VSUB size, list pattern=[]> - : MVE_VADDSUB<"vsub", suffix, size, 0b1, pattern>; +def MVE_VRSHRNi16bh : MVE_VxSHRN< + "vrshrnb", "i16", 0b0, 0b1, (ins shr_imm8:$imm)> { + let Inst{20-19} = 0b01; +} +def MVE_VRSHRNi16th : MVE_VxSHRN< + "vrshrnt", "i16", 0b1, 0b1,(ins shr_imm8:$imm)> { + let Inst{20-19} = 0b01; +} +def MVE_VRSHRNi32bh : MVE_VxSHRN< + "vrshrnb", "i32", 0b0, 0b1, (ins shr_imm16:$imm)> { + let Inst{20} = 0b1; +} +def MVE_VRSHRNi32th : MVE_VxSHRN< + "vrshrnt", "i32", 0b1, 0b1, (ins shr_imm16:$imm)> { + let Inst{20} = 0b1; +} -def MVE_VADDi8 : MVE_VADD<"i8", 0b00>; -def MVE_VADDi16 : MVE_VADD<"i16", 0b01>; -def MVE_VADDi32 : MVE_VADD<"i32", 0b10>; +def MVE_VSHRNi16bh : MVE_VxSHRN< + "vshrnb", "i16", 0b0, 0b0, (ins shr_imm8:$imm)> { + let Inst{20-19} = 0b01; +} +def MVE_VSHRNi16th : MVE_VxSHRN< + "vshrnt", "i16", 0b1, 0b0, (ins shr_imm8:$imm)> { + let Inst{20-19} = 0b01; +} +def MVE_VSHRNi32bh : MVE_VxSHRN< + "vshrnb", "i32", 0b0, 0b0, (ins shr_imm16:$imm)> { + let Inst{20} = 0b1; +} +def MVE_VSHRNi32th : MVE_VxSHRN< + "vshrnt", "i32", 0b1, 0b0, (ins shr_imm16:$imm)> { + let Inst{20} = 0b1; +} -let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (add (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), - (v16i8 (MVE_VADDi8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; - def : Pat<(v8i16 (add (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), - (v8i16 (MVE_VADDi16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; - def : Pat<(v4i32 (add (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), - (v4i32 (MVE_VADDi32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; +class MVE_VxQRSHRUN pattern=[]> + : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops), + iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc", + pattern> { + bits<5> imm; + + let Inst{28} = bit_28; + let Inst{25-23} = 0b101; + let Inst{21} = 0b0; + let Inst{20-16} = imm{4-0}; + let Inst{12} = bit_12; + let Inst{11-6} = 0b111111; + let Inst{4} = 0b0; + let Inst{0} = 0b0; } -def MVE_VSUBi8 : MVE_VSUB<"i8", 0b00>; -def MVE_VSUBi16 : MVE_VSUB<"i16", 0b01>; -def MVE_VSUBi32 : MVE_VSUB<"i32", 0b10>; +def MVE_VQRSHRUNs16bh : MVE_VxQRSHRUN< + "vqrshrunb", "s16", 0b1, 0b0, (ins shr_imm8:$imm)> { + let Inst{20-19} = 0b01; +} +def MVE_VQRSHRUNs16th : MVE_VxQRSHRUN< + "vqrshrunt", "s16", 0b1, 0b1, (ins shr_imm8:$imm)> { + let Inst{20-19} = 0b01; +} +def MVE_VQRSHRUNs32bh : MVE_VxQRSHRUN< + "vqrshrunb", "s32", 0b1, 0b0, (ins shr_imm16:$imm)> { + let Inst{20} = 0b1; +} +def MVE_VQRSHRUNs32th : MVE_VxQRSHRUN< + "vqrshrunt", "s32", 0b1, 0b1, (ins shr_imm16:$imm)> { + let Inst{20} = 0b1; +} -let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (sub (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))), - (v16i8 (MVE_VSUBi8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>; - def : Pat<(v8i16 (sub (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))), - (v8i16 (MVE_VSUBi16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>; - def : Pat<(v4i32 (sub (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))), - (v4i32 (MVE_VSUBi32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>; +def MVE_VQSHRUNs16bh : MVE_VxQRSHRUN< + "vqshrunb", "s16", 0b0, 0b0, (ins shr_imm8:$imm)> { + let Inst{20-19} = 0b01; } +def MVE_VQSHRUNs16th : MVE_VxQRSHRUN< + "vqshrunt", "s16", 0b0, 0b1, (ins shr_imm8:$imm)> { + let Inst{20-19} = 0b01; +} +def MVE_VQSHRUNs32bh : MVE_VxQRSHRUN< + "vqshrunb", "s32", 0b0, 0b0, (ins shr_imm16:$imm)> { + let Inst{20} = 0b1; +} +def MVE_VQSHRUNs32th : MVE_VxQRSHRUN< + "vqshrunt", "s32", 0b0, 0b1, (ins shr_imm16:$imm)> { + let Inst{20} = 0b1; +} + +class MVE_VxQRSHRN pattern=[]> + : MVE_shift_imm<(outs MQPR:$Qd), !con((ins MQPR:$QdSrc, MQPR:$Qm), immops), + iname, suffix, "$Qd, $Qm, $imm", vpred_n, "$Qd = $QdSrc", + pattern> { + bits<5> imm; -class MVE_VQADDSUB size, list pattern=[]> - : MVE_int { + let Inst{25-23} = 0b101; + let Inst{21} = 0b0; + let Inst{20-16} = imm{4-0}; + let Inst{12} = bit_12; + let Inst{11-6} = 0b111101; + let Inst{4} = 0b0; + let Inst{0} = bit_0; +} - let Inst{28} = U; - let Inst{25-23} = 0b110; - let Inst{16} = 0b0; - let Inst{12-10} = 0b000; - let Inst{9} = subtract; - let Inst{8} = 0b0; - let Inst{4} = 0b1; - let Inst{0} = 0b0; +multiclass MVE_VxQRSHRN_types { + def s16 : MVE_VxQRSHRN { + let Inst{28} = 0b0; + let Inst{20-19} = 0b01; + } + def u16 : MVE_VxQRSHRN { + let Inst{28} = 0b1; + let Inst{20-19} = 0b01; + } + def s32 : MVE_VxQRSHRN { + let Inst{28} = 0b0; + let Inst{20} = 0b1; + } + def u32 : MVE_VxQRSHRN { + let Inst{28} = 0b1; + let Inst{20} = 0b1; + } } -class MVE_VQADD size, list pattern=[]> - : MVE_VQADDSUB<"vqadd", suffix, U, 0b0, size, pattern>; -class MVE_VQSUB size, list pattern=[]> - : MVE_VQADDSUB<"vqsub", suffix, U, 0b1, size, pattern>; +defm MVE_VQRSHRNbh : MVE_VxQRSHRN_types<"vqrshrnb", 0b1, 0b0>; +defm MVE_VQRSHRNth : MVE_VxQRSHRN_types<"vqrshrnt", 0b1, 0b1>; +defm MVE_VQSHRNbh : MVE_VxQRSHRN_types<"vqshrnb", 0b0, 0b0>; +defm MVE_VQSHRNth : MVE_VxQRSHRN_types<"vqshrnt", 0b0, 0b1>; -def MVE_VQADDs8 : MVE_VQADD<"s8", 0b0, 0b00>; -def MVE_VQADDs16 : MVE_VQADD<"s16", 0b0, 0b01>; -def MVE_VQADDs32 : MVE_VQADD<"s32", 0b0, 0b10>; -def MVE_VQADDu8 : MVE_VQADD<"u8", 0b1, 0b00>; -def MVE_VQADDu16 : MVE_VQADD<"u16", 0b1, 0b01>; -def MVE_VQADDu32 : MVE_VQADD<"u32", 0b1, 0b10>; +// end of mve_imm_shift instructions -def MVE_VQSUBs8 : MVE_VQSUB<"s8", 0b0, 0b00>; -def MVE_VQSUBs16 : MVE_VQSUB<"s16", 0b0, 0b01>; -def MVE_VQSUBs32 : MVE_VQSUB<"s32", 0b0, 0b10>; -def MVE_VQSUBu8 : MVE_VQSUB<"u8", 0b1, 0b00>; -def MVE_VQSUBu16 : MVE_VQSUB<"u16", 0b1, 0b01>; -def MVE_VQSUBu32 : MVE_VQSUB<"u32", 0b1, 0b10>; +// start of mve_shift instructions -class MVE_VABD_int size, list pattern=[]> - : MVE_int<"vabd", suffix, size, pattern> { +class MVE_shift_by_vec size, bit bit_4, bit bit_8> + : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qm, MQPR:$Qn), NoItinerary, + iname, suffix, "$Qd, $Qm, $Qn", vpred_r, "", []> { + // Shift instructions which take a vector of shift counts + bits<4> Qd; + bits<4> Qm; + bits<4> Qn; let Inst{28} = U; - let Inst{25-23} = 0b110; + let Inst{25-24} = 0b11; + let Inst{23} = 0b0; + let Inst{22} = Qd{3}; + let Inst{21-20} = size; + let Inst{19-17} = Qn{2-0}; let Inst{16} = 0b0; - let Inst{12-8} = 0b00111; - let Inst{4} = 0b0; + let Inst{15-13} = Qd{2-0}; + let Inst{12-9} = 0b0010; + let Inst{8} = bit_8; + let Inst{7} = Qn{3}; + let Inst{6} = 0b1; + let Inst{5} = Qm{3}; + let Inst{4} = bit_4; + let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; } -def MVE_VABDs8 : MVE_VABD_int<"s8", 0b0, 0b00>; -def MVE_VABDs16 : MVE_VABD_int<"s16", 0b0, 0b01>; -def MVE_VABDs32 : MVE_VABD_int<"s32", 0b0, 0b10>; -def MVE_VABDu8 : MVE_VABD_int<"u8", 0b1, 0b00>; -def MVE_VABDu16 : MVE_VABD_int<"u16", 0b1, 0b01>; -def MVE_VABDu32 : MVE_VABD_int<"u32", 0b1, 0b10>; - -class MVE_VRHADD size, list pattern=[]> - : MVE_int<"vrhadd", suffix, size, pattern> { - - let Inst{28} = U; - let Inst{25-23} = 0b110; - let Inst{16} = 0b0; - let Inst{12-8} = 0b00001; - let Inst{4} = 0b0; - let Inst{0} = 0b0; +multiclass mve_shift_by_vec_multi { + def s8 : MVE_shift_by_vec; + def s16 : MVE_shift_by_vec; + def s32 : MVE_shift_by_vec; + def u8 : MVE_shift_by_vec; + def u16 : MVE_shift_by_vec; + def u32 : MVE_shift_by_vec; } -def MVE_VRHADDs8 : MVE_VRHADD<"s8", 0b0, 0b00>; -def MVE_VRHADDs16 : MVE_VRHADD<"s16", 0b0, 0b01>; -def MVE_VRHADDs32 : MVE_VRHADD<"s32", 0b0, 0b10>; -def MVE_VRHADDu8 : MVE_VRHADD<"u8", 0b1, 0b00>; -def MVE_VRHADDu16 : MVE_VRHADD<"u16", 0b1, 0b01>; -def MVE_VRHADDu32 : MVE_VRHADD<"u32", 0b1, 0b10>; +defm MVE_VSHL_by_vec : mve_shift_by_vec_multi<"vshl", 0b0, 0b0>; +defm MVE_VQSHL_by_vec : mve_shift_by_vec_multi<"vqshl", 0b1, 0b0>; +defm MVE_VQRSHL_by_vec : mve_shift_by_vec_multi<"vqrshl", 0b1, 0b1>; +defm MVE_VRSHL_by_vec : mve_shift_by_vec_multi<"vrshl", 0b0, 0b1>; -class MVE_VHADDSUB size, list pattern=[]> - : MVE_int { +class MVE_shift_with_imm pattern=[]> + : MVE_p { + bits<4> Qd; + bits<4> Qm; - let Inst{28} = U; - let Inst{25-23} = 0b110; - let Inst{16} = 0b0; - let Inst{12-10} = 0b000; - let Inst{9} = subtract; - let Inst{8} = 0b0; - let Inst{4} = 0b0; + let Inst{23} = 0b1; + let Inst{22} = Qd{3}; + let Inst{15-13} = Qd{2-0}; + let Inst{12-11} = 0b00; + let Inst{7-6} = 0b01; + let Inst{5} = Qm{3}; + let Inst{4} = 0b1; + let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; } -class MVE_VHADD size, - list pattern=[]> - : MVE_VHADDSUB<"vhadd", suffix, U, 0b0, size, pattern>; -class MVE_VHSUB size, - list pattern=[]> - : MVE_VHADDSUB<"vhsub", suffix, U, 0b1, size, pattern>; - -def MVE_VHADDs8 : MVE_VHADD<"s8", 0b0, 0b00>; -def MVE_VHADDs16 : MVE_VHADD<"s16", 0b0, 0b01>; -def MVE_VHADDs32 : MVE_VHADD<"s32", 0b0, 0b10>; -def MVE_VHADDu8 : MVE_VHADD<"u8", 0b1, 0b00>; -def MVE_VHADDu16 : MVE_VHADD<"u16", 0b1, 0b01>; -def MVE_VHADDu32 : MVE_VHADD<"u32", 0b1, 0b10>; - -def MVE_VHSUBs8 : MVE_VHSUB<"s8", 0b0, 0b00>; -def MVE_VHSUBs16 : MVE_VHSUB<"s16", 0b0, 0b01>; -def MVE_VHSUBs32 : MVE_VHSUB<"s32", 0b0, 0b10>; -def MVE_VHSUBu8 : MVE_VHSUB<"u8", 0b1, 0b00>; -def MVE_VHSUBu16 : MVE_VHSUB<"u16", 0b1, 0b01>; -def MVE_VHSUBu32 : MVE_VHSUB<"u32", 0b1, 0b10>; - -class MVE_VDUP pattern=[]> - : MVE_p<(outs MQPR:$Qd), (ins rGPR:$Rt), NoItinerary, - "vdup", suffix, "$Qd, $Rt", vpred_r, "", pattern> { - bits<4> Qd; - bits<4> Rt; +class MVE_VSxI_imm + : MVE_shift_with_imm { + bits<6> imm; + let Inst{28} = 0b1; + let Inst{25-24} = 0b11; + let Inst{21-16} = imm; + let Inst{10-9} = 0b10; + let Inst{8} = bit_8; +} - let Inst{28} = 0b0; - let Inst{25-23} = 0b101; - let Inst{22} = B; - let Inst{21-20} = 0b10; - let Inst{19-17} = Qd{2-0}; - let Inst{16} = 0b0; - let Inst{15-12} = Rt; - let Inst{11-8} = 0b1011; - let Inst{7} = Qd{3}; - let Inst{6} = 0b0; - let Inst{5} = E; - let Inst{4-0} = 0b10000; +def MVE_VSRIimm8 : MVE_VSxI_imm<"vsri", "8", 0b0, (ins shr_imm8:$imm)> { + let Inst{21-19} = 0b001; } -def MVE_VDUP32 : MVE_VDUP<"32", 0b0, 0b0>; -def MVE_VDUP16 : MVE_VDUP<"16", 0b0, 0b1>; -def MVE_VDUP8 : MVE_VDUP<"8", 0b1, 0b0>; +def MVE_VSRIimm16 : MVE_VSxI_imm<"vsri", "16", 0b0, (ins shr_imm16:$imm)> { + let Inst{21-20} = 0b01; +} -let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (ARMvdup (i32 rGPR:$elem))), - (MVE_VDUP8 rGPR:$elem)>; - def : Pat<(v8i16 (ARMvdup (i32 rGPR:$elem))), - (MVE_VDUP16 rGPR:$elem)>; - def : Pat<(v4i32 (ARMvdup (i32 rGPR:$elem))), - (MVE_VDUP32 rGPR:$elem)>; +def MVE_VSRIimm32 : MVE_VSxI_imm<"vsri", "32", 0b0, (ins shr_imm32:$imm)> { + let Inst{21} = 0b1; +} - def : Pat<(v4i32 (ARMvduplane (v4i32 MQPR:$src), imm:$lane)), - (MVE_VDUP32 (MVE_VMOV_from_lane_32 MQPR:$src, imm:$lane))>; - // For the 16-bit and 8-bit vduplanes we don't care about the signedness - // of the lane move operation as we only want the lowest 8/16 bits anyway. - def : Pat<(v8i16 (ARMvduplane (v8i16 MQPR:$src), imm:$lane)), - (MVE_VDUP16 (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane))>; - def : Pat<(v16i8 (ARMvduplane (v16i8 MQPR:$src), imm:$lane)), - (MVE_VDUP8 (MVE_VMOV_from_lane_u8 MQPR:$src, imm:$lane))>; +def MVE_VSLIimm8 : MVE_VSxI_imm<"vsli", "8", 0b1, (ins imm0_7:$imm)> { + let Inst{21-19} = 0b001; +} - def : Pat<(v4f32 (ARMvdup (f32 SPR:$elem))), - (v4f32 (MVE_VDUP32 (i32 (COPY_TO_REGCLASS (f32 SPR:$elem), rGPR))))>; - def : Pat<(v8f16 (ARMvdup (f16 HPR:$elem))), - (v8f16 (MVE_VDUP16 (i32 (COPY_TO_REGCLASS (f16 HPR:$elem), rGPR))))>; +def MVE_VSLIimm16 : MVE_VSxI_imm<"vsli", "16", 0b1, (ins imm0_15:$imm)> { + let Inst{21-20} = 0b01; +} - def : Pat<(v4f32 (ARMvduplane (v4f32 MQPR:$src), imm:$lane)), - (MVE_VDUP32 (MVE_VMOV_from_lane_32 MQPR:$src, imm:$lane))>; - def : Pat<(v8f16 (ARMvduplane (v8f16 MQPR:$src), imm:$lane)), - (MVE_VDUP16 (MVE_VMOV_from_lane_u16 MQPR:$src, imm:$lane))>; +def MVE_VSLIimm32 : MVE_VSxI_imm<"vsli", "32", 0b1,(ins imm0_31:$imm)> { + let Inst{21} = 0b1; } +class MVE_VQSHL_imm + : MVE_shift_with_imm<"vqshl", suffix, (outs MQPR:$Qd), + !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", + vpred_r, ""> { + bits<6> imm; -class MVEIntSingleSrc size, - list pattern=[]> - : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qm), NoItinerary, - iname, suffix, "$Qd, $Qm", vpred_r, "", pattern> { - bits<4> Qd; - bits<4> Qm; + let Inst{25-24} = 0b11; + let Inst{21-16} = imm; + let Inst{10-8} = 0b111; +} - let Inst{22} = Qd{3}; - let Inst{19-18} = size{1-0}; - let Inst{15-13} = Qd{2-0}; - let Inst{5} = Qm{3}; - let Inst{3-1} = Qm{2-0}; +def MVE_VSLIimms8 : MVE_VQSHL_imm<"s8", (ins imm0_7:$imm)> { + let Inst{28} = 0b0; + let Inst{21-19} = 0b001; } -class MVE_VCLSCLZ size, - bit count_zeroes, list pattern=[]> - : MVEIntSingleSrc { +def MVE_VSLIimmu8 : MVE_VQSHL_imm<"u8", (ins imm0_7:$imm)> { + let Inst{28} = 0b1; + let Inst{21-19} = 0b001; +} + +def MVE_VSLIimms16 : MVE_VQSHL_imm<"s16", (ins imm0_15:$imm)> { + let Inst{28} = 0b0; + let Inst{21-20} = 0b01; +} +def MVE_VSLIimmu16 : MVE_VQSHL_imm<"u16", (ins imm0_15:$imm)> { let Inst{28} = 0b1; - let Inst{25-23} = 0b111; - let Inst{21-20} = 0b11; - let Inst{17-16} = 0b00; - let Inst{12-8} = 0b00100; - let Inst{7} = count_zeroes; - let Inst{6} = 0b1; - let Inst{4} = 0b0; - let Inst{0} = 0b0; + let Inst{21-20} = 0b01; } -def MVE_VCLSs8 : MVE_VCLSCLZ<"vcls", "s8", 0b00, 0b0>; -def MVE_VCLSs16 : MVE_VCLSCLZ<"vcls", "s16", 0b01, 0b0>; -def MVE_VCLSs32 : MVE_VCLSCLZ<"vcls", "s32", 0b10, 0b0>; +def MVE_VSLIimms32 : MVE_VQSHL_imm<"s32", (ins imm0_31:$imm)> { + let Inst{28} = 0b0; + let Inst{21} = 0b1; +} -def MVE_VCLZs8 : MVE_VCLSCLZ<"vclz", "i8", 0b00, 0b1>; -def MVE_VCLZs16 : MVE_VCLSCLZ<"vclz", "i16", 0b01, 0b1>; -def MVE_VCLZs32 : MVE_VCLSCLZ<"vclz", "i32", 0b10, 0b1>; +def MVE_VSLIimmu32 : MVE_VQSHL_imm<"u32", (ins imm0_31:$imm)> { + let Inst{28} = 0b1; + let Inst{21} = 0b1; +} -class MVE_VABSNEG_int size, bit negate, - list pattern=[]> - : MVEIntSingleSrc { +class MVE_VQSHLU_imm + : MVE_shift_with_imm<"vqshlu", suffix, (outs MQPR:$Qd), + !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", + vpred_r, ""> { + bits<6> imm; let Inst{28} = 0b1; - let Inst{25-23} = 0b111; - let Inst{21-20} = 0b11; - let Inst{17-16} = 0b01; - let Inst{12-8} = 0b00011; - let Inst{7} = negate; - let Inst{6} = 0b1; - let Inst{4} = 0b0; - let Inst{0} = 0b0; + let Inst{25-24} = 0b11; + let Inst{21-16} = imm; + let Inst{10-8} = 0b110; } -def MVE_VABSs8 : MVE_VABSNEG_int<"vabs", "s8", 0b00, 0b0>; -def MVE_VABSs16 : MVE_VABSNEG_int<"vabs", "s16", 0b01, 0b0>; -def MVE_VABSs32 : MVE_VABSNEG_int<"vabs", "s32", 0b10, 0b0>; +def MVE_VQSHLU_imms8 : MVE_VQSHLU_imm<"s8", (ins imm0_7:$imm)> { + let Inst{21-19} = 0b001; +} -let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (abs (v16i8 MQPR:$v))), - (v16i8 (MVE_VABSs8 $v))>; - def : Pat<(v8i16 (abs (v8i16 MQPR:$v))), - (v8i16 (MVE_VABSs16 $v))>; - def : Pat<(v4i32 (abs (v4i32 MQPR:$v))), - (v4i32 (MVE_VABSs32 $v))>; +def MVE_VQSHLU_imms16 : MVE_VQSHLU_imm<"s16", (ins imm0_15:$imm)> { + let Inst{21-20} = 0b01; } -def MVE_VNEGs8 : MVE_VABSNEG_int<"vneg", "s8", 0b00, 0b1>; -def MVE_VNEGs16 : MVE_VABSNEG_int<"vneg", "s16", 0b01, 0b1>; -def MVE_VNEGs32 : MVE_VABSNEG_int<"vneg", "s32", 0b10, 0b1>; +def MVE_VQSHLU_imms32 : MVE_VQSHLU_imm<"s32", (ins imm0_31:$imm)> { + let Inst{21} = 0b1; +} -let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (vnegq (v16i8 MQPR:$v))), - (v16i8 (MVE_VNEGs8 $v))>; - def : Pat<(v8i16 (vnegq (v8i16 MQPR:$v))), - (v8i16 (MVE_VNEGs16 $v))>; - def : Pat<(v4i32 (vnegq (v4i32 MQPR:$v))), - (v4i32 (MVE_VNEGs32 $v))>; +class MVE_VRSHR_imm + : MVE_shift_with_imm<"vrshr", suffix, (outs MQPR:$Qd), + !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", + vpred_r, ""> { + bits<6> imm; + + let Inst{25-24} = 0b11; + let Inst{21-16} = imm; + let Inst{10-8} = 0b010; } -class MVE_VQABSNEG size, - bit negate, list pattern=[]> - : MVEIntSingleSrc { +def MVE_VRSHR_imms8 : MVE_VRSHR_imm<"s8", (ins shr_imm8:$imm)> { + let Inst{28} = 0b0; + let Inst{21-19} = 0b001; +} +def MVE_VRSHR_immu8 : MVE_VRSHR_imm<"u8", (ins shr_imm8:$imm)> { let Inst{28} = 0b1; - let Inst{25-23} = 0b111; - let Inst{21-20} = 0b11; - let Inst{17-16} = 0b00; - let Inst{12-8} = 0b00111; - let Inst{7} = negate; - let Inst{6} = 0b1; - let Inst{4} = 0b0; - let Inst{0} = 0b0; + let Inst{21-19} = 0b001; } -def MVE_VQABSs8 : MVE_VQABSNEG<"vqabs", "s8", 0b00, 0b0>; -def MVE_VQABSs16 : MVE_VQABSNEG<"vqabs", "s16", 0b01, 0b0>; -def MVE_VQABSs32 : MVE_VQABSNEG<"vqabs", "s32", 0b10, 0b0>; - -def MVE_VQNEGs8 : MVE_VQABSNEG<"vqneg", "s8", 0b00, 0b1>; -def MVE_VQNEGs16 : MVE_VQABSNEG<"vqneg", "s16", 0b01, 0b1>; -def MVE_VQNEGs32 : MVE_VQABSNEG<"vqneg", "s32", 0b10, 0b1>; +def MVE_VRSHR_imms16 : MVE_VRSHR_imm<"s16", (ins shr_imm16:$imm)> { + let Inst{28} = 0b0; + let Inst{21-20} = 0b01; +} -class MVE_mod_imm cmode, bit op, - dag iops, list pattern=[]> - : MVE_p<(outs MQPR:$Qd), iops, NoItinerary, iname, suffix, "$Qd, $imm", - vpred_r, "", pattern> { - bits<13> imm; - bits<4> Qd; +def MVE_VRSHR_immu16 : MVE_VRSHR_imm<"u16", (ins shr_imm16:$imm)> { + let Inst{28} = 0b1; + let Inst{21-20} = 0b01; +} - let Inst{28} = imm{7}; - let Inst{25-23} = 0b111; - let Inst{22} = Qd{3}; - let Inst{21-19} = 0b000; - let Inst{18-16} = imm{6-4}; - let Inst{15-13} = Qd{2-0}; - let Inst{12} = 0b0; - let Inst{11-8} = cmode{3-0}; - let Inst{7-6} = 0b01; - let Inst{5} = op; - let Inst{4} = 0b1; - let Inst{3-0} = imm{3-0}; +def MVE_VRSHR_imms32 : MVE_VRSHR_imm<"s32", (ins shr_imm32:$imm)> { + let Inst{28} = 0b0; + let Inst{21} = 0b1; +} - let DecoderMethod = "DecodeMVEModImmInstruction"; +def MVE_VRSHR_immu32 : MVE_VRSHR_imm<"u32", (ins shr_imm32:$imm)> { + let Inst{28} = 0b1; + let Inst{21} = 0b1; } -let isReMaterializable = 1 in { -let isAsCheapAsAMove = 1 in { -def MVE_VMOVimmi8 : MVE_mod_imm<"vmov", "i8", {1,1,1,0}, 0b0, (ins nImmSplatI8:$imm)>; -def MVE_VMOVimmi16 : MVE_mod_imm<"vmov", "i16", {1,0,?,0}, 0b0, (ins nImmSplatI16:$imm)> { - let Inst{9} = imm{9}; +class MVE_VSHR_imm + : MVE_shift_with_imm<"vshr", suffix, (outs MQPR:$Qd), + !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", + vpred_r, ""> { + bits<6> imm; + + let Inst{25-24} = 0b11; + let Inst{21-16} = imm; + let Inst{10-8} = 0b000; } -def MVE_VMOVimmi32 : MVE_mod_imm<"vmov", "i32", {?,?,?,?}, 0b0, (ins nImmVMOVI32:$imm)> { - let Inst{11-8} = imm{11-8}; + +def MVE_VSHR_imms8 : MVE_VSHR_imm<"s8", (ins shr_imm8:$imm)> { + let Inst{28} = 0b0; + let Inst{21-19} = 0b001; } -def MVE_VMOVimmi64 : MVE_mod_imm<"vmov", "i64", {1,1,1,0}, 0b1, (ins nImmSplatI64:$imm)>; -def MVE_VMOVimmf32 : MVE_mod_imm<"vmov", "f32", {1,1,1,1}, 0b0, (ins nImmVMOVF32:$imm)>; -} // let isAsCheapAsAMove = 1 -def MVE_VMVNimmi16 : MVE_mod_imm<"vmvn", "i16", {1,0,?,0}, 0b1, (ins nImmSplatI16:$imm)> { - let Inst{9} = imm{9}; +def MVE_VSHR_immu8 : MVE_VSHR_imm<"u8", (ins shr_imm8:$imm)> { + let Inst{28} = 0b1; + let Inst{21-19} = 0b001; } -def MVE_VMVNimmi32 : MVE_mod_imm<"vmvn", "i32", {?,?,?,?}, 0b1, (ins nImmVMOVI32:$imm)> { - let Inst{11-8} = imm{11-8}; + +def MVE_VSHR_imms16 : MVE_VSHR_imm<"s16", (ins shr_imm16:$imm)> { + let Inst{28} = 0b0; + let Inst{21-20} = 0b01; } -} // let isReMaterializable = 1 -let Predicates = [HasMVEInt] in { - def : Pat<(v16i8 (ARMvmovImm timm:$simm)), - (v16i8 (MVE_VMOVimmi8 nImmSplatI8:$simm))>; - def : Pat<(v8i16 (ARMvmovImm timm:$simm)), - (v8i16 (MVE_VMOVimmi16 nImmSplatI16:$simm))>; - def : Pat<(v4i32 (ARMvmovImm timm:$simm)), - (v4i32 (MVE_VMOVimmi32 nImmVMOVI32:$simm))>; +def MVE_VSHR_immu16 : MVE_VSHR_imm<"u16", (ins shr_imm16:$imm)> { + let Inst{28} = 0b1; + let Inst{21-20} = 0b01; +} - def : Pat<(v8i16 (ARMvmvnImm timm:$simm)), - (v8i16 (MVE_VMVNimmi16 nImmSplatI16:$simm))>; - def : Pat<(v4i32 (ARMvmvnImm timm:$simm)), - (v4i32 (MVE_VMVNimmi32 nImmVMOVI32:$simm))>; +def MVE_VSHR_imms32 : MVE_VSHR_imm<"s32", (ins shr_imm32:$imm)> { + let Inst{28} = 0b0; + let Inst{21} = 0b1; +} - def : Pat<(v4f32 (ARMvmovFPImm timm:$simm)), - (v4f32 (MVE_VMOVimmf32 nImmVMOVF32:$simm))>; +def MVE_VSHR_immu32 : MVE_VSHR_imm<"u32", (ins shr_imm32:$imm)> { + let Inst{28} = 0b1; + let Inst{21} = 0b1; } -class MVE_VMINMAXA size, - bit bit_12, list pattern=[]> - : MVE_p<(outs MQPR:$Qd), (ins MQPR:$Qd_src, MQPR:$Qm), - NoItinerary, iname, suffix, "$Qd, $Qm", vpred_n, "$Qd = $Qd_src", - pattern> { - bits<4> Qd; - bits<4> Qm; +class MVE_VSHL_imm + : MVE_shift_with_imm<"vshl", suffix, (outs MQPR:$Qd), + !con((ins MQPR:$Qm), imm), "$Qd, $Qm, $imm", + vpred_r, ""> { + bits<6> imm; let Inst{28} = 0b0; - let Inst{25-23} = 0b100; - let Inst{22} = Qd{3}; - let Inst{21-20} = 0b11; - let Inst{19-18} = size; - let Inst{17-16} = 0b11; - let Inst{15-13} = Qd{2-0}; - let Inst{12} = bit_12; - let Inst{11-6} = 0b111010; - let Inst{5} = Qm{3}; - let Inst{4} = 0b0; - let Inst{3-1} = Qm{2-0}; - let Inst{0} = 0b1; + let Inst{25-24} = 0b11; + let Inst{21-16} = imm; + let Inst{10-8} = 0b101; } -def MVE_VMAXAs8 : MVE_VMINMAXA<"vmaxa", "s8", 0b00, 0b0>; -def MVE_VMAXAs16 : MVE_VMINMAXA<"vmaxa", "s16", 0b01, 0b0>; -def MVE_VMAXAs32 : MVE_VMINMAXA<"vmaxa", "s32", 0b10, 0b0>; +def MVE_VSHL_immi8 : MVE_VSHL_imm<"i8", (ins imm0_7:$imm)> { + let Inst{21-19} = 0b001; +} -def MVE_VMINAs8 : MVE_VMINMAXA<"vmina", "s8", 0b00, 0b1>; -def MVE_VMINAs16 : MVE_VMINMAXA<"vmina", "s16", 0b01, 0b1>; -def MVE_VMINAs32 : MVE_VMINMAXA<"vmina", "s32", 0b10, 0b1>; +def MVE_VSHL_immi16 : MVE_VSHL_imm<"i16", (ins imm0_15:$imm)> { + let Inst{21-20} = 0b01; +} -// end of MVE Integer instructions +def MVE_VSHL_immi32 : MVE_VSHL_imm<"i32", (ins imm0_31:$imm)> { + let Inst{21} = 0b1; +} + +// end of mve_shift instructions // start of MVE Floating Point instructions -- 2.40.0