Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup Miri SIMD intrinsics #66468

Merged
merged 5 commits into from
Nov 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// SIMD vector types.
ty::Adt(def, ..) if def.repr.simd() => {
let element = self.layout_of(ty.simd_type(tcx))?;
let count = ty.simd_size(tcx) as u64;
let count = ty.simd_size(tcx);
assert!(count > 0);
let scalar = match element.abi {
Abi::Scalar(ref scalar) => scalar.clone(),
Expand Down
20 changes: 15 additions & 5 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1814,20 +1814,30 @@ impl<'tcx> TyS<'tcx> {

pub fn simd_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self.kind {
Adt(def, substs) => {
def.non_enum_variant().fields[0].ty(tcx, substs)
}
Adt(def, substs) => def.non_enum_variant().fields[0].ty(tcx, substs),
_ => bug!("simd_type called on invalid type")
}
}

pub fn simd_size(&self, _cx: TyCtxt<'_>) -> usize {
pub fn simd_size(&self, _tcx: TyCtxt<'tcx>) -> u64 {
// Parameter currently unused, but probably needed in the future to
// allow `#[repr(simd)] struct Simd<T, const N: usize>([T; N]);`.
match self.kind {
Adt(def, _) => def.non_enum_variant().fields.len(),
Adt(def, _) => def.non_enum_variant().fields.len() as u64,
_ => bug!("simd_size called on invalid type")
}
}

pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
match self.kind {
Adt(def, substs) => {
let variant = def.non_enum_variant();
(variant.fields.len() as u64, variant.fields[0].ty(tcx, substs))
}
_ => bug!("simd_size_and_type called on invalid type")
}
}

#[inline]
pub fn is_region_ptr(&self) -> bool {
match self.kind {
Expand Down
27 changes: 14 additions & 13 deletions src/librustc_codegen_llvm/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,8 +1105,8 @@ fn generic_simd_intrinsic(
let m_len = match in_ty.kind {
// Note that this `.unwrap()` crashes for isize/usize, that's sort
// of intentional as there's not currently a use case for that.
ty::Int(i) => i.bit_width().unwrap(),
ty::Uint(i) => i.bit_width().unwrap(),
ty::Int(i) => i.bit_width().unwrap() as u64,
ty::Uint(i) => i.bit_width().unwrap() as u64,
_ => return_error!("`{}` is not an integral type", in_ty),
};
require_simd!(arg_tys[1], "argument");
Expand All @@ -1116,7 +1116,7 @@ fn generic_simd_intrinsic(
m_len, v_len
);
let i1 = bx.type_i1();
let i1xn = bx.type_vector(i1, m_len as u64);
let i1xn = bx.type_vector(i1, m_len);
let m_i1s = bx.bitcast(args[0].immediate(), i1xn);
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
}
Expand Down Expand Up @@ -1160,7 +1160,7 @@ fn generic_simd_intrinsic(
}

if name.starts_with("simd_shuffle") {
let n: usize = name["simd_shuffle".len()..].parse().unwrap_or_else(|_|
let n: u64 = name["simd_shuffle".len()..].parse().unwrap_or_else(|_|
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?"));

require_simd!(ret_ty, "return");
Expand All @@ -1175,7 +1175,7 @@ fn generic_simd_intrinsic(
in_elem, in_ty,
ret_ty, ret_ty.simd_type(tcx));

let total_len = in_len as u128 * 2;
let total_len = u128::from(in_len) * 2;

let vector = args[2].immediate();

Expand Down Expand Up @@ -1251,7 +1251,7 @@ fn generic_simd_intrinsic(
// trailing bits.
let expected_int_bits = in_len.max(8);
match ret_ty.kind {
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (),
ty::Uint(i) if i.bit_width() == Some(expected_int_bits as usize) => (),
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
_ => return_error!(
"bitmask `{}`, expected `u{}`",
ret_ty, expected_int_bits
Expand All @@ -1276,7 +1276,8 @@ fn generic_simd_intrinsic(

// Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position.
let shift_indices = vec![
bx.cx.const_int(bx.type_ix(in_elem_bitwidth as _), (in_elem_bitwidth - 1) as _); in_len
bx.cx.const_int(bx.type_ix(in_elem_bitwidth as _), (in_elem_bitwidth - 1) as _);
in_len as _
];
let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice()));
// Truncate vector to an <i1 x N>
Expand All @@ -1291,7 +1292,7 @@ fn generic_simd_intrinsic(
name: &str,
in_elem: &::rustc::ty::TyS<'_>,
in_ty: &::rustc::ty::TyS<'_>,
in_len: usize,
in_len: u64,
bx: &mut Builder<'a, 'll, 'tcx>,
span: Span,
args: &[OperandRef<'tcx, &'ll Value>],
Expand Down Expand Up @@ -1400,7 +1401,7 @@ fn generic_simd_intrinsic(
// FIXME: use:
// https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Function.h#L182
// https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Intrinsics.h#L81
fn llvm_vector_str(elem_ty: Ty<'_>, vec_len: usize, no_pointers: usize) -> String {
fn llvm_vector_str(elem_ty: Ty<'_>, vec_len: u64, no_pointers: usize) -> String {
let p0s: String = "p0".repeat(no_pointers);
match elem_ty.kind {
ty::Int(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()),
Expand All @@ -1410,7 +1411,7 @@ fn generic_simd_intrinsic(
}
}

fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: Ty<'_>, vec_len: usize,
fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: Ty<'_>, vec_len: u64,
mut no_pointers: usize) -> &'ll Type {
// FIXME: use cx.layout_of(ty).llvm_type() ?
let mut elem_ty = match elem_ty.kind {
Expand All @@ -1423,7 +1424,7 @@ fn generic_simd_intrinsic(
elem_ty = cx.type_ptr_to(elem_ty);
no_pointers -= 1;
}
cx.type_vector(elem_ty, vec_len as u64)
cx.type_vector(elem_ty, vec_len)
}


Expand Down Expand Up @@ -1506,7 +1507,7 @@ fn generic_simd_intrinsic(
// Truncate the mask vector to a vector of i1s:
let (mask, mask_ty) = {
let i1 = bx.type_i1();
let i1xn = bx.type_vector(i1, in_len as u64);
let i1xn = bx.type_vector(i1, in_len);
(bx.trunc(args[2].immediate(), i1xn), i1xn)
};

Expand Down Expand Up @@ -1606,7 +1607,7 @@ fn generic_simd_intrinsic(
// Truncate the mask vector to a vector of i1s:
let (mask, mask_ty) = {
let i1 = bx.type_i1();
let i1xn = bx.type_vector(i1, in_len as u64);
let i1xn = bx.type_vector(i1, in_len);
(bx.trunc(args[2].immediate(), i1xn), i1xn)
};

Expand Down
18 changes: 9 additions & 9 deletions src/librustc_mir/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.copy_op_transmute(args[0], dest)?;
}
"simd_insert" => {
let index = self.read_scalar(args[1])?.to_u32()? as u64;
let scalar = args[2];
let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
let elem = args[2];
let input = args[0];
let (len, e_ty) = self.read_vector_ty(input);
let (len, e_ty) = input.layout.ty.simd_size_and_type(self.tcx.tcx);
assert!(
index < len,
"Index `{}` must be in bounds of vector type `{}`: `[0, {})`",
Expand All @@ -317,24 +317,24 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
dest.layout.ty, input.layout.ty
);
assert_eq!(
scalar.layout.ty, e_ty,
"Scalar type `{}` must match vector element type `{}`",
scalar.layout.ty, e_ty
elem.layout.ty, e_ty,
"Scalar element type `{}` must match vector element type `{}`",
elem.layout.ty, e_ty
);

for i in 0..len {
let place = self.place_field(dest, i)?;
let value = if i == index {
scalar
elem
} else {
self.operand_field(input, i)?
};
self.copy_op(value, place)?;
}
}
"simd_extract" => {
let index = self.read_scalar(args[1])?.to_u32()? as _;
let (len, e_ty) = self.read_vector_ty(args[0]);
let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx.tcx);
assert!(
index < len,
"index `{}` is out-of-bounds of vector type `{}` with length `{}`",
Expand Down
11 changes: 0 additions & 11 deletions src/librustc_mir/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,17 +315,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}

/// Read vector length and element type
pub fn read_vector_ty(
&self, op: OpTy<'tcx, M::PointerTag>
) -> (u64, &rustc::ty::TyS<'tcx>) {
if let layout::Abi::Vector { .. } = op.layout.abi {
(op.layout.ty.simd_size(*self.tcx) as _, op.layout.ty.simd_type(*self.tcx))
} else {
bug!("Type `{}` is not a SIMD vector type", op.layout.ty)
}
}

/// Read a scalar from a place
pub fn read_scalar(
&self,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {

match instance.def {
ty::InstanceDef::Intrinsic(..) => {
assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);

let old_stack = self.cur_frame();
let old_bb = self.frame().block;
M::call_intrinsic(self, span, instance, args, dest, ret, unwind)?;
Expand Down