about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_trans/mir/analyze.rs17
-rw-r--r--src/librustc_trans/mir/operand.rs20
2 files changed, 37 insertions, 0 deletions
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index bce639ac8f7..59143bc01bf 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -39,6 +39,8 @@ pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
             // in an ValueRef without an alloca.
             assert!(common::type_is_immediate(bcx.ccx(), ty) ||
                     common::type_is_fat_ptr(bcx.tcx(), ty));
+        } else if common::type_is_imm_pair(bcx.ccx(), ty) {
+            // We allow pairs and uses of any of their 2 fields.
         } else {
             // These sorts of types require an alloca. Note that
             // type_is_immediate() may *still* be true, particularly
@@ -111,6 +113,21 @@ impl<'mir, 'bcx, 'tcx> Visitor<'tcx> for TempAnalyzer<'mir, 'bcx, 'tcx> {
                     context: LvalueContext) {
         debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context);
 
+        // Allow uses of projections of immediate pair fields.
+        if let mir::Lvalue::Projection(ref proj) = *lvalue {
+            if let mir::Lvalue::Temp(index) = proj.base {
+                let ty = self.mir.temp_decls[index as usize].ty;
+                let ty = self.bcx.monomorphize(&ty);
+                if common::type_is_imm_pair(self.bcx.ccx(), ty) {
+                    if let mir::ProjectionElem::Field(..) = proj.elem {
+                        if let LvalueContext::Consume = context {
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
         match *lvalue {
             mir::Lvalue::Temp(index) => {
                 match context {
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index 9e04f1cb207..c21f112b5f6 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -187,6 +187,26 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     }
                 }
 
+                // Moves out of pair fields are trivial.
+                if let &mir::Lvalue::Projection(ref proj) = lvalue {
+                    if let mir::Lvalue::Temp(index) = proj.base {
+                        let temp_ref = &self.temps[index as usize];
+                        if let &TempRef::Operand(Some(o)) = temp_ref {
+                            match (o.val, &proj.elem) {
+                                (OperandValue::Pair(a, b),
+                                 &mir::ProjectionElem::Field(ref f, ty)) => {
+                                    let llval = [a, b][f.index()];
+                                    return OperandRef {
+                                        val: OperandValue::Immediate(llval),
+                                        ty: bcx.monomorphize(&ty)
+                                    };
+                                }
+                                _ => {}
+                            }
+                        }
+                    }
+                }
+
                 // for most lvalues, to consume them we just load them
                 // out from their home
                 let tr_lvalue = self.trans_lvalue(bcx, lvalue);