Skip to content

Commit 3c48243

Browse files
committed
Simplify Len.
1 parent 5fc23ad commit 3c48243

15 files changed

+96
-52
lines changed

compiler/rustc_mir_transform/src/gvn.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -776,10 +776,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
776776
}
777777

778778
// Operations.
779-
Rvalue::Len(ref mut place) => {
780-
let place = self.simplify_place_value(place, location)?;
781-
Value::Len(place)
782-
}
779+
Rvalue::Len(ref mut place) => return self.simplify_len(place, location),
783780
Rvalue::Cast(kind, ref mut value, to) => {
784781
let from = value.ty(self.local_decls, self.tcx);
785782
let value = self.simplify_operand(value, location)?;
@@ -1021,6 +1018,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10211018
Some(result)
10221019
}
10231020
}
1021+
1022+
fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option<VnIndex> {
1023+
// Trivial case: we are fetching a statically known length.
1024+
let place_ty = place.ty(self.local_decls, self.tcx).ty;
1025+
if let ty::Array(_, len) = place_ty.kind() {
1026+
return self.insert_constant(Const::from_ty_const(*len, self.tcx));
1027+
}
1028+
1029+
let mut inner = self.simplify_place_value(place, location)?;
1030+
1031+
// The length information is stored in the fat pointer.
1032+
// Reborrowing copies length information from one pointer to the other.
1033+
while let Value::Address { place: borrowed, .. } = self.get(inner)
1034+
&& let [PlaceElem::Deref] = borrowed.projection[..]
1035+
&& let Some(borrowed) = self.locals[borrowed.local]
1036+
{
1037+
inner = borrowed;
1038+
}
1039+
1040+
// We have an unsizing cast, which assigns the length to fat pointer metadata.
1041+
if let Value::Cast { kind, from, to, .. } = self.get(inner)
1042+
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind
1043+
&& let Some(from) = from.builtin_deref(true)
1044+
&& let ty::Array(_, len) = from.ty.kind()
1045+
&& let Some(to) = to.builtin_deref(true)
1046+
&& let ty::Slice(..) = to.ty.kind()
1047+
{
1048+
return self.insert_constant(Const::from_ty_const(*len, self.tcx));
1049+
}
1050+
1051+
// Fallback: a symbolic `Len`.
1052+
Some(self.insert(Value::Len(inner)))
1053+
}
10241054
}
10251055

10261056
fn op_to_prop_const<'tcx>(

tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
_2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
1919
StorageLive(_3);
2020
_3 = const 2_usize;
21-
_4 = Len(_2);
21+
- _4 = Len(_2);
2222
- _5 = Lt(_3, _4);
2323
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable];
24-
+ _5 = Lt(const 2_usize, _4);
25-
+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable];
24+
+ _4 = const 4_usize;
25+
+ _5 = const true;
26+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable];
2627
}
2728

2829
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
_2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
1919
StorageLive(_3);
2020
_3 = const 2_usize;
21-
_4 = Len(_2);
21+
- _4 = Len(_2);
2222
- _5 = Lt(_3, _4);
2323
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue];
24-
+ _5 = Lt(const 2_usize, _4);
25-
+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue];
24+
+ _4 = const 4_usize;
25+
+ _5 = const true;
26+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue];
2627
}
2728

2829
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
_2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
1919
StorageLive(_3);
2020
_3 = const 2_usize;
21-
_4 = Len(_2);
21+
- _4 = Len(_2);
2222
- _5 = Lt(_3, _4);
2323
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable];
24-
+ _5 = Lt(const 2_usize, _4);
25-
+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable];
24+
+ _4 = const 4_usize;
25+
+ _5 = const true;
26+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable];
2627
}
2728

2829
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
_2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
1919
StorageLive(_3);
2020
_3 = const 2_usize;
21-
_4 = Len(_2);
21+
- _4 = Len(_2);
2222
- _5 = Lt(_3, _4);
2323
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue];
24-
+ _5 = Lt(const 2_usize, _4);
25-
+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue];
24+
+ _4 = const 4_usize;
25+
+ _5 = const true;
26+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue];
2627
}
2728

2829
bb1: {

tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
_2 = [const 0_u8; 5000];
1919
StorageLive(_3);
2020
_3 = const 2_usize;
21-
_4 = Len(_2);
21+
- _4 = Len(_2);
2222
- _5 = Lt(_3, _4);
2323
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable];
24-
+ _5 = Lt(const 2_usize, _4);
25-
+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable];
24+
+ _4 = const 5000_usize;
25+
+ _5 = const true;
26+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable];
2627
}
2728

2829
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
_2 = [const 0_u8; 5000];
1919
StorageLive(_3);
2020
_3 = const 2_usize;
21-
_4 = Len(_2);
21+
- _4 = Len(_2);
2222
- _5 = Lt(_3, _4);
2323
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue];
24-
+ _5 = Lt(const 2_usize, _4);
25-
+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue];
24+
+ _4 = const 5000_usize;
25+
+ _5 = const true;
26+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue];
2627
}
2728

2829
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
_2 = [const 0_u8; 5000];
1919
StorageLive(_3);
2020
_3 = const 2_usize;
21-
_4 = Len(_2);
21+
- _4 = Len(_2);
2222
- _5 = Lt(_3, _4);
2323
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable];
24-
+ _5 = Lt(const 2_usize, _4);
25-
+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable];
24+
+ _4 = const 5000_usize;
25+
+ _5 = const true;
26+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable];
2627
}
2728

2829
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
_2 = [const 0_u8; 5000];
1919
StorageLive(_3);
2020
_3 = const 2_usize;
21-
_4 = Len(_2);
21+
- _4 = Len(_2);
2222
- _5 = Lt(_3, _4);
2323
- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue];
24-
+ _5 = Lt(const 2_usize, _4);
25-
+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue];
24+
+ _4 = const 5000_usize;
25+
+ _5 = const true;
26+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue];
2627
}
2728

2829
bb1: {

tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
_3 = [const 42_u32; 8];
2121
StorageLive(_4);
2222
_4 = const 2_usize;
23-
_5 = Len(_3);
23+
- _5 = Len(_3);
2424
- _6 = Lt(_4, _5);
2525
- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable];
26-
+ _6 = Lt(const 2_usize, _5);
27-
+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind unreachable];
26+
+ _5 = const 8_usize;
27+
+ _6 = const true;
28+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable];
2829
}
2930

3031
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
_3 = [const 42_u32; 8];
2121
StorageLive(_4);
2222
_4 = const 2_usize;
23-
_5 = Len(_3);
23+
- _5 = Len(_3);
2424
- _6 = Lt(_4, _5);
2525
- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue];
26-
+ _6 = Lt(const 2_usize, _5);
27-
+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind continue];
26+
+ _5 = const 8_usize;
27+
+ _6 = const true;
28+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue];
2829
}
2930

3031
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
_3 = [const 42_u32; 8];
2121
StorageLive(_4);
2222
_4 = const 2_usize;
23-
_5 = Len(_3);
23+
- _5 = Len(_3);
2424
- _6 = Lt(_4, _5);
2525
- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable];
26-
+ _6 = Lt(const 2_usize, _5);
27-
+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind unreachable];
26+
+ _5 = const 8_usize;
27+
+ _6 = const true;
28+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable];
2829
}
2930

3031
bb1: {

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
_3 = [const 42_u32; 8];
2121
StorageLive(_4);
2222
_4 = const 2_usize;
23-
_5 = Len(_3);
23+
- _5 = Len(_3);
2424
- _6 = Lt(_4, _5);
2525
- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue];
26-
+ _6 = Lt(const 2_usize, _5);
27-
+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind continue];
26+
+ _5 = const 8_usize;
27+
+ _6 = const true;
28+
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue];
2829
}
2930

3031
bb1: {

tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff

+7-6
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@
3232
StorageLive(_6);
3333
StorageLive(_7);
3434
_7 = const 0_usize;
35-
_8 = Len(_3);
35+
- _8 = Len(_3);
3636
- _9 = Lt(_7, _8);
3737
- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind unreachable];
38-
+ _9 = Lt(const 0_usize, _8);
39-
+ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind unreachable];
38+
+ _8 = const N;
39+
+ _9 = Lt(const 0_usize, const N);
40+
+ assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind unreachable];
4041
}
4142

4243
bb1: {
@@ -57,9 +58,9 @@
5758
- _13 = Len(_3);
5859
- _14 = Lt(_12, _13);
5960
- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind unreachable];
60-
+ _13 = _8;
61-
+ _14 = Lt(_2, _8);
62-
+ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind unreachable];
61+
+ _13 = const N;
62+
+ _14 = Lt(_2, const N);
63+
+ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, _2) -> [success: bb3, unwind unreachable];
6364
}
6465

6566
bb3: {

tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff

+7-6
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@
3232
StorageLive(_6);
3333
StorageLive(_7);
3434
_7 = const 0_usize;
35-
_8 = Len(_3);
35+
- _8 = Len(_3);
3636
- _9 = Lt(_7, _8);
3737
- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind continue];
38-
+ _9 = Lt(const 0_usize, _8);
39-
+ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind continue];
38+
+ _8 = const N;
39+
+ _9 = Lt(const 0_usize, const N);
40+
+ assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind continue];
4041
}
4142

4243
bb1: {
@@ -57,9 +58,9 @@
5758
- _13 = Len(_3);
5859
- _14 = Lt(_12, _13);
5960
- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind continue];
60-
+ _13 = _8;
61-
+ _14 = Lt(_2, _8);
62-
+ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind continue];
61+
+ _13 = const N;
62+
+ _14 = Lt(_2, const N);
63+
+ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, _2) -> [success: bb3, unwind continue];
6364
}
6465

6566
bb3: {

0 commit comments

Comments
 (0)