Avoid unnecessary temporaries when ref'ing a DST value
A DST value and a fat pointer to it have the same representation, all we have to do is to adjust the type of the datum holding the pointer.
This commit is contained in:
parent
e5ba127734
commit
bda083fa70
@ -1691,16 +1691,6 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
|
||||
}
|
||||
|
||||
fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
lval: Datum<'tcx, Lvalue>)
|
||||
-> DatumBlock<'blk, 'tcx, Expr> {
|
||||
let dest_ty = bcx.tcx().mk_imm_ref(bcx.tcx().mk_region(ty::ReStatic), lval.ty);
|
||||
let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
|
||||
memcpy_ty(bcx, scratch.val, lval.val, scratch.ty);
|
||||
|
||||
DatumBlock::new(bcx, scratch.to_expr_datum())
|
||||
}
|
||||
|
||||
fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
expr: &hir::Expr,
|
||||
subexpr: &hir::Expr)
|
||||
@ -1708,12 +1698,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let _icx = push_ctxt("trans_addr_of");
|
||||
let mut bcx = bcx;
|
||||
let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
|
||||
let ty = expr_ty(bcx, expr);
|
||||
if !type_is_sized(bcx.tcx(), sub_datum.ty) {
|
||||
// DST lvalue, close to a fat pointer
|
||||
ref_fat_ptr(bcx, sub_datum)
|
||||
// Always generate an lvalue datum, because this pointer doesn't own
|
||||
// the data and cleanup is scheduled elsewhere.
|
||||
DatumBlock::new(bcx, Datum::new(sub_datum.val, ty, LvalueExpr(sub_datum.kind)))
|
||||
} else {
|
||||
// Sized value, ref to a thin pointer
|
||||
let ty = expr_ty(bcx, expr);
|
||||
immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
|
||||
}
|
||||
}
|
||||
|
30
src/test/codegen/refs.rs
Normal file
30
src/test/codegen/refs.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2015 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
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Hack to get the correct size for the length part in slices
|
||||
// CHECK: @helper([[USIZE:i[0-9]+]])
|
||||
#[no_mangle]
|
||||
fn helper(_: usize) {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @ref_dst
|
||||
#[no_mangle]
|
||||
pub fn ref_dst(s: &[u8]) {
|
||||
// We used to generate an extra alloca and memcpy to ref the dst, so check that we copy
|
||||
// directly to the alloca for "x"
|
||||
// CHECK: [[SRC:%[0-9]+]] = bitcast { i8*, [[USIZE]] }* %s to i8*
|
||||
// CHECK: [[DST:%[0-9]+]] = bitcast { i8*, [[USIZE]] }* %x to i8*
|
||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[DST]], i8* [[SRC]],
|
||||
let x = &*s;
|
||||
}
|
Loading…
Reference in New Issue
Block a user