diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -67,6 +67,7 @@ // CHECK-NOT: __riscv_zicond {{.*$}} // CHECK-NOT: __riscv_smaia {{.*$}} // CHECK-NOT: __riscv_ssaia {{.*$}} +// CHECK-NOT: __riscv_zfbfmin {{.*$}} // RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32i -x c -E -dM %s \ // RUN: -o - | FileCheck %s @@ -674,3 +675,11 @@ // RUN: -march=rv64issaia1p0 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-SSAIA-EXT %s // CHECK-SSAIA-EXT: __riscv_ssaia 1000000{{$}} + +// RUN: %clang -target riscv32 -menable-experimental-extensions \ +// RUN: -march=rv32izfbfmin0p6 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZFBFMIN-EXT %s +// RUN: %clang -target riscv64 -menable-experimental-extensions \ +// RUN: -march=rv64izfbfmin0p6 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZFBFMIN-EXT %s +// CHECK-ZFBFMIN-EXT: __riscv_zfbfmin 6000{{$}} diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -204,6 +204,9 @@ ``experimental-zfa`` LLVM implements the `0.2 draft specification `__. +``experimental-zfbfmin`` + LLVM implements assembler support for the `0.6 draft specification `_. + ``experimental-zicond`` LLVM implements the `1.0-rc1 draft specification `__. diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -180,6 +180,8 @@ * Add sifive-x280 processor. * Zve32f is no longer allowed with Zfinx. Zve64d is no longer allowed with Zdinx. +* Assembly support was added for the experimental Zfbfmin (scalar BF16 + conversions) extension. Changes to the WebAssembly Backend ---------------------------------- diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -147,6 +147,7 @@ {"zcmp", RISCVExtensionVersion{1, 0}}, {"zcmt", RISCVExtensionVersion{1, 0}}, {"zfa", RISCVExtensionVersion{0, 2}}, + {"zfbfmin", RISCVExtensionVersion{0, 6}}, {"zicond", RISCVExtensionVersion{1, 0}}, {"zvfh", RISCVExtensionVersion{0, 1}}, {"ztso", RISCVExtensionVersion{0, 1}}, diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -611,6 +611,21 @@ "excluding the machine-level CSRs and behavior not " "directly visible to supervisor level.)", []>; +def FeatureStdExtZfbfmin + : SubtargetFeature<"experimental-zfbfmin", "HasStdExtZfbfmin", "true", + "'Zfbfmin' (Scalar BF16 Converts)", + [FeatureStdExtF]>; +def HasStdExtZfbfmin : Predicate<"Subtarget->hasStdExtZfbfmin()">, + AssemblerPredicate<(all_of FeatureStdExtZfbfmin), + "'Zfbfmin' (Scalar BF16 Converts)">; + +def HasHalfFPLoadStoreMove + : Predicate<"Subtarget->hasHalfFPLoadStoreMove()">, + AssemblerPredicate<(any_of FeatureStdExtZfh, FeatureStdExtZfhmin, FeatureStdExtZfbfmin), + "'Zfh' (Half-Precision Floating-Point) or " + "'Zfhmin' (Half-Precision Floating-Point Minimal) or " + "'Zfbfmin' (Scalar BF16 Converts)">; + //===----------------------------------------------------------------------===// // Vendor extensions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1904,6 +1904,7 @@ include "RISCVInstrInfoZk.td" include "RISCVInstrInfoV.td" include "RISCVInstrInfoZfa.td" +include "RISCVInstrInfoZfbfmin.td" include "RISCVInstrInfoZfh.td" include "RISCVInstrInfoZicbo.td" include "RISCVInstrInfoZicond.td" diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfbfmin.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfbfmin.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfbfmin.td @@ -0,0 +1,25 @@ +//===-- RISCVInstrInfoZfbfmin.td - 'Zfbfmin' instructions --*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes the RISC-V instructions from the standard 'Zfbfmin' +// extension, providing scalar conversion instructions for BFloat16. +// This version is still experimental as the 'Zfbfmin' extension hasn't been +// ratified yet. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +let Predicates = [HasStdExtZfbfmin] in { +def FCVT_BF16_S : FPUnaryOp_r_frm<0b0100010, 0b01000, FPR16, FPR32, "fcvt.bf16.s">, + Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]>; +def FCVT_S_BF16 : FPUnaryOp_r_frm<0b0100000, 0b00110, FPR32, FPR16, "fcvt.s.bf16">, + Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]>; +} // Predicates = [HasStdExtZfbfmin] diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td @@ -90,14 +90,14 @@ // Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasStdExtZfhOrZfhmin] in { +let Predicates = [HasHalfFPLoadStoreMove] in { def FLH : FPLoad_r<0b001, "flh", FPR16, WriteFLD16>; // Operands for stores are in the order srcreg, base, offset rather than // reflecting the order these fields are specified in the instruction // encoding. def FSH : FPStore_r<0b001, "fsh", FPR16, WriteFST16>; -} // Predicates = [HasStdExtZfhOrZfhmin] +} // Predicates = [HasHalfFPLoadStoreMove] let SchedRW = [WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16] in { defm FMADD_H : FPFMA_rrr_frm_m; @@ -151,7 +151,7 @@ defm FCVT_S_H : FPUnaryOp_r_m<0b0100000, 0b00010, 0b000, FHINXmin, "fcvt.s.h">, Sched<[WriteFCvtF16ToF32, ReadFCvtF16ToF32]>; -let Predicates = [HasStdExtZfhOrZfhmin] in { +let Predicates = [HasHalfFPLoadStoreMove] in { let mayRaiseFPException = 0, IsSignExtendingOpW = 1 in def FMV_X_H : FPUnaryOp_r<0b1110010, 0b00000, 0b000, GPR, FPR16, "fmv.x.h">, Sched<[WriteFMovF16ToI16, ReadFMovF16ToI16]>; @@ -159,7 +159,7 @@ let mayRaiseFPException = 0 in def FMV_H_X : FPUnaryOp_r<0b1111010, 0b00000, 0b000, FPR16, GPR, "fmv.h.x">, Sched<[WriteFMovI16ToF16, ReadFMovI16ToF16]>; -} // Predicates = [HasStdExtZfhOrZfhmin] +} // Predicates = [HasHalfFPLoadStoreMove] let SchedRW = [WriteFCmp16, ReadFCmp16, ReadFCmp16] in { defm FEQ_H : FPCmp_rr_m<0b1010010, 0b010, "feq.h", HINX, /*Commutable*/1>; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -123,6 +123,9 @@ bool hasStdExtZfhOrZfhminOrZhinxOrZhinxmin() const { return hasStdExtZfhOrZfhmin() || hasStdExtZhinxOrZhinxmin(); } + bool hasHalfFPLoadStoreMove() const { + return HasStdExtZfh || HasStdExtZfhmin || HasStdExtZfbfmin; + } bool is64Bit() const { return IsRV64; } MVT getXLenVT() const { return XLenVT; } unsigned getXLen() const { return XLen; } diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -74,6 +74,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicond %s -o - | FileCheck --check-prefix=RV32ZICOND %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-smaia %s -o - | FileCheck --check-prefixes=CHECK,RV32SMAIA %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-ssaia %s -o - | FileCheck --check-prefixes=CHECK,RV32SSAIA %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV32ZFBFMIN %s ; RUN: llc -mtriple=riscv64 %s -o - | FileCheck %s ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefixes=CHECK,RV64M %s @@ -155,6 +156,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicond %s -o - | FileCheck --check-prefix=RV64ZICOND %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-smaia %s -o - | FileCheck --check-prefixes=CHECK,RV64SMAIA %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-ssaia %s -o - | FileCheck --check-prefixes=CHECK,RV64SSAIA %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-zfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV64ZFBFMIN %s ; CHECK: .attribute 4, 16 @@ -231,6 +233,7 @@ ; RV32ZICOND: .attribute 5, "rv32i2p1_zicond1p0" ; RV32SMAIA: .attribute 5, "rv32i2p1_smaia1p0" ; RV32SSAIA: .attribute 5, "rv32i2p1_ssaia1p0" +; RV32ZFBFMIN: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfbfmin0p6" ; RV64M: .attribute 5, "rv64i2p1_m2p0" ; RV64ZMMUL: .attribute 5, "rv64i2p1_zmmul1p0" @@ -311,6 +314,7 @@ ; RV64ZICOND: .attribute 5, "rv64i2p1_zicond1p0" ; RV64SMAIA: .attribute 5, "rv64i2p1_smaia1p0" ; RV64SSAIA: .attribute 5, "rv64i2p1_ssaia1p0" +; RV64ZFBFMIN: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zfbfmin0p6" define i32 @addi(i32 %a) { %1 = add i32 %a, 1 diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -263,3 +263,6 @@ .attribute arch, "rv32i_ssaia1p0" # CHECK: attribute 5, "rv32i2p1_ssaia1p0" + +.attribute arch, "rv32if_zfbfmin0p6" +# CHECK: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfbfmin0p6" diff --git a/llvm/test/MC/RISCV/rv32zfbfmin-invalid.s b/llvm/test/MC/RISCV/rv32zfbfmin-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zfbfmin-invalid.s @@ -0,0 +1,28 @@ +# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zfbfmin,+d < %s 2>&1 | \ +# RUN: FileCheck %s +# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-zfbfmin,+d < %s 2>&1 | \ +# RUN: FileCheck %s + +# Out of range immediates +## simm12 +flh ft1, -2049(a0) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047] +fsh ft2, 2048(a1) # CHECK: :[[@LINE]]:10: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047] + +# Memory operand not formatted correctly +flh ft1, a0, -200 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + +# Invalid register names +flh ft15, 100(a0) # CHECK: :[[@LINE]]:5: error: invalid operand for instruction +flh ft1, 100(a10) # CHECK: :[[@LINE]]:14: error: expected register + +# Integer registers where FP regs are expected +fmv.x.h fs7, a2 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + +# FP registers where integer regs are expected +fmv.h.x a8, ft2 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + +# Attempting to use fcvt instructions from zfhmin +fcvt.s.h fa0, ft0 # CHECK: [[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) or 'Zfhmin' (Half-Precision Floating-Point Minimal) +fcvt.h.s ft2, fa2 # CHECK: [[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) or 'Zfhmin' (Half-Precision Floating-Point Minimal) +fcvt.d.h fa0, ft0 # CHECK: [[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) or 'Zfhmin' (Half-Precision Floating-Point Minimal) +fcvt.h.d ft2, fa2 # CHECK: [[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) or 'Zfhmin' (Half-Precision Floating-Point Minimal) diff --git a/llvm/test/MC/RISCV/rv32zfbfmin-valid.s b/llvm/test/MC/RISCV/rv32zfbfmin-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zfbfmin-valid.s @@ -0,0 +1,56 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zfbfmin,+f -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zfbfmin,+f -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zfbfmin,+d < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zfbfmin,+f -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zfbfmin,+d < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zfbfmin,+f -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: flh ft0, 12(a0) +# CHECK-ASM: encoding: [0x07,0x10,0xc5,0x00] +flh f0, 12(a0) +# CHECK-ASM-AND-OBJ: flh ft1, 4(ra) +# CHECK-ASM: encoding: [0x87,0x90,0x40,0x00] +flh f1, +4(ra) +# CHECK-ASM-AND-OBJ: flh ft2, -2048(a3) +# CHECK-ASM: encoding: [0x07,0x91,0x06,0x80] +flh f2, -2048(x13) +# CHECK-ASM-AND-OBJ: flh ft3, -2048(s1) +# CHECK-ASM: encoding: [0x87,0x91,0x04,0x80] +flh f3, %lo(2048)(s1) +# CHECK-ASM-AND-OBJ: flh ft4, 2047(s2) +# CHECK-ASM: encoding: [0x07,0x12,0xf9,0x7f] +flh f4, 2047(s2) +# CHECK-ASM-AND-OBJ: flh ft5, 0(s3) +# CHECK-ASM: encoding: [0x87,0x92,0x09,0x00] +flh f5, 0(s3) + +# CHECK-ASM-AND-OBJ: fsh ft6, 2047(s4) +# CHECK-ASM: encoding: [0xa7,0x1f,0x6a,0x7e] +fsh f6, 2047(s4) +# CHECK-ASM-AND-OBJ: fsh ft7, -2048(s5) +# CHECK-ASM: encoding: [0x27,0x90,0x7a,0x80] +fsh f7, -2048(s5) +# CHECK-ASM-AND-OBJ: fsh fs0, -2048(s6) +# CHECK-ASM: encoding: [0x27,0x10,0x8b,0x80] +fsh f8, %lo(2048)(s6) +# CHECK-ASM-AND-OBJ: fsh fs1, 999(s7) +# CHECK-ASM: encoding: [0xa7,0x93,0x9b,0x3e] +fsh f9, 999(s7) + +# CHECK-ASM-AND-OBJ: fmv.x.h a2, fs7 +# CHECK-ASM: encoding: [0x53,0x86,0x0b,0xe4] +fmv.x.h a2, fs7 +# CHECK-ASM-AND-OBJ: fmv.h.x ft1, a6 +# CHECK-ASM: encoding: [0xd3,0x00,0x08,0xf4] +fmv.h.x ft1, a6 + +# CHECK-ASM-AND-OBJ: fcvt.s.bf16 fa0, ft0 +# CHECK-ASM: encoding: [0x53,0x75,0x60,0x40] +fcvt.s.bf16 fa0, ft0 +# CHECK-ASM-AND-OBJ: fcvt.bf16.s ft2, fa2 +# CHECK-ASM: encoding: [0x53,0x71,0x86,0x44] +fcvt.bf16.s ft2, fa2 diff --git a/llvm/test/MC/RISCV/rv64zhinx-invalid.s b/llvm/test/MC/RISCV/rv64zhinx-invalid.s --- a/llvm/test/MC/RISCV/rv64zhinx-invalid.s +++ b/llvm/test/MC/RISCV/rv64zhinx-invalid.s @@ -1,7 +1,7 @@ # RUN: not llvm-mc -triple riscv64 -mattr=+zhinx %s 2>&1 | FileCheck %s # Not support float registers -flh fa4, 12(sp) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) or 'Zfhmin' (Half-Precision Floating-Point Minimal){{$}} +flh fa4, 12(sp) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) or 'Zfhmin' (Half-Precision Floating-Point Minimal) or 'Zfbfmin' (Scalar BF16 Converts){{$}} # Invalid instructions fsh a5, 12(sp) # CHECK: :[[@LINE]]:5: error: invalid operand for instruction diff --git a/llvm/test/MC/RISCV/rv64zhinxmin-invalid.s b/llvm/test/MC/RISCV/rv64zhinxmin-invalid.s --- a/llvm/test/MC/RISCV/rv64zhinxmin-invalid.s +++ b/llvm/test/MC/RISCV/rv64zhinxmin-invalid.s @@ -1,7 +1,7 @@ # RUN: not llvm-mc -triple riscv64 -mattr=+zhinxmin %s 2>&1 | FileCheck %s # Not support float registers -flh fa4, 12(sp) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) or 'Zfhmin' (Half-Precision Floating-Point Minimal){{$}} +flh fa4, 12(sp) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) or 'Zfhmin' (Half-Precision Floating-Point Minimal) or 'Zfbfmin' (Scalar BF16 Converts){{$}} # Invalid instructions fsh a5, 12(sp) # CHECK: :[[@LINE]]:5: error: invalid operand for instruction