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 @@ -160,7 +160,22 @@ // This builtin is valid for the given Log2LMULs. list Log2LMUL = [0, 1, 2, 3, -1, -2, -3]; - // Emit the automatic clang codegen. It describes what types we have to use + // Means that we won't emit automatic clang CodeGen code for this builtin + // and it will have to be provided manually. See IntrinsicTypes below. + bit HasManualCodegen = true; + + // The default lowering of clang codegen is an error diagnostic saying + // that this builtin not supported. + code ManualCodegen = [{ + CGM.ErrorUnsupported(E, "RISC-V V-extension builtin"); + return llvm::UndefValue::get(ResultType); + }]; + code ManualCodegenMask = [{ + CGM.ErrorUnsupported(E, "RISC-V V-extension builtin"); + return llvm::UndefValue::get(ResultType); + }]; + + // When emit the automatic clang codegen, it describes what types we have to use // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise, // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd // parameter of the unmasked version. k can't be the mask operand's position. @@ -172,6 +187,11 @@ // If HasMask, this is the ID of the LLVM intrinsic we want to lower to. string IRNameMask = NAME #"_mask"; + + // If non empty, this is the code emitted in the header, otherwise + // an automatic definition in header is emitted. + string HeaderCode = ""; + } //===----------------------------------------------------------------------===// @@ -181,6 +201,7 @@ class RVVBinBuiltin : RVVBuiltin { let IntrinsicTypes = [-1, 1]; + let HasManualCodegen = false; } multiclass RVVBinBuiltinSet; + + let HeaderCode = +[{ +#define vsetvlmax_e8mf8() __builtin_rvv_vsetvlimax(__rvv_e8, __rvv_mf8) +#define vsetvlmax_e8mf4() __builtin_rvv_vsetvlimax(__rvv_e8, __rvv_mf4) +#define vsetvlmax_e8mf2() __builtin_rvv_vsetvlimax(__rvv_e8, __rvv_mf2) +#define vsetvlmax_e8m1() __builtin_rvv_vsetvlimax(__rvv_e8, __rvv_m1) +#define vsetvlmax_e8m2() __builtin_rvv_vsetvlimax(__rvv_e8, __rvv_m2) +#define vsetvlmax_e8m4() __builtin_rvv_vsetvlimax(__rvv_e8, __rvv_m4) +#define vsetvlmax_e8m8() __builtin_rvv_vsetvlimax(__rvv_e8, __rvv_m8) + +#define vsetvlmax_e16mf4() __builtin_rvv_vsetvlimax(__rvv_e16, __rvv_mf4) +#define vsetvlmax_e16mf2() __builtin_rvv_vsetvlimax(__rvv_e16, __rvv_mf2) +#define vsetvlmax_e16m1() __builtin_rvv_vsetvlimax(__rvv_e16, __rvv_m1) +#define vsetvlmax_e16m2() __builtin_rvv_vsetvlimax(__rvv_e16, __rvv_m2) +#define vsetvlmax_e16m4() __builtin_rvv_vsetvlimax(__rvv_e16, __rvv_m4) +#define vsetvlmax_e16m8() __builtin_rvv_vsetvlimax(__rvv_e16, __rvv_m8) + +#define vsetvlmax_e32mf2() __builtin_rvv_vsetvlimax(__rvv_e32, __rvv_mf2) +#define vsetvlmax_e32m1() __builtin_rvv_vsetvlimax(__rvv_e32, __rvv_m1) +#define vsetvlmax_e32m2() __builtin_rvv_vsetvlimax(__rvv_e32, __rvv_m2) +#define vsetvlmax_e32m4() __builtin_rvv_vsetvlimax(__rvv_e32, __rvv_m4) +#define vsetvlmax_e32m8() __builtin_rvv_vsetvlimax(__rvv_e32, __rvv_m8) + +#define vsetvlmax_e64m1() __builtin_rvv_vsetvlimax(__rvv_e64, __rvv_m1) +#define vsetvlmax_e64m2() __builtin_rvv_vsetvlimax(__rvv_e64, __rvv_m2) +#define vsetvlmax_e64m4() __builtin_rvv_vsetvlimax(__rvv_e64, __rvv_m4) +#define vsetvlmax_e64m8() __builtin_rvv_vsetvlimax(__rvv_e64, __rvv_m8) + +}] in + def vsetvlimax : RVVBuiltin<"", "zKzKz", "i">; +} + // 12. Vector Integer Arithmetic Instructions // 12.1. Vector Single-Width Integer Add and Subtract defm vadd : RVVBinBuiltinSet<"vadd", "csil", diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -159,6 +159,22 @@ if (HasV) { Builder.defineMacro("__riscv_v", "10000"); Builder.defineMacro("__riscv_vector"); + + // SEW + Builder.defineMacro("__rvv_e8", "0"); + Builder.defineMacro("__rvv_e16", "1"); + Builder.defineMacro("__rvv_e32", "2"); + Builder.defineMacro("__rvv_e64", "3"); + Builder.defineMacro("__rvv_e128", "4"); + + // LMUL + Builder.defineMacro("__rvv_mf8", "5"); + Builder.defineMacro("__rvv_mf4", "6"); + Builder.defineMacro("__rvv_mf2", "7"); + Builder.defineMacro("__rvv_m1", "0"); + Builder.defineMacro("__rvv_m2", "1"); + Builder.defineMacro("__rvv_m4", "2"); + Builder.defineMacro("__rvv_m8", "3"); } if (HasZba) diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vsetvl.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vsetvl.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vsetvl.c @@ -0,0 +1,452 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-v -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefix=CHECK-RV32 %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-v -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefix=CHECK-RV64 %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-v -Werror -Wall -o - \ +// RUN: %s > /dev/null 2>%t +// RUN: FileCheck --check-prefix=ASM --allow-empty %s <%t + +// ASM-NOT: warning +#include + +// CHECK-RV32-LABEL: @test_vsetvl_e8m1( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 0, i32 0) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 0, i64 0) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e8m1(size_t avl) { + return vsetvl_e8m1(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e8m2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 0, i32 1) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 0, i64 1) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e8m2(size_t avl) { + return vsetvl_e8m2(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e8m4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 0, i32 2) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 0, i64 2) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e8m4(size_t avl) { + return vsetvl_e8m4(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e8m8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 0, i32 3) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 0, i64 3) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e8m8(size_t avl) { + return vsetvl_e8m8(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e8mf2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 0, i32 7) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 0, i64 7) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e8mf2(size_t avl) { + return vsetvl_e8mf2(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e8mf4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 0, i32 6) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 0, i64 6) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e8mf4(size_t avl) { + return vsetvl_e8mf4(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e8mf8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 0, i32 5) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 0, i64 5) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e8mf8(size_t avl) { + return vsetvl_e8mf8(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e16m1( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 1, i32 0) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 1, i64 0) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e16m1(size_t avl) { + return vsetvl_e16m1(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e16m2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 1, i32 1) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 1, i64 1) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e16m2(size_t avl) { + return vsetvl_e16m2(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e16m4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 1, i32 2) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 1, i64 2) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e16m4(size_t avl) { + return vsetvl_e16m4(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e16m8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 1, i32 3) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 1, i64 3) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e16m8(size_t avl) { + return vsetvl_e16m8(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e16mf2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 1, i32 7) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 1, i64 7) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e16mf2(size_t avl) { + return vsetvl_e16mf2(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e16mf4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 1, i32 6) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 1, i64 6) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e16mf4(size_t avl) { + return vsetvl_e16mf4(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e32m1( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 2, i32 0) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 2, i64 0) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e32m1(size_t avl) { + return vsetvl_e32m1(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e32m2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 2, i32 1) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 2, i64 1) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e32m2(size_t avl) { + return vsetvl_e32m2(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e32m4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 2, i32 2) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 2, i64 2) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e32m4(size_t avl) { + return vsetvl_e32m4(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e32m8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 2, i32 3) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 2, i64 3) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e32m8(size_t avl) { + return vsetvl_e32m8(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e32mf2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 2, i32 7) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 2, i64 7) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e32mf2(size_t avl) { + return vsetvl_e32mf2(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e64m1( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 3, i32 0) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 3, i64 0) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e64m1(size_t avl) { + return vsetvl_e64m1(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e64m2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 3, i32 1) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 3, i64 1) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e64m2(size_t avl) { + return vsetvl_e64m2(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e64m4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 3, i32 2) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 3, i64 2) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e64m4(size_t avl) { + return vsetvl_e64m4(avl); +} + +// CHECK-RV32-LABEL: @test_vsetvl_e64m8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[AVL_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[AVL:%.*]], i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, i32* [[AVL_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.riscv.vsetvli.i32(i32 [[TMP0]], i32 3, i32 3) +// CHECK-RV32-NEXT: ret i32 [[TMP1]] +// +// CHECK-RV64-LABEL: @test_vsetvl_e64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[AVL_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[AVL:%.*]], i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, i64* [[AVL_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[TMP0]], i64 3, i64 3) +// CHECK-RV64-NEXT: ret i64 [[TMP1]] +// +size_t test_vsetvl_e64m8(size_t avl) { + return vsetvl_e64m8(avl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vsetvlmax.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vsetvlmax.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vsetvlmax.c @@ -0,0 +1,320 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-v -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefix=CHECK-RV32 %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-v -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefix=CHECK-RV64 %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-v -Werror -Wall -o - \ +// RUN: %s > /dev/null 2>%t +// RUN: FileCheck --check-prefix=ASM --allow-empty %s <%t + +// ASM-NOT: warning +#include + +// CHECK-RV32-LABEL: @test_vsetvlmax_e8m1( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 0, i32 0) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 0, i64 0) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e8m1() { + return vsetvlmax_e8m1(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e8m2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 0, i32 1) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 0, i64 1) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e8m2() { + return vsetvlmax_e8m2(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e8m4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 0, i32 2) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 0, i64 2) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e8m4() { + return vsetvlmax_e8m4(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e8m8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 0, i32 3) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 0, i64 3) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e8m8() { + return vsetvlmax_e8m8(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e8mf2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 0, i32 7) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 0, i64 7) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e8mf2() { + return vsetvlmax_e8mf2(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e8mf4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 0, i32 6) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 0, i64 6) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e8mf4() { + return vsetvlmax_e8mf4(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e8mf8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 0, i32 5) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 0, i64 5) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e8mf8() { + return vsetvlmax_e8mf8(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e16m1( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 1, i32 0) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 1, i64 0) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e16m1() { + return vsetvlmax_e16m1(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e16m2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 1, i32 1) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 1, i64 1) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e16m2() { + return vsetvlmax_e16m2(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e16m4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 1, i32 2) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 1, i64 2) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e16m4() { + return vsetvlmax_e16m4(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e16m8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 1, i32 3) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 1, i64 3) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e16m8() { + return vsetvlmax_e16m8(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e16mf2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 1, i32 7) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 1, i64 7) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e16mf2() { + return vsetvlmax_e16mf2(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e16mf4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 1, i32 6) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 1, i64 6) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e16mf4() { + return vsetvlmax_e16mf4(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e32m1( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 2, i32 0) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 2, i64 0) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e32m1() { + return vsetvlmax_e32m1(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e32m2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 2, i32 1) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 2, i64 1) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e32m2() { + return vsetvlmax_e32m2(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e32m4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 2, i32 2) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 2, i64 2) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e32m4() { + return vsetvlmax_e32m4(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e32m8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 2, i32 3) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 2, i64 3) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e32m8() { + return vsetvlmax_e32m8(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e32mf2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 2, i32 7) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 2, i64 7) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e32mf2() { + return vsetvlmax_e32mf2(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e64m1( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 3, i32 0) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 0) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e64m1() { + return vsetvlmax_e64m1(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e64m2( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 3, i32 1) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 1) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e64m2() { + return vsetvlmax_e64m2(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e64m4( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 3, i32 2) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 2) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e64m4() { + return vsetvlmax_e64m4(); +} + +// CHECK-RV32-LABEL: @test_vsetvlmax_e64m8( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.vsetvlimax.i32(i32 3, i32 3) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_vsetvlmax_e64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 3) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +size_t test_vsetvlmax_e64m8() { + return vsetvlmax_e64m8(); +} 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 @@ -132,6 +132,9 @@ bool HasMaskedOffOperand; bool HasVL; bool HasGeneric; + bool HasAutoDef; + bool HasManualCodegen; + std::string ManualCodegen; RVVTypes Types; // Include output and other input std::vector IntrinsicTypes; // Type name in LLVM IR intrinsic suffix uint8_t RISCV_Extensions = 0; @@ -140,8 +143,9 @@ RVVIntrinsic(StringRef Name, StringRef Suffix, StringRef MangledName, StringRef IRName, bool HasSideEffects, bool IsMask, bool HasMaskedOffOperand, bool HasVL, bool HasGeneric, + bool HasAutoDef, bool HasManualCodegen, StringRef ManualCodegen, const RVVTypes &Types, - const std::vector &RVVIntrinsicTypes); + const std::vector &IntrinsicTypes); ~RVVIntrinsic() = default; StringRef getName() const { return Name; } @@ -150,6 +154,9 @@ bool hasMaskedOffOperand() const { return HasMaskedOffOperand; } bool hasVL() const { return HasVL; } bool hasGeneric() const { return HasGeneric; } + bool hasAutoDef() const { return HasAutoDef; } + bool hasManualCodegen() const { return HasManualCodegen; } + StringRef getManualCodegen() const { return ManualCodegen; } size_t getNumOperand() const { return Types.size() - 1; } // Get output and input types ArrayRef getTypes() const { return Types; } @@ -176,6 +183,7 @@ class RVVEmitter { private: RecordKeeper &Records; + std::string HeaderCode; // Concat BasicType, LMUL and Proto as key StringMap LegalTypes; StringSet<> IllegalTypes; @@ -604,11 +612,15 @@ StringRef NewMangledName, StringRef IRName, bool HasSideEffects, bool IsMask, bool HasMaskedOffOperand, bool HasVL, - bool HasGeneric, const RVVTypes &Types, + bool HasGeneric, bool HasAutoDef, + bool HasManualCodegen, StringRef ManualCodegen, + const RVVTypes &Types, const std::vector &IntrinsicTypes) : IRName(IRName), HasSideEffects(HasSideEffects), IsMask(IsMask), HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), - HasGeneric(HasGeneric), Types(Types), IntrinsicTypes(IntrinsicTypes) { + HasGeneric(HasGeneric), HasAutoDef(HasAutoDef), + HasManualCodegen(HasManualCodegen), ManualCodegen(ManualCodegen.str()), + Types(Types), IntrinsicTypes(IntrinsicTypes) { // Init Name and MangledName Name = NewName.str(); @@ -645,8 +657,6 @@ auto getIntrinsicTypesString = [this](const std::vector &IntrinsicTypes, raw_ostream &OS) { - OS << " ID = Intrinsic::riscv_" + getIRName() + ";\n"; - OS << " IntrinsicTypes = {"; for (const auto &Idx : IntrinsicTypes) { if (Idx == -1) @@ -663,6 +673,11 @@ OS << "};\n"; }; + OS << " ID = Intrinsic::riscv_" + getIRName() + ";\n"; + if (hasManualCodegen()) { + OS << getManualCodegen().str(); + return; + } if (!IsMask) { getIntrinsicTypesString(getIntrinsicTypes(), OS); return; @@ -756,6 +771,11 @@ std::vector> Defs; createRVVIntrinsics(Defs); + // Dump header + if (HeaderCode.size()) { + OS << HeaderCode; + } + // Dump RVV boolean types. auto dumpType = [&](auto T) { OS << "typedef " << T->clang_builtin_str() << " " << T->type_str() << ";\n"; @@ -875,7 +895,6 @@ void RVVEmitter::createRVVIntrinsics( std::vector> &Out) { - std::vector RV = Records.getAllDerivedDefinitions("RVVBuiltin"); for (auto *R : RV) { StringRef Name = R->getValueAsString("Name"); @@ -889,11 +908,19 @@ bool HasGeneric = R->getValueAsBit("HasGeneric"); bool HasSideEffects = R->getValueAsBit("HasSideEffects"); std::vector Log2LMULList = R->getValueAsListOfInts("Log2LMUL"); + bool HasManualCodegen = R->getValueAsBit("HasManualCodegen"); + StringRef ManualCodegen = R->getValueAsString("ManualCodegen"); + StringRef ManualCodegenMask = R->getValueAsString("ManualCodegenMask"); std::vector IntrinsicTypes = R->getValueAsListOfInts("IntrinsicTypes"); StringRef IRName = R->getValueAsString("IRName"); StringRef IRNameMask = R->getValueAsString("IRNameMask"); + StringRef HeaderCodeStr = R->getValueAsString("HeaderCode"); + bool HasAutoDef = HeaderCodeStr.empty(); + if (HeaderCodeStr.size()) { + HeaderCode += HeaderCodeStr.str(); + } // Parse prototype and create a list of primitive type with transformers // (operand) in ProtoSeq. ProtoSeq[0] is output operand. SmallVector ProtoSeq; @@ -918,7 +945,7 @@ ProtoMaskSeq.insert(ProtoMaskSeq.begin() + 2, ProtoSeq[0]); } - // Create intrinsics for each type and LMUL. + // Create Intrinsics for each type and LMUL. for (char I : TypeRange) { for (int Log2LMUL : Log2LMULList) { Optional Types = computeTypes(I, Log2LMUL, ProtoSeq); @@ -928,21 +955,45 @@ auto SuffixStr = computeType(I, Log2LMUL, Suffix).getValue()->short_str(); - // Create a non-mask intrinsic. - Out.push_back(std::make_unique( - Name, SuffixStr, MangledName, IRName, HasSideEffects, - /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, HasGeneric, - Types.getValue(), IntrinsicTypes)); - if (HasMask) { - // Create a mask intrinsic - Optional MaskTypes = - computeTypes(I, Log2LMUL, ProtoMaskSeq); + if (!HasManualCodegen) { + // Create a non-mask intrinsic + Out.push_back(std::make_unique( + Name, SuffixStr, MangledName, IRName, HasSideEffects, + /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, + HasGeneric, HasAutoDef, /*HasManualCodegen=*/false, + /*ManualCodegen=*/StringRef(), Types.getValue(), IntrinsicTypes)); + if (HasMask) { + // Create a mask intrinsic + Optional MaskTypes = + computeTypes(I, Log2LMUL, ProtoMaskSeq); + Out.push_back(std::make_unique( + Name, SuffixStr, MangledName, IRNameMask, HasSideEffects, + /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasGeneric, + HasAutoDef, /*HasManualCodegen=*/false, + /*ManualCodegen=*/StringRef(), MaskTypes.getValue(), + IntrinsicTypes)); + } + } else { + // Create a non-mask intrinsic Out.push_back(std::make_unique( - Name, SuffixStr, MangledName, IRNameMask, HasSideEffects, - /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasGeneric, - MaskTypes.getValue(), IntrinsicTypes)); + Name, SuffixStr, MangledName, IRName, HasSideEffects, + /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, + HasGeneric, HasAutoDef, /*HasManualCodegen=*/true, ManualCodegen, + Types.getValue(), + /*IntrinsicTypes*/ std::vector())); + if (HasMask) { + // Create a mask intrinsic + Optional MaskTypes = + computeTypes(I, Log2LMUL, ProtoMaskSeq); + Out.push_back(std::make_unique( + Name, SuffixStr, MangledName, IRNameMask, HasSideEffects, + /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasGeneric, + HasAutoDef, /*HasManualCodegen=*/true, ManualCodegenMask, + MaskTypes.getValue(), + /*IntrinsicTypes=*/std::vector())); + } } - } // end for Log2LMUL + } // end for Log2LMULList } // end for TypeRange } } @@ -1002,7 +1053,8 @@ OS << "\n"; } for (auto &Def : KV.getSecond()) { - DumpBody(OS, *Def); + if (Def->hasAutoDef()) + DumpBody(OS, *Def); } if (!ExtStrings.empty()) OS << "#endif\n\n";