Navigation Menu

Skip to content

Commit

Permalink
Avoid unnecessary temporaries when ref'ing a DST value
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dotdash committed Oct 1, 2015
1 parent e5ba127 commit bda083f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
17 changes: 4 additions & 13 deletions src/librustc_trans/trans/expr.rs
Expand Up @@ -1691,29 +1691,20 @@ 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)
-> DatumBlock<'blk, 'tcx, Expr> {
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()
}
}
Expand Down
30 changes: 30 additions & 0 deletions src/test/codegen/refs.rs
@@ -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;
}

0 comments on commit bda083f

Please sign in to comment.