Skip to content

Commit 9c7c058

Browse files
tedinskiadpaco-aws
andcommitted
Add support for simd insert/extract intrinsics (rust-lang#354)
* support simd_extract intrinsic * support simd_insert intrinsic * move insert/extract tests to their own tile * extract codegen_intrinsic_simd_insert Co-authored-by: Adrian Palacios <[email protected]>
1 parent 7cbce96 commit 9c7c058

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

compiler/rustc_codegen_llvm/src/gotoc/intrinsic.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,14 @@ impl<'tcx> GotocCtx<'tcx> {
375375
"simd_and" => codegen_intrinsic_binop!(bitand),
376376
"simd_div" => codegen_intrinsic_binop!(div),
377377
"simd_eq" => codegen_intrinsic_binop!(eq),
378+
"simd_extract" => {
379+
let vec = fargs.remove(0);
380+
let index = fargs.remove(0);
381+
self.codegen_expr_to_place(p, vec.index_array(index))
382+
}
378383
"simd_ge" => codegen_intrinsic_binop!(ge),
379384
"simd_gt" => codegen_intrinsic_binop!(gt),
385+
"simd_insert" => self.codegen_intrinsic_simd_insert(fargs, p, cbmc_ret_ty, loc),
380386
"simd_le" => codegen_intrinsic_binop!(le),
381387
"simd_lt" => codegen_intrinsic_binop!(lt),
382388
"simd_mul" => codegen_intrinsic_binop!(mul),
@@ -791,4 +797,33 @@ impl<'tcx> GotocCtx<'tcx> {
791797
}
792798
}
793799
}
800+
801+
/// Insert is a generic update of a single value in a SIMD vector.
802+
/// `P = simd_insert(vector, index, newval)` is here translated to
803+
/// `{ T v = vector; v[index] = (cast)newval; P = v; }`
804+
///
805+
/// CBMC does not currently seem to implement intrinsics like insert e.g.:
806+
/// `**** WARNING: no body for function __builtin_ia32_vec_set_v4si`
807+
pub fn codegen_intrinsic_simd_insert(
808+
&mut self,
809+
mut fargs: Vec<Expr>,
810+
p: &Place<'tcx>,
811+
cbmc_ret_ty: Type,
812+
loc: Location,
813+
) -> Stmt {
814+
let vec = fargs.remove(0);
815+
let index = fargs.remove(0);
816+
let newval = fargs.remove(0);
817+
// Type checker should have ensured it's a vector type
818+
let elem_ty = cbmc_ret_ty.base_type().unwrap().clone();
819+
let tmp = self.gen_temp_variable(cbmc_ret_ty, loc.clone()).to_expr();
820+
Stmt::block(
821+
vec![
822+
Stmt::decl(tmp.clone(), Some(vec), loc.clone()),
823+
tmp.clone().index_array(index).assign(newval.cast_to(elem_ty), loc.clone()),
824+
self.codegen_expr_to_place(p, tmp),
825+
],
826+
loc,
827+
)
828+
}
794829
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
#![feature(repr_simd, platform_intrinsics)]
4+
5+
#[repr(simd)]
6+
#[allow(non_camel_case_types)]
7+
#[derive(Clone, Copy, PartialEq, Eq)]
8+
pub struct i64x2(i64, i64);
9+
10+
extern "platform-intrinsic" {
11+
fn simd_extract<T, U>(x: T, idx: u32) -> U;
12+
fn simd_insert<T, U>(x: T, idx: u32, b: U) -> T;
13+
}
14+
15+
fn main() {
16+
let y = i64x2(0, 1);
17+
let z = i64x2(1, 2);
18+
19+
// Indexing into the vectors
20+
assert!(z.0 == 1);
21+
assert!(z.1 == 2);
22+
23+
{
24+
// Intrinsic indexing
25+
let y_0: i64 = unsafe { simd_extract(y, 0) };
26+
let y_1: i64 = unsafe { simd_extract(y, 1) };
27+
assert!(y_0 == 0);
28+
assert!(y_1 == 1);
29+
}
30+
{
31+
// Intrinsic updating
32+
let m = unsafe { simd_insert(y, 0, 1) };
33+
let n = unsafe { simd_insert(y, 1, 5) };
34+
assert!(m.0 == 1 && m.1 == 1);
35+
assert!(n.0 == 0 && n.1 == 5);
36+
// Original unchanged
37+
assert!(y.0 == 0 && y.1 == 1);
38+
}
39+
}

src/test/cbmc/SIMD/Operators/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ fn main() {
4141
assert_op!(res_mul, simd_mul, y, z, 0, 2);
4242
assert_op!(res_div, simd_div, v, z, 1, 1);
4343
assert_op!(res_rem, simd_rem, v, z, 0, 1);
44-
assert_op!(res_rem, simd_rem, v, z, 0, 1);
45-
assert_op!(res_shr, simd_shl, z, z, 2, 8);
44+
assert_op!(res_shl, simd_shl, z, z, 2, 8);
4645
assert_op!(res_shr, simd_shr, z, y, 1, 1);
4746
assert_op!(res_and, simd_and, y, v, 0, 1);
4847
assert_op!(res_or, simd_or, x, y, 0, 1);

0 commit comments

Comments
 (0)