From 6e88e96ccf1ca7621e6177d729a69625838db1c8 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 13 Jul 2019 17:16:57 +0200 Subject: [PATCH 01/10] Support repr(simd) on ADTs containing a single array field This PR allows using `#[repr(simd)]` on ADTs containing a single array field: ```rust #[repr(simd)] struct S0([f32; 4]); #[repr(simd)] struct S1([f32; N]); #[repr(simd)] struct S2([T; N]); ``` This should allow experimenting with portable packed SIMD abstractions on nightly that make use of const generics. --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 122 +++++++++++------- compiler/rustc_middle/src/ty/layout.rs | 109 +++++++++++++--- compiler/rustc_middle/src/ty/sty.rs | 16 --- compiler/rustc_typeck/src/check/check.rs | 4 +- .../simd-intrinsic-generic-extract-insert.rs | 47 +++++++ .../simd-intrinsic-transmute-array.rs | 44 +++++++ src/test/ui/error-codes/E0077.stderr | 2 +- .../ui/simd-type-generic-monomorphisation.rs | 4 +- .../simd-type-generic-monomorphisation.stderr | 2 +- src/test/ui/simd-type.rs | 10 ++ src/test/ui/simd-type.stderr | 20 ++- src/test/ui/simd/simd-array-type.rs | 44 +++++++ src/test/ui/simd/simd-generics.rs | 32 ++++- ...intrinsic-generic-arithmetic-saturating.rs | 68 +++++----- .../simd/simd-intrinsic-generic-arithmetic.rs | 63 +++++---- 15 files changed, 427 insertions(+), 160 deletions(-) create mode 100644 src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs create mode 100644 src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs create mode 100644 src/test/ui/simd/simd-array-type.rs diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index e9900e8bc108a..2ea7d7ac2d822 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -740,6 +740,23 @@ fn generic_simd_intrinsic( llret_ty: &'ll Type, span: Span, ) -> Result<&'ll Value, ()> { + // Given a SIMD vector type `x` return the element type and the number of + // elements in the vector. + fn simd_ty_and_len(bx: &Builder<'a, 'll, 'tcx>, simd_ty: Ty<'tcx>) -> (Ty<'tcx>, u64) { + let ty = if let ty::Adt(_def, _substs) = simd_ty.kind() { + let f0_ty = bx.layout_of(simd_ty).field(bx, 0).ty; + if let ty::Array(element_ty, _) = f0_ty.kind() { element_ty } else { f0_ty } + } else { + bug!("should only be called with a SIMD type") + }; + let count = if let abi::Abi::Vector { count, .. } = bx.layout_of(simd_ty).abi { + count + } else { + bug!("should only be called with a SIMD type") + }; + (ty, count) + } + // macros for error handling: macro_rules! emit_error { ($msg: tt) => { @@ -792,7 +809,7 @@ fn generic_simd_intrinsic( _ => return_error!("`{}` is not an integral type", in_ty), }; require_simd!(arg_tys[1], "argument"); - let v_len = arg_tys[1].simd_size(tcx); + let (_, v_len) = simd_ty_and_len(bx, arg_tys[1]); require!( // Allow masks for vectors with fewer than 8 elements to be // represented with a u8 or i8. @@ -812,8 +829,6 @@ fn generic_simd_intrinsic( // every intrinsic below takes a SIMD vector as its first argument require_simd!(arg_tys[0], "input"); let in_ty = arg_tys[0]; - let in_elem = arg_tys[0].simd_type(tcx); - let in_len = arg_tys[0].simd_size(tcx); let comparison = match name { sym::simd_eq => Some(hir::BinOpKind::Eq), @@ -825,14 +840,15 @@ fn generic_simd_intrinsic( _ => None, }; + let (in_elem, in_len) = simd_ty_and_len(bx, arg_tys[0]); if let Some(cmp_op) = comparison { require_simd!(ret_ty, "return"); - let out_len = ret_ty.simd_size(tcx); + let (out_ty, out_len) = simd_ty_and_len(bx, ret_ty); require!( in_len == out_len, "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", + found `{}` with length {}", in_len, in_ty, ret_ty, @@ -842,7 +858,7 @@ fn generic_simd_intrinsic( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, "expected return type with integer elements, found `{}` with non-integer `{}`", ret_ty, - ret_ty.simd_type(tcx) + out_ty ); return Ok(compare_simd_types( @@ -862,7 +878,7 @@ fn generic_simd_intrinsic( require_simd!(ret_ty, "return"); - let out_len = ret_ty.simd_size(tcx); + let (out_ty, out_len) = simd_ty_and_len(bx, ret_ty); require!( out_len == n, "expected return type of length {}, found `{}` with length {}", @@ -871,13 +887,13 @@ fn generic_simd_intrinsic( out_len ); require!( - in_elem == ret_ty.simd_type(tcx), + in_elem == out_ty, "expected return element type `{}` (element of input `{}`), \ - found `{}` with element type `{}`", + found `{}` with element type `{}`", in_elem, in_ty, ret_ty, - ret_ty.simd_type(tcx) + out_ty ); let total_len = u128::from(in_len) * 2; @@ -946,7 +962,7 @@ fn generic_simd_intrinsic( let m_elem_ty = in_elem; let m_len = in_len; require_simd!(arg_tys[1], "argument"); - let v_len = arg_tys[1].simd_size(tcx); + let (_, v_len) = simd_ty_and_len(bx, arg_tys[1]); require!( m_len == v_len, "mismatched lengths: mask length `{}` != other vector length `{}`", @@ -1171,25 +1187,27 @@ fn generic_simd_intrinsic( require_simd!(ret_ty, "return"); // Of the same length: + let (_, out_len) = simd_ty_and_len(bx, arg_tys[1]); + let (_, out_len2) = simd_ty_and_len(bx, arg_tys[2]); require!( - in_len == arg_tys[1].simd_size(tcx), + in_len == out_len, "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", + found `{}` with length {}", "second", in_len, in_ty, arg_tys[1], - arg_tys[1].simd_size(tcx) + out_len ); require!( - in_len == arg_tys[2].simd_size(tcx), + in_len == out_len2, "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", + found `{}` with length {}", "third", in_len, in_ty, arg_tys[2], - arg_tys[2].simd_size(tcx) + out_len2 ); // The return type must match the first argument type @@ -1213,39 +1231,40 @@ fn generic_simd_intrinsic( // The second argument must be a simd vector with an element type that's a pointer // to the element type of the first argument - let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind() { - ty::RawPtr(p) if p.ty == in_elem => { - (ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx))) - } + let (element_ty0, _) = simd_ty_and_len(bx, arg_tys[0]); + let (element_ty1, _) = simd_ty_and_len(bx, arg_tys[1]); + let (pointer_count, underlying_ty) = match element_ty1.kind() { + ty::RawPtr(p) if p.ty == in_elem => (ptr_count(element_ty1), non_ptr(element_ty1)), _ => { require!( false, "expected element type `{}` of second argument `{}` \ - to be a pointer to the element type `{}` of the first \ - argument `{}`, found `{}` != `*_ {}`", - arg_tys[1].simd_type(tcx), + to be a pointer to the element type `{}` of the first \ + argument `{}`, found `{}` != `*_ {}`", + element_ty1, arg_tys[1], in_elem, in_ty, - arg_tys[1].simd_type(tcx), + element_ty1, in_elem ); unreachable!(); } }; assert!(pointer_count > 0); - assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx))); - assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx))); + assert_eq!(pointer_count - 1, ptr_count(element_ty0)); + assert_eq!(underlying_ty, non_ptr(element_ty0)); // The element type of the third argument must be a signed integer type of any width: - match arg_tys[2].simd_type(tcx).kind() { + let (element_ty2, _) = simd_ty_and_len(bx, arg_tys[2]); + match element_ty2.kind() { ty::Int(_) => (), _ => { require!( false, "expected element type `{}` of third argument `{}` \ to be a signed integer type", - arg_tys[2].simd_type(tcx), + element_ty2, arg_tys[2] ); } @@ -1297,25 +1316,27 @@ fn generic_simd_intrinsic( require_simd!(arg_tys[2], "third"); // Of the same length: + let (_, element_len1) = simd_ty_and_len(bx, arg_tys[1]); + let (_, element_len2) = simd_ty_and_len(bx, arg_tys[2]); require!( - in_len == arg_tys[1].simd_size(tcx), + in_len == element_len1, "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", + found `{}` with length {}", "second", in_len, in_ty, arg_tys[1], - arg_tys[1].simd_size(tcx) + element_len1 ); require!( - in_len == arg_tys[2].simd_size(tcx), + in_len == element_len2, "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", + found `{}` with length {}", "third", in_len, in_ty, arg_tys[2], - arg_tys[2].simd_size(tcx) + element_len2 ); // This counts how many pointers @@ -1336,39 +1357,42 @@ fn generic_simd_intrinsic( // The second argument must be a simd vector with an element type that's a pointer // to the element type of the first argument - let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind() { + let (element_ty0, _element_len0) = simd_ty_and_len(bx, arg_tys[0]); + let (element_ty1, _element_len1) = simd_ty_and_len(bx, arg_tys[1]); + let (element_ty2, _element_len2) = simd_ty_and_len(bx, arg_tys[2]); + let (pointer_count, underlying_ty) = match element_ty1.kind() { ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mut => { - (ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx))) + (ptr_count(element_ty1), non_ptr(element_ty1)) } _ => { require!( false, "expected element type `{}` of second argument `{}` \ - to be a pointer to the element type `{}` of the first \ - argument `{}`, found `{}` != `*mut {}`", - arg_tys[1].simd_type(tcx), + to be a pointer to the element type `{}` of the first \ + argument `{}`, found `{}` != `*mut {}`", + element_ty1, arg_tys[1], in_elem, in_ty, - arg_tys[1].simd_type(tcx), + element_ty1, in_elem ); unreachable!(); } }; assert!(pointer_count > 0); - assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx))); - assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx))); + assert_eq!(pointer_count - 1, ptr_count(element_ty0)); + assert_eq!(underlying_ty, non_ptr(element_ty0)); // The element type of the third argument must be a signed integer type of any width: - match arg_tys[2].simd_type(tcx).kind() { + match element_ty2.kind() { ty::Int(_) => (), _ => { require!( false, "expected element type `{}` of third argument `{}` \ - to be a signed integer type", - arg_tys[2].simd_type(tcx), + be a signed integer type", + element_ty2, arg_tys[2] ); } @@ -1565,7 +1589,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, if name == sym::simd_cast { require_simd!(ret_ty, "return"); - let out_len = ret_ty.simd_size(tcx); + let (out_elem, out_len) = simd_ty_and_len(bx, ret_ty); require!( in_len == out_len, "expected return type with length {} (same as input type `{}`), \ @@ -1576,8 +1600,6 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, out_len ); // casting cares about nominal type, not just structural type - let out_elem = ret_ty.simd_type(tcx); - if in_elem == out_elem { return Ok(args[0].immediate()); } @@ -1693,7 +1715,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, return_error!( "expected element type `{}` of vector type `{}` \ to be a signed or unsigned integer type", - arg_tys[0].simd_type(tcx), + simd_ty_and_len(bx, arg_tys[0]).0, arg_tys[0] ); } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 91c3dcbfa81cf..b0e2469019ab6 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -631,30 +631,106 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // SIMD vector types. - ty::Adt(def, ..) if def.repr.simd() => { - let element = self.layout_of(ty.simd_type(tcx))?; - let count = ty.simd_size(tcx); - assert!(count > 0); - let scalar = match element.abi { - Abi::Scalar(ref scalar) => scalar.clone(), - _ => { + ty::Adt(def, substs) if def.repr.simd() => { + // Supported SIMD vectors are homogeneous ADTs with at least one field: + // + // * #[repr(simd)] struct S(T, T, T, T); + // * #[repr(simd)] struct S { x: T, y: T, z: T, w: T } + // * #[repr(simd)] struct S([T; 4]) + // + // where T is a primitive scalar (integer/float/pointer). + + // SIMD vectors with zero fields are not supported. + // (should be caught by typeck) + if def.non_enum_variant().fields.is_empty() { + tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty)); + } + + // Type of the first ADT field: + let f0_ty = def.non_enum_variant().fields[0].ty(tcx, substs); + + // Heterogeneous SIMD vectors are not supported: + // (should be caught by typeck) + for fi in &def.non_enum_variant().fields { + if fi.ty(tcx, substs) != f0_ty { + tcx.sess.fatal(&format!("monomorphising heterogeneous SIMD type `{}`", ty)); + } + } + + // The element type and number of elements of the SIMD vector + // are obtained from: + // + // * the element type and length of the single array field, if + // the first field is of array type, or + // + // * the homogenous field type and the number of fields. + let (e_ty, e_len, is_array) = if let ty::Array(e_ty, _) = f0_ty.kind() { + // First ADT field is an array: + + // SIMD vectors with multiple array fields are not supported: + // (should be caught by typeck) + if def.non_enum_variant().fields.len() != 1 { tcx.sess.fatal(&format!( - "monomorphising SIMD type `{}` with \ - a non-machine element type `{}`", - ty, element.ty + "monomorphising SIMD type `{}` with more than one array field", + ty )); } + + // Extract the number of elements from the layout of the array field: + let len = if let Ok(TyAndLayout { + layout: Layout { fields: FieldsShape::Array { count, .. }, .. }, + .. + }) = self.layout_of(f0_ty) + { + count + } else { + return Err(LayoutError::Unknown(ty)); + }; + + (*e_ty, *len, true) + } else { + // First ADT field is not an array: + (f0_ty, def.non_enum_variant().fields.len() as _, false) }; - let size = - element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?; + + // SIMD vectors of zero length are not supported. + // + // Can't be caught in typeck if the array length is generic. + if e_len == 0 { + tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty)); + } + + // Compute the ABI of the element type: + let e_ly = self.layout_of(e_ty)?; + let e_abi = if let Abi::Scalar(ref scalar) = e_ly.abi { + scalar.clone() + } else { + // This error isn't caught in typeck, e.g., if + // the element type of the vector is generic. + tcx.sess.fatal(&format!( + "monomorphising SIMD type `{}` with a non-primitive-scalar \ + (integer/float/pointer) element type `{}`", + ty, e_ty + )) + }; + + // Compute the size and alignment of the vector: + let size = e_ly.size.checked_mul(e_len, dl).ok_or(LayoutError::SizeOverflow(ty))?; let align = dl.vector_align(size); let size = size.align_to(align.abi); + // Compute the placement of the vector fields: + let fields = if is_array { + FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] } + } else { + FieldsShape::Array { stride: e_ly.size, count: e_len } + }; + tcx.intern_layout(Layout { variants: Variants::Single { index: VariantIdx::new(0) }, - fields: FieldsShape::Array { stride: element.size, count }, - abi: Abi::Vector { element: scalar, count }, - largest_niche: element.largest_niche.clone(), + fields, + abi: Abi::Vector { element: e_abi, count: e_len }, + largest_niche: e_ly.largest_niche.clone(), size, align, }) @@ -2121,9 +2197,6 @@ where ty::Tuple(tys) => tys[i].expect_ty(), - // SIMD vector types. - ty::Adt(def, ..) if def.repr.simd() => this.ty.simd_type(tcx), - // ADTs. ty::Adt(def, substs) => { match this.variants { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 384d08f83485c..8202d0f0ef169 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1959,22 +1959,6 @@ impl<'tcx> TyS<'tcx> { } } - pub fn simd_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match self.kind() { - Adt(def, substs) => def.non_enum_variant().fields[0].ty(tcx, substs), - _ => bug!("`simd_type` called on invalid type"), - } - } - - pub fn simd_size(&self, _tcx: TyCtxt<'tcx>) -> u64 { - // Parameter currently unused, but probably needed in the future to - // allow `#[repr(simd)] struct Simd([T; N]);`. - match self.kind() { - Adt(def, _) => def.non_enum_variant().fields.len() as u64, - _ => bug!("`simd_size` called on invalid type"), - } - } - pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { match self.kind() { Adt(def, substs) => { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 70d94ef869d05..4605238b0a1f1 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1065,12 +1065,14 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { match e.kind() { ty::Param(_) => { /* struct(T, T, T, T) is ok */ } _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ } + ty::Array(ty, _c) if ty.is_machine() => { /* struct([f32; 4]) */ } _ => { struct_span_err!( tcx.sess, sp, E0077, - "SIMD vector element type should be machine type" + "SIMD vector element type should be a \ + primitive scalar (integer/float/pointer) type" ) .emit(); return; diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs new file mode 100644 index 0000000000000..3dba044d376e8 --- /dev/null +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs @@ -0,0 +1,47 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics, const_generics)] +#![allow(non_camel_case_types, incomplete_features)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct M(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct S([f32; N]); + +extern "platform-intrinsic" { + fn simd_extract(x: T, idx: u32) -> U; + fn simd_insert(x: T, idx: u32, b: U) -> T; +} + +// CHECK-LABEL: @extract_m +#[no_mangle] +pub unsafe fn extract_m(v: M, i: u32) -> f32 { + // CHECK: extractelement <4 x float> %0, i32 %i + simd_extract(v, i) +} + +// CHECK-LABEL: @extract_s +#[no_mangle] +pub unsafe fn extract_s(v: S<4>, i: u32) -> f32 { + // CHECK: extractelement <4 x float> %0, i32 %i + simd_extract(v, i) +} + +// CHECK-LABEL: @insert_m +#[no_mangle] +pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M { + // CHECK: insertelement <4 x float> %1, float %j, i32 %i + simd_insert(v, i, j) +} + +// CHECK-LABEL: @insert_s +#[no_mangle] +pub unsafe fn insert_s(v: S<4>, i: u32, j: f32) -> S<4> { + // CHECK: insertelement <4 x float> %1, float %j, i32 %i + simd_insert(v, i, j) +} diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs new file mode 100644 index 0000000000000..23098e7f64945 --- /dev/null +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -0,0 +1,44 @@ +// ignore-tidy-linelength +// compile-flags: -C no-prepopulate-passes +// min-llvm-version 8.0 + +#![crate_type = "lib"] + +#![allow(non_camel_case_types, incomplete_features)] +#![feature(repr_simd, platform_intrinsics, const_generics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct S([f32; N]); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct T([f32; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct U(f32, f32, f32, f32); + +// CHECK-LABEL: @build_array_s +#[no_mangle] +pub fn build_array_s(x: [f32; 4]) -> S<4> { + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i64 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i64 16, i1 false) + S::<4>(x) +} + +// CHECK-LABEL: @build_array_t +#[no_mangle] +pub fn build_array_t(x: [f32; 4]) -> T { + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i64 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i64 16, i1 false) + T(x) +} + +// CHECK-LABEL: @build_array_u +#[no_mangle] +pub fn build_array_u(x: [f32; 4]) -> U { + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i64 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i64 16, i1 false) + unsafe { std::mem::transmute(x) } +} diff --git a/src/test/ui/error-codes/E0077.stderr b/src/test/ui/error-codes/E0077.stderr index 4f85d175ce65d..1938a9a272a16 100644 --- a/src/test/ui/error-codes/E0077.stderr +++ b/src/test/ui/error-codes/E0077.stderr @@ -1,4 +1,4 @@ -error[E0077]: SIMD vector element type should be machine type +error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type --> $DIR/E0077.rs:4:1 | LL | struct Bad(String); diff --git a/src/test/ui/simd-type-generic-monomorphisation.rs b/src/test/ui/simd-type-generic-monomorphisation.rs index fc5e23f49869a..0275f0ce4c159 100644 --- a/src/test/ui/simd-type-generic-monomorphisation.rs +++ b/src/test/ui/simd-type-generic-monomorphisation.rs @@ -2,7 +2,9 @@ #![feature(repr_simd, platform_intrinsics)] -// error-pattern:monomorphising SIMD type `Simd2` with a non-machine element type `X` +// ignore-tidy-linelength + +// error-pattern:monomorphising SIMD type `Simd2` with a non-primitive-scalar (integer/float/pointer) element type `X` struct X(Vec); #[repr(simd)] diff --git a/src/test/ui/simd-type-generic-monomorphisation.stderr b/src/test/ui/simd-type-generic-monomorphisation.stderr index 2a74506e80ea5..7f23893ac8536 100644 --- a/src/test/ui/simd-type-generic-monomorphisation.stderr +++ b/src/test/ui/simd-type-generic-monomorphisation.stderr @@ -1,4 +1,4 @@ -error: monomorphising SIMD type `Simd2` with a non-machine element type `X` +error: monomorphising SIMD type `Simd2` with a non-primitive-scalar (integer/float/pointer) element type `X` error: aborting due to previous error diff --git a/src/test/ui/simd-type.rs b/src/test/ui/simd-type.rs index 9e4b7e7656055..a320df85138e5 100644 --- a/src/test/ui/simd-type.rs +++ b/src/test/ui/simd-type.rs @@ -1,10 +1,20 @@ #![feature(repr_simd)] #![allow(non_camel_case_types)] +// ignore-tidy-linelength + #[repr(simd)] struct empty; //~ ERROR SIMD vector cannot be empty #[repr(simd)] struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous +struct Foo; + +#[repr(simd)] +struct FooV(Foo, Foo); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type + +#[repr(simd)] +struct FooV2([Foo; 2]); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type + fn main() {} diff --git a/src/test/ui/simd-type.stderr b/src/test/ui/simd-type.stderr index 0c4242f46b786..23004c785918c 100644 --- a/src/test/ui/simd-type.stderr +++ b/src/test/ui/simd-type.stderr @@ -1,16 +1,28 @@ error[E0075]: SIMD vector cannot be empty - --> $DIR/simd-type.rs:5:1 + --> $DIR/simd-type.rs:7:1 | LL | struct empty; | ^^^^^^^^^^^^^ error[E0076]: SIMD vector should be homogeneous - --> $DIR/simd-type.rs:8:1 + --> $DIR/simd-type.rs:10:1 | LL | struct i64f64(i64, f64); | ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type -error: aborting due to 2 previous errors +error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type + --> $DIR/simd-type.rs:15:1 + | +LL | struct FooV(Foo, Foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type + --> $DIR/simd-type.rs:18:1 + | +LL | struct FooV2([Foo; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0075, E0076. +Some errors have detailed explanations: E0075, E0076, E0077. For more information about an error, try `rustc --explain E0075`. diff --git a/src/test/ui/simd/simd-array-type.rs b/src/test/ui/simd/simd-array-type.rs new file mode 100644 index 0000000000000..c84988cffb423 --- /dev/null +++ b/src/test/ui/simd/simd-array-type.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(dead_code, incomplete_features)] + +// pretty-expanded FIXME #23616 + +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![feature(const_generics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct S([i32; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct T([i32; N]); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, y: E) -> T; + fn simd_extract(x: T, idx: u32) -> E; +} + +pub fn main() { + let mut s = S([0; 4]); + + unsafe { + for i in 0_i32..4 { + s = simd_insert(s, i as u32, i); + } + for i in 0_i32..4 { + assert_eq!(i, simd_extract(s, i as u32)); + } + } + + let mut t = T::<4>([0; 4]); + unsafe { + for i in 0_i32..4 { + t = simd_insert(t, i as u32, i); + } + for i in 0_i32..4 { + assert_eq!(i, simd_extract(t, i as u32)); + } + } +} diff --git a/src/test/ui/simd/simd-generics.rs b/src/test/ui/simd/simd-generics.rs index ab6caee9d7bce..9877e37dfb2ec 100644 --- a/src/test/ui/simd/simd-generics.rs +++ b/src/test/ui/simd/simd-generics.rs @@ -1,9 +1,6 @@ // run-pass -#![allow(non_camel_case_types)] - - - -#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types, incomplete_features)] +#![feature(repr_simd, platform_intrinsics, const_generics)] use std::ops; @@ -11,6 +8,11 @@ use std::ops; #[derive(Copy, Clone)] struct f32x4(f32, f32, f32, f32); +#[repr(simd)] +#[derive(Copy, Clone)] +struct S([f32; N]); + + extern "platform-intrinsic" { fn simd_add(x: T, y: T) -> T; } @@ -27,7 +29,16 @@ impl ops::Add for f32x4 { } } -pub fn main() { +impl ops::Add for S<4> { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + unsafe {simd_add(self, rhs)} + } +} + + +pub fn main() { unsafe { let lr = f32x4(1.0f32, 2.0f32, 3.0f32, 4.0f32); // lame-o @@ -36,4 +47,11 @@ pub fn main() { assert_eq!(y, 4.0f32); assert_eq!(z, 6.0f32); assert_eq!(w, 8.0f32); -} + + let lr2 = S::<4>([1.0f32, 2.0f32, 3.0f32, 4.0f32]); + let [x, y, z, w] = add(lr2, lr2).0; + assert_eq!(x, 2.0f32); + assert_eq!(y, 4.0f32); + assert_eq!(z, 6.0f32); + assert_eq!(w, 8.0f32); +}} diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs index b7b3ec997810e..30a4fc11368d6 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs @@ -1,16 +1,16 @@ // run-pass // ignore-emscripten -#![allow(non_camel_case_types)] -#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types, incomplete_features)] +#![feature(repr_simd, platform_intrinsics, const_generics)] #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] struct u32x4(pub u32, pub u32, pub u32, pub u32); #[repr(simd)] -#[derive(Copy, Clone, PartialEq, Debug)] -struct i32x4(pub i32, pub i32, pub i32, pub i32); +#[derive(Copy, Clone)] +struct I32([i32; N]); extern "platform-intrinsic" { fn simd_saturating_add(x: T, y: T) -> T; @@ -51,41 +51,41 @@ fn main() { const MIN: i32 = i32::MIN; const MAX: i32 = i32::MAX; - let a = i32x4(1, 2, 3, 4); - let b = i32x4(2, 4, 6, 8); - let c = i32x4(-1, -2, -3, -4); - let d = i32x4(-2, -4, -6, -8); + let a = I32::<4>([1, 2, 3, 4]); + let b = I32::<4>([2, 4, 6, 8]); + let c = I32::<4>([-1, -2, -3, -4]); + let d = I32::<4>([-2, -4, -6, -8]); - let max = i32x4(MAX, MAX, MAX, MAX); - let max1 = i32x4(MAX - 1, MAX - 1, MAX - 1, MAX - 1); - let min = i32x4(MIN, MIN, MIN, MIN); - let min1 = i32x4(MIN + 1, MIN + 1, MIN + 1, MIN + 1); + let max = I32::<4>([MAX, MAX, MAX, MAX]); + let max1 = I32::<4>([MAX - 1, MAX - 1, MAX - 1, MAX - 1]); + let min = I32::<4>([MIN, MIN, MIN, MIN]); + let min1 = I32::<4>([MIN + 1, MIN + 1, MIN + 1, MIN + 1]); - let z = i32x4(0, 0, 0, 0); + let z = I32::<4>([0, 0, 0, 0]); unsafe { - assert_eq!(simd_saturating_add(z, z), z); - assert_eq!(simd_saturating_add(z, a), a); - assert_eq!(simd_saturating_add(b, z), b); - assert_eq!(simd_saturating_add(a, a), b); - assert_eq!(simd_saturating_add(a, max), max); - assert_eq!(simd_saturating_add(max, b), max); - assert_eq!(simd_saturating_add(max1, a), max); - assert_eq!(simd_saturating_add(min1, z), min1); - assert_eq!(simd_saturating_add(min, z), min); - assert_eq!(simd_saturating_add(min1, c), min); - assert_eq!(simd_saturating_add(min, c), min); - assert_eq!(simd_saturating_add(min1, d), min); - assert_eq!(simd_saturating_add(min, d), min); + assert_eq!(simd_saturating_add(z, z).0, z.0); + assert_eq!(simd_saturating_add(z, a).0, a.0); + assert_eq!(simd_saturating_add(b, z).0, b.0); + assert_eq!(simd_saturating_add(a, a).0, b.0); + assert_eq!(simd_saturating_add(a, max).0, max.0); + assert_eq!(simd_saturating_add(max, b).0, max.0); + assert_eq!(simd_saturating_add(max1, a).0, max.0); + assert_eq!(simd_saturating_add(min1, z).0, min1.0); + assert_eq!(simd_saturating_add(min, z).0, min.0); + assert_eq!(simd_saturating_add(min1, c).0, min.0); + assert_eq!(simd_saturating_add(min, c).0, min.0); + assert_eq!(simd_saturating_add(min1, d).0, min.0); + assert_eq!(simd_saturating_add(min, d).0, min.0); - assert_eq!(simd_saturating_sub(b, z), b); - assert_eq!(simd_saturating_sub(b, a), a); - assert_eq!(simd_saturating_sub(a, a), z); - assert_eq!(simd_saturating_sub(a, b), c); - assert_eq!(simd_saturating_sub(z, max), min1); - assert_eq!(simd_saturating_sub(min1, z), min1); - assert_eq!(simd_saturating_sub(min1, a), min); - assert_eq!(simd_saturating_sub(min1, b), min); + assert_eq!(simd_saturating_sub(b, z).0, b.0); + assert_eq!(simd_saturating_sub(b, a).0, a.0); + assert_eq!(simd_saturating_sub(a, a).0, z.0); + assert_eq!(simd_saturating_sub(a, b).0, c.0); + assert_eq!(simd_saturating_sub(z, max).0, min1.0); + assert_eq!(simd_saturating_sub(min1, z).0, min1.0); + assert_eq!(simd_saturating_sub(min1, a).0, min.0); + assert_eq!(simd_saturating_sub(min1, b).0, min.0); } } } diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs index b67c0ad1eb2f1..83f11c6abdbf0 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs @@ -1,9 +1,9 @@ // run-pass -#![allow(non_camel_case_types)] +#![allow(non_camel_case_types, incomplete_features)] // ignore-emscripten FIXME(#45351) hits an LLVM assert -#![feature(repr_simd, platform_intrinsics)] +#![feature(repr_simd, platform_intrinsics, const_generics)] #[repr(simd)] #[derive(Copy, Clone)] @@ -11,7 +11,7 @@ struct i32x4(pub i32, pub i32, pub i32, pub i32); #[repr(simd)] #[derive(Copy, Clone)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct U32([u32; N]); #[repr(simd)] #[derive(Copy, Clone)] @@ -25,6 +25,15 @@ macro_rules! all_eq { }} } +macro_rules! all_eq_ { + ($a: expr, $b: expr) => {{ + let a = $a; + let b = $b; + assert!(a.0 == b.0); + }} +} + + extern "platform-intrinsic" { fn simd_add(x: T, y: T) -> T; fn simd_sub(x: T, y: T) -> T; @@ -40,81 +49,81 @@ extern "platform-intrinsic" { fn main() { let x1 = i32x4(1, 2, 3, 4); - let y1 = u32x4(1, 2, 3, 4); + let y1 = U32::<4>([1, 2, 3, 4]); let z1 = f32x4(1.0, 2.0, 3.0, 4.0); let x2 = i32x4(2, 3, 4, 5); - let y2 = u32x4(2, 3, 4, 5); + let y2 = U32::<4>([2, 3, 4, 5]); let z2 = f32x4(2.0, 3.0, 4.0, 5.0); unsafe { all_eq!(simd_add(x1, x2), i32x4(3, 5, 7, 9)); all_eq!(simd_add(x2, x1), i32x4(3, 5, 7, 9)); - all_eq!(simd_add(y1, y2), u32x4(3, 5, 7, 9)); - all_eq!(simd_add(y2, y1), u32x4(3, 5, 7, 9)); + all_eq_!(simd_add(y1, y2), U32::<4>([3, 5, 7, 9])); + all_eq_!(simd_add(y2, y1), U32::<4>([3, 5, 7, 9])); all_eq!(simd_add(z1, z2), f32x4(3.0, 5.0, 7.0, 9.0)); all_eq!(simd_add(z2, z1), f32x4(3.0, 5.0, 7.0, 9.0)); all_eq!(simd_mul(x1, x2), i32x4(2, 6, 12, 20)); all_eq!(simd_mul(x2, x1), i32x4(2, 6, 12, 20)); - all_eq!(simd_mul(y1, y2), u32x4(2, 6, 12, 20)); - all_eq!(simd_mul(y2, y1), u32x4(2, 6, 12, 20)); + all_eq_!(simd_mul(y1, y2), U32::<4>([2, 6, 12, 20])); + all_eq_!(simd_mul(y2, y1), U32::<4>([2, 6, 12, 20])); all_eq!(simd_mul(z1, z2), f32x4(2.0, 6.0, 12.0, 20.0)); all_eq!(simd_mul(z2, z1), f32x4(2.0, 6.0, 12.0, 20.0)); all_eq!(simd_sub(x2, x1), i32x4(1, 1, 1, 1)); all_eq!(simd_sub(x1, x2), i32x4(-1, -1, -1, -1)); - all_eq!(simd_sub(y2, y1), u32x4(1, 1, 1, 1)); - all_eq!(simd_sub(y1, y2), u32x4(!0, !0, !0, !0)); + all_eq_!(simd_sub(y2, y1), U32::<4>([1, 1, 1, 1])); + all_eq_!(simd_sub(y1, y2), U32::<4>([!0, !0, !0, !0])); all_eq!(simd_sub(z2, z1), f32x4(1.0, 1.0, 1.0, 1.0)); all_eq!(simd_sub(z1, z2), f32x4(-1.0, -1.0, -1.0, -1.0)); all_eq!(simd_div(x1, x1), i32x4(1, 1, 1, 1)); all_eq!(simd_div(i32x4(2, 4, 6, 8), i32x4(2, 2, 2, 2)), x1); - all_eq!(simd_div(y1, y1), u32x4(1, 1, 1, 1)); - all_eq!(simd_div(u32x4(2, 4, 6, 8), u32x4(2, 2, 2, 2)), y1); + all_eq_!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1])); + all_eq_!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1); all_eq!(simd_div(z1, z1), f32x4(1.0, 1.0, 1.0, 1.0)); all_eq!(simd_div(z1, z2), f32x4(1.0/2.0, 2.0/3.0, 3.0/4.0, 4.0/5.0)); all_eq!(simd_div(z2, z1), f32x4(2.0/1.0, 3.0/2.0, 4.0/3.0, 5.0/4.0)); all_eq!(simd_rem(x1, x1), i32x4(0, 0, 0, 0)); all_eq!(simd_rem(x2, x1), i32x4(0, 1, 1, 1)); - all_eq!(simd_rem(y1, y1), u32x4(0, 0, 0, 0)); - all_eq!(simd_rem(y2, y1), u32x4(0, 1, 1, 1)); + all_eq_!(simd_rem(y1, y1), U32::<4>([0, 0, 0, 0])); + all_eq_!(simd_rem(y2, y1), U32::<4>([0, 1, 1, 1])); all_eq!(simd_rem(z1, z1), f32x4(0.0, 0.0, 0.0, 0.0)); all_eq!(simd_rem(z1, z2), z1); all_eq!(simd_rem(z2, z1), f32x4(0.0, 1.0, 1.0, 1.0)); all_eq!(simd_shl(x1, x2), i32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5)); all_eq!(simd_shl(x2, x1), i32x4(2 << 1, 3 << 2, 4 << 3, 5 << 4)); - all_eq!(simd_shl(y1, y2), u32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5)); - all_eq!(simd_shl(y2, y1), u32x4(2 << 1, 3 << 2, 4 << 3, 5 << 4)); + all_eq_!(simd_shl(y1, y2), U32::<4>([1 << 2, 2 << 3, 3 << 4, 4 << 5])); + all_eq_!(simd_shl(y2, y1), U32::<4>([2 << 1, 3 << 2, 4 << 3, 5 << 4])); // test right-shift by assuming left-shift is correct all_eq!(simd_shr(simd_shl(x1, x2), x2), x1); all_eq!(simd_shr(simd_shl(x2, x1), x1), x2); - all_eq!(simd_shr(simd_shl(y1, y2), y2), y1); - all_eq!(simd_shr(simd_shl(y2, y1), y1), y2); + all_eq_!(simd_shr(simd_shl(y1, y2), y2), y1); + all_eq_!(simd_shr(simd_shl(y2, y1), y1), y2); // ensure we get logical vs. arithmetic shifts correct let (a, b, c, d) = (-12, -123, -1234, -12345); all_eq!(simd_shr(i32x4(a, b, c, d), x1), i32x4(a >> 1, b >> 2, c >> 3, d >> 4)); - all_eq!(simd_shr(u32x4(a as u32, b as u32, c as u32, d as u32), y1), - u32x4((a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4)); + all_eq_!(simd_shr(U32::<4>([a as u32, b as u32, c as u32, d as u32]), y1), + U32::<4>([(a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4])); all_eq!(simd_and(x1, x2), i32x4(0, 2, 0, 4)); all_eq!(simd_and(x2, x1), i32x4(0, 2, 0, 4)); - all_eq!(simd_and(y1, y2), u32x4(0, 2, 0, 4)); - all_eq!(simd_and(y2, y1), u32x4(0, 2, 0, 4)); + all_eq_!(simd_and(y1, y2), U32::<4>([0, 2, 0, 4])); + all_eq_!(simd_and(y2, y1), U32::<4>([0, 2, 0, 4])); all_eq!(simd_or(x1, x2), i32x4(3, 3, 7, 5)); all_eq!(simd_or(x2, x1), i32x4(3, 3, 7, 5)); - all_eq!(simd_or(y1, y2), u32x4(3, 3, 7, 5)); - all_eq!(simd_or(y2, y1), u32x4(3, 3, 7, 5)); + all_eq_!(simd_or(y1, y2), U32::<4>([3, 3, 7, 5])); + all_eq_!(simd_or(y2, y1), U32::<4>([3, 3, 7, 5])); all_eq!(simd_xor(x1, x2), i32x4(3, 1, 7, 1)); all_eq!(simd_xor(x2, x1), i32x4(3, 1, 7, 1)); - all_eq!(simd_xor(y1, y2), u32x4(3, 1, 7, 1)); - all_eq!(simd_xor(y2, y1), u32x4(3, 1, 7, 1)); + all_eq_!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1])); + all_eq_!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1])); } } From 9bb42021962c93b35592a0b1c29f282d3b5506c4 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 8 Nov 2020 20:21:28 +1000 Subject: [PATCH 02/10] update ui tests --- src/test/ui/simd/simd-array-type.rs | 6 ++---- src/test/ui/simd/simd-generics.rs | 12 ++++++------ .../simd-intrinsic-generic-arithmetic-saturating.rs | 4 ++-- .../ui/simd/simd-intrinsic-generic-arithmetic.rs | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/test/ui/simd/simd-array-type.rs b/src/test/ui/simd/simd-array-type.rs index c84988cffb423..e84186a42adff 100644 --- a/src/test/ui/simd/simd-array-type.rs +++ b/src/test/ui/simd/simd-array-type.rs @@ -1,11 +1,9 @@ // run-pass -#![allow(dead_code, incomplete_features)] +#![allow(dead_code)] // pretty-expanded FIXME #23616 -#![feature(repr_simd)] -#![feature(platform_intrinsics)] -#![feature(const_generics)] +#![feature(repr_simd, platform_intrinsics, min_const_generics)] #[repr(simd)] #[derive(Copy, Clone)] diff --git a/src/test/ui/simd/simd-generics.rs b/src/test/ui/simd/simd-generics.rs index 9877e37dfb2ec..dedca6276cda9 100644 --- a/src/test/ui/simd/simd-generics.rs +++ b/src/test/ui/simd/simd-generics.rs @@ -1,6 +1,6 @@ // run-pass -#![allow(non_camel_case_types, incomplete_features)] -#![feature(repr_simd, platform_intrinsics, const_generics)] +#![allow(non_camel_case_types)] +#![feature(repr_simd, platform_intrinsics, min_const_generics)] use std::ops; @@ -25,7 +25,7 @@ impl ops::Add for f32x4 { type Output = f32x4; fn add(self, rhs: f32x4) -> f32x4 { - unsafe {simd_add(self, rhs)} + unsafe { simd_add(self, rhs) } } } @@ -33,12 +33,12 @@ impl ops::Add for S<4> { type Output = Self; fn add(self, rhs: Self) -> Self { - unsafe {simd_add(self, rhs)} + unsafe { simd_add(self, rhs) } } } -pub fn main() { unsafe { +pub fn main() { let lr = f32x4(1.0f32, 2.0f32, 3.0f32, 4.0f32); // lame-o @@ -54,4 +54,4 @@ pub fn main() { unsafe { assert_eq!(y, 4.0f32); assert_eq!(z, 6.0f32); assert_eq!(w, 8.0f32); -}} +} diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs index 30a4fc11368d6..4c459fa4bc801 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs @@ -1,8 +1,8 @@ // run-pass // ignore-emscripten -#![allow(non_camel_case_types, incomplete_features)] -#![feature(repr_simd, platform_intrinsics, const_generics)] +#![allow(non_camel_case_types)] +#![feature(repr_simd, platform_intrinsics, min_const_generics)] #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs index 83f11c6abdbf0..5b0ff88432ed9 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs @@ -1,9 +1,9 @@ // run-pass -#![allow(non_camel_case_types, incomplete_features)] +#![allow(non_camel_case_types)] // ignore-emscripten FIXME(#45351) hits an LLVM assert -#![feature(repr_simd, platform_intrinsics, const_generics)] +#![feature(repr_simd, platform_intrinsics, min_const_generics)] #[repr(simd)] #[derive(Copy, Clone)] From 540b5db6306e0e7e96fb9d8dfda94cc82f6ba3bb Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 13 Nov 2020 14:31:12 +1000 Subject: [PATCH 03/10] remove const_generics from codegen tests --- .../simd-intrinsic/simd-intrinsic-generic-extract-insert.rs | 4 ++-- .../codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs index 3dba044d376e8..5f976b642eae9 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs @@ -2,8 +2,8 @@ #![crate_type = "lib"] -#![feature(repr_simd, platform_intrinsics, const_generics)] -#![allow(non_camel_case_types, incomplete_features)] +#![feature(repr_simd, platform_intrinsics, min_const_generics)] +#![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone)] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 23098e7f64945..76f2644dbc9f5 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -4,8 +4,8 @@ #![crate_type = "lib"] -#![allow(non_camel_case_types, incomplete_features)] -#![feature(repr_simd, platform_intrinsics, const_generics)] +#![allow(non_camel_case_types)] +#![feature(repr_simd, platform_intrinsics, min_const_generics)] #[repr(simd)] #[derive(Copy, Clone)] From 045105b1a2ed4d93d5e72bc34fdce55e0b3e6dad Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 13 Nov 2020 14:32:03 +1000 Subject: [PATCH 04/10] remove internal simd_size_and_ty from llvm backend --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 51 +++++++------------- compiler/rustc_middle/src/ty/sty.rs | 7 ++- 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 2ea7d7ac2d822..3df0ab5d36ca0 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -740,23 +740,6 @@ fn generic_simd_intrinsic( llret_ty: &'ll Type, span: Span, ) -> Result<&'ll Value, ()> { - // Given a SIMD vector type `x` return the element type and the number of - // elements in the vector. - fn simd_ty_and_len(bx: &Builder<'a, 'll, 'tcx>, simd_ty: Ty<'tcx>) -> (Ty<'tcx>, u64) { - let ty = if let ty::Adt(_def, _substs) = simd_ty.kind() { - let f0_ty = bx.layout_of(simd_ty).field(bx, 0).ty; - if let ty::Array(element_ty, _) = f0_ty.kind() { element_ty } else { f0_ty } - } else { - bug!("should only be called with a SIMD type") - }; - let count = if let abi::Abi::Vector { count, .. } = bx.layout_of(simd_ty).abi { - count - } else { - bug!("should only be called with a SIMD type") - }; - (ty, count) - } - // macros for error handling: macro_rules! emit_error { ($msg: tt) => { @@ -809,7 +792,7 @@ fn generic_simd_intrinsic( _ => return_error!("`{}` is not an integral type", in_ty), }; require_simd!(arg_tys[1], "argument"); - let (_, v_len) = simd_ty_and_len(bx, arg_tys[1]); + let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( // Allow masks for vectors with fewer than 8 elements to be // represented with a u8 or i8. @@ -840,11 +823,11 @@ fn generic_simd_intrinsic( _ => None, }; - let (in_elem, in_len) = simd_ty_and_len(bx, arg_tys[0]); + let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx()); if let Some(cmp_op) = comparison { require_simd!(ret_ty, "return"); - let (out_ty, out_len) = simd_ty_and_len(bx, ret_ty); + let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, "expected return type with length {} (same as input type `{}`), \ @@ -878,7 +861,7 @@ fn generic_simd_intrinsic( require_simd!(ret_ty, "return"); - let (out_ty, out_len) = simd_ty_and_len(bx, ret_ty); + let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, "expected return type of length {}, found `{}` with length {}", @@ -962,7 +945,7 @@ fn generic_simd_intrinsic( let m_elem_ty = in_elem; let m_len = in_len; require_simd!(arg_tys[1], "argument"); - let (_, v_len) = simd_ty_and_len(bx, arg_tys[1]); + let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, "mismatched lengths: mask length `{}` != other vector length `{}`", @@ -1187,8 +1170,8 @@ fn generic_simd_intrinsic( require_simd!(ret_ty, "return"); // Of the same length: - let (_, out_len) = simd_ty_and_len(bx, arg_tys[1]); - let (_, out_len2) = simd_ty_and_len(bx, arg_tys[2]); + let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); + let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); require!( in_len == out_len, "expected {} argument with length {} (same as input type `{}`), \ @@ -1231,8 +1214,8 @@ fn generic_simd_intrinsic( // The second argument must be a simd vector with an element type that's a pointer // to the element type of the first argument - let (element_ty0, _) = simd_ty_and_len(bx, arg_tys[0]); - let (element_ty1, _) = simd_ty_and_len(bx, arg_tys[1]); + let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx()); + let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx()); let (pointer_count, underlying_ty) = match element_ty1.kind() { ty::RawPtr(p) if p.ty == in_elem => (ptr_count(element_ty1), non_ptr(element_ty1)), _ => { @@ -1256,7 +1239,7 @@ fn generic_simd_intrinsic( assert_eq!(underlying_ty, non_ptr(element_ty0)); // The element type of the third argument must be a signed integer type of any width: - let (element_ty2, _) = simd_ty_and_len(bx, arg_tys[2]); + let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx()); match element_ty2.kind() { ty::Int(_) => (), _ => { @@ -1316,8 +1299,8 @@ fn generic_simd_intrinsic( require_simd!(arg_tys[2], "third"); // Of the same length: - let (_, element_len1) = simd_ty_and_len(bx, arg_tys[1]); - let (_, element_len2) = simd_ty_and_len(bx, arg_tys[2]); + let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); + let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); require!( in_len == element_len1, "expected {} argument with length {} (same as input type `{}`), \ @@ -1357,9 +1340,9 @@ fn generic_simd_intrinsic( // The second argument must be a simd vector with an element type that's a pointer // to the element type of the first argument - let (element_ty0, _element_len0) = simd_ty_and_len(bx, arg_tys[0]); - let (element_ty1, _element_len1) = simd_ty_and_len(bx, arg_tys[1]); - let (element_ty2, _element_len2) = simd_ty_and_len(bx, arg_tys[2]); + let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx()); + let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx()); + let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx()); let (pointer_count, underlying_ty) = match element_ty1.kind() { ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mut => { (ptr_count(element_ty1), non_ptr(element_ty1)) @@ -1589,7 +1572,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, if name == sym::simd_cast { require_simd!(ret_ty, "return"); - let (out_elem, out_len) = simd_ty_and_len(bx, ret_ty); + let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, "expected return type with length {} (same as input type `{}`), \ @@ -1715,7 +1698,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, return_error!( "expected element type `{}` of vector type `{}` \ to be a signed or unsigned integer type", - simd_ty_and_len(bx, arg_tys[0]).0, + arg_tys[0].simd_size_and_type(bx.tcx()).1, arg_tys[0] ); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8202d0f0ef169..d1f83d0a83e0e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1963,7 +1963,12 @@ impl<'tcx> TyS<'tcx> { match self.kind() { Adt(def, substs) => { let variant = def.non_enum_variant(); - (variant.fields.len() as u64, variant.fields[0].ty(tcx, substs)) + let f0_ty = variant.fields[0].ty(tcx, substs); + + match f0_ty.kind() { + Array(f0_elem_ty, f0_len) => (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, f0_elem_ty), + _ => (variant.fields.len() as u64, f0_ty), + } } _ => bug!("`simd_size_and_type` called on invalid type"), } From 74f2941a8ebf32a6864ea4596c755a9f65e14f42 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sat, 14 Nov 2020 21:12:15 +1000 Subject: [PATCH 05/10] tweak new codegen test to work on local --- .../simd-intrinsic-generic-extract-insert.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs index 5f976b642eae9..1ab3292378558 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs @@ -21,27 +21,27 @@ extern "platform-intrinsic" { // CHECK-LABEL: @extract_m #[no_mangle] pub unsafe fn extract_m(v: M, i: u32) -> f32 { - // CHECK: extractelement <4 x float> %0, i32 %i + // CHECK: extractelement <4 x float> %_3, i32 %i simd_extract(v, i) } // CHECK-LABEL: @extract_s #[no_mangle] pub unsafe fn extract_s(v: S<4>, i: u32) -> f32 { - // CHECK: extractelement <4 x float> %0, i32 %i + // CHECK: extractelement <4 x float> %_3, i32 %i simd_extract(v, i) } // CHECK-LABEL: @insert_m #[no_mangle] pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M { - // CHECK: insertelement <4 x float> %1, float %j, i32 %i + // CHECK: insertelement <4 x float> %_4, float %j, i32 %i simd_insert(v, i, j) } // CHECK-LABEL: @insert_s #[no_mangle] pub unsafe fn insert_s(v: S<4>, i: u32, j: f32) -> S<4> { - // CHECK: insertelement <4 x float> %1, float %j, i32 %i + // CHECK: insertelement <4 x float> %_4, float %j, i32 %i simd_insert(v, i, j) } From 75658091631afe5a8b805a340a43bef4c00def11 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 15 Nov 2020 09:35:04 +1000 Subject: [PATCH 06/10] add a canary test for complex repr(simd) --- compiler/rustc_middle/src/ty/sty.rs | 8 ++++- src/test/ui/simd/simd-array-trait.rs | 40 ++++++++++++++++++++++++ src/test/ui/simd/simd-array-trait.stderr | 10 ++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/simd/simd-array-trait.rs create mode 100644 src/test/ui/simd/simd-array-trait.stderr diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d1f83d0a83e0e..5d57ed9e2f832 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1966,7 +1966,13 @@ impl<'tcx> TyS<'tcx> { let f0_ty = variant.fields[0].ty(tcx, substs); match f0_ty.kind() { - Array(f0_elem_ty, f0_len) => (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, f0_elem_ty), + Array(f0_elem_ty, f0_len) => { + // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 + // The way we evaluate the `N` in `[T; N]` here only works since we use + // `simd_size_and_type` post-monomorphization. It will probably start to ICE + // if we use it in generic code. See the `simd-array-trait` ui test. + (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, f0_elem_ty) + } _ => (variant.fields.len() as u64, f0_ty), } } diff --git a/src/test/ui/simd/simd-array-trait.rs b/src/test/ui/simd/simd-array-trait.rs new file mode 100644 index 0000000000000..6219e7ca83b16 --- /dev/null +++ b/src/test/ui/simd/simd-array-trait.rs @@ -0,0 +1,40 @@ +// Figuring out the size of a vector type that depends on traits doesn't ICE + +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +#![feature(repr_simd, platform_intrinsics, const_generics)] +#![allow(non_camel_case_types, incomplete_features)] + +pub trait Simd { + type Lane: Clone + Copy; + const SIZE: usize; +} + +pub struct i32x4; +impl Simd for i32x4 { + type Lane = i32; + const SIZE: usize = 4; +} + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct T([S::Lane; S::SIZE]); //~ ERROR constant expression depends on a generic parameter + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, y: E) -> T; + fn simd_extract(x: T, idx: u32) -> E; +} + +pub fn main() { + let mut t = T::([0; 4]); + unsafe { + for i in 0_i32..4 { + t = simd_insert(t, i as u32, i); + } + for i in 0_i32..4 { + assert_eq!(i, simd_extract(t, i as u32)); + } + } +} diff --git a/src/test/ui/simd/simd-array-trait.stderr b/src/test/ui/simd/simd-array-trait.stderr new file mode 100644 index 0000000000000..c100e020c5490 --- /dev/null +++ b/src/test/ui/simd/simd-array-trait.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/simd-array-trait.rs:23:23 + | +LL | pub struct T([S::Lane; S::SIZE]); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + From e217fc4a06ad7b5cb39877c0dae028f9f01839e3 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 15 Nov 2020 18:03:42 +1000 Subject: [PATCH 07/10] fix up tidy --- src/test/ui/simd/simd-array-trait.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/simd/simd-array-trait.rs b/src/test/ui/simd/simd-array-trait.rs index 6219e7ca83b16..d6ed5f61a000e 100644 --- a/src/test/ui/simd/simd-array-trait.rs +++ b/src/test/ui/simd/simd-array-trait.rs @@ -20,7 +20,8 @@ impl Simd for i32x4 { #[repr(simd)] #[derive(Copy, Clone)] -pub struct T([S::Lane; S::SIZE]); //~ ERROR constant expression depends on a generic parameter +pub struct T([S::Lane; S::SIZE]); +//~^ ERROR constant expression depends on a generic parameter extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; From b5b35a9c8e3709e923c40333a8fbefc6c53ad2b7 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 24 Nov 2020 05:27:19 +1000 Subject: [PATCH 08/10] generalize codegen to non 64bit platforms --- .../simd-intrinsic/simd-intrinsic-transmute-array.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 76f2644dbc9f5..c3265ca903752 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -22,23 +22,23 @@ pub struct U(f32, f32, f32, f32); // CHECK-LABEL: @build_array_s #[no_mangle] pub fn build_array_s(x: [f32; 4]) -> S<4> { - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i64 16, i1 false) - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i64 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i{{[0-9]+}} 16, i1 false) S::<4>(x) } // CHECK-LABEL: @build_array_t #[no_mangle] pub fn build_array_t(x: [f32; 4]) -> T { - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i64 16, i1 false) - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i64 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i{{[0-9]+}} 16, i1 false) T(x) } // CHECK-LABEL: @build_array_u #[no_mangle] pub fn build_array_u(x: [f32; 4]) -> U { - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i64 16, i1 false) - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i64 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i{{[0-9]+}} 16, i1 false) unsafe { std::mem::transmute(x) } } From 90255c8da612bf5b2c0e8fef67852c76459a688f Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 29 Nov 2020 10:18:07 +1000 Subject: [PATCH 09/10] looser regex on local args --- .../simd-intrinsic/simd-intrinsic-transmute-array.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index c3265ca903752..56466a78d5a69 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -22,23 +22,23 @@ pub struct U(f32, f32, f32, f32); // CHECK-LABEL: @build_array_s #[no_mangle] pub fn build_array_s(x: [f32; 4]) -> S<4> { - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i{{[0-9]+}} 16, i1 false) - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) S::<4>(x) } // CHECK-LABEL: @build_array_t #[no_mangle] pub fn build_array_t(x: [f32; 4]) -> T { - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i{{[0-9]+}} 16, i1 false) - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) T(x) } // CHECK-LABEL: @build_array_u #[no_mangle] pub fn build_array_u(x: [f32; 4]) -> U { - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %3, i{{[0-9]+}} 16, i1 false) - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %6, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) unsafe { std::mem::transmute(x) } } From 354c7d0ab800f70e995383d498fc1fc420baa209 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 29 Nov 2020 18:36:30 +1000 Subject: [PATCH 10/10] args may be passed by value --- .../simd-intrinsic-generic-extract-insert.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs index 1ab3292378558..b5b0b1330a629 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs @@ -21,27 +21,27 @@ extern "platform-intrinsic" { // CHECK-LABEL: @extract_m #[no_mangle] pub unsafe fn extract_m(v: M, i: u32) -> f32 { - // CHECK: extractelement <4 x float> %_3, i32 %i + // CHECK: extractelement <4 x float> %{{v|_3}}, i32 %i simd_extract(v, i) } // CHECK-LABEL: @extract_s #[no_mangle] pub unsafe fn extract_s(v: S<4>, i: u32) -> f32 { - // CHECK: extractelement <4 x float> %_3, i32 %i + // CHECK: extractelement <4 x float> %{{v|_3}}, i32 %i simd_extract(v, i) } // CHECK-LABEL: @insert_m #[no_mangle] pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M { - // CHECK: insertelement <4 x float> %_4, float %j, i32 %i + // CHECK: insertelement <4 x float> %{{v|_4}}, float %j, i32 %i simd_insert(v, i, j) } // CHECK-LABEL: @insert_s #[no_mangle] pub unsafe fn insert_s(v: S<4>, i: u32, j: f32) -> S<4> { - // CHECK: insertelement <4 x float> %_4, float %j, i32 %i + // CHECK: insertelement <4 x float> %{{v|_4}}, float %j, i32 %i simd_insert(v, i, j) }