Implement floating point SIMD intrinsics over all vector widths, and limit SIMD vector lengths.
This commit is contained in:
parent
fd85ca02f6
commit
07db2bfe39
10 changed files with 141 additions and 199 deletions
|
@ -498,25 +498,6 @@ impl CodegenCx<'b, 'tcx> {
|
||||||
let t_f32 = self.type_f32();
|
let t_f32 = self.type_f32();
|
||||||
let t_f64 = self.type_f64();
|
let t_f64 = self.type_f64();
|
||||||
|
|
||||||
macro_rules! vector_types {
|
|
||||||
($id_out:ident: $elem_ty:ident, $len:expr) => {
|
|
||||||
let $id_out = self.type_vector($elem_ty, $len);
|
|
||||||
};
|
|
||||||
($($id_out:ident: $elem_ty:ident, $len:expr;)*) => {
|
|
||||||
$(vector_types!($id_out: $elem_ty, $len);)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vector_types! {
|
|
||||||
t_v2f32: t_f32, 2;
|
|
||||||
t_v4f32: t_f32, 4;
|
|
||||||
t_v8f32: t_f32, 8;
|
|
||||||
t_v16f32: t_f32, 16;
|
|
||||||
|
|
||||||
t_v2f64: t_f64, 2;
|
|
||||||
t_v4f64: t_f64, 4;
|
|
||||||
t_v8f64: t_f64, 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f32", fn(t_f32) -> t_i32);
|
ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f32", fn(t_f32) -> t_i32);
|
||||||
ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f64", fn(t_f64) -> t_i32);
|
ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f64", fn(t_f64) -> t_i32);
|
||||||
ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f32", fn(t_f32) -> t_i64);
|
ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f32", fn(t_f32) -> t_i64);
|
||||||
|
@ -540,124 +521,40 @@ impl CodegenCx<'b, 'tcx> {
|
||||||
ifn!("llvm.sideeffect", fn() -> void);
|
ifn!("llvm.sideeffect", fn() -> void);
|
||||||
|
|
||||||
ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
|
ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
|
||||||
ifn!("llvm.powi.v2f32", fn(t_v2f32, t_i32) -> t_v2f32);
|
|
||||||
ifn!("llvm.powi.v4f32", fn(t_v4f32, t_i32) -> t_v4f32);
|
|
||||||
ifn!("llvm.powi.v8f32", fn(t_v8f32, t_i32) -> t_v8f32);
|
|
||||||
ifn!("llvm.powi.v16f32", fn(t_v16f32, t_i32) -> t_v16f32);
|
|
||||||
ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
|
ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
|
||||||
ifn!("llvm.powi.v2f64", fn(t_v2f64, t_i32) -> t_v2f64);
|
|
||||||
ifn!("llvm.powi.v4f64", fn(t_v4f64, t_i32) -> t_v4f64);
|
|
||||||
ifn!("llvm.powi.v8f64", fn(t_v8f64, t_i32) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
|
ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
|
||||||
ifn!("llvm.pow.v2f32", fn(t_v2f32, t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.pow.v4f32", fn(t_v4f32, t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.pow.v8f32", fn(t_v8f32, t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.pow.v16f32", fn(t_v16f32, t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
|
ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
|
||||||
ifn!("llvm.pow.v2f64", fn(t_v2f64, t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.pow.v4f64", fn(t_v4f64, t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.pow.v8f64", fn(t_v8f64, t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.sqrt.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.sqrt.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.sqrt.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.sqrt.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.sqrt.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.sqrt.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.sqrt.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.sin.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.sin.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.sin.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.sin.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.sin.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.sin.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.sin.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.sin.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.sin.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.cos.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.cos.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.cos.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.cos.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.cos.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.cos.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.cos.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.cos.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.cos.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.exp.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.exp.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.exp.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.exp.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.exp.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.exp.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.exp.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.exp.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.exp.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.exp2.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.exp2.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.exp2.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.exp2.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.exp2.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.exp2.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.exp2.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.log.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.log.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.log.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.log.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.log.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.log.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.log.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.log.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.log.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.log10.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.log10.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.log10.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.log10.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.log10.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.log10.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.log10.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.log10.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.log10.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.log2.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.log2.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.log2.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.log2.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.log2.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.log2.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.log2.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.log2.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.log2.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32);
|
ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32);
|
||||||
ifn!("llvm.fma.v2f32", fn(t_v2f32, t_v2f32, t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.fma.v4f32", fn(t_v4f32, t_v4f32, t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.fma.v8f32", fn(t_v8f32, t_v8f32, t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.fma.v16f32", fn(t_v16f32, t_v16f32, t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64);
|
ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64);
|
||||||
ifn!("llvm.fma.v2f64", fn(t_v2f64, t_v2f64, t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.fma.v4f64", fn(t_v4f64, t_v4f64, t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.fma.v8f64", fn(t_v8f64, t_v8f64, t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.fabs.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.fabs.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.fabs.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.fabs.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.fabs.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.fabs.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.fabs.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.minnum.f32", fn(t_f32, t_f32) -> t_f32);
|
ifn!("llvm.minnum.f32", fn(t_f32, t_f32) -> t_f32);
|
||||||
ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64);
|
ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64);
|
||||||
|
@ -665,24 +562,10 @@ impl CodegenCx<'b, 'tcx> {
|
||||||
ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64);
|
ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64);
|
||||||
|
|
||||||
ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.floor.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.floor.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.floor.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.floor.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.floor.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.floor.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.floor.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.ceil.v2f32", fn(t_v2f32) -> t_v2f32);
|
|
||||||
ifn!("llvm.ceil.v4f32", fn(t_v4f32) -> t_v4f32);
|
|
||||||
ifn!("llvm.ceil.v8f32", fn(t_v8f32) -> t_v8f32);
|
|
||||||
ifn!("llvm.ceil.v16f32", fn(t_v16f32) -> t_v16f32);
|
|
||||||
ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
|
||||||
ifn!("llvm.ceil.v2f64", fn(t_v2f64) -> t_v2f64);
|
|
||||||
ifn!("llvm.ceil.v4f64", fn(t_v4f64) -> t_v4f64);
|
|
||||||
ifn!("llvm.ceil.v8f64", fn(t_v8f64) -> t_v8f64);
|
|
||||||
|
|
||||||
ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
|
ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
|
||||||
ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
|
ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
|
||||||
|
|
|
@ -1009,7 +1009,7 @@ fn generic_simd_intrinsic(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simd_simple_float_intrinsic(
|
fn simd_simple_float_intrinsic(
|
||||||
name: &str,
|
name: Symbol,
|
||||||
in_elem: &::rustc_middle::ty::TyS<'_>,
|
in_elem: &::rustc_middle::ty::TyS<'_>,
|
||||||
in_ty: &::rustc_middle::ty::TyS<'_>,
|
in_ty: &::rustc_middle::ty::TyS<'_>,
|
||||||
in_len: u64,
|
in_len: u64,
|
||||||
|
@ -1036,93 +1036,70 @@ fn generic_simd_intrinsic(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ety = match in_elem.kind() {
|
|
||||||
ty::Float(f) if f.bit_width() == 32 => {
|
let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() {
|
||||||
if in_len < 2 || in_len > 16 {
|
let elem_ty = bx.cx.type_float_from_ty(*f);
|
||||||
|
match f.bit_width() {
|
||||||
|
32 => ("f32", elem_ty),
|
||||||
|
64 => ("f64", elem_ty),
|
||||||
|
_ => {
|
||||||
return_error!(
|
return_error!(
|
||||||
"unsupported floating-point vector `{}` with length `{}` \
|
"unsupported element type `{}` of floating-point vector `{}`",
|
||||||
out-of-range [2, 16]",
|
f.name_str(),
|
||||||
in_ty,
|
in_ty
|
||||||
in_len
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
"f32"
|
|
||||||
}
|
|
||||||
ty::Float(f) if f.bit_width() == 64 => {
|
|
||||||
if in_len < 2 || in_len > 8 {
|
|
||||||
return_error!(
|
|
||||||
"unsupported floating-point vector `{}` with length `{}` \
|
|
||||||
out-of-range [2, 8]",
|
|
||||||
in_ty,
|
|
||||||
in_len
|
|
||||||
);
|
|
||||||
}
|
|
||||||
"f64"
|
|
||||||
}
|
|
||||||
ty::Float(f) => {
|
|
||||||
return_error!(
|
|
||||||
"unsupported element type `{}` of floating-point vector `{}`",
|
|
||||||
f.name_str(),
|
|
||||||
in_ty
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return_error!("`{}` is not a floating-point type", in_ty);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return_error!("`{}` is not a floating-point type", in_ty);
|
||||||
};
|
};
|
||||||
|
|
||||||
let llvm_name = &format!("llvm.{0}.v{1}{2}", name, in_len, ety);
|
let vec_ty = bx.type_vector(elem_ty, in_len);
|
||||||
let intrinsic = bx.get_intrinsic(&llvm_name);
|
|
||||||
let c =
|
let (intr_name, fn_ty) = match name {
|
||||||
bx.call(intrinsic, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None);
|
sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)),
|
||||||
|
sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)),
|
||||||
|
sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
|
||||||
|
_ => return_error!("unrecognized intrinsic `{}`", name),
|
||||||
|
};
|
||||||
|
|
||||||
|
let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str);
|
||||||
|
let f = bx.declare_cfn(&llvm_name, fn_ty);
|
||||||
|
llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No);
|
||||||
|
let c = bx.call(f, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None);
|
||||||
unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) };
|
unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) };
|
||||||
Ok(c)
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
match name {
|
if std::matches!(
|
||||||
sym::simd_fsqrt => {
|
name,
|
||||||
return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args);
|
sym::simd_fsqrt
|
||||||
}
|
| sym::simd_fsin
|
||||||
sym::simd_fsin => {
|
| sym::simd_fcos
|
||||||
return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args);
|
| sym::simd_fabs
|
||||||
}
|
| sym::simd_floor
|
||||||
sym::simd_fcos => {
|
| sym::simd_ceil
|
||||||
return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args);
|
| sym::simd_fexp
|
||||||
}
|
| sym::simd_fexp2
|
||||||
sym::simd_fabs => {
|
| sym::simd_flog10
|
||||||
return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args);
|
| sym::simd_flog2
|
||||||
}
|
| sym::simd_flog
|
||||||
sym::simd_floor => {
|
| sym::simd_fpowi
|
||||||
return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args);
|
| sym::simd_fpow
|
||||||
}
|
| sym::simd_fma
|
||||||
sym::simd_ceil => {
|
) {
|
||||||
return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args);
|
return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args);
|
||||||
}
|
|
||||||
sym::simd_fexp => {
|
|
||||||
return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
sym::simd_fexp2 => {
|
|
||||||
return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
sym::simd_flog10 => {
|
|
||||||
return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
sym::simd_flog2 => {
|
|
||||||
return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
sym::simd_flog => {
|
|
||||||
return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
sym::simd_fpowi => {
|
|
||||||
return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
sym::simd_fpow => {
|
|
||||||
return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
sym::simd_fma => {
|
|
||||||
return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args);
|
|
||||||
}
|
|
||||||
_ => { /* fallthrough */ }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: use:
|
// FIXME: use:
|
||||||
|
|
|
@ -694,10 +694,17 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// SIMD vectors of zero length are not supported.
|
// SIMD vectors of zero length are not supported.
|
||||||
|
// Additionally, lengths are capped at 2^16 as a fixed maximum backends must
|
||||||
|
// support.
|
||||||
//
|
//
|
||||||
// Can't be caught in typeck if the array length is generic.
|
// Can't be caught in typeck if the array length is generic.
|
||||||
if e_len == 0 {
|
if e_len == 0 {
|
||||||
tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
|
tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
|
||||||
|
} else if e_len > 65536 {
|
||||||
|
tcx.sess.fatal(&format!(
|
||||||
|
"monomorphising SIMD type `{}` of length greater than 65536",
|
||||||
|
ty,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the ABI of the element type:
|
// Compute the ABI of the element type:
|
||||||
|
|
|
@ -1098,6 +1098,28 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
|
||||||
.emit();
|
.emit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let len = if let ty::Array(_ty, c) = e.kind() {
|
||||||
|
c.try_eval_usize(tcx, tcx.param_env(def.did))
|
||||||
|
} else {
|
||||||
|
Some(fields.len() as u64)
|
||||||
|
};
|
||||||
|
if let Some(len) = len {
|
||||||
|
if len == 0 {
|
||||||
|
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
|
||||||
|
return;
|
||||||
|
} else if len > 65536 {
|
||||||
|
struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
sp,
|
||||||
|
E0075,
|
||||||
|
"SIMD vector cannot have more than 65536 elements"
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match e.kind() {
|
match e.kind() {
|
||||||
ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
|
ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
|
||||||
_ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
|
_ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
|
||||||
|
|
12
src/test/ui/simd-type-generic-monomorphisation-empty.rs
Normal file
12
src/test/ui/simd-type-generic-monomorphisation-empty.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// build-fail
|
||||||
|
|
||||||
|
#![feature(repr_simd, platform_intrinsics)]
|
||||||
|
|
||||||
|
// error-pattern:monomorphising SIMD type `Simd<0_usize>` of zero length
|
||||||
|
|
||||||
|
#[repr(simd)]
|
||||||
|
struct Simd<const N: usize>([f32; N]);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = Simd::<0>([]);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
error: monomorphising SIMD type `Simd<0_usize>` of zero length
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
12
src/test/ui/simd-type-generic-monomorphisation-oversized.rs
Normal file
12
src/test/ui/simd-type-generic-monomorphisation-oversized.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// build-fail
|
||||||
|
|
||||||
|
#![feature(repr_simd, platform_intrinsics)]
|
||||||
|
|
||||||
|
// error-pattern:monomorphising SIMD type `Simd<65537_usize>` of length greater than 65536
|
||||||
|
|
||||||
|
#[repr(simd)]
|
||||||
|
struct Simd<const N: usize>([f32; N]);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = Simd::<65537>([0.; 65537]);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
error: monomorphising SIMD type `Simd<65537_usize>` of length greater than 65536
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
#[repr(simd)]
|
#[repr(simd)]
|
||||||
struct empty; //~ ERROR SIMD vector cannot be empty
|
struct empty; //~ ERROR SIMD vector cannot be empty
|
||||||
|
|
||||||
|
#[repr(simd)]
|
||||||
|
struct empty2([f32; 0]); //~ ERROR SIMD vector cannot be empty
|
||||||
|
|
||||||
#[repr(simd)]
|
#[repr(simd)]
|
||||||
struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous
|
struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous
|
||||||
|
|
||||||
|
@ -17,4 +20,10 @@ struct FooV(Foo, Foo); //~ ERROR SIMD vector element type should be a primitive
|
||||||
#[repr(simd)]
|
#[repr(simd)]
|
||||||
struct FooV2([Foo; 2]); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type
|
struct FooV2([Foo; 2]); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type
|
||||||
|
|
||||||
|
#[repr(simd)]
|
||||||
|
struct TooBig([f32; 65537]); //~ ERROR SIMD vector cannot have more than 65536 elements
|
||||||
|
|
||||||
|
#[repr(simd)]
|
||||||
|
struct JustRight([u128; 65536]);
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,25 +4,37 @@ error[E0075]: SIMD vector cannot be empty
|
||||||
LL | struct empty;
|
LL | struct empty;
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0076]: SIMD vector should be homogeneous
|
error[E0075]: SIMD vector cannot be empty
|
||||||
--> $DIR/simd-type.rs:10:1
|
--> $DIR/simd-type.rs:10:1
|
||||||
|
|
|
|
||||||
|
LL | struct empty2([f32; 0]);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0076]: SIMD vector should be homogeneous
|
||||||
|
--> $DIR/simd-type.rs:13:1
|
||||||
|
|
|
||||||
LL | struct i64f64(i64, f64);
|
LL | struct i64f64(i64, f64);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type
|
||||||
|
|
||||||
error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type
|
error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type
|
||||||
--> $DIR/simd-type.rs:15:1
|
--> $DIR/simd-type.rs:18:1
|
||||||
|
|
|
|
||||||
LL | struct FooV(Foo, Foo);
|
LL | struct FooV(Foo, Foo);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type
|
error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type
|
||||||
--> $DIR/simd-type.rs:18:1
|
--> $DIR/simd-type.rs:21:1
|
||||||
|
|
|
|
||||||
LL | struct FooV2([Foo; 2]);
|
LL | struct FooV2([Foo; 2]);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error[E0075]: SIMD vector cannot have more than 65536 elements
|
||||||
|
--> $DIR/simd-type.rs:24:1
|
||||||
|
|
|
||||||
|
LL | struct TooBig([f32; 65537]);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0075, E0076, E0077.
|
Some errors have detailed explanations: E0075, E0076, E0077.
|
||||||
For more information about an error, try `rustc --explain E0075`.
|
For more information about an error, try `rustc --explain E0075`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue