diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td --- a/clang/include/clang/Basic/riscv_vector.td +++ b/clang/include/clang/Basic/riscv_vector.td @@ -1853,7 +1853,8 @@ def vfwcvt_rtz_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_rtz_x">; def vfwcvt_f_xu_v : RVVConvBuiltin<"Fw", "FwUv", "csi", "vfwcvt_f">; def vfwcvt_f_x_v : RVVConvBuiltin<"Fw", "Fwv", "csi", "vfwcvt_f">; - def vfwcvt_f_f_v : RVVConvBuiltin<"w", "wv", "xf", "vfwcvt_f">; + let RequiredFeatures = ["ZvfhminOrZvfh"] in + def vfwcvt_f_f_v : RVVConvBuiltin<"w", "wv", "xf", "vfwcvt_f">; } // 14.19. Narrowing Floating-Point/Integer Type-Convert Instructions @@ -1864,7 +1865,8 @@ def vfncvt_rtz_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_rtz_x">; def vfncvt_f_xu_w : RVVConvBuiltin<"Fv", "FvUw", "csi", "vfncvt_f">; def vfncvt_f_x_w : RVVConvBuiltin<"Fv", "Fvw", "csi", "vfncvt_f">; - def vfncvt_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_f">; + let RequiredFeatures = ["ZvfhminOrZvfh"] in + def vfncvt_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_f">; def vfncvt_rod_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_rod_f">; } } diff --git a/clang/include/clang/Support/RISCVVIntrinsicUtils.h b/clang/include/clang/Support/RISCVVIntrinsicUtils.h --- a/clang/include/clang/Support/RISCVVIntrinsicUtils.h +++ b/clang/include/clang/Support/RISCVVIntrinsicUtils.h @@ -462,7 +462,8 @@ RVV_REQ_None = 0, RVV_REQ_RV64 = 1 << 0, RVV_REQ_FullMultiply = 1 << 1, - RVV_REQ_Xsfvcp = 1 << 2, + RVV_REQ_ZvfhminOrZvfh = 1 << 2, + RVV_REQ_Xsfvcp = 1 << 3, LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_Xsfvcp) }; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -2042,9 +2042,9 @@ !TI.hasFeature("zve64x")) Diag(Loc, diag::err_riscv_type_requires_extension, FD) << Ty << "zve64x"; if (Ty->isRVVType(/* Bitwidth */ 16, /* IsFloat */ true) && - !TI.hasFeature("experimental-zvfh")) - Diag(Loc, diag::err_riscv_type_requires_extension, FD) - << Ty << "zvfh"; + !TI.hasFeature("experimental-zvfh") && + !TI.hasFeature("experimental-zvfhmin")) + Diag(Loc, diag::err_riscv_type_requires_extension, FD) << Ty << "zvfh"; if (Ty->isRVVType(/* Bitwidth */ 32, /* IsFloat */ true) && !TI.hasFeature("zve32f")) Diag(Loc, diag::err_riscv_type_requires_extension, FD) << Ty << "zve32f"; diff --git a/clang/lib/Sema/SemaRISCVVectorLookup.cpp b/clang/lib/Sema/SemaRISCVVectorLookup.cpp --- a/clang/lib/Sema/SemaRISCVVectorLookup.cpp +++ b/clang/lib/Sema/SemaRISCVVectorLookup.cpp @@ -191,6 +191,9 @@ const TargetInfo &TI = Context.getTargetInfo(); bool HasRV64 = TI.hasFeature("64bit"); bool HasFullMultiply = TI.hasFeature("v"); + bool HasZvfh = TI.hasFeature("experimental-zvfh"); + bool HasZvfhminOrZvfh = TI.hasFeature("experimental-zvfhmin") || + TI.hasFeature("experimental-zvfh"); auto ConstructRVVIntrinsics = [&](ArrayRef Recs, IntrinsicKind K) { @@ -252,6 +255,16 @@ !HasFullMultiply) continue; + if (BaseType == BasicType::Float16) { + if ((Record.RequiredExtensions & RVV_REQ_ZvfhminOrZvfh) == + RVV_REQ_ZvfhminOrZvfh) { + if (!HasZvfhminOrZvfh) + continue; + } else if (!HasZvfh) { + continue; + } + } + // Expanded with different LMUL. for (int Log2LMUL = -3; Log2LMUL <= 3; Log2LMUL++) { if (!(Record.Log2LMULMask & (1 << (Log2LMUL + 3)))) diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/zvfhmin-error.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/zvfhmin-error.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/zvfhmin-error.c @@ -0,0 +1,27 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +v \ +// RUN: -target-feature +experimental-zvfh -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-ZVF %s + +// RUN: not %clang_cc1 -triple riscv64 -target-feature +v \ +// RUN: -target-feature +experimental-zvfhmin -emit-llvm-only %s 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-ZVFHMIN-ERR + +#include + + + + +// CHECK-ZVF-LABEL: @test_vfadd_vv_f16m1( +// CHECK-ZVF-NEXT: entry: +// CHECK-ZVF-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vfadd.nxv4f16.nxv4f16.i64( poison, [[OP1:%.*]], [[OP2:%.*]], i64 [[VL:%.*]]) +// CHECK-ZVF-NEXT: ret [[TMP0]] +// + +// CHECK-ZVFHMIN-ERR: no matching function for call to '__riscv_vfadd' + +vfloat16m1_t test_vfadd_vv_f16m1(vfloat16m1_t op1, vfloat16m1_t op2, size_t vl) { + return __riscv_vfadd(op1, op2, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/zvfhmin.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/zvfhmin.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/zvfhmin.c @@ -0,0 +1,28 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +v \ +// RUN: -target-feature +experimental-zvfhmin -disable-O0-optnone \ +// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \ +// RUN: FileCheck --check-prefix=CHECK-ZVFHMIN %s + +#include + + +// CHECK-ZVFHMIN-LABEL: @test_vfncvt_f_f_w_f16m1( +// CHECK-ZVFHMIN-NEXT: entry: +// CHECK-ZVFHMIN-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vfncvt.f.f.w.nxv4f16.nxv4f32.i64( poison, [[SRC:%.*]], i64 [[VL:%.*]]) +// CHECK-ZVFHMIN-NEXT: ret [[TMP0]] +// +vfloat16m1_t test_vfncvt_f_f_w_f16m1(vfloat32m2_t src, size_t vl) { + return __riscv_vfncvt_f(src, vl); +} + + +// CHECK-ZVFHMIN-LABEL: @test_vfwcvt_f_f_v_f16m1( +// CHECK-ZVFHMIN-NEXT: entry: +// CHECK-ZVFHMIN-NEXT: [[TMP0:%.*]] = call @llvm.riscv.vfwcvt.f.f.v.nxv4f32.nxv4f16.i64( poison, [[SRC:%.*]], i64 [[VL:%.*]]) +// CHECK-ZVFHMIN-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vfwcvt_f_f_v_f16m1(vfloat16m1_t src, size_t vl) { + return __riscv_vfwcvt_f(src, vl); +} diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -633,6 +633,7 @@ RVVRequire RequireExt = StringSwitch(RequiredFeature) .Case("RV64", RVV_REQ_RV64) .Case("FullMultiply", RVV_REQ_FullMultiply) + .Case("ZvfhminOrZvfh", RVV_REQ_ZvfhminOrZvfh) .Case("Xsfvcp", RVV_REQ_Xsfvcp) .Default(RVV_REQ_None); assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?"); 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 @@ -148,6 +148,7 @@ {"zcmt", RISCVExtensionVersion{1, 0}}, {"zfa", RISCVExtensionVersion{0, 2}}, {"zicond", RISCVExtensionVersion{1, 0}}, + {"zvfhmin", RISCVExtensionVersion{0, 1}}, {"zvfh", RISCVExtensionVersion{0, 1}}, {"ztso", RISCVExtensionVersion{0, 1}}, @@ -936,6 +937,7 @@ static const char *ImpliedExtsZve64d[] = {"zve64f", "d"}; static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"}; static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"}; +static const char *ImpliedExtsZvfhmin[] = {"zve32f"}; static const char *ImpliedExtsZvfh[] = {"zve32f", "zfhmin"}; static const char *ImpliedExtsZvkn[] = {"zvbb", "zvbc", "zvkned", "zvknhb", "zvkt"}; @@ -994,6 +996,7 @@ {{"zve64d"}, {ImpliedExtsZve64d}}, {{"zve64f"}, {ImpliedExtsZve64f}}, {{"zve64x"}, {ImpliedExtsZve64x}}, + {{"zvfhmin"}, {ImpliedExtsZvfhmin}}, {{"zvfh"}, {ImpliedExtsZvfh}}, {{"zvkn"}, {ImpliedExtsZvkn}}, {{"zvkng"}, {ImpliedExtsZvkng}}, 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 @@ -446,6 +446,11 @@ "'V' (Vector Extension for Application Processors), 'Zve32f', " "'Zve64f' or 'Zve64d' (Vector Extensions for Embedded Processors)">; +def FeatureStdExtZvfhmin + : SubtargetFeature<"experimental-zvfhmin", "HasStdExtZvfhmin", "true", + "'Zvfhmin' (Vector Half-Precision Floating-Point Minimal)", + [FeatureStdExtZve32f]>; + def FeatureStdExtZvfh : SubtargetFeature<"experimental-zvfh", "HasStdExtZvfh", "true", "'Zvfh' (Vector Half-Precision Floating-Point)",