Skip to content

Commit e5484ce

Browse files
committed
Auto merge of rust-lang#88242 - bonega:allocation_range, r=oli-obk
Use custom wrap-around type instead of RangeInclusive Two reasons: 1. More memory is allocated than necessary for `valid_range` in `Scalar`. The range is not used as an iterator and `exhausted` is never used. 2. `contains`, `count` etc. methods in `RangeInclusive` are doing very unhelpful(and dangerous!) things when used as a wrap-around range. - In general this PR wants to limit potentially confusing methods, that have a low probability of working. Doing a local perf run, every metric shows improvement except for instructions. Max-rss seem to have a very consistent improvement. Sorry - newbie here, probably doing something wrong.
2 parents faa0a10 + f17e384 commit e5484ce

File tree

8 files changed

+116
-82
lines changed

8 files changed

+116
-82
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -462,15 +462,14 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
462462
load: &'ll Value,
463463
scalar: &abi::Scalar,
464464
) {
465-
let vr = scalar.valid_range.clone();
466465
match scalar.value {
467466
abi::Int(..) => {
468467
let range = scalar.valid_range_exclusive(bx);
469468
if range.start != range.end {
470469
bx.range_metadata(load, range);
471470
}
472471
}
473-
abi::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
472+
abi::Pointer if !scalar.valid_range.contains_zero() => {
474473
bx.nonnull_metadata(load);
475474
}
476475
_ => {}

compiler/rustc_codegen_llvm/src/consts.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ use rustc_middle::mir::interpret::{
1616
use rustc_middle::mir::mono::MonoItem;
1717
use rustc_middle::ty::{self, Instance, Ty};
1818
use rustc_middle::{bug, span_bug};
19-
use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
19+
use rustc_target::abi::{
20+
AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size, WrappingRange,
21+
};
2022
use tracing::debug;
2123

2224
pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
@@ -59,7 +61,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
5961
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
6062
&cx.tcx,
6163
),
62-
&Scalar { value: Primitive::Pointer, valid_range: 0..=!0 },
64+
&Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
6365
cx.type_i8p_ext(address_space),
6466
));
6567
next_offset = offset + pointer_size;

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -406,11 +406,11 @@ fn push_debuginfo_type_name<'tcx>(
406406
let dataful_discriminant_range =
407407
&dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range;
408408

409-
let min = dataful_discriminant_range.start();
410-
let min = tag.value.size(&tcx).truncate(*min);
409+
let min = dataful_discriminant_range.start;
410+
let min = tag.value.size(&tcx).truncate(min);
411411

412-
let max = dataful_discriminant_range.end();
413-
let max = tag.value.size(&tcx).truncate(*max);
412+
let max = dataful_discriminant_range.end;
413+
let max = tag.value.size(&tcx).truncate(max);
414414

415415
let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
416416

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
310310

311311
let er = scalar.valid_range_exclusive(bx.cx());
312312
if er.end != er.start
313-
&& scalar.valid_range.end() >= scalar.valid_range.start()
313+
&& scalar.valid_range.end >= scalar.valid_range.start
314314
{
315315
// We want `table[e as usize ± k]` to not
316316
// have bound checks, and this is the most
317317
// convenient place to put the `assume`s.
318-
if *scalar.valid_range.start() > 0 {
318+
if scalar.valid_range.start > 0 {
319319
let enum_value_lower_bound = bx
320320
.cx()
321-
.const_uint_big(ll_t_in, *scalar.valid_range.start());
321+
.const_uint_big(ll_t_in, scalar.valid_range.start);
322322
let cmp_start = bx.icmp(
323323
IntPredicate::IntUGE,
324324
llval,
@@ -328,7 +328,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
328328
}
329329

330330
let enum_value_upper_bound =
331-
bx.cx().const_uint_big(ll_t_in, *scalar.valid_range.end());
331+
bx.cx().const_uint_big(ll_t_in, scalar.valid_range.end);
332332
let cmp_end = bx.icmp(
333333
IntPredicate::IntULE,
334334
llval,

compiler/rustc_lint/src/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ crate fn repr_nullable_ptr<'tcx>(
795795
// Return the nullable type this Option-like enum can be safely represented with.
796796
let field_ty_abi = &cx.layout_of(field_ty).unwrap().abi;
797797
if let Abi::Scalar(field_ty_scalar) = field_ty_abi {
798-
match (field_ty_scalar.valid_range.start(), field_ty_scalar.valid_range.end()) {
798+
match (field_ty_scalar.valid_range.start, field_ty_scalar.valid_range.end) {
799799
(0, _) => unreachable!("Non-null optimisation extended to a non-zero value."),
800800
(1, _) => {
801801
return Some(get_nullable_type(cx, field_ty).unwrap());

compiler/rustc_middle/src/ty/layout.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
499499
let scalar_unit = |value: Primitive| {
500500
let bits = value.size(dl).bits();
501501
assert!(bits <= 128);
502-
Scalar { value, valid_range: 0..=(!0 >> (128 - bits)) }
502+
Scalar { value, valid_range: WrappingRange { start: 0, end: (!0 >> (128 - bits)) } }
503503
};
504504
let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value)));
505505

@@ -512,11 +512,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
512512
// Basic scalars.
513513
ty::Bool => tcx.intern_layout(Layout::scalar(
514514
self,
515-
Scalar { value: Int(I8, false), valid_range: 0..=1 },
515+
Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } },
516516
)),
517517
ty::Char => tcx.intern_layout(Layout::scalar(
518518
self,
519-
Scalar { value: Int(I32, false), valid_range: 0..=0x10FFFF },
519+
Scalar {
520+
value: Int(I32, false),
521+
valid_range: WrappingRange { start: 0, end: 0x10FFFF },
522+
},
520523
)),
521524
ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
522525
ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
@@ -526,7 +529,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
526529
}),
527530
ty::FnPtr(_) => {
528531
let mut ptr = scalar_unit(Pointer);
529-
ptr.valid_range = 1..=*ptr.valid_range.end();
532+
ptr.valid_range = ptr.valid_range.with_start(1);
530533
tcx.intern_layout(Layout::scalar(self, ptr))
531534
}
532535

@@ -544,7 +547,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
544547
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
545548
let mut data_ptr = scalar_unit(Pointer);
546549
if !ty.is_unsafe_ptr() {
547-
data_ptr.valid_range = 1..=*data_ptr.valid_range.end();
550+
data_ptr.valid_range = data_ptr.valid_range.with_start(1);
548551
}
549552

550553
let pointee = tcx.normalize_erasing_regions(param_env, pointee);
@@ -560,7 +563,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
560563
ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
561564
ty::Dynamic(..) => {
562565
let mut vtable = scalar_unit(Pointer);
563-
vtable.valid_range = 1..=*vtable.valid_range.end();
566+
vtable.valid_range = vtable.valid_range.with_start(1);
564567
vtable
565568
}
566569
_ => return Err(LayoutError::Unknown(unsized_part)),
@@ -933,14 +936,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
933936
if let Bound::Included(start) = start {
934937
// FIXME(eddyb) this might be incorrect - it doesn't
935938
// account for wrap-around (end < start) ranges.
936-
assert!(*scalar.valid_range.start() <= start);
937-
scalar.valid_range = start..=*scalar.valid_range.end();
939+
assert!(scalar.valid_range.start <= start);
940+
scalar.valid_range.start = start;
938941
}
939942
if let Bound::Included(end) = end {
940943
// FIXME(eddyb) this might be incorrect - it doesn't
941944
// account for wrap-around (end < start) ranges.
942-
assert!(*scalar.valid_range.end() >= end);
943-
scalar.valid_range = *scalar.valid_range.start()..=end;
945+
assert!(scalar.valid_range.end >= end);
946+
scalar.valid_range.end = end;
944947
}
945948

946949
// Update `largest_niche` if we have introduced a larger niche.
@@ -1256,7 +1259,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
12561259
let tag_mask = !0u128 >> (128 - ity.size().bits());
12571260
let tag = Scalar {
12581261
value: Int(ity, signed),
1259-
valid_range: (min as u128 & tag_mask)..=(max as u128 & tag_mask),
1262+
valid_range: WrappingRange {
1263+
start: (min as u128 & tag_mask),
1264+
end: (max as u128 & tag_mask),
1265+
},
12601266
};
12611267
let mut abi = Abi::Aggregate { sized: true };
12621268
if tag.value.size(dl) == size {
@@ -1535,7 +1541,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
15351541
let max_discr = (info.variant_fields.len() - 1) as u128;
15361542
let discr_int = Integer::fit_unsigned(max_discr);
15371543
let discr_int_ty = discr_int.to_ty(tcx, false);
1538-
let tag = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr };
1544+
let tag = Scalar {
1545+
value: Primitive::Int(discr_int, false),
1546+
valid_range: WrappingRange { start: 0, end: max_discr },
1547+
};
15391548
let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone()));
15401549
let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
15411550

@@ -2846,10 +2855,8 @@ where
28462855
return;
28472856
}
28482857

2849-
if scalar.valid_range.start() < scalar.valid_range.end() {
2850-
if *scalar.valid_range.start() > 0 {
2851-
attrs.set(ArgAttribute::NonNull);
2852-
}
2858+
if !scalar.valid_range.contains_zero() {
2859+
attrs.set(ArgAttribute::NonNull);
28532860
}
28542861

28552862
if let Some(pointee) = layout.pointee_info_at(cx, offset) {

compiler/rustc_mir/src/interpret/validity.rs

+8-19
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77
use std::convert::TryFrom;
88
use std::fmt::Write;
99
use std::num::NonZeroUsize;
10-
use std::ops::RangeInclusive;
1110

1211
use rustc_data_structures::fx::FxHashSet;
1312
use rustc_hir as hir;
1413
use rustc_middle::mir::interpret::InterpError;
1514
use rustc_middle::ty;
1615
use rustc_middle::ty::layout::TyAndLayout;
1716
use rustc_span::symbol::{sym, Symbol};
18-
use rustc_target::abi::{Abi, LayoutOf, Scalar as ScalarAbi, Size, VariantIdx, Variants};
17+
use rustc_target::abi::{
18+
Abi, LayoutOf, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
19+
};
1920

2021
use std::hash::Hash;
2122

@@ -181,22 +182,10 @@ fn write_path(out: &mut String, path: &[PathElem]) {
181182
}
182183
}
183184

184-
// Test if a range that wraps at overflow contains `test`
185-
fn wrapping_range_contains(r: &RangeInclusive<u128>, test: u128) -> bool {
186-
let (lo, hi) = r.clone().into_inner();
187-
if lo > hi {
188-
// Wrapped
189-
(..=hi).contains(&test) || (lo..).contains(&test)
190-
} else {
191-
// Normal
192-
r.contains(&test)
193-
}
194-
}
195-
196185
// Formats such that a sentence like "expected something {}" to mean
197186
// "expected something <in the given range>" makes sense.
198-
fn wrapping_range_format(r: &RangeInclusive<u128>, max_hi: u128) -> String {
199-
let (lo, hi) = r.clone().into_inner();
187+
fn wrapping_range_format(r: WrappingRange, max_hi: u128) -> String {
188+
let WrappingRange { start: lo, end: hi } = r;
200189
assert!(hi <= max_hi);
201190
if lo > hi {
202191
format!("less or equal to {}, or greater or equal to {}", hi, lo)
@@ -634,8 +623,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
634623
scalar_layout: &ScalarAbi,
635624
) -> InterpResult<'tcx> {
636625
let value = self.read_scalar(op)?;
637-
let valid_range = &scalar_layout.valid_range;
638-
let (lo, hi) = valid_range.clone().into_inner();
626+
let valid_range = scalar_layout.valid_range.clone();
627+
let WrappingRange { start: lo, end: hi } = valid_range;
639628
// Determine the allowed range
640629
// `max_hi` is as big as the size fits
641630
let max_hi = u128::MAX >> (128 - op.layout.size.bits());
@@ -684,7 +673,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
684673
Ok(int) => int.assert_bits(op.layout.size),
685674
};
686675
// Now compare. This is slightly subtle because this is a special "wrap-around" range.
687-
if wrapping_range_contains(&valid_range, bits) {
676+
if valid_range.contains(bits) {
688677
Ok(())
689678
} else {
690679
throw_validation_failure!(self.path,

0 commit comments

Comments
 (0)