Rollup merge of #137256 - workingjubilee:untangle-vector-abi-assumptions, r=bjorn3,RalfJung
compiler: untangle SIMD alignment assumptions There were a number of puzzling assumptions being made about SIMD types and their layout that I have corrected in this diff. These are mostly no-op edits in actual fact, but they do subtly alter a pair of checks in our invariant-checking and union layout computation that rested on those peculiar assumptions. Those unfortunately stand in the way of any further actual fixes. I submit this for review, even though it's not clearly motivated without its followups, because it should still be possible to independently conclude whether this is correct.
This commit is contained in:
commit
86008eaeac
6 changed files with 108 additions and 86 deletions
|
@ -547,12 +547,15 @@ fn layout_of_uncached<'tcx>(
|
|||
(
|
||||
BackendRepr::Memory { sized: true },
|
||||
AbiAndPrefAlign {
|
||||
abi: Align::max_for_offset(size),
|
||||
pref: dl.vector_align(size).pref,
|
||||
abi: Align::max_aligned_factor(size),
|
||||
pref: dl.llvmlike_vector_align(size).pref,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(BackendRepr::Vector { element: e_abi, count: e_len }, dl.vector_align(size))
|
||||
(
|
||||
BackendRepr::Vector { element: e_abi, count: e_len },
|
||||
dl.llvmlike_vector_align(size),
|
||||
)
|
||||
};
|
||||
let size = size.align_to(align.abi);
|
||||
|
||||
|
|
|
@ -69,31 +69,30 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
|
|||
}
|
||||
|
||||
fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
|
||||
// Verify the ABI mandated alignment and size.
|
||||
let align = layout.backend_repr.inherent_align(cx).map(|align| align.abi);
|
||||
let size = layout.backend_repr.inherent_size(cx);
|
||||
let Some((align, size)) = align.zip(size) else {
|
||||
assert_matches!(
|
||||
layout.layout.backend_repr(),
|
||||
BackendRepr::Memory { .. },
|
||||
"ABI unexpectedly missing alignment and/or size in {layout:#?}"
|
||||
// Verify the ABI-mandated alignment and size for scalars.
|
||||
let align = layout.backend_repr.scalar_align(cx);
|
||||
let size = layout.backend_repr.scalar_size(cx);
|
||||
if let Some(align) = align {
|
||||
assert_eq!(
|
||||
layout.layout.align().abi,
|
||||
align,
|
||||
"alignment mismatch between ABI and layout in {layout:#?}"
|
||||
);
|
||||
return;
|
||||
};
|
||||
assert_eq!(
|
||||
layout.layout.align().abi,
|
||||
align,
|
||||
"alignment mismatch between ABI and layout in {layout:#?}"
|
||||
);
|
||||
assert_eq!(
|
||||
layout.layout.size(),
|
||||
size,
|
||||
"size mismatch between ABI and layout in {layout:#?}"
|
||||
);
|
||||
}
|
||||
if let Some(size) = size {
|
||||
assert_eq!(
|
||||
layout.layout.size(),
|
||||
size,
|
||||
"size mismatch between ABI and layout in {layout:#?}"
|
||||
);
|
||||
}
|
||||
|
||||
// Verify per-ABI invariants
|
||||
match layout.layout.backend_repr() {
|
||||
BackendRepr::Scalar(_) => {
|
||||
// These must always be present for `Scalar` types.
|
||||
let align = align.unwrap();
|
||||
let size = size.unwrap();
|
||||
// Check that this matches the underlying field.
|
||||
let inner = skip_newtypes(cx, layout);
|
||||
assert!(
|
||||
|
@ -235,9 +234,15 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
|
|||
"`ScalarPair` second field with bad ABI in {inner:#?}",
|
||||
);
|
||||
}
|
||||
BackendRepr::Vector { element, .. } => {
|
||||
assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`.
|
||||
// FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
|
||||
BackendRepr::Vector { element, count } => {
|
||||
let align = layout.align.abi;
|
||||
let size = layout.size;
|
||||
let element_align = element.align(cx).abi;
|
||||
let element_size = element.size(cx);
|
||||
// Currently, vectors must always be aligned to at least their elements:
|
||||
assert!(align >= element_align);
|
||||
// And the size has to be element * count plus alignment padding, of course
|
||||
assert!(size == (element_size * count).align_to(align));
|
||||
}
|
||||
BackendRepr::Memory { .. } => {} // Nothing to check.
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue