256 lines · c
1// REQUIRES: riscv-registered-target2// RUN: %clang_cc1 -triple riscv64 -target-feature +v \3// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s4// RUN: %clang_cc1 -triple riscv64 -target-feature +zve32x \5// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM-ZVE32X %s6// RUN: %clang_cc1 -std=c23 -triple riscv64 -target-feature +v \7// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s8 9#include <riscv_vector.h>10 11// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar12vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input);13vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {14 vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);15 vint32m1_t ret = bar(input);16 __riscv_vse32_v_i32m1(base, val, vl);17 return ret;18}19 20// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar21[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input);22vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) {23 vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);24 vint32m1_t ret = bar(input);25 __riscv_vse32_v_i32m1(base, val, vl);26 return ret;27}28 29// CHECK-LLVM: call <vscale x 2 x i32> @baz30vint32m1_t baz(vint32m1_t input);31vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) {32 vint32m1_t val = __riscv_vle32_v_i32m1(base, vl);33 vint32m1_t ret = baz(input);34 __riscv_vse32_v_i32m1(base, val, vl);35 return ret;36}37 38// CHECK-LLVM: define dso_local void @test_vls_no_cc(i128 noundef %arg.coerce)39void test_vls_no_cc(__attribute__((vector_size(16))) int arg) {}40 41// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen(<vscale x 2 x i32> noundef %arg.coerce)42void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen(__attribute__((vector_size(16))) int arg) {}43 44// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23(<vscale x 2 x i32> noundef %arg.coerce)45[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}46 47// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature(<vscale x 8 x i8> noundef %arg.coerce)48void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}49 50// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature(<vscale x 8 x i8> noundef %arg.coerce)51[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature(__attribute__((vector_size(16))) _Float16 arg) {}52 53// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature_zve32x(<vscale x 8 x i8> noundef %arg.coerce)54void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}55 56// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(<vscale x 8 x i8> noundef %arg.coerce)57[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature_zve32x(__attribute__((vector_size(16))) float arg) {}58 59// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_unsupported_feature_no_zve64x(<vscale x 8 x i8> noundef %arg.coerce)60void __attribute__((riscv_vls_cc)) test_vls_default_abi_vlen_unsupported_feature_no_zve64x(__attribute__((vector_size(16))) uint64_t arg) {}61 62// CHECK-LLVM-ZVE32X: define dso_local riscv_vls_cc(128) void @test_vls_default_abi_vlen_c23_unsupported_feature_no_zve64x(<vscale x 8 x i8> noundef %arg.coerce)63[[riscv::vls_cc]] void test_vls_default_abi_vlen_c23_unsupported_feature_no_zve64x(__attribute__((vector_size(16))) uint64_t arg) {}64 65// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_vls_256_abi_vlen(<vscale x 1 x i32> noundef %arg.coerce)66void __attribute__((riscv_vls_cc(256))) test_vls_256_abi_vlen(__attribute__((vector_size(16))) int arg) {}67 68// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_vls_256_abi_vlen_c23(<vscale x 1 x i32> noundef %arg.coerce)69[[riscv::vls_cc(256)]] void test_vls_256_abi_vlen_c23(__attribute__((vector_size(16))) int arg) {}70 71// CHECK-LLVM: define dso_local riscv_vls_cc(1024) void @test_vls_least_element(<vscale x 1 x i32> noundef %arg.coerce)72void __attribute__((riscv_vls_cc(1024))) test_vls_least_element(__attribute__((vector_size(8))) int arg) {}73 74// CHECK-LLVM: define dso_local riscv_vls_cc(1024) void @test_vls_least_element_c23(<vscale x 1 x i32> noundef %arg.coerce)75[[riscv::vls_cc(1024)]] void test_vls_least_element_c23(__attribute__((vector_size(8))) int arg) {}76 77 78struct st_i32x4 {79 __attribute__((vector_size(16))) int i32;80};81 82struct st_i32x4_arr1 {83 __attribute__((vector_size(16))) int i32[1];84};85 86struct st_i32x4_arr4 {87 __attribute__((vector_size(16))) int i32[4];88};89 90struct st_i32x4_arr8 {91 __attribute__((vector_size(16))) int i32[8];92};93 94 95struct st_i32x4x2 {96 __attribute__((vector_size(16))) int i32_1;97 __attribute__((vector_size(16))) int i32_2;98};99 100struct st_i32x8x2 {101 __attribute__((vector_size(32))) int i32_1;102 __attribute__((vector_size(32))) int i32_2;103};104 105struct st_i32x64x2 {106 __attribute__((vector_size(256))) int i32_1;107 __attribute__((vector_size(256))) int i32_2;108};109 110struct st_i32x4x3 {111 __attribute__((vector_size(16))) int i32_1;112 __attribute__((vector_size(16))) int i32_2;113 __attribute__((vector_size(16))) int i32_3;114};115 116struct st_i32x4x8 {117 __attribute__((vector_size(16))) int i32_1;118 __attribute__((vector_size(16))) int i32_2;119 __attribute__((vector_size(16))) int i32_3;120 __attribute__((vector_size(16))) int i32_4;121 __attribute__((vector_size(16))) int i32_5;122 __attribute__((vector_size(16))) int i32_6;123 __attribute__((vector_size(16))) int i32_7;124 __attribute__((vector_size(16))) int i32_8;125};126 127struct st_i32x4x9 {128 __attribute__((vector_size(16))) int i32_1;129 __attribute__((vector_size(16))) int i32_2;130 __attribute__((vector_size(16))) int i32_3;131 __attribute__((vector_size(16))) int i32_4;132 __attribute__((vector_size(16))) int i32_5;133 __attribute__((vector_size(16))) int i32_6;134 __attribute__((vector_size(16))) int i32_7;135 __attribute__((vector_size(16))) int i32_8;136 __attribute__((vector_size(16))) int i32_9;137};138 139typedef int __attribute__((vector_size(256))) int32x64_t;140 141// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_too_large(ptr dead_on_return noundef %0)142void __attribute__((riscv_vls_cc)) test_too_large(int32x64_t arg) {}143// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_too_large_256(<vscale x 16 x i32> noundef %arg.coerce)144void __attribute__((riscv_vls_cc(256))) test_too_large_256(int32x64_t arg) {}145 146// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4(<vscale x 2 x i32> %arg.target_coerce)147void __attribute__((riscv_vls_cc)) test_st_i32x4(struct st_i32x4 arg) {}148// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4_256(<vscale x 1 x i32> %arg.target_coerce)149void __attribute__((riscv_vls_cc(256))) test_st_i32x4_256(struct st_i32x4 arg) {}150 151// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4_arr1(<vscale x 2 x i32> %arg.target_coerce)152void __attribute__((riscv_vls_cc)) test_st_i32x4_arr1(struct st_i32x4_arr1 arg) {}153// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4_arr1_256(<vscale x 1 x i32> %arg.target_coerce)154void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr1_256(struct st_i32x4_arr1 arg) {}155 156// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4_arr4(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %arg.target_coerce)157void __attribute__((riscv_vls_cc)) test_st_i32x4_arr4(struct st_i32x4_arr4 arg) {}158// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4_arr4_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 4) %arg.target_coerce)159void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr4_256(struct st_i32x4_arr4 arg) {}160 161// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4_arr8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg.target_coerce)162void __attribute__((riscv_vls_cc)) test_st_i32x4_arr8(struct st_i32x4_arr8 arg) {}163// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4_arr8_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg.target_coerce)164void __attribute__((riscv_vls_cc(256))) test_st_i32x4_arr8_256(struct st_i32x4_arr8 arg) {}165 166// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x2(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce)167void __attribute__((riscv_vls_cc)) test_st_i32x4x2(struct st_i32x4x2 arg) {}168// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x2_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 2) %arg.target_coerce)169void __attribute__((riscv_vls_cc(256))) test_st_i32x4x2_256(struct st_i32x4x2 arg) {}170 171// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x8x2(target("riscv.vector.tuple", <vscale x 16 x i8>, 2) %arg.target_coerce)172void __attribute__((riscv_vls_cc)) test_st_i32x8x2(struct st_i32x8x2 arg) {}173// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x8x2_256(target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %arg.target_coerce)174void __attribute__((riscv_vls_cc(256))) test_st_i32x8x2_256(struct st_i32x8x2 arg) {}175 176// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x64x2(ptr dead_on_return noundef %arg)177void __attribute__((riscv_vls_cc)) test_st_i32x64x2(struct st_i32x64x2 arg) {}178// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x64x2_256(ptr dead_on_return noundef %arg)179void __attribute__((riscv_vls_cc(256))) test_st_i32x64x2_256(struct st_i32x64x2 arg) {}180 181// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x3(target("riscv.vector.tuple", <vscale x 8 x i8>, 3) %arg.target_coerce)182void __attribute__((riscv_vls_cc)) test_st_i32x4x3(struct st_i32x4x3 arg) {}183// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x3_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 3) %arg.target_coerce)184void __attribute__((riscv_vls_cc(256))) test_st_i32x4x3_256(struct st_i32x4x3 arg) {}185 186// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x8(target("riscv.vector.tuple", <vscale x 8 x i8>, 8) %arg.target_coerce)187void __attribute__((riscv_vls_cc)) test_st_i32x4x8(struct st_i32x4x8 arg) {}188// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x8_256(target("riscv.vector.tuple", <vscale x 4 x i8>, 8) %arg.target_coerce)189void __attribute__((riscv_vls_cc(256))) test_st_i32x4x8_256(struct st_i32x4x8 arg) {}190 191// CHECK-LLVM: define dso_local riscv_vls_cc(128) void @test_st_i32x4x9(ptr dead_on_return noundef %arg)192void __attribute__((riscv_vls_cc)) test_st_i32x4x9(struct st_i32x4x9 arg) {}193// CHECK-LLVM: define dso_local riscv_vls_cc(256) void @test_st_i32x4x9_256(ptr dead_on_return noundef %arg)194void __attribute__((riscv_vls_cc(256))) test_st_i32x4x9_256(struct st_i32x4x9 arg) {}195 196// CHECK-LLVM-LABEL: define dso_local riscv_vls_cc(128) target("riscv.vector.tuple", <vscale x 8 x i8>, 4) @test_function_prolog_epilog(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %arg.target_coerce) #0 {197// CHECK-LLVM-NEXT: entry:198// CHECK-LLVM-NEXT: %retval = alloca %struct.st_i32x4_arr4, align 16199// CHECK-LLVM-NEXT: %arg = alloca %struct.st_i32x4_arr4, align 16200// CHECK-LLVM-NEXT: %0 = call <vscale x 2 x i32> @llvm.riscv.tuple.extract.nxv2i32.triscv.vector.tuple_nxv8i8_4t(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %arg.target_coerce, i32 0)201// CHECK-LLVM-NEXT: %1 = call <4 x i32> @llvm.vector.extract.v4i32.nxv2i32(<vscale x 2 x i32> %0, i64 0)202// CHECK-LLVM-NEXT: %2 = getelementptr inbounds [4 x <4 x i32>], ptr %arg, i64 0, i64 0203// CHECK-LLVM-NEXT: store <4 x i32> %1, ptr %2, align 16204// CHECK-LLVM-NEXT: %3 = call <vscale x 2 x i32> @llvm.riscv.tuple.extract.nxv2i32.triscv.vector.tuple_nxv8i8_4t(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %arg.target_coerce, i32 1)205// CHECK-LLVM-NEXT: %4 = call <4 x i32> @llvm.vector.extract.v4i32.nxv2i32(<vscale x 2 x i32> %3, i64 0)206// CHECK-LLVM-NEXT: %5 = getelementptr inbounds [4 x <4 x i32>], ptr %arg, i64 0, i64 1207// CHECK-LLVM-NEXT: store <4 x i32> %4, ptr %5, align 16208// CHECK-LLVM-NEXT: %6 = call <vscale x 2 x i32> @llvm.riscv.tuple.extract.nxv2i32.triscv.vector.tuple_nxv8i8_4t(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %arg.target_coerce, i32 2)209// CHECK-LLVM-NEXT: %7 = call <4 x i32> @llvm.vector.extract.v4i32.nxv2i32(<vscale x 2 x i32> %6, i64 0)210// CHECK-LLVM-NEXT: %8 = getelementptr inbounds [4 x <4 x i32>], ptr %arg, i64 0, i64 2211// CHECK-LLVM-NEXT: store <4 x i32> %7, ptr %8, align 16212// CHECK-LLVM-NEXT: %9 = call <vscale x 2 x i32> @llvm.riscv.tuple.extract.nxv2i32.triscv.vector.tuple_nxv8i8_4t(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %arg.target_coerce, i32 3)213// CHECK-LLVM-NEXT: %10 = call <4 x i32> @llvm.vector.extract.v4i32.nxv2i32(<vscale x 2 x i32> %9, i64 0)214// CHECK-LLVM-NEXT: %11 = getelementptr inbounds [4 x <4 x i32>], ptr %arg, i64 0, i64 3215// CHECK-LLVM-NEXT: store <4 x i32> %10, ptr %11, align 16216// CHECK-LLVM-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %retval, ptr align 16 %arg, i64 64, i1 false)217// CHECK-LLVM-NEXT: %12 = load [4 x <4 x i32>], ptr %retval, align 16218// CHECK-LLVM-NEXT: %13 = extractvalue [4 x <4 x i32>] %12, 0219// CHECK-LLVM-NEXT: %cast.scalable = call <vscale x 2 x i32> @llvm.vector.insert.nxv2i32.v4i32(<vscale x 2 x i32> poison, <4 x i32> %13, i64 0)220// CHECK-LLVM-NEXT: %14 = call target("riscv.vector.tuple", <vscale x 8 x i8>, 4) @llvm.riscv.tuple.insert.triscv.vector.tuple_nxv8i8_4t.nxv2i32(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) poison, <vscale x 2 x i32> %cast.scalable, i32 0)221// CHECK-LLVM-NEXT: %15 = extractvalue [4 x <4 x i32>] %12, 1222// CHECK-LLVM-NEXT: %cast.scalable1 = call <vscale x 2 x i32> @llvm.vector.insert.nxv2i32.v4i32(<vscale x 2 x i32> poison, <4 x i32> %15, i64 0)223// CHECK-LLVM-NEXT: %16 = call target("riscv.vector.tuple", <vscale x 8 x i8>, 4) @llvm.riscv.tuple.insert.triscv.vector.tuple_nxv8i8_4t.nxv2i32(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %14, <vscale x 2 x i32> %cast.scalable1, i32 1)224// CHECK-LLVM-NEXT: %17 = extractvalue [4 x <4 x i32>] %12, 2225// CHECK-LLVM-NEXT: %cast.scalable2 = call <vscale x 2 x i32> @llvm.vector.insert.nxv2i32.v4i32(<vscale x 2 x i32> poison, <4 x i32> %17, i64 0)226// CHECK-LLVM-NEXT: %18 = call target("riscv.vector.tuple", <vscale x 8 x i8>, 4) @llvm.riscv.tuple.insert.triscv.vector.tuple_nxv8i8_4t.nxv2i32(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %16, <vscale x 2 x i32> %cast.scalable2, i32 2)227// CHECK-LLVM-NEXT: %19 = extractvalue [4 x <4 x i32>] %12, 3228// CHECK-LLVM-NEXT: %cast.scalable3 = call <vscale x 2 x i32> @llvm.vector.insert.nxv2i32.v4i32(<vscale x 2 x i32> poison, <4 x i32> %19, i64 0)229// CHECK-LLVM-NEXT: %20 = call target("riscv.vector.tuple", <vscale x 8 x i8>, 4) @llvm.riscv.tuple.insert.triscv.vector.tuple_nxv8i8_4t.nxv2i32(target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %18, <vscale x 2 x i32> %cast.scalable3, i32 3)230// CHECK-LLVM-NEXT: ret target("riscv.vector.tuple", <vscale x 8 x i8>, 4) %20231// CHECK-LLVM-NEXT: }232struct st_i32x4_arr4 __attribute__((riscv_vls_cc)) test_function_prolog_epilog(struct st_i32x4_arr4 arg) {233 return arg;234}235 236struct st_i32x4 __attribute__((riscv_vls_cc)) dummy(struct st_i32x4);237// CHECK-LLVM-LABEL: define dso_local riscv_vls_cc(128) <vscale x 2 x i32> @test_call(<vscale x 2 x i32> %arg.target_coerce) #0 {238// CHECK-LLVM-NEXT: entry:239// CHECK-LLVM-NEXT: %retval = alloca %struct.st_i32x4, align 16240// CHECK-LLVM-NEXT: %arg = alloca %struct.st_i32x4, align 16241// CHECK-LLVM-NEXT: %0 = call <4 x i32> @llvm.vector.extract.v4i32.nxv2i32(<vscale x 2 x i32> %arg.target_coerce, i64 0)242// CHECK-LLVM-NEXT: store <4 x i32> %0, ptr %arg, align 16243// CHECK-LLVM-NEXT: %1 = load <4 x i32>, ptr %arg, align 16244// CHECK-LLVM-NEXT: %cast.scalable = call <vscale x 2 x i32> @llvm.vector.insert.nxv2i32.v4i32(<vscale x 2 x i32> poison, <4 x i32> %1, i64 0)245// CHECK-LLVM-NEXT: %call = call riscv_vls_cc(128) <vscale x 2 x i32> @dummy(<vscale x 2 x i32> %cast.scalable)246// CHECK-LLVM-NEXT: %2 = call <4 x i32> @llvm.vector.extract.v4i32.nxv2i32(<vscale x 2 x i32> %call, i64 0)247// CHECK-LLVM-NEXT: store <4 x i32> %2, ptr %retval, align 16248// CHECK-LLVM-NEXT: %3 = load <4 x i32>, ptr %retval, align 16249// CHECK-LLVM-NEXT: %cast.scalable1 = call <vscale x 2 x i32> @llvm.vector.insert.nxv2i32.v4i32(<vscale x 2 x i32> poison, <4 x i32> %3, i64 0)250// CHECK-LLVM-NEXT: ret <vscale x 2 x i32> %cast.scalable1251// CHECK-LLVM-NEXT: }252struct st_i32x4 __attribute__((riscv_vls_cc)) test_call(struct st_i32x4 arg) {253 struct st_i32x4 abc = dummy(arg);254 return abc;255}256