mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-30 14:01:51 +00:00
Forbid old-style simd_shuffleN
intrinsics
This commit is contained in:
parent
2e6ac7fe5b
commit
4457ef2c6d
@ -117,8 +117,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||
});
|
||||
}
|
||||
|
||||
// simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U
|
||||
_ if intrinsic.as_str().starts_with("simd_shuffle") => {
|
||||
// simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U
|
||||
sym::simd_shuffle => {
|
||||
let (x, y, idx) = match args {
|
||||
[x, y, idx] => (x, y, idx),
|
||||
_ => {
|
||||
@ -133,36 +133,26 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||
return;
|
||||
}
|
||||
|
||||
// If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
|
||||
// If there is no suffix, use the index array length.
|
||||
let n: u16 = if intrinsic == sym::simd_shuffle {
|
||||
// Make sure this is actually an array, since typeck only checks the length-suffixed
|
||||
// version of this intrinsic.
|
||||
let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx));
|
||||
match idx_ty.kind() {
|
||||
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len
|
||||
.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
|
||||
.unwrap_or_else(|| {
|
||||
span_bug!(span, "could not evaluate shuffle index array length")
|
||||
})
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
_ => {
|
||||
fx.tcx.sess.span_err(
|
||||
span,
|
||||
format!(
|
||||
"simd_shuffle index must be an array of `u32`, got `{}`",
|
||||
idx_ty,
|
||||
),
|
||||
);
|
||||
// Prevent verifier error
|
||||
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
|
||||
return;
|
||||
}
|
||||
// Make sure this is actually an array, since typeck only checks the length-suffixed
|
||||
// version of this intrinsic.
|
||||
let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx));
|
||||
let n: u16 = match idx_ty.kind() {
|
||||
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len
|
||||
.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
|
||||
.unwrap_or_else(|| {
|
||||
span_bug!(span, "could not evaluate shuffle index array length")
|
||||
})
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
_ => {
|
||||
fx.tcx.sess.span_err(
|
||||
span,
|
||||
format!("simd_shuffle index must be an array of `u32`, got `{}`", idx_ty),
|
||||
);
|
||||
// Prevent verifier error
|
||||
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// FIXME remove this case
|
||||
intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(x.layout(), y.layout());
|
||||
@ -179,7 +169,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||
let indexes = {
|
||||
use rustc_middle::mir::interpret::*;
|
||||
let idx_const = crate::constant::mir_operand_get_const_val(fx, idx)
|
||||
.expect("simd_shuffle* idx not const");
|
||||
.expect("simd_shuffle idx not const");
|
||||
|
||||
let idx_bytes = match idx_const {
|
||||
ConstValue::ByRef { alloc, offset } => {
|
||||
|
@ -1,11 +1,11 @@
|
||||
#[cfg(feature="master")]
|
||||
use gccjit::{ComparisonOp, UnaryOp};
|
||||
use gccjit::ToRValue;
|
||||
use gccjit::{BinaryOp, RValue, Type};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{ComparisonOp, UnaryOp};
|
||||
|
||||
use rustc_codegen_ssa::base::compare_simd_types;
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_codegen_ssa::errors::ExpectedPointerMutability;
|
||||
use rustc_codegen_ssa::errors::InvalidMonomorphization;
|
||||
use rustc_codegen_ssa::mir::operand::OperandRef;
|
||||
@ -19,7 +19,7 @@ use rustc_span::{sym, Span, Symbol};
|
||||
use rustc_target::abi::Align;
|
||||
|
||||
use crate::builder::Builder;
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(feature = "master")]
|
||||
use crate::context::CodegenCx;
|
||||
|
||||
pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
@ -57,7 +57,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
let arg_tys = sig.inputs();
|
||||
|
||||
if name == sym::simd_select_bitmask {
|
||||
require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] });
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
|
||||
let expected_int_bits = (len.max(8) - 1).next_power_of_two();
|
||||
@ -95,7 +98,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
// NOTE: since the arguments can be vectors of floats, make sure the mask is a vector of
|
||||
// integer.
|
||||
let mask_element_type = bx.type_ix(arg1_element_type.get_size() as u64 * 8);
|
||||
let vector_mask_type = bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64);
|
||||
let vector_mask_type =
|
||||
bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64);
|
||||
|
||||
let mut elements = vec![];
|
||||
let one = bx.context.new_rvalue_one(mask.get_type());
|
||||
@ -149,38 +153,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
// compare them as equal, so bitcast.
|
||||
// FIXME(antoyo): allow comparing vector types as equal in libgccjit.
|
||||
let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type());
|
||||
return Ok(compare_simd_types(
|
||||
bx,
|
||||
arg1,
|
||||
arg2,
|
||||
in_elem,
|
||||
llret_ty,
|
||||
cmp_op,
|
||||
));
|
||||
return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op));
|
||||
}
|
||||
|
||||
if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") {
|
||||
let n: u64 = if stripped.is_empty() {
|
||||
// Make sure this is actually an array, since typeck only checks the length-suffixed
|
||||
// version of this intrinsic.
|
||||
match args[2].layout.ty.kind() {
|
||||
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
|
||||
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|
||||
|| span_bug!(span, "could not evaluate shuffle index array length"),
|
||||
)
|
||||
}
|
||||
_ => return_error!(InvalidMonomorphization::SimdShuffle {
|
||||
span,
|
||||
name,
|
||||
ty: args[2].layout.ty
|
||||
}),
|
||||
if name == sym::simd_shuffle {
|
||||
// Make sure this is actually an array, since typeck only checks the length-suffixed
|
||||
// version of this intrinsic.
|
||||
let n: u64 = match args[2].layout.ty.kind() {
|
||||
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
|
||||
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|
||||
|| span_bug!(span, "could not evaluate shuffle index array length"),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
stripped.parse().unwrap_or_else(|_| {
|
||||
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
|
||||
})
|
||||
_ => return_error!(InvalidMonomorphization::SimdShuffle {
|
||||
span,
|
||||
name,
|
||||
ty: args[2].layout.ty
|
||||
}),
|
||||
};
|
||||
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
@ -202,7 +192,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
if name == sym::simd_insert {
|
||||
require!(
|
||||
in_elem == arg_tys[2],
|
||||
InvalidMonomorphization::InsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] }
|
||||
InvalidMonomorphization::InsertedType {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
out_ty: arg_tys[2]
|
||||
}
|
||||
);
|
||||
let vector = args[0].immediate();
|
||||
let index = args[1].immediate();
|
||||
@ -228,7 +224,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
if name == sym::simd_select {
|
||||
let m_elem_ty = in_elem;
|
||||
let m_len = in_len;
|
||||
require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] });
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
m_len == v_len,
|
||||
@ -241,7 +240,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate()));
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(feature = "master")]
|
||||
if name == sym::simd_cast || name == sym::simd_as {
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
@ -267,19 +266,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
Unsupported,
|
||||
}
|
||||
|
||||
let in_style =
|
||||
match in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Style::Int,
|
||||
ty::Float(_) => Style::Float,
|
||||
_ => Style::Unsupported,
|
||||
};
|
||||
let in_style = match in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Style::Int,
|
||||
ty::Float(_) => Style::Float,
|
||||
_ => Style::Unsupported,
|
||||
};
|
||||
|
||||
let out_style =
|
||||
match out_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Style::Int,
|
||||
ty::Float(_) => Style::Float,
|
||||
_ => Style::Unsupported,
|
||||
};
|
||||
let out_style = match out_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Style::Int,
|
||||
ty::Float(_) => Style::Float,
|
||||
_ => Style::Unsupported,
|
||||
};
|
||||
|
||||
match (in_style, out_style) {
|
||||
(Style::Unsupported, Style::Unsupported) => {
|
||||
@ -294,7 +291,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
out_elem
|
||||
}
|
||||
);
|
||||
},
|
||||
}
|
||||
_ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)),
|
||||
}
|
||||
}
|
||||
@ -342,10 +339,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
|
||||
let mut shift = 0;
|
||||
for i in 0..in_len {
|
||||
let elem = bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32));
|
||||
let elem =
|
||||
bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32));
|
||||
let shifted = elem >> sign_shift;
|
||||
let masked = shifted & one;
|
||||
result = result | (bx.context.new_cast(None, masked, result_type) << bx.context.new_rvalue_from_int(result_type, shift));
|
||||
result = result
|
||||
| (bx.context.new_cast(None, masked, result_type)
|
||||
<< bx.context.new_rvalue_from_int(result_type, shift));
|
||||
shift += 1;
|
||||
}
|
||||
|
||||
@ -394,46 +394,50 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
return Err(());
|
||||
}};
|
||||
}
|
||||
let (elem_ty_str, elem_ty) =
|
||||
if let ty::Float(f) = in_elem.kind() {
|
||||
let elem_ty = bx.cx.type_float_from_ty(*f);
|
||||
match f.bit_width() {
|
||||
32 => ("f", elem_ty),
|
||||
64 => ("", elem_ty),
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::FloatingPointVector { span, name, f_ty: *f, in_ty });
|
||||
}
|
||||
let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() {
|
||||
let elem_ty = bx.cx.type_float_from_ty(*f);
|
||||
match f.bit_width() {
|
||||
32 => ("f", elem_ty),
|
||||
64 => ("", elem_ty),
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::FloatingPointVector {
|
||||
span,
|
||||
name,
|
||||
f_ty: *f,
|
||||
in_ty
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
|
||||
};
|
||||
} else {
|
||||
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
|
||||
};
|
||||
|
||||
let vec_ty = bx.cx.type_vector(elem_ty, in_len);
|
||||
|
||||
let intr_name =
|
||||
match name {
|
||||
sym::simd_ceil => "ceil",
|
||||
sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103
|
||||
sym::simd_fcos => "cos",
|
||||
sym::simd_fexp2 => "exp2",
|
||||
sym::simd_fexp => "exp",
|
||||
sym::simd_flog10 => "log10",
|
||||
sym::simd_flog2 => "log2",
|
||||
sym::simd_flog => "log",
|
||||
sym::simd_floor => "floor",
|
||||
sym::simd_fma => "fma",
|
||||
sym::simd_fpowi => "__builtin_powi",
|
||||
sym::simd_fpow => "pow",
|
||||
sym::simd_fsin => "sin",
|
||||
sym::simd_fsqrt => "sqrt",
|
||||
sym::simd_round => "round",
|
||||
sym::simd_trunc => "trunc",
|
||||
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name })
|
||||
};
|
||||
let intr_name = match name {
|
||||
sym::simd_ceil => "ceil",
|
||||
sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103
|
||||
sym::simd_fcos => "cos",
|
||||
sym::simd_fexp2 => "exp2",
|
||||
sym::simd_fexp => "exp",
|
||||
sym::simd_flog10 => "log10",
|
||||
sym::simd_flog2 => "log2",
|
||||
sym::simd_flog => "log",
|
||||
sym::simd_floor => "floor",
|
||||
sym::simd_fma => "fma",
|
||||
sym::simd_fpowi => "__builtin_powi",
|
||||
sym::simd_fpow => "pow",
|
||||
sym::simd_fsin => "sin",
|
||||
sym::simd_fsqrt => "sqrt",
|
||||
sym::simd_round => "round",
|
||||
sym::simd_trunc => "trunc",
|
||||
_ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
|
||||
};
|
||||
let builtin_name = format!("{}{}", intr_name, elem_ty_str);
|
||||
let funcs = bx.cx.functions.borrow();
|
||||
let function = funcs.get(&builtin_name).unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name));
|
||||
let function = funcs
|
||||
.get(&builtin_name)
|
||||
.unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name));
|
||||
|
||||
// TODO(antoyo): add platform-specific behavior here for architectures that have these
|
||||
// intrinsics as instructions (for instance, gpus)
|
||||
@ -479,8 +483,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args);
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn vector_ty<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, elem_ty: Ty<'tcx>, vec_len: u64) -> Type<'gcc> {
|
||||
#[cfg(feature = "master")]
|
||||
fn vector_ty<'gcc, 'tcx>(
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
elem_ty: Ty<'tcx>,
|
||||
vec_len: u64,
|
||||
) -> Type<'gcc> {
|
||||
// FIXME: use cx.layout_of(ty).llvm_type() ?
|
||||
let elem_ty = match *elem_ty.kind() {
|
||||
ty::Int(v) => cx.type_int_from_ty(v),
|
||||
@ -491,15 +499,22 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
cx.type_vector(elem_ty, vec_len)
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
fn gather<'a, 'gcc, 'tcx>(default: RValue<'gcc>, pointers: RValue<'gcc>, mask: RValue<'gcc>, pointer_count: usize, bx: &mut Builder<'a, 'gcc, 'tcx>, in_len: u64, underlying_ty: Ty<'tcx>, invert: bool) -> RValue<'gcc> {
|
||||
let vector_type =
|
||||
if pointer_count > 1 {
|
||||
bx.context.new_vector_type(bx.usize_type, in_len)
|
||||
}
|
||||
else {
|
||||
vector_ty(bx, underlying_ty, in_len)
|
||||
};
|
||||
#[cfg(feature = "master")]
|
||||
fn gather<'a, 'gcc, 'tcx>(
|
||||
default: RValue<'gcc>,
|
||||
pointers: RValue<'gcc>,
|
||||
mask: RValue<'gcc>,
|
||||
pointer_count: usize,
|
||||
bx: &mut Builder<'a, 'gcc, 'tcx>,
|
||||
in_len: u64,
|
||||
underlying_ty: Ty<'tcx>,
|
||||
invert: bool,
|
||||
) -> RValue<'gcc> {
|
||||
let vector_type = if pointer_count > 1 {
|
||||
bx.context.new_vector_type(bx.usize_type, in_len)
|
||||
} else {
|
||||
vector_ty(bx, underlying_ty, in_len)
|
||||
};
|
||||
let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type();
|
||||
|
||||
let mut values = vec![];
|
||||
@ -530,13 +545,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
|
||||
if invert {
|
||||
bx.shuffle_vector(vector, default, mask)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
bx.shuffle_vector(default, vector, mask)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(feature = "master")]
|
||||
if name == sym::simd_gather {
|
||||
// simd_gather(values: <N x T>, pointers: <N x *_ T>,
|
||||
// mask: <N x i{M}>) -> <N x T>
|
||||
@ -546,8 +560,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
|
||||
// All types must be simd vector types
|
||||
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
|
||||
require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] });
|
||||
require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] });
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
require_simd!(
|
||||
arg_tys[2],
|
||||
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
|
||||
);
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
// Of the same length:
|
||||
@ -641,10 +661,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, false));
|
||||
return Ok(gather(
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
pointer_count,
|
||||
bx,
|
||||
in_len,
|
||||
underlying_ty,
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(feature = "master")]
|
||||
if name == sym::simd_scatter {
|
||||
// simd_scatter(values: <N x T>, pointers: <N x *mut T>,
|
||||
// mask: <N x i{M}>) -> ()
|
||||
@ -654,8 +683,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
|
||||
// All types must be simd vector types
|
||||
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
|
||||
require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] });
|
||||
require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] });
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
require_simd!(
|
||||
arg_tys[2],
|
||||
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
|
||||
);
|
||||
|
||||
// Of the same length:
|
||||
let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
@ -744,17 +779,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
let result = gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, true);
|
||||
let result = gather(
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
pointer_count,
|
||||
bx,
|
||||
in_len,
|
||||
underlying_ty,
|
||||
true,
|
||||
);
|
||||
|
||||
let pointers = args[1].immediate();
|
||||
|
||||
let vector_type =
|
||||
if pointer_count > 1 {
|
||||
bx.context.new_vector_type(bx.usize_type, in_len)
|
||||
}
|
||||
else {
|
||||
vector_ty(bx, underlying_ty, in_len)
|
||||
};
|
||||
let vector_type = if pointer_count > 1 {
|
||||
bx.context.new_vector_type(bx.usize_type, in_len)
|
||||
} else {
|
||||
vector_ty(bx, underlying_ty, in_len)
|
||||
};
|
||||
let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type();
|
||||
|
||||
for i in 0..in_len {
|
||||
@ -809,11 +851,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
let rhs = args[1].immediate();
|
||||
let is_add = name == sym::simd_saturating_add;
|
||||
let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _;
|
||||
let (signed, elem_width, elem_ty) =
|
||||
match *in_elem.kind() {
|
||||
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
|
||||
ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)),
|
||||
_ => {
|
||||
let (signed, elem_width, elem_ty) = match *in_elem.kind() {
|
||||
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
|
||||
ty::Uint(i) => {
|
||||
(false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i))
|
||||
}
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedVectorElementType {
|
||||
span,
|
||||
name,
|
||||
@ -823,77 +866,82 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
}
|
||||
};
|
||||
|
||||
let result =
|
||||
match (signed, is_add) {
|
||||
(false, true) => {
|
||||
let res = lhs + rhs;
|
||||
let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs);
|
||||
res | cmp
|
||||
},
|
||||
(true, true) => {
|
||||
// Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition
|
||||
// TODO(antoyo): improve using conditional operators if possible.
|
||||
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
|
||||
let arg_type = lhs.get_type().unqualified();
|
||||
// TODO(antoyo): convert lhs and rhs to unsigned.
|
||||
let sum = lhs + rhs;
|
||||
let vector_type = arg_type.dyncast_vector().expect("vector type");
|
||||
let unit = vector_type.get_num_units();
|
||||
let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1);
|
||||
let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]);
|
||||
let result = match (signed, is_add) {
|
||||
(false, true) => {
|
||||
let res = lhs + rhs;
|
||||
let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs);
|
||||
res | cmp
|
||||
}
|
||||
(true, true) => {
|
||||
// Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition
|
||||
// TODO(antoyo): improve using conditional operators if possible.
|
||||
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
|
||||
let arg_type = lhs.get_type().unqualified();
|
||||
// TODO(antoyo): convert lhs and rhs to unsigned.
|
||||
let sum = lhs + rhs;
|
||||
let vector_type = arg_type.dyncast_vector().expect("vector type");
|
||||
let unit = vector_type.get_num_units();
|
||||
let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1);
|
||||
let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]);
|
||||
|
||||
let xor1 = lhs ^ rhs;
|
||||
let xor2 = lhs ^ sum;
|
||||
let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2;
|
||||
let mask = and >> width;
|
||||
let xor1 = lhs ^ rhs;
|
||||
let xor2 = lhs ^ sum;
|
||||
let and =
|
||||
bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2;
|
||||
let mask = and >> width;
|
||||
|
||||
let one = bx.context.new_rvalue_one(elem_ty);
|
||||
let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]);
|
||||
let shift1 = ones << width;
|
||||
let shift2 = sum >> width;
|
||||
let mask_min = shift1 ^ shift2;
|
||||
let one = bx.context.new_rvalue_one(elem_ty);
|
||||
let ones =
|
||||
bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]);
|
||||
let shift1 = ones << width;
|
||||
let shift2 = sum >> width;
|
||||
let mask_min = shift1 ^ shift2;
|
||||
|
||||
let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum;
|
||||
let and2 = mask & mask_min;
|
||||
let and1 =
|
||||
bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum;
|
||||
let and2 = mask & mask_min;
|
||||
|
||||
and1 + and2
|
||||
},
|
||||
(false, false) => {
|
||||
let res = lhs - rhs;
|
||||
let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs);
|
||||
res & cmp
|
||||
},
|
||||
(true, false) => {
|
||||
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
|
||||
let arg_type = lhs.get_type().unqualified();
|
||||
// TODO(antoyo): this uses the same algorithm from saturating add, but add the
|
||||
// negative of the right operand. Find a proper subtraction algorithm.
|
||||
let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs);
|
||||
and1 + and2
|
||||
}
|
||||
(false, false) => {
|
||||
let res = lhs - rhs;
|
||||
let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs);
|
||||
res & cmp
|
||||
}
|
||||
(true, false) => {
|
||||
// TODO(antoyo): dyncast_vector should not require a call to unqualified.
|
||||
let arg_type = lhs.get_type().unqualified();
|
||||
// TODO(antoyo): this uses the same algorithm from saturating add, but add the
|
||||
// negative of the right operand. Find a proper subtraction algorithm.
|
||||
let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs);
|
||||
|
||||
// TODO(antoyo): convert lhs and rhs to unsigned.
|
||||
let sum = lhs + rhs;
|
||||
let vector_type = arg_type.dyncast_vector().expect("vector type");
|
||||
let unit = vector_type.get_num_units();
|
||||
let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1);
|
||||
let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]);
|
||||
// TODO(antoyo): convert lhs and rhs to unsigned.
|
||||
let sum = lhs + rhs;
|
||||
let vector_type = arg_type.dyncast_vector().expect("vector type");
|
||||
let unit = vector_type.get_num_units();
|
||||
let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1);
|
||||
let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]);
|
||||
|
||||
let xor1 = lhs ^ rhs;
|
||||
let xor2 = lhs ^ sum;
|
||||
let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2;
|
||||
let mask = and >> width;
|
||||
let xor1 = lhs ^ rhs;
|
||||
let xor2 = lhs ^ sum;
|
||||
let and =
|
||||
bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2;
|
||||
let mask = and >> width;
|
||||
|
||||
let one = bx.context.new_rvalue_one(elem_ty);
|
||||
let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]);
|
||||
let shift1 = ones << width;
|
||||
let shift2 = sum >> width;
|
||||
let mask_min = shift1 ^ shift2;
|
||||
let one = bx.context.new_rvalue_one(elem_ty);
|
||||
let ones =
|
||||
bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]);
|
||||
let shift1 = ones << width;
|
||||
let shift2 = sum >> width;
|
||||
let mask_min = shift1 ^ shift2;
|
||||
|
||||
let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum;
|
||||
let and2 = mask & mask_min;
|
||||
let and1 =
|
||||
bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum;
|
||||
let and2 = mask & mask_min;
|
||||
|
||||
and1 + and2
|
||||
}
|
||||
};
|
||||
and1 + and2
|
||||
}
|
||||
};
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
@ -968,7 +1016,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
1.0
|
||||
);
|
||||
|
||||
|
||||
macro_rules! minmax_red {
|
||||
($name:ident: $int_red:ident, $float_red:ident) => {
|
||||
if name == sym::$name {
|
||||
@ -979,13 +1026,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
return match in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())),
|
||||
ty::Float(_) => Ok(bx.$float_red(args[0].immediate())),
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
name,
|
||||
symbol: sym::$name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty
|
||||
in_elem,
|
||||
ret_ty
|
||||
}),
|
||||
};
|
||||
}
|
||||
@ -1025,7 +1072,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
return match in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {
|
||||
let r = bx.vector_reduce_op(input, $op);
|
||||
Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) })
|
||||
Ok(if !$boolean {
|
||||
r
|
||||
} else {
|
||||
bx.icmp(
|
||||
IntPredicate::IntNE,
|
||||
r,
|
||||
bx.context.new_rvalue_zero(r.get_type()),
|
||||
)
|
||||
})
|
||||
}
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
|
@ -1020,28 +1020,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") {
|
||||
// If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
|
||||
// If there is no suffix, use the index array length.
|
||||
let n: u64 = if stripped.is_empty() {
|
||||
// Make sure this is actually an array, since typeck only checks the length-suffixed
|
||||
// version of this intrinsic.
|
||||
match args[2].layout.ty.kind() {
|
||||
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
|
||||
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|
||||
|| span_bug!(span, "could not evaluate shuffle index array length"),
|
||||
)
|
||||
}
|
||||
_ => return_error!(InvalidMonomorphization::SimdShuffle {
|
||||
span,
|
||||
name,
|
||||
ty: args[2].layout.ty
|
||||
}),
|
||||
if name == sym::simd_shuffle {
|
||||
// Make sure this is actually an array, since typeck only checks the length-suffixed
|
||||
// version of this intrinsic.
|
||||
let n: u64 = match args[2].layout.ty.kind() {
|
||||
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
|
||||
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|
||||
|| span_bug!(span, "could not evaluate shuffle index array length"),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
stripped.parse().unwrap_or_else(|_| {
|
||||
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
|
||||
})
|
||||
_ => return_error!(InvalidMonomorphization::SimdShuffle {
|
||||
span,
|
||||
name,
|
||||
ty: args[2].layout.ty
|
||||
}),
|
||||
};
|
||||
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
@ -862,11 +862,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, arg)| {
|
||||
// The indices passed to simd_shuffle* in the
|
||||
// The indices passed to simd_shuffle in the
|
||||
// third argument must be constant. This is
|
||||
// checked by const-qualification, which also
|
||||
// promotes any complex rvalues to constants.
|
||||
if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
|
||||
if i == 2 && intrinsic == sym::simd_shuffle {
|
||||
if let mir::Operand::Constant(constant) = arg {
|
||||
let (llval, ty) = self.simd_shuffle_indices(&bx, constant);
|
||||
return OperandRef {
|
||||
|
@ -16,7 +16,7 @@ extern "platform-intrinsic" {
|
||||
The `simd_shuffle` function needs the length of the array passed as
|
||||
last parameter in its name. Example:
|
||||
|
||||
```
|
||||
```ignore (no longer compiles)
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
|
@ -567,20 +567,6 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
|
||||
| sym::simd_reduce_min_nanless
|
||||
| sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
|
||||
sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)),
|
||||
name if name.as_str().starts_with("simd_shuffle") => {
|
||||
match name.as_str()["simd_shuffle".len()..].parse() {
|
||||
Ok(n) => {
|
||||
let params = vec![param(0), param(0), Ty::new_array(tcx, tcx.types.u32, n)];
|
||||
(2, params, param(1))
|
||||
}
|
||||
Err(_) => {
|
||||
let msg =
|
||||
format!("unrecognized platform-specific intrinsic function: `{name}`");
|
||||
tcx.sess.struct_span_err(it.span, msg).emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let msg = format!("unrecognized platform-specific intrinsic function: `{name}`");
|
||||
tcx.sess.struct_span_err(it.span, msg).emit();
|
||||
|
@ -305,7 +305,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||
terminator.kind = TerminatorKind::Unreachable;
|
||||
}
|
||||
}
|
||||
_ if intrinsic_name.as_str().starts_with("simd_shuffle") => {
|
||||
sym::simd_shuffle => {
|
||||
validate_simd_shuffle(tcx, args, terminator.source_info.span);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -6,13 +6,13 @@
|
||||
struct I32x2(i32, i32);
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
|
||||
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
const IDX: [u32; 2] = [0, 0];
|
||||
let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX);
|
||||
let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX);
|
||||
let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX);
|
||||
let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX);
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,7 @@ extern "platform-intrinsic" {
|
||||
fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
|
||||
fn simd_extract<T, E>(x: T, idx: u32) -> E;
|
||||
|
||||
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
|
||||
fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
|
||||
fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
|
||||
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
|
||||
}
|
||||
|
||||
macro_rules! all_eq {
|
||||
@ -83,19 +81,19 @@ fn main() {
|
||||
let y4 = i32x4(140, 141, 142, 143);
|
||||
let y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187);
|
||||
unsafe {
|
||||
all_eq!(simd_shuffle2(x2, y2, const { [3u32, 0] }), i32x2(121, 20));
|
||||
all_eq!(simd_shuffle4(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120));
|
||||
all_eq!(simd_shuffle8(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }),
|
||||
all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2(121, 20));
|
||||
all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120));
|
||||
all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }),
|
||||
i32x8(121, 20, 21, 120, 21, 120, 121, 20));
|
||||
|
||||
all_eq!(simd_shuffle2(x4, y4, const { [7u32, 2] }), i32x2(143, 42));
|
||||
all_eq!(simd_shuffle4(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40));
|
||||
all_eq!(simd_shuffle8(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }),
|
||||
all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2(143, 42));
|
||||
all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40));
|
||||
all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }),
|
||||
i32x8(143, 42, 141, 40, 43, 142, 140, 41));
|
||||
|
||||
all_eq!(simd_shuffle2(x8, y8, const { [11u32, 5] }), i32x2(183, 85));
|
||||
all_eq!(simd_shuffle4(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80));
|
||||
all_eq!(simd_shuffle8(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }),
|
||||
all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2(183, 85));
|
||||
all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80));
|
||||
all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }),
|
||||
i32x8(183, 85, 187, 80, 83, 180, 184, 81));
|
||||
}
|
||||
|
||||
|
@ -34,9 +34,7 @@ extern "platform-intrinsic" {
|
||||
fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
|
||||
fn simd_extract<T, E>(x: T, idx: u32) -> E;
|
||||
|
||||
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
|
||||
fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
|
||||
fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
|
||||
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -51,27 +49,27 @@ fn main() {
|
||||
//~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32`
|
||||
|
||||
const IDX2: [u32; 2] = [0; 2];
|
||||
simd_shuffle2::<i32, i32>(0, 0, IDX2);
|
||||
simd_shuffle::<i32, _, i32>(0, 0, IDX2);
|
||||
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
|
||||
const IDX4: [u32; 4] = [0; 4];
|
||||
simd_shuffle4::<i32, i32>(0, 0, IDX4);
|
||||
simd_shuffle::<i32, _, i32>(0, 0, IDX4);
|
||||
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
|
||||
const IDX8: [u32; 8] = [0; 8];
|
||||
simd_shuffle8::<i32, i32>(0, 0, IDX8);
|
||||
simd_shuffle::<i32, _, i32>(0, 0, IDX8);
|
||||
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
|
||||
|
||||
simd_shuffle2::<_, f32x2>(x, x, IDX2);
|
||||
simd_shuffle::<_, _, f32x2>(x, x, IDX2);
|
||||
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
|
||||
simd_shuffle4::<_, f32x4>(x, x, IDX4);
|
||||
simd_shuffle::<_, _, f32x4>(x, x, IDX4);
|
||||
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
|
||||
simd_shuffle8::<_, f32x8>(x, x, IDX8);
|
||||
simd_shuffle::<_, _, f32x8>(x, x, IDX8);
|
||||
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
|
||||
|
||||
simd_shuffle2::<_, i32x8>(x, x, IDX2);
|
||||
simd_shuffle::<_, _, i32x8>(x, x, IDX2);
|
||||
//~^ ERROR expected return type of length 2, found `i32x8` with length 8
|
||||
simd_shuffle4::<_, i32x8>(x, x, IDX4);
|
||||
simd_shuffle::<_, _, i32x8>(x, x, IDX4);
|
||||
//~^ ERROR expected return type of length 4, found `i32x8` with length 8
|
||||
simd_shuffle8::<_, i32x2>(x, x, IDX8);
|
||||
simd_shuffle::<_, _, i32x2>(x, x, IDX8);
|
||||
//~^ ERROR expected return type of length 8, found `i32x2` with length 2
|
||||
}
|
||||
}
|
||||
|
@ -1,74 +1,74 @@
|
||||
error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32`
|
||||
--> $DIR/generic-elements.rs:46:9
|
||||
--> $DIR/generic-elements.rs:44:9
|
||||
|
|
||||
LL | simd_insert(0, 0, 0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64`
|
||||
--> $DIR/generic-elements.rs:48:9
|
||||
--> $DIR/generic-elements.rs:46:9
|
||||
|
|
||||
LL | simd_insert(x, 0, 1.0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32`
|
||||
--> $DIR/generic-elements.rs:50:9
|
||||
--> $DIR/generic-elements.rs:48:9
|
||||
|
|
||||
LL | simd_extract::<_, f32>(x, 0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32`
|
||||
--> $DIR/generic-elements.rs:54:9
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
|
||||
--> $DIR/generic-elements.rs:52:9
|
||||
|
|
||||
LL | simd_shuffle2::<i32, i32>(0, 0, IDX2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | simd_shuffle::<i32, _, i32>(0, 0, IDX2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32`
|
||||
--> $DIR/generic-elements.rs:57:9
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
|
||||
--> $DIR/generic-elements.rs:55:9
|
||||
|
|
||||
LL | simd_shuffle4::<i32, i32>(0, 0, IDX4);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | simd_shuffle::<i32, _, i32>(0, 0, IDX4);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32`
|
||||
--> $DIR/generic-elements.rs:60:9
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
|
||||
--> $DIR/generic-elements.rs:58:9
|
||||
|
|
||||
LL | simd_shuffle8::<i32, i32>(0, 0, IDX8);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | simd_shuffle::<i32, _, i32>(0, 0, IDX8);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
|
||||
--> $DIR/generic-elements.rs:61:9
|
||||
|
|
||||
LL | simd_shuffle::<_, _, f32x2>(x, x, IDX2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
|
||||
--> $DIR/generic-elements.rs:63:9
|
||||
|
|
||||
LL | simd_shuffle2::<_, f32x2>(x, x, IDX2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | simd_shuffle::<_, _, f32x4>(x, x, IDX4);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
|
||||
--> $DIR/generic-elements.rs:65:9
|
||||
|
|
||||
LL | simd_shuffle4::<_, f32x4>(x, x, IDX4);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | simd_shuffle::<_, _, f32x8>(x, x, IDX8);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
|
||||
--> $DIR/generic-elements.rs:67:9
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8
|
||||
--> $DIR/generic-elements.rs:68:9
|
||||
|
|
||||
LL | simd_shuffle8::<_, f32x8>(x, x, IDX8);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | simd_shuffle::<_, _, i32x8>(x, x, IDX2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8
|
||||
--> $DIR/generic-elements.rs:70:9
|
||||
|
|
||||
LL | simd_shuffle2::<_, i32x8>(x, x, IDX2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | simd_shuffle::<_, _, i32x8>(x, x, IDX4);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x8` with length 8
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2
|
||||
--> $DIR/generic-elements.rs:72:9
|
||||
|
|
||||
LL | simd_shuffle4::<_, i32x8>(x, x, IDX4);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2
|
||||
--> $DIR/generic-elements.rs:74:9
|
||||
|
|
||||
LL | simd_shuffle8::<_, i32x2>(x, x, IDX8);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | simd_shuffle::<_, _, i32x2>(x, x, IDX8);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#![feature(platform_intrinsics, repr_simd)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
|
||||
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
|
||||
}
|
||||
|
||||
#[repr(simd)]
|
||||
@ -22,5 +22,5 @@ fn main() {
|
||||
#[inline(always)]
|
||||
unsafe fn inline_me() -> Simd2 {
|
||||
const IDX: [u32; 2] = [0, 3];
|
||||
simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX)
|
||||
simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#![feature(platform_intrinsics, repr_simd)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
|
||||
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
|
||||
}
|
||||
|
||||
#[repr(simd)]
|
||||
@ -16,7 +16,7 @@ struct Simd2(u8, u8);
|
||||
fn main() {
|
||||
unsafe {
|
||||
const IDX: [u32; 2] = [0, 1];
|
||||
let p_res: Simd2 = simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX);
|
||||
let p_res: Simd2 = simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX);
|
||||
let a_res: Simd2 = inline_me();
|
||||
|
||||
assert_10_11(p_res);
|
||||
@ -38,5 +38,5 @@ fn assert_10_13(x: Simd2) {
|
||||
#[inline(always)]
|
||||
unsafe fn inline_me() -> Simd2 {
|
||||
const IDX: [u32; 2] = [0, 3];
|
||||
simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX)
|
||||
simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX)
|
||||
}
|
||||
|
@ -29,12 +29,7 @@ struct u8x32([u8; 32]);
|
||||
struct u8x64([u8; 64]);
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
pub fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
|
||||
pub fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
|
||||
pub fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
|
||||
pub fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
|
||||
pub fn simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U;
|
||||
pub fn simd_shuffle64<T, U>(x: T, y: T, idx: [u32; 64]) -> U;
|
||||
pub fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
|
||||
}
|
||||
|
||||
// Test vectors by lane size. Since LLVM does not distinguish between a shuffle
|
||||
@ -58,22 +53,22 @@ macro_rules! test_shuffle_lanes {
|
||||
}
|
||||
}
|
||||
}
|
||||
//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle2` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle4` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle8` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle16` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle32` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle64` intrinsic
|
||||
//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
|
||||
//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic
|
||||
// Because the test is mostly embedded in a macro, all the errors have the same origin point.
|
||||
// And unfortunately, standard comments, as in the UI test harness, disappear in macros!
|
||||
|
||||
fn main() {
|
||||
test_shuffle_lanes!(2, u8x2, simd_shuffle2);
|
||||
test_shuffle_lanes!(4, u8x4, simd_shuffle4);
|
||||
test_shuffle_lanes!(8, u8x8, simd_shuffle8);
|
||||
test_shuffle_lanes!(16, u8x16, simd_shuffle16);
|
||||
test_shuffle_lanes!(32, u8x32, simd_shuffle32);
|
||||
test_shuffle_lanes!(64, u8x64, simd_shuffle64);
|
||||
test_shuffle_lanes!(2, u8x2, simd_shuffle);
|
||||
test_shuffle_lanes!(4, u8x4, simd_shuffle);
|
||||
test_shuffle_lanes!(8, u8x8, simd_shuffle);
|
||||
test_shuffle_lanes!(16, u8x16, simd_shuffle);
|
||||
test_shuffle_lanes!(32, u8x32, simd_shuffle);
|
||||
test_shuffle_lanes!(64, u8x64, simd_shuffle);
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
|
||||
|
@ -1,71 +1,71 @@
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: shuffle index #0 is out of bounds (limit 4)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:51:21
|
||||
|
|
||||
LL | $y(vec1, vec2, ARR)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | test_shuffle_lanes!(2, u8x2, simd_shuffle2);
|
||||
| ------------------------------------------- in this macro invocation
|
||||
LL | test_shuffle_lanes!(2, u8x2, simd_shuffle);
|
||||
| ------------------------------------------ in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: shuffle index #0 is out of bounds (limit 8)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 8)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:51:21
|
||||
|
|
||||
LL | $y(vec1, vec2, ARR)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | test_shuffle_lanes!(4, u8x4, simd_shuffle4);
|
||||
| ------------------------------------------- in this macro invocation
|
||||
LL | test_shuffle_lanes!(4, u8x4, simd_shuffle);
|
||||
| ------------------------------------------ in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: shuffle index #0 is out of bounds (limit 16)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 16)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:51:21
|
||||
|
|
||||
LL | $y(vec1, vec2, ARR)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | test_shuffle_lanes!(8, u8x8, simd_shuffle8);
|
||||
| ------------------------------------------- in this macro invocation
|
||||
LL | test_shuffle_lanes!(8, u8x8, simd_shuffle);
|
||||
| ------------------------------------------ in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle16` intrinsic: shuffle index #0 is out of bounds (limit 32)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 32)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:51:21
|
||||
|
|
||||
LL | $y(vec1, vec2, ARR)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | test_shuffle_lanes!(16, u8x16, simd_shuffle16);
|
||||
| ---------------------------------------------- in this macro invocation
|
||||
LL | test_shuffle_lanes!(16, u8x16, simd_shuffle);
|
||||
| -------------------------------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle32` intrinsic: shuffle index #0 is out of bounds (limit 64)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 64)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:51:21
|
||||
|
|
||||
LL | $y(vec1, vec2, ARR)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | test_shuffle_lanes!(32, u8x32, simd_shuffle32);
|
||||
| ---------------------------------------------- in this macro invocation
|
||||
LL | test_shuffle_lanes!(32, u8x32, simd_shuffle);
|
||||
| -------------------------------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle64` intrinsic: shuffle index #0 is out of bounds (limit 128)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:56:21
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 128)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:51:21
|
||||
|
|
||||
LL | $y(vec1, vec2, ARR)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | test_shuffle_lanes!(64, u8x64, simd_shuffle64);
|
||||
| ---------------------------------------------- in this macro invocation
|
||||
LL | test_shuffle_lanes!(64, u8x64, simd_shuffle);
|
||||
| -------------------------------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4)
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:84:23
|
||||
--> $DIR/shuffle-not-out-of-bounds.rs:79:23
|
||||
|
|
||||
LL | let _: u8x2 = simd_shuffle(v, v, I);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
|
||||
fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -16,7 +15,7 @@ extern "platform-intrinsic" {
|
||||
struct Simd<T, const N: usize>([T; N]);
|
||||
|
||||
pub unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U {
|
||||
simd_shuffle16(x, y, IDX)
|
||||
simd_shuffle(x, y, IDX)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
Loading…
Reference in New Issue
Block a user