about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-09-23 16:23:37 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-10-25 06:46:48 +0000
commitdbf9ea30dd18db67cdb3f1271c7297876b65e675 (patch)
tree3eded0f78a1d9a5b0f1d1d29f6bb421517bfd704
parent80a5e8522de648d70a9ef1dfba7621f730832fb3 (diff)
downloadrust-dbf9ea30dd18db67cdb3f1271c7297876b65e675.tar.gz
rust-dbf9ea30dd18db67cdb3f1271c7297876b65e675.zip
Transform large arrays into Repeat expressions when possible.
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs14
-rw-r--r--tests/mir-opt/gvn.aggregates.GVN.panic-abort.diff67
-rw-r--r--tests/mir-opt/gvn.aggregates.GVN.panic-unwind.diff67
-rw-r--r--tests/mir-opt/gvn.rs4
4 files changed, 151 insertions, 1 deletions
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 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             .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<T: Copy>(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() {