diff options
Diffstat (limited to 'lib/Target/ARM/ARMInstrNEON.td')
| -rw-r--r-- | lib/Target/ARM/ARMInstrNEON.td | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 858136a82078..cd67dded5853 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -108,6 +108,7 @@ def nImmSplatI64 : Operand<i32> { def VectorIndex8Operand : AsmOperandClass { let Name = "VectorIndex8"; } def VectorIndex16Operand : AsmOperandClass { let Name = "VectorIndex16"; } def VectorIndex32Operand : AsmOperandClass { let Name = "VectorIndex32"; } +def VectorIndex64Operand : AsmOperandClass { let Name = "VectorIndex64"; } def VectorIndex8 : Operand<i32>, ImmLeaf<i32, [{ return ((uint64_t)Imm) < 8; }]> { @@ -129,6 +130,13 @@ def VectorIndex32 : Operand<i32>, ImmLeaf<i32, [{ let PrintMethod = "printVectorIndex"; let MIOperandInfo = (ops i32imm); } +def VectorIndex64 : Operand<i32>, ImmLeaf<i32, [{ + return ((uint64_t)Imm) < 1; +}]> { + let ParserMatchClass = VectorIndex64Operand; + let PrintMethod = "printVectorIndex"; + let MIOperandInfo = (ops i32imm); +} // Register list of one D register. def VecListOneDAsmOperand : AsmOperandClass { @@ -1111,6 +1119,22 @@ def : Pat<(vector_insert (v4f32 QPR:$src), (f32 (load addrmode6:$addr)), imm:$lane), (VLD1LNq32Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>; +// A 64-bit subvector insert to the first 128-bit vector position +// is a subregister copy that needs no instruction. +def : Pat<(insert_subvector undef, (v1i64 DPR:$src), (i32 0)), + (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; +def : Pat<(insert_subvector undef, (v2i32 DPR:$src), (i32 0)), + (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; +def : Pat<(insert_subvector undef, (v2f32 DPR:$src), (i32 0)), + (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; +def : Pat<(insert_subvector undef, (v4i16 DPR:$src), (i32 0)), + (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; +def : Pat<(insert_subvector undef, (v4f16 DPR:$src), (i32 0)), + (INSERT_SUBREG (v8f16 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; +def : Pat<(insert_subvector (v16i8 undef), (v8i8 DPR:$src), (i32 0)), + (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; + + let mayLoad = 1, hasSideEffects = 0, hasExtraDefRegAllocReq = 1 in { // ...with address register writeback: @@ -4672,6 +4696,167 @@ def : Pat<(v4f32 (fma (fneg QPR:$Vn), QPR:$Vm, QPR:$src1)), (VFMSfq QPR:$src1, QPR:$Vn, QPR:$Vm)>, Requires<[HasVFP4]>; +// ARMv8.2a dot product instructions. +// We put them in the VFPV8 decoder namespace because the ARM and Thumb +// encodings are the same and thus no further bit twiddling is necessary +// in the disassembler. +let Predicates = [HasDotProd], DecoderNamespace = "VFPV8" in { + +def VUDOTD : N3Vnp<0b11000, 0b10, 0b1101, 0b0, 0b1, + (outs DPR:$Vd), (ins DPR:$Vn, DPR:$Vm), + N3RegFrm, IIC_VDOTPROD, "vudot", "u8", []>; +def VSDOTD : N3Vnp<0b11000, 0b10, 0b1101, 0b0, 0b0, + (outs DPR:$Vd), (ins DPR:$Vn, DPR:$Vm), + N3RegFrm, IIC_VDOTPROD, "vsdot", "s8", []>; +def VUDOTQ : N3Vnp<0b11000, 0b10, 0b1101, 0b1, 0b1, + (outs QPR:$Vd), (ins QPR:$Vn, QPR:$Vm), + N3RegFrm, IIC_VDOTPROD, "vudot", "u8", []>; +def VSDOTQ : N3Vnp<0b11000, 0b10, 0b1101, 0b1, 0b0, + (outs QPR:$Vd), (ins QPR:$Vn, QPR:$Vm), + N3RegFrm, IIC_VDOTPROD, "vsdot", "s8", []>; + +// Indexed dot product instructions: +class DOTI<string opc, string dt, bit Q, bit U, RegisterClass Ty> : + N3Vnp<0b11100, 0b10, 0b1101, Q, U, + (outs Ty:$Vd), (ins Ty:$Vn, DPR_VFP2:$Vm, VectorIndex32:$lane), + N3RegFrm, IIC_VDOTPROD, opc, dt, []> { + bit lane; + let Inst{5} = lane; + let AsmString = !strconcat(opc, ".", dt, "\t$Vd, $Vn, $Vm$lane"); +} + +def VUDOTDI : DOTI<"vudot", "u8", 0b0, 0b1, DPR>; +def VSDOTDI : DOTI<"vsdot", "s8", 0b0, 0b0, DPR>; +def VUDOTQI : DOTI<"vudot", "u8", 0b1, 0b1, QPR>; +def VSDOTQI : DOTI<"vsdot", "s8", 0b1, 0b0, QPR>; + +} // HasDotProd + +// ARMv8.3 complex operations +class BaseN3VCP8ComplexTied<bit op21, bit op4, bit s, bit q, + InstrItinClass itin, dag oops, dag iops, + string opc, string dt, list<dag> pattern> + : N3VCP8<{?,?}, {op21,s}, q, op4, oops, + iops, itin, opc, dt, "$Vd, $Vn, $Vm, $rot", "$src1 = $Vd", pattern>{ + bits<2> rot; + let Inst{24-23} = rot; +} + +class BaseN3VCP8ComplexOdd<bit op23, bit op21, bit op4, bit s, bit q, + InstrItinClass itin, dag oops, dag iops, string opc, + string dt, list<dag> pattern> + : N3VCP8<{?,op23}, {op21,s}, q, op4, oops, + iops, itin, opc, dt, "$Vd, $Vn, $Vm, $rot", "", pattern> { + bits<1> rot; + let Inst{24} = rot; +} + +class BaseN3VCP8ComplexTiedLane32<bit op4, bit s, bit q, InstrItinClass itin, + dag oops, dag iops, string opc, string dt, + list<dag> pattern> + : N3VLaneCP8<s, {?,?}, q, op4, oops, iops, itin, opc, dt, + "$Vd, $Vn, $Vm$lane, $rot", "$src1 = $Vd", pattern> { + bits<2> rot; + bit lane; + + let Inst{21-20} = rot; + let Inst{5} = lane; +} + +class BaseN3VCP8ComplexTiedLane64<bit op4, bit s, bit q, InstrItinClass itin, + dag oops, dag iops, string opc, string dt, + list<dag> pattern> + : N3VLaneCP8<s, {?,?}, q, op4, oops, iops, itin, opc, dt, + "$Vd, $Vn, $Vm$lane, $rot", "$src1 = $Vd", pattern> { + bits<2> rot; + bit lane; + + let Inst{21-20} = rot; + let Inst{5} = Vm{4}; + // This is needed because the lane operand does not have any bits in the + // encoding (it only has one possible value), so we need to manually set it + // to it's default value. + let DecoderMethod = "DecodeNEONComplexLane64Instruction"; +} + +multiclass N3VCP8ComplexTied<bit op21, bit op4, + string OpcodeStr, SDPatternOperator Op> { + let Predicates = [HasNEON,HasV8_3a,HasFullFP16] in { + def v4f16 : BaseN3VCP8ComplexTied<op21, op4, 0, 0, IIC_VMACD, (outs DPR:$Vd), + (ins DPR:$src1, DPR:$Vn, DPR:$Vm, complexrotateop:$rot), + OpcodeStr, "f16", []>; + def v8f16 : BaseN3VCP8ComplexTied<op21, op4, 0, 1, IIC_VMACQ, (outs QPR:$Vd), + (ins QPR:$src1, QPR:$Vn, QPR:$Vm, complexrotateop:$rot), + OpcodeStr, "f16", []>; + } + let Predicates = [HasNEON,HasV8_3a] in { + def v2f32 : BaseN3VCP8ComplexTied<op21, op4, 1, 0, IIC_VMACD, (outs DPR:$Vd), + (ins DPR:$src1, DPR:$Vn, DPR:$Vm, complexrotateop:$rot), + OpcodeStr, "f32", []>; + def v4f32 : BaseN3VCP8ComplexTied<op21, op4, 1, 1, IIC_VMACQ, (outs QPR:$Vd), + (ins QPR:$src1, QPR:$Vn, QPR:$Vm, complexrotateop:$rot), + OpcodeStr, "f32", []>; + } +} + +multiclass N3VCP8ComplexOdd<bit op23, bit op21, bit op4, + string OpcodeStr, SDPatternOperator Op> { + let Predicates = [HasNEON,HasV8_3a,HasFullFP16] in { + def v4f16 : BaseN3VCP8ComplexOdd<op23, op21, op4, 0, 0, IIC_VMACD, + (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$Vm, complexrotateopodd:$rot), + OpcodeStr, "f16", []>; + def v8f16 : BaseN3VCP8ComplexOdd<op23, op21, op4, 0, 1, IIC_VMACQ, + (outs QPR:$Vd), + (ins QPR:$Vn, QPR:$Vm, complexrotateopodd:$rot), + OpcodeStr, "f16", []>; + } + let Predicates = [HasNEON,HasV8_3a] in { + def v2f32 : BaseN3VCP8ComplexOdd<op23, op21, op4, 1, 0, IIC_VMACD, + (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$Vm, complexrotateopodd:$rot), + OpcodeStr, "f32", []>; + def v4f32 : BaseN3VCP8ComplexOdd<op23, op21, op4, 1, 1, IIC_VMACQ, + (outs QPR:$Vd), + (ins QPR:$Vn, QPR:$Vm, complexrotateopodd:$rot), + OpcodeStr, "f32", []>; + } +} + +// These instructions index by pairs of lanes, so the VectorIndexes are twice +// as wide as the data types. +multiclass N3VCP8ComplexTiedLane<bit op4, string OpcodeStr, + SDPatternOperator Op> { + let Predicates = [HasNEON,HasV8_3a,HasFullFP16] in { + def v4f16_indexed : BaseN3VCP8ComplexTiedLane32<op4, 0, 0, IIC_VMACD, + (outs DPR:$Vd), + (ins DPR:$src1, DPR:$Vn, DPR_VFP2:$Vm, + VectorIndex32:$lane, complexrotateop:$rot), + OpcodeStr, "f16", []>; + def v8f16_indexed : BaseN3VCP8ComplexTiedLane32<op4, 0, 1, IIC_VMACQ, + (outs QPR:$Vd), + (ins QPR:$src1, QPR:$Vn, DPR_VFP2:$Vm, + VectorIndex32:$lane, complexrotateop:$rot), + OpcodeStr, "f16", []>; + } + let Predicates = [HasNEON,HasV8_3a] in { + def v2f32_indexed : BaseN3VCP8ComplexTiedLane64<op4, 1, 0, IIC_VMACD, + (outs DPR:$Vd), + (ins DPR:$src1, DPR:$Vn, DPR:$Vm, VectorIndex64:$lane, + complexrotateop:$rot), + OpcodeStr, "f32", []>; + def v4f32_indexed : BaseN3VCP8ComplexTiedLane64<op4, 1, 1, IIC_VMACQ, + (outs QPR:$Vd), + (ins QPR:$src1, QPR:$Vn, DPR:$Vm, VectorIndex64:$lane, + complexrotateop:$rot), + OpcodeStr, "f32", []>; + } +} + +defm VCMLA : N3VCP8ComplexTied<1, 0, "vcmla", null_frag>; +defm VCADD : N3VCP8ComplexOdd<1, 0, 0, "vcadd", null_frag>; +defm VCMLA : N3VCP8ComplexTiedLane<0, "vcmla", null_frag>; + // Vector Subtract Operations. // VSUB : Vector Subtract (integer and floating-point) @@ -5477,6 +5662,12 @@ def : Pat<(v4i32 (NEONvshl (sext (v4i16 DPR:$Rn)), (i32 16))), (VSHLLi16 DPR:$Rn, 16)>; def : Pat<(v2i64 (NEONvshl (sext (v2i32 DPR:$Rn)), (i32 32))), (VSHLLi32 DPR:$Rn, 32)>; +def : Pat<(v8i16 (NEONvshl (anyext (v8i8 DPR:$Rn)), (i32 8))), + (VSHLLi8 DPR:$Rn, 8)>; +def : Pat<(v4i32 (NEONvshl (anyext (v4i16 DPR:$Rn)), (i32 16))), + (VSHLLi16 DPR:$Rn, 16)>; +def : Pat<(v2i64 (NEONvshl (anyext (v2i32 DPR:$Rn)), (i32 32))), + (VSHLLi32 DPR:$Rn, 32)>; // VSHRN : Vector Shift Right and Narrow defm VSHRN : N2VNSh_HSD<0,1,0b1000,0,0,1, IIC_VSHLiD, "vshrn", "i", |
