diff options
| author | Björn Steinbrink <bsteinbr@gmail.com> | 2015-10-01 11:55:52 +0200 |
|---|---|---|
| committer | Björn Steinbrink <bsteinbr@gmail.com> | 2015-10-01 15:24:23 +0200 |
| commit | bda083fa706c1a5a26a5c197960197086a84b4b9 (patch) | |
| tree | aae79fcb6c7a6f2568b7fcb8980b690eb1101607 | |
| parent | e5ba127734f7754a326d3197229e94c8a5a3be23 (diff) | |
| download | rust-bda083fa706c1a5a26a5c197960197086a84b4b9.tar.gz rust-bda083fa706c1a5a26a5c197960197086a84b4b9.zip | |
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.
| -rw-r--r-- | src/librustc_trans/trans/expr.rs | 17 | ||||
| -rw-r--r-- | src/test/codegen/refs.rs | 30 |
2 files changed, 34 insertions, 13 deletions
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 722089e42f9..9d006771445 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -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() } } diff --git a/src/test/codegen/refs.rs b/src/test/codegen/refs.rs new file mode 100644 index 00000000000..08eec0045f7 --- /dev/null +++ b/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; +} |
