From bda083fa706c1a5a26a5c197960197086a84b4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Thu, 1 Oct 2015 11:55:52 +0200 Subject: [PATCH] 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. --- src/librustc_trans/trans/expr.rs | 17 ++++------------- src/test/codegen/refs.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 src/test/codegen/refs.rs 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 or the MIT license +// , 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; +}