Skip to content

Commit

Permalink
Rollup merge of rust-lang#66468 - RalfJung:simd-cleanup, r=oli-obk
Browse files Browse the repository at this point in the history
Cleanup Miri SIMD intrinsics

r? @oli-obk @eddyb Cc @gnzlbg
  • Loading branch information
Centril authored Nov 21, 2019
2 parents 3fcba01 + 5e115a2 commit 4aceeff
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 39 deletions.
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 @@ -1813,20 +1813,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) => (),
_ => 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 @@ -316,17 +316,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

0 comments on commit 4aceeff

Please sign in to comment.