From ac0cb5bf759232be291c0c110d143efd9678a16e Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Wed, 18 Jul 2018 08:10:03 +0000 Subject: [PATCH] [AArch64][SVE] Asm: Support for integer MUL instructions. This patch adds the following instructions: MUL - multiply vectors, e.g. mul z0.h, p0/m, z0.h, z1.h - multiply with immediate, e.g. mul z0.h, z0.h, #127 SMULH - signed multiply returning high half, e.g. smulh z0.h, p0/m, z0.h, z1.h UMULH - unsigned multiply returning high half, e.g. umulh z0.h, p0/m, z0.h, z1.h llvm-svn: 337358 --- llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td | 5 ++ llvm/lib/Target/AArch64/SVEInstrFormats.td | 29 +++++++--- llvm/test/MC/AArch64/SVE/mul-diagnostics.s | 38 ++++++++++++ llvm/test/MC/AArch64/SVE/mul.s | 80 ++++++++++++++++++++++++++ llvm/test/MC/AArch64/SVE/smulh-diagnostics.s | 19 ++++++ llvm/test/MC/AArch64/SVE/smulh.s | 32 +++++++++++ llvm/test/MC/AArch64/SVE/umulh-diagnostics.s | 19 ++++++ llvm/test/MC/AArch64/SVE/umulh.s | 32 +++++++++++ 8 files changed, 246 insertions(+), 8 deletions(-) create mode 100644 llvm/test/MC/AArch64/SVE/mul-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE/mul.s create mode 100644 llvm/test/MC/AArch64/SVE/smulh-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE/smulh.s create mode 100644 llvm/test/MC/AArch64/SVE/umulh-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE/umulh.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 42c3df3..52b19dd 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -62,6 +62,11 @@ let Predicates = [HasSVE] in { defm UMAX_ZI : sve_int_arith_imm1<0b01, "umax", imm0_255>; defm UMIN_ZI : sve_int_arith_imm1<0b11, "umin", imm0_255>; + defm MUL_ZI : sve_int_arith_imm2<"mul">; + defm MUL_ZPmZ : sve_int_bin_pred_arit_2<0b000, "mul">; + defm SMULH_ZPmZ : sve_int_bin_pred_arit_2<0b010, "smulh">; + defm UMULH_ZPmZ : sve_int_bin_pred_arit_2<0b011, "umulh">; + defm SXTB_ZPmZ : sve_int_un_pred_arit_0_h<0b000, "sxtb">; defm UXTB_ZPmZ : sve_int_un_pred_arit_0_h<0b001, "uxtb">; defm SXTH_ZPmZ : sve_int_un_pred_arit_0_w<0b010, "sxth">; diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index fced9d0..783d85c 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -1380,6 +1380,13 @@ multiclass sve_int_bin_pred_arit_1 opc, string asm> { def _D : sve_int_bin_pred_arit_log<0b11, 0b01, opc, asm, ZPR64>; } +multiclass sve_int_bin_pred_arit_2 opc, string asm> { + def _B : sve_int_bin_pred_arit_log<0b00, 0b10, opc, asm, ZPR8>; + def _H : sve_int_bin_pred_arit_log<0b01, 0b10, opc, asm, ZPR16>; + def _S : sve_int_bin_pred_arit_log<0b10, 0b10, opc, asm, ZPR32>; + def _D : sve_int_bin_pred_arit_log<0b11, 0b10, opc, asm, ZPR64>; +} + //===----------------------------------------------------------------------===// // SVE Integer Multiply-Add Group //===----------------------------------------------------------------------===// @@ -1607,8 +1614,8 @@ multiclass sve_int_arith_imm0 opc, string asm> { def _D : sve_int_arith_imm0<0b11, opc, asm, ZPR64, addsub_imm8_opt_lsl_i64>; } -class sve_int_arith_imm1 sz8_64, bits<2> opc, string asm, - ZPRRegOp zprty, Operand immtype> +class sve_int_arith_imm sz8_64, bits<6> opc, string asm, + ZPRRegOp zprty, Operand immtype> : I<(outs zprty:$Zdn), (ins zprty:$_Zdn, immtype:$imm), asm, "\t$Zdn, $_Zdn, $imm", "", @@ -1617,8 +1624,7 @@ class sve_int_arith_imm1 sz8_64, bits<2> opc, string asm, bits<8> imm; let Inst{31-24} = 0b00100101; let Inst{23-22} = sz8_64; - let Inst{21-18} = 0b1010; - let Inst{17-16} = opc; + let Inst{21-16} = opc; let Inst{15-13} = 0b110; let Inst{12-5} = imm; let Inst{4-0} = Zdn; @@ -1627,10 +1633,17 @@ class sve_int_arith_imm1 sz8_64, bits<2> opc, string asm, } multiclass sve_int_arith_imm1 opc, string asm, Operand immtype> { - def _B : sve_int_arith_imm1<0b00, opc, asm, ZPR8, immtype>; - def _H : sve_int_arith_imm1<0b01, opc, asm, ZPR16, immtype>; - def _S : sve_int_arith_imm1<0b10, opc, asm, ZPR32, immtype>; - def _D : sve_int_arith_imm1<0b11, opc, asm, ZPR64, immtype>; + def _B : sve_int_arith_imm<0b00, { 0b1010, opc }, asm, ZPR8, immtype>; + def _H : sve_int_arith_imm<0b01, { 0b1010, opc }, asm, ZPR16, immtype>; + def _S : sve_int_arith_imm<0b10, { 0b1010, opc }, asm, ZPR32, immtype>; + def _D : sve_int_arith_imm<0b11, { 0b1010, opc }, asm, ZPR64, immtype>; +} + +multiclass sve_int_arith_imm2 { + def _B : sve_int_arith_imm<0b00, 0b110000, asm, ZPR8, simm8>; + def _H : sve_int_arith_imm<0b01, 0b110000, asm, ZPR16, simm8>; + def _S : sve_int_arith_imm<0b10, 0b110000, asm, ZPR32, simm8>; + def _D : sve_int_arith_imm<0b11, 0b110000, asm, ZPR64, simm8>; } //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AArch64/SVE/mul-diagnostics.s b/llvm/test/MC/AArch64/SVE/mul-diagnostics.s new file mode 100644 index 0000000..745c35d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/mul-diagnostics.s @@ -0,0 +1,38 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid immediate range + +mul z0.b, z0.b, #-129 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be an integer in range [-128, 127]. +// CHECK-NEXT: mul z0.b, z0.b, #-129 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +mul z0.b, z0.b, #128 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: index must be an integer in range [-128, 127]. +// CHECK-NEXT: mul z0.b, z0.b, #128 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// ------------------------------------------------------------------------- // +// Tied operands must match + +mul z0.b, z1.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: mul z0.b, z1.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +mul z0.b, p7/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: mul z0.b, p7/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// ------------------------------------------------------------------------- // +// Invalid predicate + +mul z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: mul z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/mul.s b/llvm/test/MC/AArch64/SVE/mul.s new file mode 100644 index 0000000..f83b88ee7 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/mul.s @@ -0,0 +1,80 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +mul z0.b, p7/m, z0.b, z31.b +// CHECK-INST: mul z0.b, p7/m, z0.b, z31.b +// CHECK-ENCODING: [0xe0,0x1f,0x10,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 10 04 + +mul z0.h, p7/m, z0.h, z31.h +// CHECK-INST: mul z0.h, p7/m, z0.h, z31.h +// CHECK-ENCODING: [0xe0,0x1f,0x50,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 50 04 + +mul z0.s, p7/m, z0.s, z31.s +// CHECK-INST: mul z0.s, p7/m, z0.s, z31.s +// CHECK-ENCODING: [0xe0,0x1f,0x90,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 90 04 + +mul z0.d, p7/m, z0.d, z31.d +// CHECK-INST: mul z0.d, p7/m, z0.d, z31.d +// CHECK-ENCODING: [0xe0,0x1f,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f d0 04 + +mul z31.b, z31.b, #-128 +// CHECK-INST: mul z31.b, z31.b, #-128 +// CHECK-ENCODING: [0x1f,0xd0,0x30,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 1f d0 30 25 + +mul z31.b, z31.b, #127 +// CHECK-INST: mul z31.b, z31.b, #127 +// CHECK-ENCODING: [0xff,0xcf,0x30,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff cf 30 25 + +mul z31.h, z31.h, #-128 +// CHECK-INST: mul z31.h, z31.h, #-128 +// CHECK-ENCODING: [0x1f,0xd0,0x70,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 1f d0 70 25 + +mul z31.h, z31.h, #127 +// CHECK-INST: mul z31.h, z31.h, #127 +// CHECK-ENCODING: [0xff,0xcf,0x70,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff cf 70 25 + +mul z31.s, z31.s, #-128 +// CHECK-INST: mul z31.s, z31.s, #-128 +// CHECK-ENCODING: [0x1f,0xd0,0xb0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 1f d0 b0 25 + +mul z31.s, z31.s, #127 +// CHECK-INST: mul z31.s, z31.s, #127 +// CHECK-ENCODING: [0xff,0xcf,0xb0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff cf b0 25 + +mul z31.d, z31.d, #-128 +// CHECK-INST: mul z31.d, z31.d, #-128 +// CHECK-ENCODING: [0x1f,0xd0,0xf0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 1f d0 f0 25 + +mul z31.d, z31.d, #127 +// CHECK-INST: mul z31.d, z31.d, #127 +// CHECK-ENCODING: [0xff,0xcf,0xf0,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff cf f0 25 diff --git a/llvm/test/MC/AArch64/SVE/smulh-diagnostics.s b/llvm/test/MC/AArch64/SVE/smulh-diagnostics.s new file mode 100644 index 0000000..a856d32 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/smulh-diagnostics.s @@ -0,0 +1,19 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Tied operands must match + +smulh z0.b, p7/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: smulh z0.b, p7/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// ------------------------------------------------------------------------- // +// Invalid predicate + +smulh z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: smulh z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/smulh.s b/llvm/test/MC/AArch64/SVE/smulh.s new file mode 100644 index 0000000..354dfd8 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/smulh.s @@ -0,0 +1,32 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +smulh z0.b, p7/m, z0.b, z31.b +// CHECK-INST: smulh z0.b, p7/m, z0.b, z31.b +// CHECK-ENCODING: [0xe0,0x1f,0x12,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 12 04 + +smulh z0.h, p7/m, z0.h, z31.h +// CHECK-INST: smulh z0.h, p7/m, z0.h, z31.h +// CHECK-ENCODING: [0xe0,0x1f,0x52,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 52 04 + +smulh z0.s, p7/m, z0.s, z31.s +// CHECK-INST: smulh z0.s, p7/m, z0.s, z31.s +// CHECK-ENCODING: [0xe0,0x1f,0x92,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 92 04 + +smulh z0.d, p7/m, z0.d, z31.d +// CHECK-INST: smulh z0.d, p7/m, z0.d, z31.d +// CHECK-ENCODING: [0xe0,0x1f,0xd2,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f d2 04 diff --git a/llvm/test/MC/AArch64/SVE/umulh-diagnostics.s b/llvm/test/MC/AArch64/SVE/umulh-diagnostics.s new file mode 100644 index 0000000..b2cf7457 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/umulh-diagnostics.s @@ -0,0 +1,19 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Tied operands must match + +umulh z0.b, p7/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: umulh z0.b, p7/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// ------------------------------------------------------------------------- // +// Invalid predicate + +umulh z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: umulh z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/umulh.s b/llvm/test/MC/AArch64/SVE/umulh.s new file mode 100644 index 0000000..5234283 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/umulh.s @@ -0,0 +1,32 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d -mattr=+sve - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +umulh z0.b, p7/m, z0.b, z31.b +// CHECK-INST: umulh z0.b, p7/m, z0.b, z31.b +// CHECK-ENCODING: [0xe0,0x1f,0x13,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 13 04 + +umulh z0.h, p7/m, z0.h, z31.h +// CHECK-INST: umulh z0.h, p7/m, z0.h, z31.h +// CHECK-ENCODING: [0xe0,0x1f,0x53,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 53 04 + +umulh z0.s, p7/m, z0.s, z31.s +// CHECK-INST: umulh z0.s, p7/m, z0.s, z31.s +// CHECK-ENCODING: [0xe0,0x1f,0x93,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f 93 04 + +umulh z0.d, p7/m, z0.d, z31.d +// CHECK-INST: umulh z0.d, p7/m, z0.d, z31.d +// CHECK-ENCODING: [0xe0,0x1f,0xd3,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 1f d3 04 -- 2.7.4