|
| 1 | +//@ build-pass |
| 2 | +//@ only-aarch64 |
| 3 | +#![crate_type = "lib"] |
| 4 | +#![allow(incomplete_features, internal_features)] |
| 5 | +#![feature(abi_unadjusted, core_intrinsics, link_llvm_intrinsics, rustc_attrs)] |
| 6 | + |
| 7 | +// Tests that tuples of scalable vectors are passed as immediates and that the intrinsics for |
| 8 | +// creating/getting/setting tuples of scalable vectors generate the correct assembly |
| 9 | + |
| 10 | +#[derive(Copy, Clone)] |
| 11 | +#[rustc_scalable_vector(4)] |
| 12 | +#[allow(non_camel_case_types)] |
| 13 | +pub struct svfloat32_t(f32); |
| 14 | + |
| 15 | +#[derive(Copy, Clone)] |
| 16 | +#[rustc_scalable_vector] |
| 17 | +#[allow(non_camel_case_types)] |
| 18 | +pub struct svfloat32x2_t(svfloat32_t, svfloat32_t); |
| 19 | + |
| 20 | +#[derive(Copy, Clone)] |
| 21 | +#[rustc_scalable_vector] |
| 22 | +#[allow(non_camel_case_types)] |
| 23 | +pub struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t); |
| 24 | + |
| 25 | +#[derive(Copy, Clone)] |
| 26 | +#[rustc_scalable_vector] |
| 27 | +#[allow(non_camel_case_types)] |
| 28 | +pub struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t); |
| 29 | + |
| 30 | +#[inline(never)] |
| 31 | +#[target_feature(enable = "sve")] |
| 32 | +pub fn svdup_n_f32(op: f32) -> svfloat32_t { |
| 33 | + extern "C" { |
| 34 | + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.dup.x.nxv4f32")] |
| 35 | + fn _svdup_n_f32(op: f32) -> svfloat32_t; |
| 36 | + } |
| 37 | + unsafe { _svdup_n_f32(op) } |
| 38 | +} |
| 39 | + |
| 40 | +// CHECK: define { <vscale x 4 x float>, <vscale x 4 x float> } @svcreate2_f32(<vscale x 4 x float> %x0, <vscale x 4 x float> %x1) |
| 41 | +#[no_mangle] |
| 42 | +#[target_feature(enable = "sve")] |
| 43 | +pub fn svcreate2_f32(x0: svfloat32_t, x1: svfloat32_t) -> svfloat32x2_t { |
| 44 | + // CHECK: %1 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float> } poison, <vscale x 4 x float> %x0, 0 |
| 45 | + // CHECK-NEXT: %2 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float> } %1, <vscale x 4 x float> %x1, 1 |
| 46 | + unsafe { std::intrinsics::simd::scalable::sve_tuple_create2(x0, x1) } |
| 47 | +} |
| 48 | + |
| 49 | +// CHECK: define { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } @svcreate3_f32(<vscale x 4 x float> %x0, <vscale x 4 x float> %x1, <vscale x 4 x float> %x2) |
| 50 | +#[no_mangle] |
| 51 | +#[target_feature(enable = "sve")] |
| 52 | +pub fn svcreate3_f32(x0: svfloat32_t, x1: svfloat32_t, x2: svfloat32_t) -> svfloat32x3_t { |
| 53 | + // CHECK-LABEL: @_RNvCsk3YxfLN8zWY_6tuples13svcreate3_f32 |
| 54 | + // CHECK: %1 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } poison, <vscale x 4 x float> %x0, 0 |
| 55 | + // CHECK-NEXT: %2 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %1, <vscale x 4 x float> %x1, 1 |
| 56 | + // CHECK-NEXT: %3 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %2, <vscale x 4 x float> %x2, 2 |
| 57 | + unsafe { std::intrinsics::simd::scalable::sve_tuple_create3(x0, x1, x2) } |
| 58 | +} |
| 59 | + |
| 60 | +// CHECK: define { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } @svcreate4_f32(<vscale x 4 x float> %x0, <vscale x 4 x float> %x1, <vscale x 4 x float> %x2, <vscale x 4 x float> %x3) |
| 61 | +#[no_mangle] |
| 62 | +#[target_feature(enable = "sve")] |
| 63 | +pub fn svcreate4_f32( |
| 64 | + x0: svfloat32_t, |
| 65 | + x1: svfloat32_t, |
| 66 | + x2: svfloat32_t, |
| 67 | + x3: svfloat32_t, |
| 68 | +) -> svfloat32x4_t { |
| 69 | + // CHECK-LABEL: @_RNvCsk3YxfLN8zWY_6tuples13svcreate4_f32 |
| 70 | + // CHECK: %1 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } poison, <vscale x 4 x float> %x0, 0 |
| 71 | + // CHECK-NEXT: %2 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %1, <vscale x 4 x float> %x1, 1 |
| 72 | + // CHECK-NEXT: %3 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %2, <vscale x 4 x float> %x2, 2 |
| 73 | + // CHECK-NEXT: %4 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } %3, <vscale x 4 x float> %x3, 3 |
| 74 | + unsafe { std::intrinsics::simd::scalable::sve_tuple_create4(x0, x1, x2, x3) } |
| 75 | +} |
| 76 | + |
| 77 | +// CHECK: define <vscale x 4 x float> @svget2_f32({ <vscale x 4 x float>, <vscale x 4 x float> } %tup) |
| 78 | +#[no_mangle] |
| 79 | +#[target_feature(enable = "sve")] |
| 80 | +pub fn svget2_f32<const IDX: i32>(tup: svfloat32x2_t) -> svfloat32_t { |
| 81 | + // CHECK: %1 = extractvalue { <vscale x 4 x float>, <vscale x 4 x float> } %tup, 0 |
| 82 | + unsafe { std::intrinsics::simd::scalable::sve_tuple_get::<_, _, { IDX }>(tup) } |
| 83 | +} |
| 84 | + |
| 85 | +// CHECK: define { <vscale x 4 x float>, <vscale x 4 x float> } @svset2_f32({ <vscale x 4 x float>, <vscale x 4 x float> } %tup, <vscale x 4 x float> %x) |
| 86 | +#[no_mangle] |
| 87 | +#[target_feature(enable = "sve")] |
| 88 | +pub fn svset2_f32<const IDX: i32>(tup: svfloat32x2_t, x: svfloat32_t) -> svfloat32x2_t { |
| 89 | + // CHECK: %1 = insertvalue { <vscale x 4 x float>, <vscale x 4 x float> } %tup, <vscale x 4 x float> %x, 0 |
| 90 | + unsafe { std::intrinsics::simd::scalable::sve_tuple_set::<_, _, { IDX }>(tup, x) } |
| 91 | +} |
| 92 | + |
| 93 | +// This function exists only so there are calls to the generic functions |
| 94 | +#[target_feature(enable = "sve")] |
| 95 | +pub fn test() { |
| 96 | + let x = svdup_n_f32(2f32); |
| 97 | + let tup = svcreate2_f32(x, x); |
| 98 | + let x = svget2_f32::<0>(tup); |
| 99 | + let tup = svset2_f32::<0>(tup, x); |
| 100 | +} |
0 commit comments