Skip to content
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
23 changes: 11 additions & 12 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt::{self, Write};
use std::num::NonZero;
use std::ops::Deref;
use std::range::{RangeFrom, RangeInclusive, RangeToInclusive};
use std::{cmp, iter};
Expand All @@ -9,8 +10,8 @@ use rustc_index::bit_set::BitMatrix;
use tracing::{debug, trace};

use crate::{
AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer,
LayoutData, Niche, NonZeroUsize, NumScalableVectors, Primitive, ReprOptions, Scalar, Size,
AbiAlign, Align, BackendLaneCount, BackendRepr, FieldsShape, HasDataLayout, IndexSlice,
IndexVec, Integer, LayoutData, Niche, NumScalableVectors, Primitive, ReprOptions, Scalar, Size,
StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, WrappingRange,
};

Expand Down Expand Up @@ -127,7 +128,7 @@ pub enum LayoutCalculatorError<F> {
ZeroLengthSimdType,

/// The length of an SIMD type exceeds the maximum number of lanes
OversizedSimdType { max_lanes: u64 },
OversizedSimdType { max_lanes: usize },
Comment thread
programmerjake marked this conversation as resolved.

/// An element type of an SIMD type isn't a primitive
NonPrimitiveSimdType(F),
Expand Down Expand Up @@ -495,7 +496,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
},
};

let Some(union_field_count) = NonZeroUsize::new(only_variant.len()) else {
let Some(union_field_count) = NonZero::new(only_variant.len()) else {
return Err(LayoutCalculatorError::EmptyUnion);
};

Expand Down Expand Up @@ -1476,19 +1477,17 @@ where
F: AsRef<LayoutData<FieldIdx, VariantIdx>> + fmt::Debug,
{
let elt = element.as_ref();
if count == 0 {
return Err(LayoutCalculatorError::ZeroLengthSimdType);
} else if count > crate::MAX_SIMD_LANES {
return Err(LayoutCalculatorError::OversizedSimdType { max_lanes: crate::MAX_SIMD_LANES });
}
let count = BackendLaneCount::new(count)?;

let BackendRepr::Scalar(element) = elt.backend_repr else {
return Err(LayoutCalculatorError::NonPrimitiveSimdType(element));
};

// Compute the size and alignment of the vector
let size =
elt.size.checked_mul(count, dl).ok_or_else(|| LayoutCalculatorError::SizeOverflow)?;
let size = elt
.size
.checked_mul(count.as_u64(), dl)
.ok_or_else(|| LayoutCalculatorError::SizeOverflow)?;
let (repr, size, align) = match kind {
SimdVectorKind::Scalable(number_of_vectors) => (
BackendRepr::SimdScalableVector { element, count, number_of_vectors },
Expand Down Expand Up @@ -1521,6 +1520,6 @@ where
align: AbiAlign::new(align),
max_repr_align: None,
unadjusted_abi_align: elt.align.abi,
randomization_seed: elt.randomization_seed.wrapping_add(Hash64::new(count)),
randomization_seed: elt.randomization_seed.wrapping_add(Hash64::new(count.as_u64())),
})
}
47 changes: 41 additions & 6 deletions compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use std::cmp::min;
use std::fmt;
#[cfg(feature = "nightly")]
use std::iter::Step;
use std::num::{NonZeroUsize, ParseIntError};
use std::num::{NonZero, ParseIntError};
use std::ops::{Add, AddAssign, Deref, Mul, Sub};
use std::range::RangeInclusive;
use std::str::FromStr;
Expand Down Expand Up @@ -244,7 +244,42 @@ impl ReprOptions {
/// This value is selected based on backend support:
/// * LLVM does not appear to have a vector width limit.
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
pub const MAX_SIMD_LANES: u16 = 1 << 0xF;

/// The number of lanes in a [`BackendRepr::SimdVector`], `1..=`[`MAX_SIMD_LANES`].
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash))]
pub struct BackendLaneCount(NonZero<u16>);

impl BackendLaneCount {
pub fn new<N>(count: u64) -> Result<Self, LayoutCalculatorError<N>> {
let Ok(count @ ..=MAX_SIMD_LANES) = u16::try_from(count) else {
return Err(LayoutCalculatorError::OversizedSimdType {
max_lanes: crate::MAX_SIMD_LANES.into(),
});
};
if let Some(count) = NonZero::new(count) {
Ok(BackendLaneCount(count))
} else {
Err(LayoutCalculatorError::ZeroLengthSimdType)
}
}

#[inline]
pub fn is_power_of_two(self) -> bool {
self.0.is_power_of_two()
}

#[inline]
pub fn as_u64(self) -> u64 {
self.0.get().into()
}

#[inline]
pub fn as_u32(self) -> u32 {
self.0.get().into()
}
}

/// How pointers are represented in a given address space
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -1611,7 +1646,7 @@ pub enum FieldsShape<FieldIdx: Idx> {
Primitive,

/// All fields start at no offset. The `usize` is the field count.
Union(NonZeroUsize),
Union(NonZero<usize>),

/// Array/vector-like placement, with all fields of identical types.
Array { stride: Size, count: u64 },
Expand Down Expand Up @@ -1770,12 +1805,12 @@ pub enum BackendRepr {
},
SimdScalableVector {
element: Scalar,
count: u64,
count: BackendLaneCount,
number_of_vectors: NumScalableVectors,
},
SimdVector {
element: Scalar,
count: u64,
count: BackendLaneCount,
},
// FIXME: I sometimes use memory, sometimes use an IR aggregate!
Memory {
Expand Down Expand Up @@ -2260,7 +2295,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
}

/// Returns the elements count of a scalable vector.
pub fn scalable_vector_element_count(&self) -> Option<u64> {
pub fn scalable_vector_element_count(&self) -> Option<BackendLaneCount> {
match self.backend_repr {
BackendRepr::SimdScalableVector { count, .. } => Some(count),
_ => None,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx
_ => unreachable!(),
};

scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()).unwrap()
scalar_to_clif_type(tcx, element).by(count.as_u32()).unwrap()
}

fn simd_for_each_lane<'tcx>(
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_codegen_cranelift/src/value_and_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,7 @@ impl<'tcx> CValue<'tcx> {
let clif_ty = match layout.backend_repr {
BackendRepr::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar),
BackendRepr::SimdVector { element, count } => {
scalar_to_clif_type(fx.tcx, element)
.by(u32::try_from(count).unwrap())
.unwrap()
scalar_to_clif_type(fx.tcx, element).by(count.as_u32()).unwrap()
}
_ => unreachable!("{:?}", layout.ty),
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_gcc/src/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
else {
element
};
return cx.context.new_vector_type(element, count);
return cx.context.new_vector_type(element, count.as_u64());
}
BackendRepr::ScalarPair { .. } => {
return cx.type_struct(
Expand Down
50 changes: 35 additions & 15 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,8 +1119,9 @@ fn llvm_fixup_input<'ll, 'tcx>(
BackendRepr::SimdVector { element, count },
) if layout.size.bytes() == 8 => {
let elem_ty = llvm_asm_scalar_type(bx.cx, element);
let vec_ty = bx.cx.type_vector(elem_ty, count);
let indices: Vec<_> = (0..count * 2).map(|x| bx.const_i32(x as i32)).collect();
let count = count.as_u32();
let vec_ty = bx.cx.type_vector(elem_ty, u64::from(count));
let indices: Vec<_> = (0..count * 2).map(|x| bx.const_u32(x)).collect();
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
}
(X86(X86InlineAsmRegClass::reg_abcd), BackendRepr::Scalar(s))
Expand Down Expand Up @@ -1165,8 +1166,11 @@ fn llvm_fixup_input<'ll, 'tcx>(
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
BackendRepr::SimdVector { element, count: count @ (8 | 16) },
) if element.primitive() == Primitive::Float(Float::F16) => {
BackendRepr::SimdVector { element, count },
) if let count = count.as_u64()
&& let 8 | 16 = count
&& element.primitive() == Primitive::Float(Float::F16) =>
{
bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
}
(
Expand Down Expand Up @@ -1202,8 +1206,11 @@ fn llvm_fixup_input<'ll, 'tcx>(
| ArmInlineAsmRegClass::qreg_low4
| ArmInlineAsmRegClass::qreg_low8,
),
BackendRepr::SimdVector { element, count: count @ (4 | 8) },
) if element.primitive() == Primitive::Float(Float::F16) => {
BackendRepr::SimdVector { element, count },
) if let count = count.as_u64()
&& let 4 | 8 = count
&& element.primitive() == Primitive::Float(Float::F16) =>
{
bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
}
(LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
Expand Down Expand Up @@ -1291,6 +1298,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
BackendRepr::SimdVector { element, count },
) if layout.size.bytes() == 8 => {
let elem_ty = llvm_asm_scalar_type(bx.cx, element);
let count = count.as_u64();
let vec_ty = bx.cx.type_vector(elem_ty, count * 2);
let indices: Vec<_> = (0..count).map(|x| bx.const_i32(x as i32)).collect();
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
Expand Down Expand Up @@ -1333,8 +1341,11 @@ fn llvm_fixup_output<'ll, 'tcx>(
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
BackendRepr::SimdVector { element, count: count @ (8 | 16) },
) if element.primitive() == Primitive::Float(Float::F16) => {
BackendRepr::SimdVector { element, count },
) if let count = count.as_u64()
&& let 8 | 16 = count
&& element.primitive() == Primitive::Float(Float::F16) =>
{
bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
}
(
Expand Down Expand Up @@ -1370,8 +1381,11 @@ fn llvm_fixup_output<'ll, 'tcx>(
| ArmInlineAsmRegClass::qreg_low4
| ArmInlineAsmRegClass::qreg_low8,
),
BackendRepr::SimdVector { element, count: count @ (4 | 8) },
) if element.primitive() == Primitive::Float(Float::F16) => {
BackendRepr::SimdVector { element, count },
) if let count = count.as_u64()
&& let 4 | 8 = count
&& element.primitive() == Primitive::Float(Float::F16) =>
{
bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
}
(LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
Expand Down Expand Up @@ -1445,7 +1459,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
BackendRepr::SimdVector { element, count },
) if layout.size.bytes() == 8 => {
let elem_ty = llvm_asm_scalar_type(cx, element);
cx.type_vector(elem_ty, count * 2)
cx.type_vector(elem_ty, count.as_u64() * 2)
}
(X86(X86InlineAsmRegClass::reg_abcd), BackendRepr::Scalar(s))
if s.primitive() == Primitive::Float(Float::F64) =>
Expand Down Expand Up @@ -1482,8 +1496,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
BackendRepr::SimdVector { element, count: count @ (8 | 16) },
) if element.primitive() == Primitive::Float(Float::F16) => {
BackendRepr::SimdVector { element, count },
) if let count = count.as_u64()
&& let 8 | 16 = count
&& element.primitive() == Primitive::Float(Float::F16) =>
{
cx.type_vector(cx.type_i16(), count)
}
(
Expand Down Expand Up @@ -1519,8 +1536,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
| ArmInlineAsmRegClass::qreg_low4
| ArmInlineAsmRegClass::qreg_low8,
),
BackendRepr::SimdVector { element, count: count @ (4 | 8) },
) if element.primitive() == Primitive::Float(Float::F16) => {
BackendRepr::SimdVector { element, count },
) if let count = count.as_u64()
&& let 4 | 8 = count
&& element.primitive() == Primitive::Float(Float::F16) =>
{
cx.type_vector(cx.type_i16(), count)
}
(LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
llvm::LLVMIntTypeInContext(self.llcx(), num_bits as c_uint)
}

pub(crate) fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
unsafe { llvm::LLVMVectorType(ty, len as c_uint) }
pub(crate) fn type_vector(&self, ty: &'ll Type, count: u64) -> &'ll Type {
unsafe { llvm::LLVMVectorType(ty, count as c_uint) }
}

pub(crate) fn type_scalable_vector(&self, ty: &'ll Type, count: u64) -> &'ll Type {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn uncached_llvm_type<'a, 'tcx>(
BackendRepr::Scalar(_) => bug!("handled elsewhere"),
BackendRepr::SimdVector { element, count } => {
let element = layout.scalar_llvm_type_at(cx, element);
return cx.type_vector(element, count);
return cx.type_vector(element, count.as_u64());
}
BackendRepr::SimdScalableVector { ref element, count, number_of_vectors } => {
let element = if element.is_bool() {
Expand All @@ -31,7 +31,7 @@ fn uncached_llvm_type<'a, 'tcx>(
layout.scalar_llvm_type_at(cx, *element)
};

let vector_type = cx.type_scalable_vector(element, count);
let vector_type = cx.type_scalable_vector(element, count.as_u64());
return match number_of_vectors.0 {
1 => vector_type,
2 => cx.type_struct(&[vector_type, vector_type], false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ fn check_validity_requirement_lax<'tcx>(
BackendRepr::ScalarPair { a: s1, b: s2, b_offset: _ } => {
scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2)
}
BackendRepr::SimdVector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
BackendRepr::SimdVector { element: s, count: _ } => scalar_allows_raw_init(s),
BackendRepr::Memory { .. } => true, // Fields are checked below.
BackendRepr::SimdScalableVector { element, .. } => scalar_allows_raw_init(element),
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(nonzero_internals)]
#![feature(pattern_type_macro)]
#![feature(pattern_types)]
#![feature(ptr_alignment_type)]
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_data_structures/src/stable_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,14 +238,7 @@ impl<T> StableHash for PhantomData<T> {
fn stable_hash<Hcx>(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {}
}

impl StableHash for NonZero<u32> {
#[inline]
fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
self.get().stable_hash(hcx, hasher)
}
}

impl StableHash for NonZero<usize> {
impl<T: StableHash + std::num::ZeroablePrimitive> StableHash for NonZero<T> {
#[inline]
fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
self.get().stable_hash(hcx, hasher)
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::cell::LazyCell;
use std::ops::ControlFlow;

use rustc_abi::{ExternAbi, FieldIdx, ScalableElt};
use rustc_abi::{ExternAbi, FieldIdx, MAX_SIMD_LANES, ScalableElt};
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::codes::*;
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan};
Expand All @@ -17,7 +17,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::util::Discr;
use rustc_middle::ty::{
AdtDef, BottomUpFolder, FnSig, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable,
Expand Down Expand Up @@ -1493,7 +1493,7 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
if len == 0 {
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
return;
} else if len > MAX_SIMD_LANES {
} else if len > MAX_SIMD_LANES.into() {
struct_span_code_err!(
tcx.dcx(),
sp,
Expand Down
Loading
Loading