Skip to content

Commit

Permalink
cache Ty::is_simd
Browse files Browse the repository at this point in the history
  • Loading branch information
Ariel Ben-Yehuda committed Aug 6, 2015
1 parent 612760b commit 0153001
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 36 deletions.
28 changes: 19 additions & 9 deletions src/librustc/middle/ty.rs
Expand Up @@ -3179,11 +3179,12 @@ impl<'tcx> TraitDef<'tcx> {
bitflags! {
flags ADTFlags: u32 {
const NO_ADT_FLAGS = 0,
const IS_FUNDAMENTAL = 1 << 0,
const IS_PHANTOM_DATA = 1 << 1,
const IS_DTORCK = 1 << 2, // is this a dtorck type?
const IS_DTORCK_VALID = 1 << 3,
const IS_ENUM = 1 << 4
const IS_ENUM = 1 << 0,
const IS_DTORCK = 1 << 1, // is this a dtorck type?
const IS_DTORCK_VALID = 1 << 2,
const IS_PHANTOM_DATA = 1 << 3,
const IS_SIMD = 1 << 4,
const IS_FUNDAMENTAL = 1 << 5,
}
}

Expand Down Expand Up @@ -3244,9 +3245,13 @@ impl<'tcx, 'lt> ADTDef_<'tcx, 'lt> {
kind: ADTKind,
variants: Vec<VariantDef_<'tcx, 'lt>>) -> Self {
let mut flags = ADTFlags::NO_ADT_FLAGS;
if tcx.has_attr(did, "fundamental") {
let attrs = tcx.get_attrs(did);
if attrs.iter().any(|item| item.check_name("fundamental")) {
flags = flags | ADTFlags::IS_FUNDAMENTAL;
}
if attrs.iter().any(|item| item.check_name("simd")) {
flags = flags | ADTFlags::IS_SIMD;
}
if Some(did) == tcx.lang_items.phantom_data() {
flags = flags | ADTFlags::IS_PHANTOM_DATA;
}
Expand Down Expand Up @@ -3289,6 +3294,11 @@ impl<'tcx, 'lt> ADTDef_<'tcx, 'lt> {
self.flags.get().intersects(ADTFlags::IS_FUNDAMENTAL)
}

#[inline]
pub fn is_simd(&self) -> bool {
self.flags.get().intersects(ADTFlags::IS_SIMD)
}

#[inline]
pub fn is_phantom_data(&self) -> bool {
self.flags.get().intersects(ADTFlags::IS_PHANTOM_DATA)
Expand Down Expand Up @@ -4203,9 +4213,10 @@ impl<'tcx> TyS<'tcx> {
}
}

pub fn is_simd(&self, cx: &ctxt) -> bool {
#[inline]
pub fn is_simd(&self) -> bool {
match self.sty {
TyStruct(def, _) => cx.lookup_simd(def.did),
TyStruct(def, _) => def.is_simd(),
_ => false
}
}
Expand Down Expand Up @@ -5979,7 +5990,6 @@ impl<'tcx> ctxt<'tcx> {

/// Obtain the representation annotation for a struct definition.
pub fn lookup_repr_hints(&self, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
// TODO: remove
memoized(&self.repr_hint_cache, did, |did: DefId| {
Rc::new(if did.krate == LOCAL_CRATE {
self.get_attrs(did).iter().flat_map(|meta| {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/base.rs
Expand Up @@ -621,7 +621,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
(ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
}
ty::TyStruct(_, _) if rhs_t.is_simd(cx.tcx()) => {
ty::TyStruct(def, _) if def.is_simd() => {
let mut res = C_bool(cx.ccx(), false);
for i in 0 .. rhs_t.simd_size(cx.tcx()) {
res = Or(cx, res,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/common.rs
Expand Up @@ -192,7 +192,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
let simple = ty.is_scalar() ||
ty.is_unique() || ty.is_region_ptr() ||
type_is_newtype_immediate(ccx, ty) ||
ty.is_simd(tcx);
ty.is_simd();
if simple && !type_is_fat_ptr(tcx, ty) {
return true;
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_trans/trans/consts.rs
Expand Up @@ -500,7 +500,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
debug!("const_expr_unadjusted: te1={}, ty={:?}",
cx.tn().val_to_string(te1),
ty);
let is_simd = ty.is_simd(cx.tcx());
let is_simd = ty.is_simd();
let intype = if is_simd {
ty.simd_type(cx.tcx())
} else {
Expand Down Expand Up @@ -754,7 +754,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
(_, None) => cx.sess().span_bug(e.span, "missing struct field"),
}
}).collect::<Vec<_>>();
if ety.is_simd(cx.tcx()) {
if ety.is_simd() {
C_vector(&cs[..])
} else {
adt::trans_const(cx, &*repr, discr, &cs[..])
Expand Down Expand Up @@ -850,7 +850,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
const_fn_call(cx, ExprId(callee.id), did, &arg_vals, param_substs)
}
def::DefStruct(_) => {
if ety.is_simd(cx.tcx()) {
if ety.is_simd() {
C_vector(&arg_vals[..])
} else {
let repr = adt::represent_type(cx, ety);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/debuginfo/metadata.rs
Expand Up @@ -1175,7 +1175,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
StructMDF(StructMemberDescriptionFactory {
variant: variant,
substs: substs,
is_simd: struct_type.is_simd(cx.tcx()),
is_simd: struct_type.is_simd(),
span: span,
})
)
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_trans/trans/expr.rs
Expand Up @@ -1453,7 +1453,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
// panic occur before the ADT as a whole is ready.
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();

if ty.is_simd(bcx.tcx()) {
if ty.is_simd() {
// Issue 23112: The original logic appeared vulnerable to same
// order-of-eval bug. But, SIMD values are tuple-structs;
// i.e. functional record update (FRU) syntax is unavailable.
Expand Down Expand Up @@ -1697,7 +1697,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_eager_binop");

let tcx = bcx.tcx();
let is_simd = lhs_t.is_simd(tcx);
let is_simd = lhs_t.is_simd();
let intype = if is_simd {
lhs_t.simd_type(tcx)
} else {
Expand Down Expand Up @@ -2502,7 +2502,7 @@ fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// #1877, #10183: Ensure that input is always valid
let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
let tcx = bcx.tcx();
let is_simd = lhs_t.is_simd(tcx);
let is_simd = lhs_t.is_simd();
let intype = if is_simd {
lhs_t.simd_type(tcx)
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/foreign.rs
Expand Up @@ -449,7 +449,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
if !tcx.sess.features.borrow().simd_ffi {
let check = |ast_ty: &ast::Ty, ty: ty::Ty| {
if ty.is_simd(tcx) {
if ty.is_simd() {
tcx.sess.span_err(ast_ty.span,
&format!("use of SIMD type `{}` in FFI is highly experimental and \
may result in invalid code",
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/glue.rs
Expand Up @@ -419,7 +419,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
let ccx = bcx.ccx();
// First get the size of all statically known fields.
// Don't use type_of::sizing_type_of because that expects t to be sized.
assert!(!t.is_simd(bcx.tcx()));
assert!(!t.is_simd());
let repr = adt::represent_type(ccx, t);
let sizing_type = adt::sizing_type_context_of(ccx, &*repr, true);
debug!("DST {} sizing_type: {}", t, sizing_type.to_string());
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_trans/trans/type_of.rs
Expand Up @@ -222,7 +222,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
}

ty::TyStruct(..) => {
if t.is_simd(cx.tcx()) {
if t.is_simd() {
let llet = type_of(cx, t.simd_type(cx.tcx()));
let n = t.simd_size(cx.tcx()) as u64;
ensure_array_fits_in_address_space(cx, llet, n, t);
Expand Down Expand Up @@ -404,7 +404,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
adt::type_of(cx, &*repr)
}
ty::TyStruct(def, ref substs) => {
if t.is_simd(cx.tcx()) {
if t.is_simd() {
let llet = in_memory_type_of(cx, t.simd_type(cx.tcx()));
let n = t.simd_size(cx.tcx()) as u64;
ensure_array_fits_in_address_space(cx, llet, n, t);
Expand Down Expand Up @@ -436,7 +436,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
// If this was an enum or struct, fill in the type now.
match t.sty {
ty::TyEnum(..) | ty::TyStruct(..) | ty::TyClosure(..)
if !t.is_simd(cx.tcx()) => {
if !t.is_simd() => {
let repr = adt::represent_type(cx, t);
adt::finish_type_of(cx, &*repr, &mut llty);
}
Expand Down
25 changes: 12 additions & 13 deletions src/librustc_typeck/check/op.rs
Expand Up @@ -21,7 +21,7 @@ use super::{
structurally_resolved_type,
};
use middle::traits;
use middle::ty::{self, Ty, HasTypeFlags};
use middle::ty::{Ty, HasTypeFlags};
use syntax::ast;
use syntax::ast_util;
use syntax::parse::token;
Expand All @@ -41,7 +41,7 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
let lhs_ty = structurally_resolved_type(fcx, lhs_expr.span, fcx.expr_ty(lhs_expr));
let rhs_ty = structurally_resolved_type(fcx, rhs_expr.span, fcx.expr_ty(rhs_expr));

if is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op) {
if is_builtin_binop(lhs_ty, rhs_ty, op) {
enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
fcx.write_nil(expr.id);
} else {
Expand Down Expand Up @@ -86,7 +86,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// traits, because their return type is not bool. Perhaps this
// should change, but for now if LHS is SIMD we go down a
// different path that bypassess all traits.
if lhs_ty.is_simd(fcx.tcx()) {
if lhs_ty.is_simd() {
check_expr_coercable_to_type(fcx, rhs_expr, lhs_ty);
let rhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr));
let return_ty = enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
Expand Down Expand Up @@ -123,7 +123,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let rhs_ty = fcx.resolve_type_vars_if_possible(rhs_ty);
if
!lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() &&
is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op)
is_builtin_binop(lhs_ty, rhs_ty, op)
{
let builtin_return_ty =
enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
Expand All @@ -143,7 +143,7 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
op: ast::BinOp)
-> Ty<'tcx>
{
debug_assert!(is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op));
debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op));

let tcx = fcx.tcx();
match BinOpCategory::from(op) {
Expand All @@ -156,7 +156,7 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
BinOpCategory::Shift => {
// For integers, the shift amount can be of any integral
// type. For simd, the type must match exactly.
if lhs_ty.is_simd(tcx) {
if lhs_ty.is_simd() {
demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty);
}

Expand All @@ -176,7 +176,7 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty);

// if this is simd, result is same as lhs, else bool
if lhs_ty.is_simd(tcx) {
if lhs_ty.is_simd() {
let unit_ty = lhs_ty.simd_type(tcx);
debug!("enforce_builtin_binop_types: lhs_ty={:?} unit_ty={:?}",
lhs_ty,
Expand Down Expand Up @@ -415,8 +415,7 @@ impl BinOpCategory {
/// Reason #2 is the killer. I tried for a while to always use
/// overloaded logic and just check the types in constants/trans after
/// the fact, and it worked fine, except for SIMD types. -nmatsakis
fn is_builtin_binop<'tcx>(cx: &ty::ctxt<'tcx>,
lhs: Ty<'tcx>,
fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>,
rhs: Ty<'tcx>,
op: ast::BinOp)
-> bool
Expand All @@ -429,28 +428,28 @@ fn is_builtin_binop<'tcx>(cx: &ty::ctxt<'tcx>,
BinOpCategory::Shift => {
lhs.references_error() || rhs.references_error() ||
lhs.is_integral() && rhs.is_integral() ||
lhs.is_simd(cx) && rhs.is_simd(cx)
lhs.is_simd() && rhs.is_simd()
}

BinOpCategory::Math => {
lhs.references_error() || rhs.references_error() ||
lhs.is_integral() && rhs.is_integral() ||
lhs.is_floating_point() && rhs.is_floating_point() ||
lhs.is_simd(cx) && rhs.is_simd(cx)
lhs.is_simd() && rhs.is_simd()
}

BinOpCategory::Bitwise => {
lhs.references_error() || rhs.references_error() ||
lhs.is_integral() && rhs.is_integral() ||
lhs.is_floating_point() && rhs.is_floating_point() ||
lhs.is_simd(cx) && rhs.is_simd(cx) ||
lhs.is_simd() && rhs.is_simd() ||
lhs.is_bool() && rhs.is_bool()
}

BinOpCategory::Comparison => {
lhs.references_error() || rhs.references_error() ||
lhs.is_scalar() && rhs.is_scalar() ||
lhs.is_simd(cx) && rhs.is_simd(cx)
lhs.is_simd() && rhs.is_simd()
}
}
}

0 comments on commit 0153001

Please sign in to comment.