Skip to content

Commit 50fc361

Browse files
compiler: split vector_align into cabi and llvmlike
Introduce a pair of functions that actually describe what they do. Use cabi_vector_align in required_align, so it matches requirements. Skip over checks that assumed required_align, formerly inherent_align, described an alignment that must be followed at all times for vectors.
1 parent a4deaf5 commit 50fc361

File tree

5 files changed

+38
-29
lines changed

5 files changed

+38
-29
lines changed

compiler/rustc_abi/src/callconv/reg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl Reg {
5757
128 => dl.f128_align.abi,
5858
_ => panic!("unsupported float: {self:?}"),
5959
},
60-
RegKind::Vector => dl.vector_align(self.size).abi,
60+
RegKind::Vector => dl.llvmlike_vector_align(self.size).abi,
6161
}
6262
}
6363
}

compiler/rustc_abi/src/layout.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
308308
let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
309309
let mut max_repr_align = repr.align;
310310

311-
// If all the non-ZST fields have the same ABI and union ABI optimizations aren't
312-
// disabled, we can use that common ABI for the union as a whole.
311+
// If all the non-ZST fields have the same repr and union repr optimizations aren't
312+
// disabled, we can use that common repr for the union as a whole.
313313
struct AbiMismatch;
314-
let mut common_non_zst_abi_and_align = if repr.inhibits_union_abi_opt() {
314+
let mut common_non_zst_repr_and_align = if repr.inhibits_union_abi_opt() {
315315
// Can't optimize
316316
Err(AbiMismatch)
317317
} else {
@@ -335,14 +335,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
335335
continue;
336336
}
337337

338-
if let Ok(common) = common_non_zst_abi_and_align {
338+
if let Ok(common) = common_non_zst_repr_and_align {
339339
// Discard valid range information and allow undef
340340
let field_abi = field.backend_repr.to_union();
341341

342342
if let Some((common_abi, common_align)) = common {
343343
if common_abi != field_abi {
344344
// Different fields have different ABI: disable opt
345-
common_non_zst_abi_and_align = Err(AbiMismatch);
345+
common_non_zst_repr_and_align = Err(AbiMismatch);
346346
} else {
347347
// Fields with the same non-Aggregate ABI should also
348348
// have the same alignment
@@ -355,7 +355,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
355355
}
356356
} else {
357357
// First non-ZST field: record its ABI and alignment
358-
common_non_zst_abi_and_align = Ok(Some((field_abi, field.align.abi)));
358+
common_non_zst_repr_and_align = Ok(Some((field_abi, field.align.abi)));
359359
}
360360
}
361361
}
@@ -374,16 +374,17 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
374374

375375
// If all non-ZST fields have the same ABI, we may forward that ABI
376376
// for the union as a whole, unless otherwise inhibited.
377-
let abi = match common_non_zst_abi_and_align {
377+
let backend_repr = match common_non_zst_repr_and_align {
378378
Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true },
379-
Ok(Some((abi, _))) => {
380-
if abi.required_align(dl) != Some(align.abi) {
381-
// Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
382-
BackendRepr::Memory { sized: true }
383-
} else {
384-
abi
385-
}
379+
Ok(Some((backend_repr, _)))
380+
if backend_repr
381+
.required_align(dl)
382+
.is_some_and(|abi_align| abi_align != align.abi) =>
383+
{
384+
// Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
385+
BackendRepr::Memory { sized: true }
386386
}
387+
Ok(Some((backend_repr, _))) => backend_repr,
387388
};
388389

389390
let Some(union_field_count) = NonZeroUsize::new(only_variant.len()) else {
@@ -398,7 +399,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
398399
Ok(LayoutData {
399400
variants: Variants::Single { index: only_variant_idx },
400401
fields: FieldsShape::Union(union_field_count),
401-
backend_repr: abi,
402+
backend_repr,
402403
largest_niche: None,
403404
align,
404405
size: size.align_to(align.abi),

compiler/rustc_abi/src/lib.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -408,16 +408,21 @@ impl TargetDataLayout {
408408
}
409409
}
410410

411+
/// psABI-mandated alignment for a vector type, if any
411412
#[inline]
412-
pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
413-
for &(size, align) in &self.vector_align {
414-
if size == vec_size {
415-
return align;
416-
}
417-
}
418-
// Default to natural alignment, which is what LLVM does.
419-
// That is, use the size, rounded up to a power of 2.
420-
AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap())
413+
pub fn cabi_vector_align(&self, vec_size: Size) -> Option<AbiAndPrefAlign> {
414+
self.vector_align
415+
.iter()
416+
.find(|(size, _align)| *size == vec_size)
417+
.map(|(_size, align)| *align)
418+
}
419+
420+
/// an alignment resembling the one LLVM would pick for a vector
421+
#[inline]
422+
pub fn llvmlike_vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
423+
self.cabi_vector_align(vec_size).unwrap_or(AbiAndPrefAlign::new(
424+
Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(),
425+
))
421426
}
422427
}
423428

@@ -1470,7 +1475,7 @@ impl BackendRepr {
14701475
BackendRepr::Scalar(s) => Some(s.align(cx).abi),
14711476
BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi),
14721477
BackendRepr::Vector { element, count } => {
1473-
Some(cx.data_layout().vector_align(element.size(cx) * count).abi)
1478+
cx.data_layout().cabi_vector_align(element.size(cx) * count).map(|align| align.abi)
14741479
}
14751480
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => None,
14761481
}

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,11 +564,14 @@ fn layout_of_uncached<'tcx>(
564564
BackendRepr::Memory { sized: true },
565565
AbiAndPrefAlign {
566566
abi: Align::max_aligned_factor(size),
567-
pref: dl.vector_align(size).pref,
567+
pref: dl.llvmlike_vector_align(size).pref,
568568
},
569569
)
570570
} else {
571-
(BackendRepr::Vector { element: e_abi, count: e_len }, dl.vector_align(size))
571+
(
572+
BackendRepr::Vector { element: e_abi, count: e_len },
573+
dl.llvmlike_vector_align(size),
574+
)
572575
};
573576
let size = size.align_to(align.abi);
574577

compiler/rustc_ty_utils/src/layout/invariant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
7171
let Some((align, size)) = align.zip(size) else {
7272
assert_matches!(
7373
layout.layout.backend_repr(),
74-
BackendRepr::Uninhabited | BackendRepr::Memory { .. },
74+
BackendRepr::Uninhabited | BackendRepr::Memory { .. } | BackendRepr::Vector { .. },
7575
"ABI unexpectedly missing alignment and/or size in {layout:#?}"
7676
);
7777
return;

0 commit comments

Comments
 (0)