@@ -1556,7 +1556,8 @@ impl GotocCtx<'_> {
1556
1556
}
1557
1557
1558
1558
/// `simd_shuffle` constructs a new vector from the elements of two input
1559
- /// vectors, choosing values according to an input array of indexes.
1559
+ /// vectors, choosing values according to an input array of indexes. See
1560
+ /// https://doc.rust-lang.org/std/intrinsics/simd/fn.simd_shuffle.html
1560
1561
///
1561
1562
/// We check that:
1562
1563
/// 1. The return type length is equal to the expected length (`n`) of the
@@ -1571,13 +1572,6 @@ impl GotocCtx<'_> {
1571
1572
/// TODO: Check that `indexes` contains constant values which are within the
1572
1573
/// expected bounds. See
1573
1574
/// <https://github.com/model-checking/kani/issues/1960> for more details.
1574
- ///
1575
- /// This code mimics CBMC's `shuffle_vector_exprt::lower()` here:
1576
- /// <https://github.com/diffblue/cbmc/blob/develop/src/ansi-c/c_expr.cpp>
1577
- ///
1578
- /// We can't use shuffle_vector_exprt because it's not understood by the CBMC backend,
1579
- /// it's immediately lowered by the C frontend.
1580
- /// Issue: <https://github.com/diffblue/cbmc/issues/6297>
1581
1575
fn codegen_intrinsic_simd_shuffle (
1582
1576
& mut self ,
1583
1577
mut fargs : Vec < Expr > ,
@@ -1593,7 +1587,7 @@ impl GotocCtx<'_> {
1593
1587
// [u32; n]: translated wrapped in a struct
1594
1588
let indexes = fargs. remove ( 0 ) ;
1595
1589
1596
- let ( in_type_len , vec_subtype) = self . simd_size_and_type ( rust_arg_types[ 0 ] ) ;
1590
+ let ( _ , vec_subtype) = self . simd_size_and_type ( rust_arg_types[ 0 ] ) ;
1597
1591
let ( ret_type_len, ret_type_subtype) = self . simd_size_and_type ( rust_ret_type) ;
1598
1592
if ret_type_len != n {
1599
1593
let err_msg = format ! (
@@ -1617,24 +1611,20 @@ impl GotocCtx<'_> {
1617
1611
// An unsigned type here causes an invariant violation in CBMC.
1618
1612
// Issue: https://github.com/diffblue/cbmc/issues/6298
1619
1613
let st_rep = Type :: ssize_t ( ) ;
1620
- let n_rep = Expr :: int_constant ( in_type_len, st_rep. clone ( ) ) ;
1621
1614
1622
- // P = indexes.expanded_map(v -> if v < N then vec1[v] else vec2[v-N])
1623
1615
let elems = ( 0 ..n)
1624
1616
. map ( |i| {
1625
1617
let idx = Expr :: int_constant ( i, st_rep. clone ( ) ) ;
1626
1618
// Must not use `indexes.index(i)` directly, because codegen wraps arrays in struct
1627
- let v = self . codegen_idx_array ( indexes. clone ( ) , idx) . cast_to ( st_rep. clone ( ) ) ;
1628
- let cond = v. clone ( ) . lt ( n_rep. clone ( ) ) ;
1629
- let t = vec1. clone ( ) . index ( v. clone ( ) ) ;
1630
- let e = vec2. clone ( ) . index ( v. sub ( n_rep. clone ( ) ) ) ;
1631
- cond. ternary ( t, e)
1619
+ self . codegen_idx_array ( indexes. clone ( ) , idx) . cast_to ( st_rep. clone ( ) )
1632
1620
} )
1633
1621
. collect ( ) ;
1634
1622
self . tcx . dcx ( ) . abort_if_errors ( ) ;
1635
1623
let cbmc_ret_ty = self . codegen_ty_stable ( rust_ret_type) ;
1636
1624
let loc = self . codegen_span_stable ( span) ;
1637
- self . codegen_expr_to_place_stable ( p, Expr :: vector_expr ( cbmc_ret_ty, elems) , loc)
1625
+ let shuffle_vector = Expr :: shuffle_vector ( vec1, vec2, elems) ;
1626
+ assert_eq ! ( * shuffle_vector. typ( ) , cbmc_ret_ty) ;
1627
+ self . codegen_expr_to_place_stable ( p, shuffle_vector, loc)
1638
1628
}
1639
1629
1640
1630
/// A volatile load of a memory location:
0 commit comments