Add simd_saturating_{add,sub} intrinsics

This commit is contained in:
gnzlbg 2019-02-08 15:23:48 +01:00
parent d173180116
commit 94defa9364
7 changed files with 894 additions and 8 deletions

View file

@ -510,14 +510,24 @@ impl CodegenCx<'b, 'tcx> {
let t_f32 = self.type_f32();
let t_f64 = self.type_f64();
let t_v2f32 = self.type_vector(t_f32, 2);
let t_v4f32 = self.type_vector(t_f32, 4);
let t_v8f32 = self.type_vector(t_f32, 8);
let t_v16f32 = self.type_vector(t_f32, 16);
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;
let t_v2f64 = self.type_vector(t_f64, 2);
let t_v4f64 = self.type_vector(t_f64, 4);
let t_v8f64 = self.type_vector(t_f64, 8);
t_v2f64: t_f64, 2;
t_v4f64: t_f64, 4;
t_v8f64: t_f64, 8;
}
ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);

View file

@ -1850,7 +1850,52 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
simd_xor: Uint, Int => xor;
simd_fmax: Float => maxnum;
simd_fmin: Float => minnum;
}
if name == "simd_saturating_add" || name == "simd_saturating_sub" {
let lhs = args[0].immediate();
let rhs = args[1].immediate();
let is_add = name == "simd_saturating_add";
let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _;
let (signed, elem_width, elem_ty) = match in_elem.sty {
ty::Int(i) =>
(
true,
i.bit_width().unwrap_or(ptr_bits),
bx.cx.type_int_from_ty(i)
),
ty::Uint(i) =>
(
false,
i.bit_width().unwrap_or(ptr_bits),
bx.cx.type_uint_from_ty(i)
),
_ => {
return_error!(
"expected element type `{}` of vector type `{}` \
to be a signed or unsigned integer type",
arg_tys[0].simd_type(tcx).sty, arg_tys[0]
);
}
};
let llvm_intrinsic = &format!(
"llvm.{}{}.sat.v{}i{}",
if signed { 's' } else { 'u' },
if is_add { "add" } else { "sub" },
in_len, elem_width
);
let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64);
let f = bx.declare_cfn(
&llvm_intrinsic,
bx.type_func(&[vec_ty, vec_ty], vec_ty)
);
llvm::SetUnnamedAddr(f, false);
let v = bx.call(f, &[lhs, rhs], None);
return Ok(v);
}
span_bug!(span, "unknown SIMD intrinsic");
}