Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove layouting dead code for non-array SIMD types. #137852

Merged
merged 1 commit into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions compiler/rustc_ty_utils/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ ty_utils_logical_op_not_supported = unsupported operation in generic constants,

ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants

ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field

ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop

ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_ty_utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,6 @@ pub(crate) struct ZeroLengthSimdType<'tcx> {
pub ty: Ty<'tcx>,
}

#[derive(Diagnostic)]
#[diag(ty_utils_multiple_array_fields_simd_type)]
pub(crate) struct MultipleArrayFieldsSimdType<'tcx> {
pub ty: Ty<'tcx>,
}

#[derive(Diagnostic)]
#[diag(ty_utils_oversized_simd_type)]
pub(crate) struct OversizedSimdType<'tcx> {
Expand Down
89 changes: 19 additions & 70 deletions compiler/rustc_ty_utils/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ use rustc_span::{Symbol, sym};
use tracing::{debug, instrument, trace};
use {rustc_abi as abi, rustc_hir as hir};

use crate::errors::{
MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType,
};
use crate::errors::{NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType};

mod invariant;

Expand Down Expand Up @@ -450,71 +448,26 @@ fn layout_of_uncached<'tcx>(

// SIMD vector types.
ty::Adt(def, args) if def.repr().simd() => {
if !def.is_struct() {
// Should have yielded E0517 by now.
let guar = tcx
.dcx()
.delayed_bug("#[repr(simd)] was applied to an ADT that is not a struct");
return Err(error(cx, LayoutError::ReferencesError(guar)));
}

let fields = &def.non_enum_variant().fields;

// Supported SIMD vectors are homogeneous ADTs with at least one field:
// Supported SIMD vectors are ADTs with a single array 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 fields.is_empty() {
tcx.dcx().emit_fatal(ZeroLengthSimdType { ty })
}

// Type of the first ADT field:
let f0_ty = fields[FieldIdx::ZERO].ty(tcx, args);

// Heterogeneous SIMD vectors are not supported:
// (should be caught by typeck)
for fi in fields {
if fi.ty(tcx, args) != f0_ty {
let guar = tcx.dcx().delayed_bug(
"#[repr(simd)] was applied to an ADT with heterogeneous field type",
);
return Err(error(cx, LayoutError::ReferencesError(guar)));
}
}

// 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 homogeneous 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:
// Can't be caught by typeck with a generic simd type.
if def.non_enum_variant().fields.len() != 1 {
tcx.dcx().emit_fatal(MultipleArrayFieldsSimdType { ty });
}

// Extract the number of elements from the layout of the array field:
let FieldsShape::Array { count, .. } = cx.layout_of(f0_ty)?.layout.fields() else {
return Err(error(cx, LayoutError::Unknown(ty)));
};

(*e_ty, *count, true)
} else {
// First ADT field is not an array:
(f0_ty, def.non_enum_variant().fields.len() as _, false)
let Some(ty::Array(e_ty, e_len)) = def
.is_struct()
.then(|| &def.variant(FIRST_VARIANT).fields)
.filter(|fields| fields.len() == 1)
.map(|fields| *fields[FieldIdx::ZERO].ty(tcx, args).kind())
else {
// Invalid SIMD types should have been caught by typeck by now.
let guar = tcx.dcx().delayed_bug("#[repr(simd)] was applied to an invalid ADT");
return Err(error(cx, LayoutError::ReferencesError(guar)));
};

let e_len = extract_const_value(cx, ty, e_len)?
.try_to_target_usize(tcx)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;

// SIMD vectors of zero length are not supported.
// Additionally, lengths are capped at 2^16 as a fixed maximum backends must
// support.
Expand Down Expand Up @@ -559,16 +512,12 @@ fn layout_of_uncached<'tcx>(
};
let size = size.align_to(align.abi);

// Compute the placement of the vector fields:
let fields = if is_array {
FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() }
} else {
FieldsShape::Array { stride: e_ly.size, count: e_len }
};

tcx.mk_layout(LayoutData {
variants: Variants::Single { index: FIRST_VARIANT },
fields,
fields: FieldsShape::Arbitrary {
offsets: [Size::ZERO].into(),
memory_index: [0].into(),
},
backend_repr: abi,
largest_niche: e_ly.largest_niche,
uninhabited: false,
Expand Down
47 changes: 11 additions & 36 deletions src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,40 +133,22 @@ fn layout_of_simd_ty(
env: Arc<TraitEnvironment>,
dl: &TargetDataLayout,
) -> Result<Arc<Layout>, LayoutError> {
let fields = db.field_types(id.into());

// Supported SIMD vectors are homogeneous ADTs with at least one field:
// Supported SIMD vectors are homogeneous ADTs with exactly one array field:
//
// * #[repr(simd)] struct S(T, T, T, T);
// * #[repr(simd)] struct S { it: T, y: T, z: T, w: T }
// * #[repr(simd)] struct S([T; 4])
//
// where T is a primitive scalar (integer/float/pointer).

let f0_ty = match fields.iter().next() {
Some(it) => it.1.clone().substitute(Interner, subst),
None => return Err(LayoutError::InvalidSimdType),
let fields = db.field_types(id.into());
let mut fields = fields.iter();
let Some(TyKind::Array(e_ty, e_len)) = fields
.next()
.filter(|_| fields.next().is_none())
.map(|f| f.1.clone().substitute(Interner, subst).kind(Interner).clone())
else {
return Err(LayoutError::InvalidSimdType);
};

// 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 homogeneous field type and the number of fields.
let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
// Extract the number of elements from the layout of the array field:
let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields
else {
return Err(LayoutError::Unknown);
};

(e_ty.clone(), count, true)
} else {
// First ADT field is not an array:
(f0_ty, fields.iter().count() as u64, false)
};
let e_len = try_const_usize(db, &e_len).ok_or(LayoutError::HasErrorConst)? as u64;

// Compute the ABI of the element type:
let e_ly = db.layout_of_ty(e_ty, env)?;
Expand All @@ -182,16 +164,9 @@ fn layout_of_simd_ty(
let align = dl.llvmlike_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: [Size::ZERO].into(), memory_index: [0].into() }
} else {
FieldsShape::Array { stride: e_ly.size, count: e_len }
};

Ok(Arc::new(Layout {
variants: Variants::Single { index: struct_variant_idx() },
fields,
fields: FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() },
backend_repr: BackendRepr::SimdVector { element: e_abi, count: e_len },
largest_niche: e_ly.largest_niche,
uninhabited: false,
Expand Down
Loading