Skip to content

Commit

Permalink
[AArch32] Armv8.6a Matrix Mul Assembly Parsing Support
Browse files Browse the repository at this point in the history
This patch upstreams support for the Armv8.6-a Matrix Multiplication
Extension. A summary of the features can be found here:

https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-architecture-developments-armv8-6-a

This patch includes:

- Assembly support for AArch32 and Assembly Parsing

D77872 has already added the MC representations of the instructions so that
they can be used in code gen; this patch fills in the details needed to
make assembly parsing work, and adds tests for asm and disasm

This is part of a patch series, starting with BFloat16 support and
the other components in the armv8.6a extension (in previous patches
linked in phabricator)

Based on work by:
- Luke Geeson
- Oliver Stannard
- Luke Cheeseman

Reviewers: t.p.northover, simon_tatham

Reviewed By: simon_tatham

Subscribers: simon_tatham, ostannard, kristof.beyls, hiraditya,
danielkiss, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D77874
  • Loading branch information
lukeg101 committed Apr 24, 2020
1 parent e714683 commit 659ca50
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 1 deletion.
4 changes: 3 additions & 1 deletion llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Expand Up @@ -6465,7 +6465,9 @@ void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic,
Mnemonic == "vfmat" || Mnemonic == "vfmab" ||
Mnemonic == "vdot" || Mnemonic == "vmmla" ||
Mnemonic == "sb" || Mnemonic == "ssbb" ||
Mnemonic == "pssbb" ||
Mnemonic == "pssbb" || Mnemonic == "vsmmla" ||
Mnemonic == "vummla" || Mnemonic == "vusmmla" ||
Mnemonic == "vusdot" || Mnemonic == "vsudot" ||
Mnemonic == "bfcsel" || Mnemonic == "wls" ||
Mnemonic == "dls" || Mnemonic == "le" || Mnemonic == "csel" ||
Mnemonic == "csinc" || Mnemonic == "csinv" || Mnemonic == "csneg" ||
Expand Down
113 changes: 113 additions & 0 deletions llvm/test/MC/ARM/armv8.6a-matmul-error.s
@@ -0,0 +1,113 @@
// RUN: not llvm-mc -triple armv8a -show-encoding -mattr=+i8mm < %s 2>&1 | FileCheck %s
// RUN: not llvm-mc -triple thumbv8a -show-encoding -mattr=+i8mm < %s 2>&1 | FileCheck %s


// VSMMLA, VUMMLA, VUSMMLA

// Data type specifier must match instruction

vsmmla.u8 q0, q1, q2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: vsmmla.u8 q0, q1, q2
// CHECK-NEXT: {{^ \^}}

vummla.s8 q0, q1, q2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: vummla.s8 q0, q1, q2
// CHECK-NEXT: {{^ \^}}

vusmmla.u8 q0, q1, q2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: vusmmla.u8 q0, q1, q2
// CHECK-NEXT: {{^ \^}}


// Incorrect register type

vsmmla.s8 d0, q1, q2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must be a register in range [q0, q15]
// CHECK-NEXT: vsmmla.s8 d0, q1, q2
// CHECK-NEXT: {{^ \^}}

vummla.u8 q0, d1, q2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must be a register in range [q0, q15]
// CHECK-NEXT: vummla.u8 q0, d1, q2
// CHECK-NEXT: {{^ \^}}

vusmmla.s8 q0, q1, d2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must be a register in range [q0, q15]
// CHECK-NEXT: vusmmla.s8 q0, q1, d2
// CHECK-NEXT: {{^ \^}}


// VUSDOT (vector)

// Data type specifier must match instruction

vusdot.u8 q0, q1, q2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: vusdot.u8 q0, q1, q2
// CHECK-NEXT: {{^ \^}}

// Mis-matched register types

vusdot.s8 q0, d1, d2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must be a register in range [d0, d31]
vusdot.s8 d0, q1, d2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must be a register in range [d0, d31]
vusdot.s8 d0, d1, q2
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must be a register in range [d0, d31]


// VUSDOT, VSUDOT (by scalar)

// Data type specifier must match instruction

vusdot.u8 d0, d1, d2[0]
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: vusdot.u8 d0, d1, d2[0]
// CHECK-NEXT: {{^ \^}}

vsudot.s8 d0, d1, d2[0]
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: vsudot.s8 d0, d1, d2[0]
// CHECK-NEXT: {{^ \^}}

// Incorrect register types

vusdot.s8 q0, d1, d2[0]
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this:
// CHECK-NEXT: vusdot.s8 q0, d1, d2[0]
// CHECK: [[@LINE-3]]:{{[0-9]+}}: note: operand must be a register in range [d0, d31]
// CHECK-NEXT: vusdot.s8 q0, d1, d2[0]
// CHECK-NEXT: {{^ \^}}
// CHECK: [[@LINE-6]]:{{[0-9]+}}: note: operand must be a register in range [q0, q15]
// CHECK-NEXT: vusdot.s8 q0, d1, d2[0]
// CHECK-NEXT: {{^ \^}}

vusdot.s8 d0, q1, d2[0]
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this:
// CHECK-NEXT: vusdot.s8 d0, q1, d2[0]
// CHECK: [[@LINE-3]]:{{[0-9]+}}: note: operand must be a register in range [d0, d31]
// CHECK-NEXT: vusdot.s8 d0, q1, d2[0]
// CHECK-NEXT: {{^ \^}}
// CHECK: [[@LINE-6]]:{{[0-9]+}}: note: operand must be a register in range [q0, q15]
// CHECK-NEXT: vusdot.s8 d0, q1, d2[0]
// CHECK-NEXT: {{^ \^}}

vusdot.s8 q0, q1, q2[0]
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this:
// CHECK-NEXT: vusdot.s8 q0, q1, q2[0]
// CHECK: [[@LINE-3]]:{{[0-9]+}}: note: operand must be a register in range [d0, d15]
// CHECK-NEXT: vusdot.s8 q0, q1, q2[0]
// CHECK-NEXT: {{^ \^}}
// CHECK: [[@LINE-6]]:{{[0-9]+}}: note: too many operands for instruction
// CHECK-NEXT: vusdot.s8 q0, q1, q2[0]
// CHECK-NEXT: {{^ \^}}

// Out of range lane index

vusdot.s8 d0, d1, d2[2]
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
vsudot.u8 q0, q1, d2[2]
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
49 changes: 49 additions & 0 deletions llvm/test/MC/ARM/armv8.6a-matmul.s
@@ -0,0 +1,49 @@
// RUN: llvm-mc -triple armv8a -show-encoding -mattr=+i8mm < %s | FileCheck %s --check-prefix=ARM
// RUN: llvm-mc -triple thumbv8a -show-encoding -mattr=+i8mm < %s | FileCheck %s --check-prefix=THUMB
// RUN: not llvm-mc -triple armv8a -show-encoding -mattr=v8.5a < %s 2>&1 | FileCheck %s --check-prefix=NOMATMUL
// RUN: not llvm-mc -triple thumbv8a -show-encoding -mattr=v8.5a < %s 2>&1 | FileCheck %s --check-prefix=NOMATMUL

vsmmla.s8 q0, q1, q2
// ARM: vsmmla.s8 q0, q1, q2 @ encoding: [0x44,0x0c,0x22,0xfc]
// THUMB: vsmmla.s8 q0, q1, q2 @ encoding: [0x22,0xfc,0x44,0x0c]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply

vummla.u8 q0, q1, q2
// ARM: vummla.u8 q0, q1, q2 @ encoding: [0x54,0x0c,0x22,0xfc]
// THUMB: vummla.u8 q0, q1, q2 @ encoding: [0x22,0xfc,0x54,0x0c]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply

vusmmla.s8 q0, q1, q2
// ARM: vusmmla.s8 q0, q1, q2 @ encoding: [0x44,0x0c,0xa2,0xfc]
// THUMB: vusmmla.s8 q0, q1, q2 @ encoding: [0xa2,0xfc,0x44,0x0c]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply

vusdot.s8 d0, d1, d2
// ARM: vusdot.s8 d0, d1, d2 @ encoding: [0x02,0x0d,0xa1,0xfc]
// THUMB: vusdot.s8 d0, d1, d2 @ encoding: [0xa1,0xfc,0x02,0x0d]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply

vusdot.s8 q0, q1, q2
// ARM: vusdot.s8 q0, q1, q2 @ encoding: [0x44,0x0d,0xa2,0xfc]
// THUMB: vusdot.s8 q0, q1, q2 @ encoding: [0xa2,0xfc,0x44,0x0d]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply

vusdot.s8 d0, d1, d2[0]
// ARM: vusdot.s8 d0, d1, d2[0] @ encoding: [0x02,0x0d,0x81,0xfe]
// THUMB: vusdot.s8 d0, d1, d2[0] @ encoding: [0x81,0xfe,0x02,0x0d]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply

vsudot.u8 d0, d1, d2[1]
// ARM: vsudot.u8 d0, d1, d2[1] @ encoding: [0x32,0x0d,0x81,0xfe]
// THUMB: vsudot.u8 d0, d1, d2[1] @ encoding: [0x81,0xfe,0x32,0x0d]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply

vusdot.s8 q0, q1, d2[0]
// ARM: vusdot.s8 q0, q1, d2[0] @ encoding: [0x42,0x0d,0x82,0xfe]
// THUMB: vusdot.s8 q0, q1, d2[0] @ encoding: [0x82,0xfe,0x42,0x0d]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply

vsudot.u8 q0, q1, d2[1]
// ARM: vsudot.u8 q0, q1, d2[1] @ encoding: [0x72,0x0d,0x82,0xfe]
// THUMB: vsudot.u8 q0, q1, d2[1] @ encoding: [0x82,0xfe,0x72,0x0d]
// NOMATMUL: [[@LINE-3]]:{{[0-9]+}}: error: instruction requires: 8-bit integer matrix multiply
38 changes: 38 additions & 0 deletions llvm/test/MC/Disassembler/ARM/armv8.6a-matmul-arm.txt
@@ -0,0 +1,38 @@
# RUN: llvm-mc -triple=armv8 -mattr=+i8mm -disassemble < %s | FileCheck %s
# RUN: not llvm-mc -triple=armv8 -mattr=+v8.4a -disassemble < %s 2>&1 | FileCheck %s --check-prefix=NOMATMUL

[0x44,0x0c,0x22,0xfc]
# CHECK: vsmmla.s8 q0, q1, q2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x54,0x0c,0x22,0xfc]
# CHECK: vummla.u8 q0, q1, q2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x44,0x0c,0xa2,0xfc]
# CHECK: vusmmla.s8 q0, q1, q2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x02,0x0d,0xa1,0xfc]
# CHECK: vusdot.s8 d0, d1, d2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x44,0x0d,0xa2,0xfc]
# CHECK: vusdot.s8 q0, q1, q2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x02,0x0d,0x81,0xfe]
# CHECK: vusdot.s8 d0, d1, d2[0]
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x32,0x0d,0x81,0xfe]
# CHECK: vsudot.u8 d0, d1, d2[1]
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x42,0x0d,0x82,0xfe]
# CHECK: vusdot.s8 q0, q1, d2[0]
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x72,0x0d,0x82,0xfe]
# CHECK: vsudot.u8 q0, q1, d2[1]
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding
38 changes: 38 additions & 0 deletions llvm/test/MC/Disassembler/ARM/armv8.6a-matmul-thumb.txt
@@ -0,0 +1,38 @@
# RUN: llvm-mc -triple=thumbv8a -mattr=+i8mm -disassemble < %s | FileCheck %s
# RUN: not llvm-mc -triple=thumbv8a -mattr=+v8.4a -disassemble < %s 2>&1 | FileCheck %s --check-prefix=NOMATMUL

[0x22,0xfc,0x44,0x0c]
# CHECK: vsmmla.s8 q0, q1, q2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x22,0xfc,0x54,0x0c]
# CHECK: vummla.u8 q0, q1, q2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0xa2,0xfc,0x44,0x0c]
# CHECK: vusmmla.s8 q0, q1, q2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0xa1,0xfc,0x02,0x0d]
# CHECK: vusdot.s8 d0, d1, d2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0xa2,0xfc,0x44,0x0d]
# CHECK: vusdot.s8 q0, q1, q2
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x81,0xfe,0x02,0x0d]
# CHECK: vusdot.s8 d0, d1, d2[0]
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x81,0xfe,0x32,0x0d]
# CHECK: vsudot.u8 d0, d1, d2[1]
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x82,0xfe,0x42,0x0d]
# CHECK: vusdot.s8 q0, q1, d2[0]
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

[0x82,0xfe,0x72,0x0d]
# CHECK: vsudot.u8 q0, q1, d2[1]
# NOMATMUL: :[[@LINE-2]]:{{[0-9]+}}: warning: invalid instruction encoding

0 comments on commit 659ca50

Please sign in to comment.