From 746103860848a7fa6d57c996bc2e5322760e1d88 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 5 Jan 2017 11:31:47 -0700 Subject: [PATCH 1/4] Make type_is_immediate not depend on LLVM. This has the nice benefit of making it much simpler to work with, since it now consists of a single match statement. --- src/librustc_trans/common.rs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index eb6ea8fa94b0a..b72c1e553730d 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -58,24 +58,23 @@ pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> } pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - use machine::llsize_of_alloc; - use type_of::sizing_type_of; - - let simple = ty.is_scalar() || - ty.is_unique() || ty.is_region_ptr() || - ty.is_simd(); - if simple && !type_is_fat_ptr(ccx, ty) { - return true; - } - if !ccx.shared().type_is_sized(ty) { - return false; - } - match ty.sty { - ty::TyAdt(..) | ty::TyTuple(..) | ty::TyArray(..) | ty::TyClosure(..) => { - let llty = sizing_type_of(ccx, ty); - llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type()) + let layout = ccx.layout_of(ty); + match *layout { + Layout::CEnum { .. } | + Layout::Scalar { .. } | + Layout::Vector { .. } => true, + + Layout::FatPointer { .. } => false, + + Layout::Array { .. } | + Layout::Univariant { .. } | + Layout::General { .. } | + Layout::UntaggedUnion { .. } | + Layout::RawNullablePointer { .. } | + Layout::StructWrappedNullablePointer { .. } => { + let dl = &ccx.tcx().data_layout; + !layout.is_unsized() && layout.size(dl) <= dl.pointer_size } - _ => type_is_zero_size(ccx, ty) } } From 08290b20c4e406349d6bb11422558b095223a4ac Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 5 Jan 2017 11:35:30 -0700 Subject: [PATCH 2/4] Make type_is_fat_ptr not depend on LLVM. --- src/librustc_trans/common.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index b72c1e553730d..24bc5558093bc 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -45,15 +45,10 @@ use rustc_i128::u128; pub use context::{CrateContext, SharedCrateContext}; pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty::TyRawPtr(ty::TypeAndMut{ty, ..}) | - ty::TyRef(_, ty::TypeAndMut{ty, ..}) | - ty::TyBox(ty) => { - !ccx.shared().type_is_sized(ty) - } - _ => { - false - } + if let Layout::FatPointer { .. } = *ccx.layout_of(ty) { + true + } else { + false } } From e3930463801cfcc4c98974d627e8bbe8c9880fa0 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 5 Jan 2017 12:22:58 -0700 Subject: [PATCH 3/4] Simplify code since CEnum is always immediate now. --- src/librustc_trans/mir/rvalue.rs | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 67fb8cf576d62..1b97a8d010cfe 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -260,22 +260,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); let ll_t_in = type_of::immediate_type_of(bcx.ccx, operand.ty); let ll_t_out = type_of::immediate_type_of(bcx.ccx, cast_ty); - let (llval, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in { - let l = bcx.ccx.layout_of(operand.ty); - let discr = match operand.val { - OperandValue::Immediate(llval) => llval, - OperandValue::Ref(llptr) => { - adt::trans_get_discr(&bcx, operand.ty, llptr, None, true) - } - OperandValue::Pair(..) => bug!("Unexpected Pair operand") - }; - let (signed, min, max) = match l { - &Layout::CEnum { signed, min, max, .. } => { - (signed, min, max) - } - _ => bug!("CEnum {:?} is not an enum", operand) - }; - + let llval = operand.immediate(); + let l = bcx.ccx.layout_of(operand.ty); + let signed = if let Layout::CEnum { signed, min, max, .. } = *l { if max > min { // We want `table[e as usize]` to not // have bound checks, and this is the most @@ -283,14 +270,14 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { base::call_assume(&bcx, bcx.icmp( llvm::IntULE, - discr, - C_integral(common::val_ty(discr), max, false) - )) + llval, + C_integral(common::val_ty(llval), max, false) + )); } - (discr, signed) + signed } else { - (operand.immediate(), operand.ty.is_signed()) + operand.ty.is_signed() }; let newval = match (r_t_in, r_t_out) { From 43cf5b92310be5abb35a872f52615ace28bbed32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sat, 7 Jan 2017 11:06:28 -0700 Subject: [PATCH 4/4] Avoid using load/stores on first class aggregates LLVM usually prefers using memcpys over direct loads/store of first class aggregates. The check in type_is_immediate to mark certain small structs was originally part of the code to handle such immediates in function arguments, and it had a counterpart in load_ty/store_ty to actually convert small aggregates to integers. But since then, the ABI handling has been refactored and takes care of converting small aggregates to integers. During that refactoring, the code to handle small aggregates in load_ty/store_ty has been removed, and so we accidentally started using loads/stores on FCA values. Since type_is_immediate() is no longer responsible for ABI-related conversions, and using a memcpy even for small aggregates is usually better than performing a FCA load/store, we can remove that code part and only handle simple types as immediates there. This integrates PR #38906 onto this branch. Fixes #38906. --- src/librustc_trans/common.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 24bc5558093bc..419267cb269c9 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -67,8 +67,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) - Layout::UntaggedUnion { .. } | Layout::RawNullablePointer { .. } | Layout::StructWrappedNullablePointer { .. } => { - let dl = &ccx.tcx().data_layout; - !layout.is_unsized() && layout.size(dl) <= dl.pointer_size + !layout.is_unsized() && layout.size(&ccx.tcx().data_layout).bytes() == 0 } } }