1
Fork 0

Auto merge of #138634 - saethlin:repeated-uninit, r=scottmcm,oli-obk

Lower to a memset(undef) when Rvalue::Repeat repeats uninit

Fixes https://github.com/rust-lang/rust/issues/138625.

It is technically correct to just do nothing. But if we actually do nothing, we may miss that this is de-initializing something, so instead we just lower to a single memset that writes undef. This is still superior to the memcpy loop, in both quality of code we hand to the backend and LLVM's final output.
This commit is contained in:
bors 2025-03-25 02:09:15 +00:00
commit e61403aa4c
3 changed files with 66 additions and 4 deletions

View file

@ -9,7 +9,9 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
use rustc_type_ir::TypeVisitableExt;
use super::interpret::ReportedErrorInfo;
use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range};
use crate::mir::interpret::{
AllocId, AllocRange, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar, alloc_range,
};
use crate::mir::{Promoted, pretty_print_const_value};
use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt};
@ -192,9 +194,31 @@ impl<'tcx> ConstValue<'tcx> {
.unwrap_memory()
.inner()
.provenance()
.range_empty(super::AllocRange::from(offset..offset + size), &tcx),
.range_empty(AllocRange::from(offset..offset + size), &tcx),
}
}
/// Check if a constant only contains uninitialized bytes.
pub fn all_bytes_uninit(&self, tcx: TyCtxt<'tcx>) -> bool {
let ConstValue::Indirect { alloc_id, .. } = self else {
return false;
};
let alloc = tcx.global_alloc(*alloc_id);
let GlobalAlloc::Memory(alloc) = alloc else {
return false;
};
let init_mask = alloc.0.init_mask();
let init_range = init_mask.is_range_initialized(AllocRange {
start: Size::ZERO,
size: Size::from_bytes(alloc.0.len()),
});
if let Err(range) = init_range {
if range.size == alloc.0.size() {
return true;
}
}
false
}
}
///////////////////////////////////////////////////////////////////////////