]> git.lizzy.rs Git - rust.git/commitdiff
[MIR] Avoid some code generation for stores of ZST
authorSimonas Kazlauskas <git@kazlauskas.me>
Tue, 12 Jan 2016 14:36:47 +0000 (16:36 +0200)
committerSimonas Kazlauskas <git@kazlauskas.me>
Tue, 12 Jan 2016 19:35:10 +0000 (21:35 +0200)
Fixes #30831

src/librustc_trans/trans/mir/operand.rs
src/librustc_trans/trans/mir/rvalue.rs
src/test/codegen/mir_zst_stores.rs [new file with mode: 0644]

index 6240473b78ec3ecd4875414961ebb4b2c36e6946..114e78b05bddd0b72d55611b49dbde390676694f 100644 (file)
@@ -169,6 +169,11 @@ pub fn store_operand(&mut self,
                          operand: OperandRef<'tcx>)
     {
         debug!("store_operand: operand={}", operand.repr(bcx));
+        // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
+        // value is through `undef`, and store itself is useless.
+        if common::type_is_zero_size(bcx.ccx(), operand.ty) {
+            return;
+        }
         match operand.val {
             OperandValue::Ref(r) => base::memcpy_ty(bcx, lldest, r, operand.ty),
             OperandValue::Immediate(s) => base::store_ty(bcx, s, lldest, operand.ty),
index b57d3b107fb45c058f5a8a83beb682185c956333..f0842554277cc7e50fcfcaa1bf824665bb25d325 100644 (file)
@@ -108,11 +108,15 @@ pub fn trans_rvalue(&mut self,
                     },
                     _ => {
                         for (i, operand) in operands.iter().enumerate() {
-                            // Note: perhaps this should be StructGep, but
-                            // note that in some cases the values here will
-                            // not be structs but arrays.
-                            let lldest_i = build::GEPi(bcx, dest.llval, &[0, i]);
-                            self.trans_operand_into(bcx, lldest_i, operand);
+                            let op = self.trans_operand(bcx, operand);
+                            // Do not generate stores and GEPis for zero-sized fields.
+                            if !common::type_is_zero_size(bcx.ccx(), op.ty) {
+                                // Note: perhaps this should be StructGep, but
+                                // note that in some cases the values here will
+                                // not be structs but arrays.
+                                let dest = build::GEPi(bcx, dest.llval, &[0, i]);
+                                self.store_operand(bcx, dest, op);
+                            }
                         }
                     }
                 }
diff --git a/src/test/codegen/mir_zst_stores.rs b/src/test/codegen/mir_zst_stores.rs
new file mode 100644 (file)
index 0000000..c1acdaf
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(rustc_attrs)]
+#![crate_type = "lib"]
+use std::marker::PhantomData;
+
+
+struct Zst { phantom: PhantomData<Zst> }
+
+// CHECK-LABEL: @mir
+#[no_mangle]
+#[rustc_mir]
+fn mir(){
+    // CHECK-NOT: getelementptr
+    // CHECK-NOT: store{{.*}}undef
+    let x = Zst { phantom: PhantomData };
+}