diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64RegisterInfo.td | 44 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td | 3 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 20 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp | 22 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/SVEInstrFormats.td | 39 | ||||
| -rw-r--r-- | llvm/test/MC/AArch64/SVE/fmul-diagnostics.s | 58 | ||||
| -rw-r--r-- | llvm/test/MC/AArch64/SVE/fmul.s | 36 |
7 files changed, 219 insertions, 3 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td index 182451ceeb0..b2bc642f864 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td @@ -835,12 +835,34 @@ def ZPR : RegisterClass<"AArch64", let Size = 128; } -class ZPRAsmOperand <string name, int Width>: AsmOperandClass { +// SVE restricted 4 bit scalable vector register class +def ZPR_4b : RegisterClass<"AArch64", + [nxv16i8, nxv8i16, nxv4i32, nxv2i64, + nxv2f16, nxv4f16, nxv8f16, + nxv1f32, nxv2f32, nxv4f32, + nxv1f64, nxv2f64], + 128, (sequence "Z%u", 0, 15)> { + let Size = 128; +} + +// SVE restricted 3 bit scalable vector register class +def ZPR_3b : RegisterClass<"AArch64", + [nxv16i8, nxv8i16, nxv4i32, nxv2i64, + nxv2f16, nxv4f16, nxv8f16, + nxv1f32, nxv2f32, nxv4f32, + nxv1f64, nxv2f64], + 128, (sequence "Z%u", 0, 7)> { + let Size = 128; +} + +class ZPRAsmOperand<string name, int Width, string RegClassSuffix = ""> + : AsmOperandClass { let Name = "SVE" # name # "Reg"; let PredicateMethod = "isSVEDataVectorRegOfWidth<" - # Width # ", AArch64::ZPRRegClassID>"; + # Width # ", AArch64::ZPR" + # RegClassSuffix # "RegClassID>"; let RenderMethod = "addRegOperands"; - let DiagnosticType = "InvalidZPR" # Width; + let DiagnosticType = "InvalidZPR" # RegClassSuffix # Width; let ParserMethod = "tryParseSVEDataVector<false, " # !if(!eq(Width, 0), "false", "true") # ">"; } @@ -859,6 +881,22 @@ def ZPR32 : ZPRRegOp<"s", ZPRAsmOp32, ZPR>; def ZPR64 : ZPRRegOp<"d", ZPRAsmOp64, ZPR>; def ZPR128 : ZPRRegOp<"q", ZPRAsmOp128, ZPR>; +def ZPRAsmOp3b8 : ZPRAsmOperand<"Vector3bB", 8, "_3b">; +def ZPRAsmOp3b16 : ZPRAsmOperand<"Vector3bH", 16, "_3b">; +def ZPRAsmOp3b32 : ZPRAsmOperand<"Vector3bS", 32, "_3b">; + +def ZPR3b8 : ZPRRegOp<"b", ZPRAsmOp3b8, ZPR_3b>; +def ZPR3b16 : ZPRRegOp<"h", ZPRAsmOp3b16, ZPR_3b>; +def ZPR3b32 : ZPRRegOp<"s", ZPRAsmOp3b32, ZPR_3b>; + +def ZPRAsmOp4b16 : ZPRAsmOperand<"Vector4bH", 16, "_4b">; +def ZPRAsmOp4b32 : ZPRAsmOperand<"Vector4bS", 32, "_4b">; +def ZPRAsmOp4b64 : ZPRAsmOperand<"Vector4bD", 64, "_4b">; + +def ZPR4b16 : ZPRRegOp<"h", ZPRAsmOp4b16, ZPR_4b>; +def ZPR4b32 : ZPRRegOp<"s", ZPRAsmOp4b32, ZPR_4b>; +def ZPR4b64 : ZPRRegOp<"d", ZPRAsmOp4b64, ZPR_4b>; + class FPRasZPR<int Width> : AsmOperandClass{ let Name = "FPR" # Width # "asZPR"; let PredicateMethod = "isFPRasZPR<AArch64::FPR" # Width # "RegClassID>"; diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 76f114bc820..ee075d0eaa9 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -56,6 +56,9 @@ let Predicates = [HasSVE] in { defm FMUL_ZPmI : sve_fp_2op_i_p_zds<0b010, "fmul", sve_fpimm_half_two>; defm FMAX_ZPmI : sve_fp_2op_i_p_zds<0b110, "fmax", sve_fpimm_zero_one>; + + defm FMUL_ZZZI : sve_fp_fmul_by_indexed_elem<"fmul">; + // Splat immediate (unpredicated) defm DUP_ZI : sve_int_dup_imm<"dup">; defm FDUP_ZI : sve_int_dup_fpimm<"fdup">; diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 37c27fe67eb..61a8205efd5 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -953,6 +953,8 @@ public: RegKind RK; switch (Class) { case AArch64::ZPRRegClassID: + case AArch64::ZPR_3bRegClassID: + case AArch64::ZPR_4bRegClassID: RK = RegKind::SVEDataVector; break; case AArch64::PPRRegClassID: @@ -4093,6 +4095,18 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode, case Match_InvalidZPR64: case Match_InvalidZPR128: return Error(Loc, "invalid element width"); + case Match_InvalidZPR_3b8: + return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b"); + case Match_InvalidZPR_3b16: + return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h"); + case Match_InvalidZPR_3b32: + return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s"); + case Match_InvalidZPR_4b16: + return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h"); + case Match_InvalidZPR_4b32: + return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s"); + case Match_InvalidZPR_4b64: + return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d"); case Match_InvalidSVEPattern: return Error(Loc, "invalid predicate pattern"); case Match_InvalidSVEPredicateAnyReg: @@ -4600,6 +4614,12 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_InvalidZPR32: case Match_InvalidZPR64: case Match_InvalidZPR128: + case Match_InvalidZPR_3b8: + case Match_InvalidZPR_3b16: + case Match_InvalidZPR_3b32: + case Match_InvalidZPR_4b16: + case Match_InvalidZPR_4b32: + case Match_InvalidZPR_4b64: case Match_InvalidSVEPredicateAnyReg: case Match_InvalidSVEPattern: case Match_InvalidSVEPredicateBReg: diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index 6fb8ba0f3f6..b2b542bc944 100644 --- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -91,6 +91,12 @@ static DecodeStatus DecodeDDDDRegisterClass(MCInst &Inst, unsigned RegNo, static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decode); +static DecodeStatus DecodeZPR_4bRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decode); +static DecodeStatus DecodeZPR_3bRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decode); static DecodeStatus DecodeZPR2RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decode); @@ -499,6 +505,22 @@ static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo, return Success; } +static DecodeStatus DecodeZPR_4bRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 15) + return Fail; + return DecodeZPRRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeZPR_3bRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 7) + return Fail; + return DecodeZPRRegisterClass(Inst, RegNo, Address, Decoder); +} + static const unsigned ZZDecoderTable[] = { AArch64::Z0_Z1, AArch64::Z1_Z2, AArch64::Z2_Z3, AArch64::Z3_Z4, AArch64::Z4_Z5, AArch64::Z5_Z6, AArch64::Z6_Z7, AArch64::Z7_Z8, diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index f780ef01a9e..27b1885a4a0 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -781,6 +781,45 @@ multiclass sve_fp_2op_i_p_zds<bits<3> opc, string asm, Operand imm_ty> { def _D : sve_fp_2op_i_p_zds<0b11, opc, asm, ZPR64, imm_ty>; } +//===----------------------------------------------------------------------===// +// SVE Floating Point Multiply - Indexed Group +//===----------------------------------------------------------------------===// + +class sve_fp_fmul_by_indexed_elem<bits<2> sz, string asm, ZPRRegOp zprty, + ZPRRegOp zprty2, Operand itype> +: I<(outs zprty:$Zd), (ins zprty:$Zn, zprty2:$Zm, itype:$iop), + asm, "\t$Zd, $Zn, $Zm$iop", "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + let Inst{31-24} = 0b01100100; + let Inst{23-22} = sz; + let Inst{21} = 0b1; + let Inst{15-10} = 0b001000; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve_fp_fmul_by_indexed_elem<string asm> { + def _H : sve_fp_fmul_by_indexed_elem<{0, ?}, asm, ZPR16, ZPR3b16, VectorIndexH> { + bits<3> Zm; + bits<3> iop; + let Inst{22} = iop{2}; + let Inst{20-19} = iop{1-0}; + let Inst{18-16} = Zm; + } + def _S : sve_fp_fmul_by_indexed_elem<0b10, asm, ZPR32, ZPR3b32, VectorIndexS> { + bits<3> Zm; + bits<2> iop; + let Inst{20-19} = iop; + let Inst{18-16} = Zm; + } + def _D : sve_fp_fmul_by_indexed_elem<0b11, asm, ZPR64, ZPR4b64, VectorIndexD> { + bits<4> Zm; + bit iop; + let Inst{20} = iop; + let Inst{19-16} = Zm; + } +} //===----------------------------------------------------------------------===// // SVE Stack Allocation Group diff --git a/llvm/test/MC/AArch64/SVE/fmul-diagnostics.s b/llvm/test/MC/AArch64/SVE/fmul-diagnostics.s index 10b2a757c23..6b5ddc893fa 100644 --- a/llvm/test/MC/AArch64/SVE/fmul-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/fmul-diagnostics.s @@ -32,3 +32,61 @@ fmul z0.h, p0/m, z0.h, #1.9999999999999999999999999 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid floating point constant, expected 0.5 or 2.0. // CHECK-NEXT: fmul z0.h, p0/m, z0.h, #1.9999999999999999999999999 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Restricted ZPR range + +fmul z0.h, z0.h, z8.b[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z7.h +// CHECK-NEXT: fmul z0.h, z0.h, z8.b[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.h, z0.h, z8.h[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z7.h +// CHECK-NEXT: fmul z0.h, z0.h, z8.h[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.s, z0.s, z8.s[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.s..z7.s +// CHECK-NEXT: fmul z0.s, z0.s, z8.s[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.d, z0.d, z16.d[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.d..z15.d +// CHECK-NEXT: fmul z0.d, z0.d, z16.d[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Index out of bounds + +fmul z0.h, z0.h, z0.h[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7]. +// CHECK-NEXT: fmul z0.h, z0.h, z0.h[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.h, z0.h, z0.h[8] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7]. +// CHECK-NEXT: fmul z0.h, z0.h, z0.h[8] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.s, z0.s, z0.s[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3]. +// CHECK-NEXT: fmul z0.s, z0.s, z0.s[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.s, z0.s, z0.s[4] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3]. +// CHECK-NEXT: fmul z0.s, z0.s, z0.s[4] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.d, z0.d, z0.d[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 1]. +// CHECK-NEXT: fmul z0.d, z0.d, z0.d[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.d, z0.d, z0.d[2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 1]. +// CHECK-NEXT: fmul z0.d, z0.d, z0.d[2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/fmul.s b/llvm/test/MC/AArch64/SVE/fmul.s index c809278bb3e..4f71cb5452a 100644 --- a/llvm/test/MC/AArch64/SVE/fmul.s +++ b/llvm/test/MC/AArch64/SVE/fmul.s @@ -48,3 +48,39 @@ fmul z31.d, p7/m, z31.d, #2.0 // CHECK-ENCODING: [0x3f,0x9c,0xda,0x65] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 3f 9c da 65 <unknown> + +fmul z0.h, z0.h, z0.h[0] +// CHECK-INST: fmul z0.h, z0.h, z0.h[0] +// CHECK-ENCODING: [0x00,0x20,0x20,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 20 64 <unknown> + +fmul z0.s, z0.s, z0.s[0] +// CHECK-INST: fmul z0.s, z0.s, z0.s[0] +// CHECK-ENCODING: [0x00,0x20,0xa0,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 a0 64 <unknown> + +fmul z0.d, z0.d, z0.d[0] +// CHECK-INST: fmul z0.d, z0.d, z0.d[0] +// CHECK-ENCODING: [0x00,0x20,0xe0,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 e0 64 <unknown> + +fmul z31.h, z31.h, z7.h[7] +// CHECK-INST: fmul z31.h, z31.h, z7.h[7] +// CHECK-ENCODING: [0xff,0x23,0x7f,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 23 7f 64 <unknown> + +fmul z31.s, z31.s, z7.s[3] +// CHECK-INST: fmul z31.s, z31.s, z7.s[3] +// CHECK-ENCODING: [0xff,0x23,0xbf,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 23 bf 64 <unknown> + +fmul z31.d, z31.d, z15.d[1] +// CHECK-INST: fmul z31.d, z31.d, z15.d[1] +// CHECK-ENCODING: [0xff,0x23,0xff,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 23 ff 64 <unknown> |

