From ff0c6b75916e2c9f7fc9caf5dfacad4bbca03f38 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Mon, 10 Jun 2024 14:08:02 +0000 Subject: [PATCH 01/15] add regression test --- .../mir-opt/const_array_locals.main.GVN.diff | 44 ++++++++++++++++++ tests/mir-opt/const_array_locals.rs | 46 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 tests/mir-opt/const_array_locals.main.GVN.diff create mode 100644 tests/mir-opt/const_array_locals.rs diff --git a/tests/mir-opt/const_array_locals.main.GVN.diff b/tests/mir-opt/const_array_locals.main.GVN.diff new file mode 100644 index 0000000000000..b29f620945d56 --- /dev/null +++ b/tests/mir-opt/const_array_locals.main.GVN.diff @@ -0,0 +1,44 @@ +- // MIR for `main` before GVN ++ // MIR for `main` after GVN + + fn main() -> () { + let mut _0: (); + let _1: [i32; 32]; + let mut _4: &[i32; 32]; + let _5: [i32; 32]; + scope 1 { + debug _arr => _1; + let _2: [i32; 32]; + scope 2 { + debug _barr => _2; + let _3: [i32; 32]; + let mut _6: &[i32; 32]; + scope 3 { + debug _darr => _3; + } + } + } + + bb0: { +- StorageLive(_1); ++ nop; + _1 = [const 255_i32, const 105_i32, const 15_i32, const 39_i32, const 62_i32, const 251_i32, const 191_i32, const 178_i32, const 9_i32, const 4_i32, const 56_i32, const 221_i32, const 193_i32, const 164_i32, const 194_i32, const 197_i32, const 6_i32, const 243_i32, const 218_i32, const 171_i32, const 87_i32, const 247_i32, const 104_i32, const 159_i32, const 22_i32, const 157_i32, const 105_i32, const 31_i32, const 96_i32, const 173_i32, const 50_i32, const 1_i32]; + StorageLive(_2); +- _2 = [const 255_i32, const 105_i32, const 15_i32, const 39_i32, const 62_i32, const 251_i32, const 191_i32, const 178_i32, const 9_i32, const 4_i32, const 56_i32, const 221_i32, const 193_i32, const 164_i32, const 194_i32, const 197_i32, const 6_i32, const 243_i32, const 218_i32, const 171_i32, const 87_i32, const 247_i32, const 104_i32, const 159_i32, const 22_i32, const 157_i32, const 105_i32, const 31_i32, const 96_i32, const 173_i32, const 50_i32, const 1_i32]; ++ _2 = _1; + StorageLive(_3); + StorageLive(_4); + _6 = const main::promoted[0]; + _4 = &(*_6); +- _3 = (*_4); ++ _3 = (*_6); + StorageDead(_4); + _0 = const (); + StorageDead(_3); + StorageDead(_2); +- StorageDead(_1); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/const_array_locals.rs b/tests/mir-opt/const_array_locals.rs new file mode 100644 index 0000000000000..029da366d6958 --- /dev/null +++ b/tests/mir-opt/const_array_locals.rs @@ -0,0 +1,46 @@ +//@ test-mir-pass: GVN +#![feature(repr_simd)] + +// #[repr(simd)] +// struct F32x8([f32; 8]); + +// EMIT_MIR const_array_locals.main.GVN.diff +// CHECK-LABEL: fn main( +#[rustfmt::skip] +pub fn main() { + // CHECK: let [[array_lit:_.*]]: [i32; 32]; + // CHECK: debug _arr => [[arr:_.*]]; + + let _arr = [ + 255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, + 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, + 159, 22, 157, 105, 31, 96, 173, 50, 1, + ]; + let _barr = [ + 255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, + 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, + 159, 22, 157, 105, 31, 96, 173, 50, 1, + ]; + // let _foo = [ + // [255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221], + // [193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, 42], + // ]; + let _darr = *&[ + 255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, + 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, + 159, 22, 157, 105, 31, 96, 173, 50, 1, + ]; + + // consume([255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, + // 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, + // 159, 22, 157, 105, 31, 96, 173, 50, 1,]); + + // let _f = F32x8([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]); + + // // ice + // [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; // 2D array +} + +// fn consume(_arr: [u16; 32]) { +// unimplemented!() +// } From bc9586d9b468fc568adb6f4fa399b91644efc404 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Tue, 11 Jun 2024 07:09:15 +0000 Subject: [PATCH 02/15] wip --- compiler/rustc_mir_transform/src/gvn.rs | 27 +++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 459d15b1cacc3..9310127d5d6e1 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -367,7 +367,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { #[instrument(level = "trace", skip(self), ret)] fn eval_to_const(&mut self, value: VnIndex) -> Option> { use Value::*; - let op = match *self.get(value) { + let vvalue = self.get(value); + debug!(?vvalue); + let op = match *vvalue { Opaque(_) => return None, // Do not bother evaluating repeat expressions. This would uselessly consume memory. Repeat(..) => return None, @@ -376,10 +378,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.ecx.eval_mir_constant(value, DUMMY_SP, None).ok()? } Aggregate(kind, variant, ref fields) => { + debug!(?kind, ?variant, ?fields); let fields = fields .iter() .map(|&f| self.evaluated[f].as_ref()) - .collect::>>()?; + .collect::>>>()?; let ty = match kind { AggregateTy::Array => { assert!(fields.len() > 0); @@ -407,6 +410,24 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { }; let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx); ImmTy::from_immediate(ptr_imm, ty).into() + } else if matches!(kind, AggregateTy::Array) { + let mut mplace = None; + let alloc_id = self.ecx.intern_with_temp_alloc(ty, |ecx, dest| { + for (field_index, op) in fields.iter().copied().enumerate() { + let field_dest = ecx.project_field(dest, field_index)?; + ecx.copy_op(op, &field_dest)?; + } + + let place = dest.assert_mem_place(); + mplace.replace(place); + Ok(()) + }).ok()?; + let GlobalAlloc::Memory(_alloc) = self.tcx.global_alloc(alloc_id) else { + bug!() + }; + let mplace = mplace.unwrap(); + debug!(?mplace); + return Some(mplace.into()); } else if matches!(ty.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { let dest = self.ecx.allocate(ty, MemoryKind::Stack).ok()?; let variant_dest = if let Some(variant) = variant { @@ -429,6 +450,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } Projection(base, elem) => { + debug!(?base, ?elem); let value = self.evaluated[base].as_ref()?; let elem = match elem { ProjectionElem::Deref => ProjectionElem::Deref, @@ -450,6 +472,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.ecx.project(value, elem).ok()? } Address { place, kind, provenance: _ } => { + debug!(?place, ?kind); if !place.is_indirect_first_projection() { return None; } From a1899325ca561cfbbcd8399258d42bbaf294ff0e Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 12 Jun 2024 07:03:41 +0000 Subject: [PATCH 03/15] set memplace as immutable --- compiler/rustc_mir_transform/src/gvn.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 9310127d5d6e1..1f8cd04be4d0b 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -418,8 +418,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ecx.copy_op(op, &field_dest)?; } - let place = dest.assert_mem_place(); - mplace.replace(place); + let dest = dest.assert_mem_place(); + //ecx.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()).unwrap(); + let dest = dest.map_provenance(|prov| prov.as_immutable()); + mplace.replace(dest); Ok(()) }).ok()?; let GlobalAlloc::Memory(_alloc) = self.tcx.global_alloc(alloc_id) else { From 699916feb5f0f909c6017e4db0bb56b1330c68a8 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 08:57:07 +0000 Subject: [PATCH 04/15] remove redundant condition --- compiler/rustc_mir_transform/src/gvn.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 1f8cd04be4d0b..8e93e7674a6a2 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1258,6 +1258,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } +#[instrument(level = "trace", skip(ecx), ret)] fn op_to_prop_const<'tcx>( ecx: &mut InterpCx<'tcx, DummyMachine>, op: &OpTy<'tcx>, @@ -1338,10 +1339,6 @@ impl<'tcx> VnState<'_, 'tcx> { } let op = self.evaluated[index].as_ref()?; - if op.layout.is_unsized() { - // Do not attempt to propagate unsized locals. - return None; - } let value = op_to_prop_const(&mut self.ecx, op)?; From 6c3d0d2e4276c1638c9aefbb89971f15e0fb3d51 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 21:04:34 +0000 Subject: [PATCH 05/15] clearer reasoning --- compiler/rustc_mir_transform/src/gvn.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 8e93e7674a6a2..b30fff2e8b314 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -418,9 +418,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ecx.copy_op(op, &field_dest)?; } - let dest = dest.assert_mem_place(); - //ecx.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()).unwrap(); - let dest = dest.map_provenance(|prov| prov.as_immutable()); + let dest = dest.assert_mem_place().map_provenance(|prov| prov.as_immutable()); mplace.replace(dest); Ok(()) }).ok()?; @@ -1388,6 +1386,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { .as_local() .and_then(|local| self.locals[local]) .or_else(|| self.simplify_rvalue(rvalue, location)); + debug!(?value); let Some(value) = value else { return }; if let Some(const_) = self.try_as_constant(value) { From a269f23842b17e8b314d99bd47af786835c37602 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 21:06:55 +0000 Subject: [PATCH 06/15] ignore nested arrays --- compiler/rustc_mir_transform/src/gvn.rs | 42 +++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index b30fff2e8b314..40ac3fec54bc1 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -414,6 +414,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let mut mplace = None; let alloc_id = self.ecx.intern_with_temp_alloc(ty, |ecx, dest| { for (field_index, op) in fields.iter().copied().enumerate() { + // ignore nested arrays + if let Either::Left(_) = op.as_mplace_or_imm() { + interpret::throw_inval!(TooGeneric); + } let field_dest = ecx.project_field(dest, field_index)?; ecx.copy_op(op, &field_dest)?; } @@ -732,7 +736,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { place.projection = self.tcx.mk_place_elems(&projection); } - trace!(?place); + trace!(after_place = ?place); } /// Represent the *value* which would be read from `place`, and point `place` to a preexisting @@ -1272,7 +1276,7 @@ fn op_to_prop_const<'tcx>( } // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to avoid. - if !matches!(op.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { + if !(op.layout.ty.is_array() || matches!(op.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))) { return None; } @@ -1326,14 +1330,37 @@ fn op_to_prop_const<'tcx>( impl<'tcx> VnState<'_, 'tcx> { /// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR. + #[instrument(level = "trace", skip(self, index), ret)] fn try_as_constant(&mut self, index: VnIndex) -> Option> { // This was already constant in MIR, do not change it. - if let Value::Constant { value, disambiguator: _ } = *self.get(index) + let value = self.get(index); + debug!(?index, ?value); + match value { // If the constant is not deterministic, adding an additional mention of it in MIR will // not give the same value as the former mention. - && value.is_deterministic() - { - return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value }); + Value::Constant { value, disambiguator: _ } if value.is_deterministic() => { + return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: *value }); + } + // ignore nested arrays + Value::Aggregate(AggregateTy::Array, _, fields) => { + for f in fields { + if let Value::Constant { value: Const::Val(const_, _), .. } = self.get(*f) + && let ConstValue::Indirect { .. } = const_ { + return None; + } + } + } + // ignore promoted arrays + Value::Projection(index, ProjectionElem::Deref) => { + if let Value::Constant { value: Const::Val(const_, ty), .. } = self.get(*index) + && let ConstValue::Scalar(Scalar::Ptr(..)) = const_ + && let ty::Ref(region, ty, _mutability) = ty.kind() + && region.is_erased() + && ty.is_array() { + return None; + } + } + _ => {} } let op = self.evaluated[index].as_ref()?; @@ -1373,6 +1400,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { self.simplify_operand(operand, location); } + #[instrument(level = "trace", skip(self, stmt))] fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) { if let StatementKind::Assign(box (ref mut lhs, ref mut rvalue)) = stmt.kind { self.simplify_place_projection(lhs, location); @@ -1389,6 +1417,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { debug!(?value); let Some(value) = value else { return }; + debug!(before_rvalue = ?rvalue); if let Some(const_) = self.try_as_constant(value) { *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); } else if let Some(local) = self.try_as_local(value, location) @@ -1397,6 +1426,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { *rvalue = Rvalue::Use(Operand::Copy(local.into())); self.reused_locals.insert(local); } + debug!(after_rvalue = ?rvalue); return; } From 9b1a9321a818af16f1e2eedd067173ec73ee2ba4 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 21:31:24 +0000 Subject: [PATCH 07/15] cache propagated const --- compiler/rustc_mir_transform/src/gvn.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 40ac3fec54bc1..3adf550776db5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1373,6 +1373,10 @@ impl<'tcx> VnState<'_, 'tcx> { assert!(!value.may_have_provenance(self.tcx, op.layout.size)); let const_ = Const::Val(value, op.layout.ty); + // cache the propagated const + if let Some(new_index) = self.insert_constant(const_) { + self.values.swap_indices(index.as_usize(), new_index.as_usize()); + } Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_ }) } From 852bea0d677958bc5ddd917cec91fb434eb765a8 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 21:38:36 +0000 Subject: [PATCH 08/15] add codegen test --- .../issue-73825-gvn-const-local-array.rs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/codegen/issue-73825-gvn-const-local-array.rs diff --git a/tests/codegen/issue-73825-gvn-const-local-array.rs b/tests/codegen/issue-73825-gvn-const-local-array.rs new file mode 100644 index 0000000000000..19c5ae811d092 --- /dev/null +++ b/tests/codegen/issue-73825-gvn-const-local-array.rs @@ -0,0 +1,25 @@ +// issue: +//@ compile-flags: -C opt-level=1 +#![crate_type = "lib"] + +// CHECK-LABEL: @foo +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: and +// CHECK-NEXT: getelementptr inbounds +// CHECK-NEXT: load i32 +// CHECK-NEXT: ret i32 +#[no_mangle] +#[rustfmt::skip] +pub fn foo(x: usize) -> i32 { + let base: [i32; 64] = [ + 67, 754, 860, 559, 368, 870, 548, 972, + 141, 731, 351, 664, 32, 4, 996, 741, + 203, 292, 237, 480, 151, 940, 777, 540, + 143, 587, 747, 65, 152, 517, 882, 880, + 712, 595, 370, 901, 237, 53, 789, 785, + 912, 650, 896, 367, 316, 392, 62, 473, + 675, 691, 281, 192, 445, 970, 225, 425, + 628, 324, 322, 206, 912, 867, 462, 92 + ]; + base[x % 64] +} From 9c24e141802ebede48ad1341233f5fd238ce2b94 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 21:39:02 +0000 Subject: [PATCH 09/15] fmt --- compiler/rustc_mir_transform/src/gvn.rs | 37 +++++++++++++++---------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 3adf550776db5..6d4a52b461816 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -412,20 +412,24 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ImmTy::from_immediate(ptr_imm, ty).into() } else if matches!(kind, AggregateTy::Array) { let mut mplace = None; - let alloc_id = self.ecx.intern_with_temp_alloc(ty, |ecx, dest| { - for (field_index, op) in fields.iter().copied().enumerate() { - // ignore nested arrays - if let Either::Left(_) = op.as_mplace_or_imm() { - interpret::throw_inval!(TooGeneric); + let alloc_id = self + .ecx + .intern_with_temp_alloc(ty, |ecx, dest| { + for (field_index, op) in fields.iter().copied().enumerate() { + // ignore nested arrays + if let Either::Left(_) = op.as_mplace_or_imm() { + interpret::throw_inval!(TooGeneric); + } + let field_dest = ecx.project_field(dest, field_index)?; + ecx.copy_op(op, &field_dest)?; } - let field_dest = ecx.project_field(dest, field_index)?; - ecx.copy_op(op, &field_dest)?; - } - let dest = dest.assert_mem_place().map_provenance(|prov| prov.as_immutable()); - mplace.replace(dest); - Ok(()) - }).ok()?; + let dest = + dest.assert_mem_place().map_provenance(|prov| prov.as_immutable()); + mplace.replace(dest); + Ok(()) + }) + .ok()?; let GlobalAlloc::Memory(_alloc) = self.tcx.global_alloc(alloc_id) else { bug!() }; @@ -1276,7 +1280,8 @@ fn op_to_prop_const<'tcx>( } // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to avoid. - if !(op.layout.ty.is_array() || matches!(op.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))) { + if !(op.layout.ty.is_array() || matches!(op.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))) + { return None; } @@ -1345,7 +1350,8 @@ impl<'tcx> VnState<'_, 'tcx> { Value::Aggregate(AggregateTy::Array, _, fields) => { for f in fields { if let Value::Constant { value: Const::Val(const_, _), .. } = self.get(*f) - && let ConstValue::Indirect { .. } = const_ { + && let ConstValue::Indirect { .. } = const_ + { return None; } } @@ -1356,7 +1362,8 @@ impl<'tcx> VnState<'_, 'tcx> { && let ConstValue::Scalar(Scalar::Ptr(..)) = const_ && let ty::Ref(region, ty, _mutability) = ty.kind() && region.is_erased() - && ty.is_array() { + && ty.is_array() + { return None; } } From ec7d227b8aed9c8451535bc0821b1c183732e774 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 21:39:18 +0000 Subject: [PATCH 10/15] bless else --- .../array_index.main.GVN.64bit.panic-unwind.diff | 7 ++++++- .../const_prop/read_immutable_static.main.GVN.diff | 6 ++---- ...timizes_into_variable.main.GVN.64bit.panic-unwind.diff | 8 +++++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff index 7e2f72ab31bce..38e7b2b688dd4 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff @@ -15,7 +15,8 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; +- _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; ++ _2 = const [0_u32, 1_u32, 2_u32, 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); @@ -35,5 +36,9 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 16, align: 4) { ++ 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 │ ................ } diff --git a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff index 38f235052303f..04311718c8f9d 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff +++ b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff @@ -14,9 +14,8 @@ bb0: { StorageLive(_1); -- StorageLive(_2); + StorageLive(_2); - StorageLive(_3); -+ nop; + nop; _3 = const {ALLOC0: &u8}; - _2 = (*_3); @@ -29,8 +28,7 @@ + _4 = const 2_u8; + _1 = const 4_u8; StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageDead(_5); - StorageDead(_3); + nop; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff index da7add371a5bf..1f403c7806809 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff @@ -35,7 +35,8 @@ + _1 = const 4_i32; StorageLive(_3); StorageLive(_4); - _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; +- _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; ++ _4 = const [0_i32, 1_i32, 2_i32, 3_i32, 4_i32, 5_i32]; StorageLive(_5); _5 = const 3_usize; _6 = const 6_usize; @@ -65,5 +66,10 @@ + + ALLOC0 (size: 8, align: 4) { + 04 00 00 00 00 __ __ __ │ .....░░░ ++ } ++ ++ ALLOC1 (size: 24, align: 4) { ++ 0x00 │ 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 │ ................ ++ 0x10 │ 04 00 00 00 05 00 00 00 │ ........ } From 8d11d46b17fd52a76840414d8e8b81cdf6ab7e47 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 21:35:34 +0000 Subject: [PATCH 11/15] bless --- .../mir-opt/const_array_locals.main.GVN.diff | 140 ++++++++++++++++-- tests/mir-opt/const_array_locals.rs | 34 ++--- 2 files changed, 141 insertions(+), 33 deletions(-) diff --git a/tests/mir-opt/const_array_locals.main.GVN.diff b/tests/mir-opt/const_array_locals.main.GVN.diff index b29f620945d56..49063410236a8 100644 --- a/tests/mir-opt/const_array_locals.main.GVN.diff +++ b/tests/mir-opt/const_array_locals.main.GVN.diff @@ -4,41 +4,151 @@ fn main() -> () { let mut _0: (); let _1: [i32; 32]; - let mut _4: &[i32; 32]; - let _5: [i32; 32]; + let mut _4: [i32; 12]; + let mut _5: [i32; 12]; + let mut _7: &[i32; 32]; + let _8: [i32; 32]; + let _9: (); + let mut _10: [u16; 32]; + let mut _12: [f32; 8]; + let _13: [[i32; 3]; 3]; + let mut _14: [i32; 3]; + let mut _15: [i32; 3]; + let mut _16: [i32; 3]; scope 1 { debug _arr => _1; let _2: [i32; 32]; scope 2 { debug _barr => _2; - let _3: [i32; 32]; - let mut _6: &[i32; 32]; + let _3: [[i32; 12]; 2]; scope 3 { - debug _darr => _3; + debug _foo => _3; + let _6: [i32; 32]; + let mut _17: &[i32; 32]; + scope 4 { + debug _darr => _6; + let _11: F32x8; + scope 5 { + debug _f => _11; + } + } } } } bb0: { -- StorageLive(_1); -+ nop; - _1 = [const 255_i32, const 105_i32, const 15_i32, const 39_i32, const 62_i32, const 251_i32, const 191_i32, const 178_i32, const 9_i32, const 4_i32, const 56_i32, const 221_i32, const 193_i32, const 164_i32, const 194_i32, const 197_i32, const 6_i32, const 243_i32, const 218_i32, const 171_i32, const 87_i32, const 247_i32, const 104_i32, const 159_i32, const 22_i32, const 157_i32, const 105_i32, const 31_i32, const 96_i32, const 173_i32, const 50_i32, const 1_i32]; + StorageLive(_1); +- _1 = [const 255_i32, const 105_i32, const 15_i32, const 39_i32, const 62_i32, const 251_i32, const 191_i32, const 178_i32, const 9_i32, const 4_i32, const 56_i32, const 221_i32, const 193_i32, const 164_i32, const 194_i32, const 197_i32, const 6_i32, const 243_i32, const 218_i32, const 171_i32, const 87_i32, const 247_i32, const 104_i32, const 159_i32, const 22_i32, const 157_i32, const 105_i32, const 31_i32, const 96_i32, const 173_i32, const 50_i32, const 1_i32]; ++ _1 = const [255_i32, 105_i32, 15_i32, 39_i32, 62_i32, 251_i32, 191_i32, 178_i32, 9_i32, 4_i32, 56_i32, 221_i32, 193_i32, 164_i32, 194_i32, 197_i32, 6_i32, 243_i32, 218_i32, 171_i32, 87_i32, 247_i32, 104_i32, 159_i32, 22_i32, 157_i32, 105_i32, 31_i32, 96_i32, 173_i32, 50_i32, 1_i32]; StorageLive(_2); - _2 = [const 255_i32, const 105_i32, const 15_i32, const 39_i32, const 62_i32, const 251_i32, const 191_i32, const 178_i32, const 9_i32, const 4_i32, const 56_i32, const 221_i32, const 193_i32, const 164_i32, const 194_i32, const 197_i32, const 6_i32, const 243_i32, const 218_i32, const 171_i32, const 87_i32, const 247_i32, const 104_i32, const 159_i32, const 22_i32, const 157_i32, const 105_i32, const 31_i32, const 96_i32, const 173_i32, const 50_i32, const 1_i32]; -+ _2 = _1; ++ _2 = const [255_i32, 105_i32, 15_i32, 39_i32, 62_i32, 251_i32, 191_i32, 178_i32, 9_i32, 4_i32, 56_i32, 221_i32, 193_i32, 164_i32, 194_i32, 197_i32, 6_i32, 243_i32, 218_i32, 171_i32, 87_i32, 247_i32, 104_i32, 159_i32, 22_i32, 157_i32, 105_i32, 31_i32, 96_i32, 173_i32, 50_i32, 1_i32]; StorageLive(_3); StorageLive(_4); - _6 = const main::promoted[0]; - _4 = &(*_6); -- _3 = (*_4); -+ _3 = (*_6); +- _4 = [const 255_i32, const 105_i32, const 15_i32, const 39_i32, const 62_i32, const 251_i32, const 191_i32, const 178_i32, const 9_i32, const 4_i32, const 56_i32, const 221_i32]; ++ _4 = const [255_i32, 105_i32, 15_i32, 39_i32, 62_i32, 251_i32, 191_i32, 178_i32, 9_i32, 4_i32, 56_i32, 221_i32]; + StorageLive(_5); +- _5 = [const 193_i32, const 164_i32, const 194_i32, const 197_i32, const 6_i32, const 243_i32, const 218_i32, const 171_i32, const 87_i32, const 247_i32, const 104_i32, const 42_i32]; +- _3 = [move _4, move _5]; ++ _5 = const [193_i32, 164_i32, 194_i32, 197_i32, 6_i32, 243_i32, 218_i32, 171_i32, 87_i32, 247_i32, 104_i32, 42_i32]; ++ _3 = [const [255_i32, 105_i32, 15_i32, 39_i32, 62_i32, 251_i32, 191_i32, 178_i32, 9_i32, 4_i32, 56_i32, 221_i32], const [193_i32, 164_i32, 194_i32, 197_i32, 6_i32, 243_i32, 218_i32, 171_i32, 87_i32, 247_i32, 104_i32, 42_i32]]; + StorageDead(_5); StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _17 = const main::promoted[0]; + _7 = &(*_17); +- _6 = (*_7); ++ _6 = (*_17); + StorageDead(_7); + StorageLive(_9); + StorageLive(_10); +- _10 = [const 255_u16, const 105_u16, const 15_u16, const 39_u16, const 62_u16, const 251_u16, const 191_u16, const 178_u16, const 9_u16, const 4_u16, const 56_u16, const 221_u16, const 193_u16, const 164_u16, const 194_u16, const 197_u16, const 6_u16, const 243_u16, const 218_u16, const 171_u16, const 87_u16, const 247_u16, const 104_u16, const 159_u16, const 22_u16, const 157_u16, const 105_u16, const 31_u16, const 96_u16, const 173_u16, const 50_u16, const 1_u16]; +- _9 = consume(move _10) -> [return: bb1, unwind continue]; ++ _10 = const [255_u16, 105_u16, 15_u16, 39_u16, 62_u16, 251_u16, 191_u16, 178_u16, 9_u16, 4_u16, 56_u16, 221_u16, 193_u16, 164_u16, 194_u16, 197_u16, 6_u16, 243_u16, 218_u16, 171_u16, 87_u16, 247_u16, 104_u16, 159_u16, 22_u16, 157_u16, 105_u16, 31_u16, 96_u16, 173_u16, 50_u16, 1_u16]; ++ _9 = consume(const [255_u16, 105_u16, 15_u16, 39_u16, 62_u16, 251_u16, 191_u16, 178_u16, 9_u16, 4_u16, 56_u16, 221_u16, 193_u16, 164_u16, 194_u16, 197_u16, 6_u16, 243_u16, 218_u16, 171_u16, 87_u16, 247_u16, 104_u16, 159_u16, 22_u16, 157_u16, 105_u16, 31_u16, 96_u16, 173_u16, 50_u16, 1_u16]) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); +- _12 = [const 1f32, const 2f32, const 3f32, const 1f32, const 1f32, const 1f32, const 1f32, const 42f32]; +- _11 = F32x8(move _12); ++ _12 = const [1f32, 2f32, 3f32, 1f32, 1f32, 1f32, 1f32, 42f32]; ++ _11 = F32x8(const [1f32, 2f32, 3f32, 1f32, 1f32, 1f32, 1f32, 42f32]); + StorageDead(_12); + StorageLive(_13); + StorageLive(_14); +- _14 = [const 1_i32, const 0_i32, const 0_i32]; ++ _14 = const [1_i32, 0_i32, 0_i32]; + StorageLive(_15); +- _15 = [const 0_i32, const 1_i32, const 0_i32]; ++ _15 = const [0_i32, 1_i32, 0_i32]; + StorageLive(_16); +- _16 = [const 0_i32, const 0_i32, const 1_i32]; +- _13 = [move _14, move _15, move _16]; ++ _16 = const [0_i32, 0_i32, 1_i32]; ++ _13 = [const [1_i32, 0_i32, 0_i32], const [0_i32, 1_i32, 0_i32], const [0_i32, 0_i32, 1_i32]]; + StorageDead(_16); + StorageDead(_15); + StorageDead(_14); + StorageDead(_13); _0 = const (); + StorageDead(_11); + StorageDead(_6); StorageDead(_3); StorageDead(_2); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 12, align: 4) { ++ 00 00 00 00 00 00 00 00 01 00 00 00 │ ............ ++ } ++ ++ ALLOC1 (size: 12, align: 4) { ++ 00 00 00 00 01 00 00 00 00 00 00 00 │ ............ ++ } ++ ++ ALLOC2 (size: 12, align: 4) { ++ 01 00 00 00 00 00 00 00 00 00 00 00 │ ............ ++ } ++ ++ ALLOC3 (size: 32, align: 4) { ++ 0x00 │ 00 00 80 3f 00 00 00 40 00 00 40 40 00 00 80 3f │ ...?...@..@@...? ++ 0x10 │ 00 00 80 3f 00 00 80 3f 00 00 80 3f 00 00 28 42 │ ...?...?...?..(B ++ } ++ ++ ALLOC4 (size: 64, align: 2) { ++ 0x00 │ ff 00 69 00 0f 00 27 00 3e 00 fb 00 bf 00 b2 00 │ ..i...'.>....... ++ 0x10 │ 09 00 04 00 38 00 dd 00 c1 00 a4 00 c2 00 c5 00 │ ....8........... ++ 0x20 │ 06 00 f3 00 da 00 ab 00 57 00 f7 00 68 00 9f 00 │ ........W...h... ++ 0x30 │ 16 00 9d 00 69 00 1f 00 60 00 ad 00 32 00 01 00 │ ....i...`...2... ++ } ++ ++ ALLOC5 (size: 48, align: 4) { ++ 0x00 │ c1 00 00 00 a4 00 00 00 c2 00 00 00 c5 00 00 00 │ ................ ++ 0x10 │ 06 00 00 00 f3 00 00 00 da 00 00 00 ab 00 00 00 │ ................ ++ 0x20 │ 57 00 00 00 f7 00 00 00 68 00 00 00 2a 00 00 00 │ W.......h...*... ++ } ++ ++ ALLOC6 (size: 48, align: 4) { ++ 0x00 │ ff 00 00 00 69 00 00 00 0f 00 00 00 27 00 00 00 │ ....i.......'... ++ 0x10 │ 3e 00 00 00 fb 00 00 00 bf 00 00 00 b2 00 00 00 │ >............... ++ 0x20 │ 09 00 00 00 04 00 00 00 38 00 00 00 dd 00 00 00 │ ........8....... ++ } ++ ++ ALLOC7 (size: 128, align: 4) { ++ 0x00 │ ff 00 00 00 69 00 00 00 0f 00 00 00 27 00 00 00 │ ....i.......'... ++ 0x10 │ 3e 00 00 00 fb 00 00 00 bf 00 00 00 b2 00 00 00 │ >............... ++ 0x20 │ 09 00 00 00 04 00 00 00 38 00 00 00 dd 00 00 00 │ ........8....... ++ 0x30 │ c1 00 00 00 a4 00 00 00 c2 00 00 00 c5 00 00 00 │ ................ ++ 0x40 │ 06 00 00 00 f3 00 00 00 da 00 00 00 ab 00 00 00 │ ................ ++ 0x50 │ 57 00 00 00 f7 00 00 00 68 00 00 00 9f 00 00 00 │ W.......h....... ++ 0x60 │ 16 00 00 00 9d 00 00 00 69 00 00 00 1f 00 00 00 │ ........i....... ++ 0x70 │ 60 00 00 00 ad 00 00 00 32 00 00 00 01 00 00 00 │ `.......2....... } diff --git a/tests/mir-opt/const_array_locals.rs b/tests/mir-opt/const_array_locals.rs index 029da366d6958..88cceeff9ac56 100644 --- a/tests/mir-opt/const_array_locals.rs +++ b/tests/mir-opt/const_array_locals.rs @@ -1,46 +1,44 @@ //@ test-mir-pass: GVN #![feature(repr_simd)] -// #[repr(simd)] -// struct F32x8([f32; 8]); +#[repr(simd)] +struct F32x8([f32; 8]); // EMIT_MIR const_array_locals.main.GVN.diff // CHECK-LABEL: fn main( #[rustfmt::skip] pub fn main() { - // CHECK: let [[array_lit:_.*]]: [i32; 32]; - // CHECK: debug _arr => [[arr:_.*]]; - let _arr = [ 255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, 159, 22, 157, 105, 31, 96, 173, 50, 1, ]; + // duplicate item let _barr = [ 255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, 159, 22, 157, 105, 31, 96, 173, 50, 1, ]; - // let _foo = [ - // [255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221], - // [193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, 42], - // ]; + let _foo = [ + [255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221], + [193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, 42], + ]; let _darr = *&[ 255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, 159, 22, 157, 105, 31, 96, 173, 50, 1, ]; - // consume([255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, - // 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, - // 159, 22, 157, 105, 31, 96, 173, 50, 1,]); + consume([255, 105, 15, 39, 62, 251, 191, 178, 9, 4, 56, 221, + 193, 164, 194, 197, 6, 243, 218, 171, 87, 247, 104, + 159, 22, 157, 105, 31, 96, 173, 50, 1,]); - // let _f = F32x8([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]); + let _f = F32x8([1.0, 2.0, 3.0, 1.0, 1.0, 1.0, 1.0, 42.0]); - // // ice - // [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; // 2D array + // ice + [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; // 2D array } -// fn consume(_arr: [u16; 32]) { -// unimplemented!() -// } +fn consume(_arr: [u16; 32]) { + unimplemented!() +} From 550fb81e1833b0f35feaa58a026f0c190656acf6 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 13 Jun 2024 21:56:04 +0000 Subject: [PATCH 12/15] ignore array.size() <= 16 bytes --- compiler/rustc_mir_transform/src/gvn.rs | 8 +++++ .../mir-opt/const_array_locals.main.GVN.diff | 34 +++++-------------- ...ray_index.main.GVN.64bit.panic-unwind.diff | 7 +--- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 6d4a52b461816..f5e432bf3e641 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -366,7 +366,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { #[instrument(level = "trace", skip(self), ret)] fn eval_to_const(&mut self, value: VnIndex) -> Option> { + use abi::HasDataLayout; use Value::*; + // LLVM optimizes the load of `sizeof(size_t) * 2` as a single `mov`, + // which is cheap. Bigger values make more `mov` instructions generated. + // After GVN, it becomes a single load (`lea`) of an address in `.rodata`. + let stack_threshold = self.tcx.data_layout().pointer_size * 2; let vvalue = self.get(value); debug!(?vvalue); let op = match *vvalue { @@ -411,6 +416,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx); ImmTy::from_immediate(ptr_imm, ty).into() } else if matches!(kind, AggregateTy::Array) { + if ty.layout.size() <= stack_threshold { + return None; + } let mut mplace = None; let alloc_id = self .ecx diff --git a/tests/mir-opt/const_array_locals.main.GVN.diff b/tests/mir-opt/const_array_locals.main.GVN.diff index 49063410236a8..2276176b1cbd4 100644 --- a/tests/mir-opt/const_array_locals.main.GVN.diff +++ b/tests/mir-opt/const_array_locals.main.GVN.diff @@ -81,16 +81,12 @@ StorageDead(_12); StorageLive(_13); StorageLive(_14); -- _14 = [const 1_i32, const 0_i32, const 0_i32]; -+ _14 = const [1_i32, 0_i32, 0_i32]; + _14 = [const 1_i32, const 0_i32, const 0_i32]; StorageLive(_15); -- _15 = [const 0_i32, const 1_i32, const 0_i32]; -+ _15 = const [0_i32, 1_i32, 0_i32]; + _15 = [const 0_i32, const 1_i32, const 0_i32]; StorageLive(_16); -- _16 = [const 0_i32, const 0_i32, const 1_i32]; -- _13 = [move _14, move _15, move _16]; -+ _16 = const [0_i32, 0_i32, 1_i32]; -+ _13 = [const [1_i32, 0_i32, 0_i32], const [0_i32, 1_i32, 0_i32], const [0_i32, 0_i32, 1_i32]]; + _16 = [const 0_i32, const 0_i32, const 1_i32]; + _13 = [move _14, move _15, move _16]; StorageDead(_16); StorageDead(_15); StorageDead(_14); @@ -105,43 +101,31 @@ } + } + -+ ALLOC0 (size: 12, align: 4) { -+ 00 00 00 00 00 00 00 00 01 00 00 00 │ ............ -+ } -+ -+ ALLOC1 (size: 12, align: 4) { -+ 00 00 00 00 01 00 00 00 00 00 00 00 │ ............ -+ } -+ -+ ALLOC2 (size: 12, align: 4) { -+ 01 00 00 00 00 00 00 00 00 00 00 00 │ ............ -+ } -+ -+ ALLOC3 (size: 32, align: 4) { ++ ALLOC0 (size: 32, align: 4) { + 0x00 │ 00 00 80 3f 00 00 00 40 00 00 40 40 00 00 80 3f │ ...?...@..@@...? + 0x10 │ 00 00 80 3f 00 00 80 3f 00 00 80 3f 00 00 28 42 │ ...?...?...?..(B + } + -+ ALLOC4 (size: 64, align: 2) { ++ ALLOC1 (size: 64, align: 2) { + 0x00 │ ff 00 69 00 0f 00 27 00 3e 00 fb 00 bf 00 b2 00 │ ..i...'.>....... + 0x10 │ 09 00 04 00 38 00 dd 00 c1 00 a4 00 c2 00 c5 00 │ ....8........... + 0x20 │ 06 00 f3 00 da 00 ab 00 57 00 f7 00 68 00 9f 00 │ ........W...h... + 0x30 │ 16 00 9d 00 69 00 1f 00 60 00 ad 00 32 00 01 00 │ ....i...`...2... + } + -+ ALLOC5 (size: 48, align: 4) { ++ ALLOC2 (size: 48, align: 4) { + 0x00 │ c1 00 00 00 a4 00 00 00 c2 00 00 00 c5 00 00 00 │ ................ + 0x10 │ 06 00 00 00 f3 00 00 00 da 00 00 00 ab 00 00 00 │ ................ + 0x20 │ 57 00 00 00 f7 00 00 00 68 00 00 00 2a 00 00 00 │ W.......h...*... + } + -+ ALLOC6 (size: 48, align: 4) { ++ ALLOC3 (size: 48, align: 4) { + 0x00 │ ff 00 00 00 69 00 00 00 0f 00 00 00 27 00 00 00 │ ....i.......'... + 0x10 │ 3e 00 00 00 fb 00 00 00 bf 00 00 00 b2 00 00 00 │ >............... + 0x20 │ 09 00 00 00 04 00 00 00 38 00 00 00 dd 00 00 00 │ ........8....... + } + -+ ALLOC7 (size: 128, align: 4) { ++ ALLOC4 (size: 128, align: 4) { + 0x00 │ ff 00 00 00 69 00 00 00 0f 00 00 00 27 00 00 00 │ ....i.......'... + 0x10 │ 3e 00 00 00 fb 00 00 00 bf 00 00 00 b2 00 00 00 │ >............... + 0x20 │ 09 00 00 00 04 00 00 00 38 00 00 00 dd 00 00 00 │ ........8....... diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff index 38e7b2b688dd4..7e2f72ab31bce 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff @@ -15,8 +15,7 @@ bb0: { StorageLive(_1); StorageLive(_2); -- _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; -+ _2 = const [0_u32, 1_u32, 2_u32, 3_u32]; + _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); @@ -36,9 +35,5 @@ StorageDead(_1); return; } -+ } -+ -+ ALLOC0 (size: 16, align: 4) { -+ 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 │ ................ } From 7246da36889806dfbb3b2cb93e05f9045b6f72a4 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 14 Jun 2024 09:05:34 +0000 Subject: [PATCH 13/15] rewrite ignore nested array condition --- compiler/rustc_mir_transform/src/gvn.rs | 43 ++++++++++--------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index f5e432bf3e641..5b216249c5abf 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1348,38 +1348,29 @@ impl<'tcx> VnState<'_, 'tcx> { // This was already constant in MIR, do not change it. let value = self.get(index); debug!(?index, ?value); - match value { - // If the constant is not deterministic, adding an additional mention of it in MIR will - // not give the same value as the former mention. - Value::Constant { value, disambiguator: _ } if value.is_deterministic() => { - return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: *value }); - } + // If the constant is not deterministic, adding an additional mention of it in MIR will + // not give the same value as the former mention. + if let Value::Constant { value, disambiguator: _ } = value + && value.is_deterministic() + { + return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: *value }); + } + + let op = self.evaluated[index].as_ref()?; + + if let Either::Left(mplace) = op.as_mplace_or_imm() + && let ty::Array(ty, _const) = mplace.layout.ty.kind() + { // ignore nested arrays - Value::Aggregate(AggregateTy::Array, _, fields) => { - for f in fields { - if let Value::Constant { value: Const::Val(const_, _), .. } = self.get(*f) - && let ConstValue::Indirect { .. } = const_ - { - return None; - } - } + if ty.is_array() { + return None; } // ignore promoted arrays - Value::Projection(index, ProjectionElem::Deref) => { - if let Value::Constant { value: Const::Val(const_, ty), .. } = self.get(*index) - && let ConstValue::Scalar(Scalar::Ptr(..)) = const_ - && let ty::Ref(region, ty, _mutability) = ty.kind() - && region.is_erased() - && ty.is_array() - { - return None; - } + else if let Value::Projection(_index, ProjectionElem::Deref) = value { + return None; } - _ => {} } - let op = self.evaluated[index].as_ref()?; - let value = op_to_prop_const(&mut self.ecx, op)?; // Check that we do not leak a pointer. From b375e331e17b11d86bb2afa71f0c0dfe58b42cc9 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 14 Jun 2024 12:38:10 +0000 Subject: [PATCH 14/15] move ignoring condition out of loop --- compiler/rustc_mir_transform/src/gvn.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 5b216249c5abf..cdc1563288df5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -390,8 +390,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { .collect::>>>()?; let ty = match kind { AggregateTy::Array => { - assert!(fields.len() > 0); - Ty::new_array(self.tcx, fields[0].layout.ty, fields.len() as u64) + let [field, ..] = fields.as_slice() else { + bug!("fields.len() == 0"); + }; + let field_ty = field.layout.ty; + // Ignore nested array + if field_ty.is_array() { + trace!( + "ignoring nested array of type: [{field_ty}; {len}]", + len = fields.len(), + ); + return None; + } + Ty::new_array(self.tcx, field_ty, fields.len() as u64) } AggregateTy::Tuple => { Ty::new_tup_from_iter(self.tcx, fields.iter().map(|f| f.layout.ty)) @@ -424,10 +435,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { .ecx .intern_with_temp_alloc(ty, |ecx, dest| { for (field_index, op) in fields.iter().copied().enumerate() { - // ignore nested arrays - if let Either::Left(_) = op.as_mplace_or_imm() { - interpret::throw_inval!(TooGeneric); - } let field_dest = ecx.project_field(dest, field_index)?; ecx.copy_op(op, &field_dest)?; } From 6c6de58635dee93d6de851e90027deea8934e59f Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 14 Jun 2024 12:49:15 +0000 Subject: [PATCH 15/15] add fixme about potential perf --- compiler/rustc_mir_transform/src/gvn.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index cdc1563288df5..22da641f48b35 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -434,6 +434,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let alloc_id = self .ecx .intern_with_temp_alloc(ty, |ecx, dest| { + // FIXME: Can we speed it up by using `ecx.write_immediate(.ScalarPair(_), dest)`? for (field_index, op) in fields.iter().copied().enumerate() { let field_dest = ecx.project_field(dest, field_index)?; ecx.copy_op(op, &field_dest)?;