diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index bbcb39226b7..f71e9de4123 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -795,6 +795,20 @@ fn simplify_aggregate( .collect(); let fields = fields?; + if let AggregateTy::Array = ty && fields.len() > 4 { + let first = fields[0]; + if fields.iter().all(|&v| v == first) { + let len = ty::Const::from_target_usize(self.tcx, fields.len().try_into().unwrap()); + if let Some(const_) = self.try_as_constant(first) { + *rvalue = Rvalue::Repeat(Operand::Constant(Box::new(const_)), len); + } else if let Some(local) = self.try_as_local(first, location) { + *rvalue = Rvalue::Repeat(Operand::Copy(local.into()), len); + self.reused_locals.insert(local); + } + return Some(Value::Repeat(first, len)); + } + } + let value = Value::Aggregate(ty, variant_index, fields); Some(value) } diff --git a/tests/mir-opt/gvn.aggregates.GVN.panic-abort.diff b/tests/mir-opt/gvn.aggregates.GVN.panic-abort.diff index c442835bfa9..b1dae36ab6c 100644 --- a/tests/mir-opt/gvn.aggregates.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.aggregates.GVN.panic-abort.diff @@ -8,6 +8,16 @@ let mut _4: [u16; 0]; let mut _6: (); let mut _8: (); + let mut _11: i32; + let mut _12: i32; + let mut _13: i32; + let mut _14: i32; + let mut _15: i32; + let mut _16: i32; + let mut _17: i32; + let mut _18: i32; + let mut _19: i32; + let mut _20: i32; scope 1 { debug a_array => _1; let _3: S<[u16; 0]>; @@ -19,6 +29,14 @@ let _7: S<()>; scope 4 { debug b_tuple => _7; + let _9: i32; + scope 5 { + debug val => _9; + let _10: [i32; 10]; + scope 6 { + debug array => _10; + } + } } } } @@ -55,7 +73,56 @@ + _8 = const (); + _7 = const S::<()>(()); StorageDead(_8); +- StorageLive(_9); ++ nop; + _9 = const 5_i32; + StorageLive(_10); + StorageLive(_11); +- _11 = _9; ++ _11 = const 5_i32; + StorageLive(_12); +- _12 = _9; ++ _12 = const 5_i32; + StorageLive(_13); +- _13 = _9; ++ _13 = const 5_i32; + StorageLive(_14); +- _14 = _9; ++ _14 = const 5_i32; + StorageLive(_15); +- _15 = _9; ++ _15 = const 5_i32; + StorageLive(_16); +- _16 = _9; ++ _16 = const 5_i32; + StorageLive(_17); +- _17 = _9; ++ _17 = const 5_i32; + StorageLive(_18); +- _18 = _9; ++ _18 = const 5_i32; + StorageLive(_19); +- _19 = _9; ++ _19 = const 5_i32; + StorageLive(_20); +- _20 = _9; +- _10 = [move _11, move _12, move _13, move _14, move _15, move _16, move _17, move _18, move _19, move _20]; ++ _20 = const 5_i32; ++ _10 = [const 5_i32; 10]; + StorageDead(_20); + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); _0 = const (); + StorageDead(_10); +- StorageDead(_9); ++ nop; StorageDead(_7); StorageDead(_5); StorageDead(_3); diff --git a/tests/mir-opt/gvn.aggregates.GVN.panic-unwind.diff b/tests/mir-opt/gvn.aggregates.GVN.panic-unwind.diff index c442835bfa9..b1dae36ab6c 100644 --- a/tests/mir-opt/gvn.aggregates.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.aggregates.GVN.panic-unwind.diff @@ -8,6 +8,16 @@ let mut _4: [u16; 0]; let mut _6: (); let mut _8: (); + let mut _11: i32; + let mut _12: i32; + let mut _13: i32; + let mut _14: i32; + let mut _15: i32; + let mut _16: i32; + let mut _17: i32; + let mut _18: i32; + let mut _19: i32; + let mut _20: i32; scope 1 { debug a_array => _1; let _3: S<[u16; 0]>; @@ -19,6 +29,14 @@ let _7: S<()>; scope 4 { debug b_tuple => _7; + let _9: i32; + scope 5 { + debug val => _9; + let _10: [i32; 10]; + scope 6 { + debug array => _10; + } + } } } } @@ -55,7 +73,56 @@ + _8 = const (); + _7 = const S::<()>(()); StorageDead(_8); +- StorageLive(_9); ++ nop; + _9 = const 5_i32; + StorageLive(_10); + StorageLive(_11); +- _11 = _9; ++ _11 = const 5_i32; + StorageLive(_12); +- _12 = _9; ++ _12 = const 5_i32; + StorageLive(_13); +- _13 = _9; ++ _13 = const 5_i32; + StorageLive(_14); +- _14 = _9; ++ _14 = const 5_i32; + StorageLive(_15); +- _15 = _9; ++ _15 = const 5_i32; + StorageLive(_16); +- _16 = _9; ++ _16 = const 5_i32; + StorageLive(_17); +- _17 = _9; ++ _17 = const 5_i32; + StorageLive(_18); +- _18 = _9; ++ _18 = const 5_i32; + StorageLive(_19); +- _19 = _9; ++ _19 = const 5_i32; + StorageLive(_20); +- _20 = _9; +- _10 = [move _11, move _12, move _13, move _14, move _15, move _16, move _17, move _18, move _19, move _20]; ++ _20 = const 5_i32; ++ _10 = [const 5_i32; 10]; + StorageDead(_20); + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); _0 = const (); + StorageDead(_10); +- StorageDead(_9); ++ nop; StorageDead(_7); StorageDead(_5); StorageDead(_3); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index ff176a6597b..406fe106add 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -61,7 +61,6 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { let e = &z; opaque(*e + x); opaque(*e + x); - } fn wrap_unwrap(x: T) -> T { @@ -237,6 +236,9 @@ fn aggregates() { let a_tuple: S<()> = S(()); let b_tuple: S<()> = S(()); // But this can be with `a_tuple`. + + let val = 5; + let array = [val, val, val, val, val, val, val, val, val, val]; } fn main() {