Skip to content

Commit 1dc7eae

Browse files
committed
add should_skip_bounds_check to MIR Builder
1 parent 98e7077 commit 1dc7eae

19 files changed

Lines changed: 550 additions & 646 deletions

compiler/rustc_mir_build/src/builder/expr/as_place.rs

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
use std::{assert_matches, iter};
44

55
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
6+
use rustc_ast::{IntTy, LitKind, UintTy};
67
use rustc_hir::def_id::LocalDefId;
78
use rustc_middle::hir::place::{Projection as HirProjection, ProjectionKind as HirProjectionKind};
89
use rustc_middle::mir::AssertKind::BoundsCheck;
910
use rustc_middle::mir::*;
1011
use rustc_middle::thir::*;
11-
use rustc_middle::ty::{self, AdtDef, CanonicalUserTypeAnnotation, Ty, Variance};
12+
use rustc_middle::ty::{self, AdtDef, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance};
1213
use rustc_middle::{bug, span_bug};
1314
use rustc_span::Span;
1415
use tracing::{debug, instrument, trace};
@@ -639,18 +640,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
639640
let index_lifetime = self.region_scope_tree.temporary_scope(self.thir[index].temp_scope_id);
640641
let idx = unpack!(block = self.as_temp(block, index_lifetime, index, Mutability::Not));
641642

642-
block = self.bounds_check(block, &base_place, idx, expr_span, source_info);
643+
let slice = base_place.to_place(self);
644+
645+
if self.should_skip_bounds_check(slice, index) {
646+
self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, slice);
647+
} else {
648+
block = self.bounds_check(block, slice, idx, expr_span, source_info);
649+
}
643650

644651
if is_outermost_index {
645652
self.read_fake_borrows(block, fake_borrow_temps, source_info)
646653
} else {
647-
self.add_fake_borrows_of_base(
648-
base_place.to_place(self),
649-
block,
650-
fake_borrow_temps,
651-
expr_span,
652-
source_info,
653-
);
654+
self.add_fake_borrows_of_base(slice, block, fake_borrow_temps, expr_span, source_info);
654655
}
655656

656657
block.and(base_place.index(idx))
@@ -722,13 +723,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
722723
fn bounds_check(
723724
&mut self,
724725
block: BasicBlock,
725-
slice: &PlaceBuilder<'tcx>,
726+
slice: Place<'tcx>,
726727
index: Local,
727728
expr_span: Span,
728729
source_info: SourceInfo,
729730
) -> BasicBlock {
730-
let slice = slice.to_place(self);
731-
732731
// len = len(slice)
733732
let len = self.len_of_slice_or_array(block, slice, expr_span, source_info);
734733

@@ -750,6 +749,52 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
750749
self.assert(block, Operand::Move(lt), true, msg, expr_span)
751750
}
752751

752+
fn should_skip_bounds_check(&self, slice: Place<'tcx>, index: ExprId) -> bool {
753+
let slice_ty = slice.ty(&self.local_decls, self.tcx);
754+
fn check_kind<'tcx>(
755+
thir: &Thir<'tcx>,
756+
tcx: TyCtxt<'tcx>,
757+
source: ExprId,
758+
array_len: u128,
759+
array_ty: Ty<'tcx>,
760+
) -> bool {
761+
match thir[source].kind {
762+
ExprKind::Cast { source } => match thir[source].ty.kind() {
763+
ty::Int(int_ty) => match int_ty {
764+
IntTy::I8 => (i8::MAX as u128) < array_len,
765+
IntTy::I16 => (i16::MAX as u128) < array_len,
766+
IntTy::I32 => (i32::MAX as u128) < array_len,
767+
IntTy::I64 => (i64::MAX as u128) < array_len,
768+
IntTy::I128 => (i128::MAX as u128) < array_len,
769+
IntTy::Isize => (isize::MAX as u128) < array_len,
770+
},
771+
ty::Uint(uint_ty) => match uint_ty {
772+
UintTy::U8 => (u8::MAX as u128) < array_len,
773+
UintTy::U16 => (u16::MAX as u128) < array_len,
774+
UintTy::U32 => (u32::MAX as u128) < array_len,
775+
UintTy::U64 => (u64::MAX as u128) < array_len,
776+
UintTy::U128 => u128::MAX < array_len,
777+
UintTy::Usize => (usize::MAX as u128) < array_len,
778+
},
779+
_ => false,
780+
},
781+
ExprKind::Scope { value, .. } => check_kind(thir, tcx, value, array_len, array_ty),
782+
ExprKind::Literal { lit, .. } if let LitKind::Int(num, _) = lit.node => {
783+
num.get() < array_len as u128
784+
}
785+
_ => false,
786+
}
787+
}
788+
789+
let ty::Array(_, const_array_len) = slice_ty.ty.kind() else { return false };
790+
791+
let Some(array_len) = const_array_len.try_to_target_usize(self.tcx) else {
792+
return false;
793+
};
794+
795+
check_kind(&self.thir, self.tcx, index, array_len as u128, slice_ty.ty)
796+
}
797+
753798
fn add_fake_borrows_of_base(
754799
&mut self,
755800
base_place: Place<'tcx>,

tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
let _1: u32;
77
let mut _2: [u32; 4];
88
let _3: usize;
9-
let mut _4: bool;
109
scope 1 {
1110
debug x => _1;
1211
}
@@ -17,13 +16,6 @@
1716
_2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
1817
StorageLive(_3);
1918
_3 = const 2_usize;
20-
- _4 = Lt(copy _3, const 4_usize);
21-
- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue];
22-
+ _4 = const true;
23-
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue];
24-
}
25-
26-
bb1: {
2719
- _1 = copy _2[_3];
2820
+ _1 = const 2_u32;
2921
StorageDead(_3);

tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
let _1: u8;
77
let mut _2: [u8; 5000];
88
let _3: usize;
9-
let mut _4: bool;
109
scope 1 {
1110
debug x => _1;
1211
}
@@ -17,13 +16,6 @@
1716
_2 = [const 0_u8; 5000];
1817
StorageLive(_3);
1918
_3 = const 2_usize;
20-
- _4 = Lt(copy _3, const 5000_usize);
21-
- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue];
22-
+ _4 = const true;
23-
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue];
24-
}
25-
26-
bb1: {
2719
- _1 = copy _2[_3];
2820
+ _1 = const 0_u8;
2921
StorageDead(_3);

tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
let mut _2: u32;
88
let mut _3: [u32; 8];
99
let _4: usize;
10-
let mut _5: bool;
1110
scope 1 {
1211
debug x => _1;
1312
}
@@ -19,13 +18,6 @@
1918
_3 = [const 42_u32; 8];
2019
StorageLive(_4);
2120
_4 = const 2_usize;
22-
- _5 = Lt(copy _4, const 8_usize);
23-
- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue];
24-
+ _5 = const true;
25-
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue];
26-
}
27-
28-
bb1: {
2921
- _2 = copy _3[_4];
3022
- _1 = Add(move _2, const 0_u32);
3123
+ _2 = const 42_u32;

tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
let _1: u32;
77
let mut _2: [u32; 4];
88
let _3: usize;
9-
let mut _4: bool;
109
scope 1 {
1110
debug x => _1;
1211
}
@@ -17,13 +16,6 @@
1716
_2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
1817
StorageLive(_3);
1918
_3 = const 2_usize;
20-
- _4 = Lt(copy _3, const 4_usize);
21-
- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue];
22-
+ _4 = const true;
23-
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue];
24-
}
25-
26-
bb1: {
2719
- _1 = copy _2[_3];
2820
+ _1 = copy _2[2 of 3];
2921
StorageDead(_3);

tests/mir-opt/dataflow-const-prop/array_index.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ fn main() {
1515
// CHECK-NOT: {{_.*}} = Lt(
1616
// CHECK-NOT: assert(move _
1717
// CHECK: {{_.*}} = const 2_usize;
18-
// CHECK: {{_.*}} = const true;
19-
// CHECK: assert(const true
2018
// CHECK: [[x]] = copy [[array_lit]][2 of 3];
2119
let x: u32 = [0, 1, 2, 3][2];
2220
}

tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
let _1: u8;
77
let mut _2: [u8; 5000];
88
let _3: usize;
9-
let mut _4: bool;
109
scope 1 {
1110
debug x => _1;
1211
}
@@ -17,13 +16,6 @@
1716
_2 = [const 0_u8; 5000];
1817
StorageLive(_3);
1918
_3 = const 2_usize;
20-
- _4 = Lt(copy _3, const 5000_usize);
21-
- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue];
22-
+ _4 = const true;
23-
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue];
24-
}
25-
26-
bb1: {
2719
- _1 = copy _2[_3];
2820
+ _1 = copy _2[2 of 3];
2921
StorageDead(_3);

tests/mir-opt/dataflow-const-prop/large_array_index.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ fn main() {
1111
// CHECK: debug x => [[x:_.*]];
1212
// CHECK: [[array_lit:_.*]] = [const 0_u8; 5000];
1313
// CHECK: {{_.*}} = const 2_usize;
14-
// CHECK: {{_.*}} = const true;
15-
// CHECK: assert(const true
1614
// CHECK: [[x]] = copy [[array_lit]][2 of 3];
1715
let x: u8 = [0_u8; 5000][2];
1816
}

tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
let mut _2: u32;
88
let mut _3: [u32; 8];
99
let _4: usize;
10-
let mut _5: bool;
1110
scope 1 {
1211
debug x => _1;
1312
}
@@ -19,13 +18,6 @@
1918
_3 = [const 42_u32; 8];
2019
StorageLive(_4);
2120
_4 = const 2_usize;
22-
- _5 = Lt(copy _4, const 8_usize);
23-
- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue];
24-
+ _5 = const true;
25-
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue];
26-
}
27-
28-
bb1: {
2921
- _2 = copy _3[_4];
3022
+ _2 = copy _3[2 of 3];
3123
_1 = Add(move _2, const 0_u32);

tests/mir-opt/dataflow-const-prop/repeat.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ fn main() {
1212
// CHECK-NOT: {{_.*}} = PtrMetadata(
1313
// CHECK-NOT: {{_.*}} = Lt(
1414
// CHECK: {{_.*}} = const 2_usize;
15-
// CHECK: {{_.*}} = const true;
16-
// CHECK: assert(const true
1715

1816
// CHECK-NOT: [[t:_.*]] = {{copy|move}} [[array_lit]][_
1917
// CHECK: [[t:_.*]] = copy [[array_lit]][2 of 3];

0 commit comments

Comments
 (0)