Skip to content

Commit 94defa9

Browse files
committed
Add simd_saturating_{add,sub} intrinsics
1 parent d173180 commit 94defa9

File tree

7 files changed

+895
-9
lines changed

7 files changed

+895
-9
lines changed

src/librustc_codegen_llvm/context.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -510,14 +510,24 @@ impl CodegenCx<'b, 'tcx> {
510510
let t_f32 = self.type_f32();
511511
let t_f64 = self.type_f64();
512512

513-
let t_v2f32 = self.type_vector(t_f32, 2);
514-
let t_v4f32 = self.type_vector(t_f32, 4);
515-
let t_v8f32 = self.type_vector(t_f32, 8);
516-
let t_v16f32 = self.type_vector(t_f32, 16);
517-
518-
let t_v2f64 = self.type_vector(t_f64, 2);
519-
let t_v4f64 = self.type_vector(t_f64, 4);
520-
let t_v8f64 = self.type_vector(t_f64, 8);
513+
macro_rules! vector_types {
514+
($id_out:ident: $elem_ty:ident, $len:expr) => {
515+
let $id_out = self.type_vector($elem_ty, $len);
516+
};
517+
($($id_out:ident: $elem_ty:ident, $len:expr;)*) => {
518+
$(vector_types!($id_out: $elem_ty, $len);)*
519+
}
520+
}
521+
vector_types! {
522+
t_v2f32: t_f32, 2;
523+
t_v4f32: t_f32, 4;
524+
t_v8f32: t_f32, 8;
525+
t_v16f32: t_f32, 16;
526+
527+
t_v2f64: t_f64, 2;
528+
t_v4f64: t_f64, 4;
529+
t_v8f64: t_f64, 8;
530+
}
521531

522532
ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
523533
ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,7 +1850,52 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
18501850
simd_xor: Uint, Int => xor;
18511851
simd_fmax: Float => maxnum;
18521852
simd_fmin: Float => minnum;
1853+
1854+
}
1855+
1856+
if name == "simd_saturating_add" || name == "simd_saturating_sub" {
1857+
let lhs = args[0].immediate();
1858+
let rhs = args[1].immediate();
1859+
let is_add = name == "simd_saturating_add";
1860+
let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _;
1861+
let (signed, elem_width, elem_ty) = match in_elem.sty {
1862+
ty::Int(i) =>
1863+
(
1864+
true,
1865+
i.bit_width().unwrap_or(ptr_bits),
1866+
bx.cx.type_int_from_ty(i)
1867+
),
1868+
ty::Uint(i) =>
1869+
(
1870+
false,
1871+
i.bit_width().unwrap_or(ptr_bits),
1872+
bx.cx.type_uint_from_ty(i)
1873+
),
1874+
_ => {
1875+
return_error!(
1876+
"expected element type `{}` of vector type `{}` \
1877+
to be a signed or unsigned integer type",
1878+
arg_tys[0].simd_type(tcx).sty, arg_tys[0]
1879+
);
1880+
}
1881+
};
1882+
let llvm_intrinsic = &format!(
1883+
"llvm.{}{}.sat.v{}i{}",
1884+
if signed { 's' } else { 'u' },
1885+
if is_add { "add" } else { "sub" },
1886+
in_len, elem_width
1887+
);
1888+
let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64);
1889+
1890+
let f = bx.declare_cfn(
1891+
&llvm_intrinsic,
1892+
bx.type_func(&[vec_ty, vec_ty], vec_ty)
1893+
);
1894+
llvm::SetUnnamedAddr(f, false);
1895+
let v = bx.call(f, &[lhs, rhs], None);
1896+
return Ok(v);
18531897
}
1898+
18541899
span_bug!(span, "unknown SIMD intrinsic");
18551900
}
18561901

src/librustc_typeck/check/intrinsic.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,8 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
410410
"simd_add" | "simd_sub" | "simd_mul" | "simd_rem" |
411411
"simd_div" | "simd_shl" | "simd_shr" |
412412
"simd_and" | "simd_or" | "simd_xor" |
413-
"simd_fmin" | "simd_fmax" | "simd_fpow" => {
413+
"simd_fmin" | "simd_fmax" | "simd_fpow" |
414+
"simd_saturating_add" | "simd_saturating_sub" => {
414415
(1, vec![param(0), param(0)], param(0))
415416
}
416417
"simd_fsqrt" | "simd_fsin" | "simd_fcos" | "simd_fexp" | "simd_fexp2" |

0 commit comments

Comments
 (0)