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);