Skip to content

Commit 3373698

Browse files
authored
Restore simd_shl and simd_shr intrinsics (rust-lang#1964)
1 parent 2ed8f2f commit 3373698

File tree

13 files changed

+204
-7
lines changed

13 files changed

+204
-7
lines changed

docs/src/rust-feature-support/intrinsics.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,8 @@ Name | Support | Notes |
268268
`simd_ne` | Yes | |
269269
`simd_or` | Yes | |
270270
`simd_rem` | No | |
271-
`simd_shl` | No | |
272-
`simd_shr` | No | |
271+
`simd_shl` | Yes | Doesn't check for overflow cases (#1963)[https://github.com/model-checking/kani/issues/1963] |
272+
`simd_shr` | Yes | Doesn't check for overflow cases (#1963)[https://github.com/model-checking/kani/issues/1963] |
273273
`simd_shuffle*` | No | |
274274
`simd_sub` | Yes | |
275275
`simd_xor` | Yes | |

kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -606,15 +606,15 @@ impl<'tcx> GotocCtx<'tcx> {
606606
}
607607
"simd_or" => codegen_intrinsic_binop!(bitor),
608608
"simd_rem" => unstable_codegen!(codegen_intrinsic_binop!(rem)),
609-
"simd_shl" => unstable_codegen!(codegen_intrinsic_binop!(shl)),
609+
// TODO: `simd_shl` and `simd_shr` don't check overflow cases.
610+
// <https://github.com/model-checking/kani/issues/1963>
611+
"simd_shl" => codegen_intrinsic_binop!(shl),
610612
"simd_shr" => {
611-
// Remove this attribute once unstable_codegen! is removed.
612-
#[allow(clippy::if_same_then_else)]
613613
if fargs[0].typ().base_type().unwrap().is_signed(self.symbol_table.machine_model())
614614
{
615-
unstable_codegen!(codegen_intrinsic_binop!(ashr))
615+
codegen_intrinsic_binop!(ashr)
616616
} else {
617-
unstable_codegen!(codegen_intrinsic_binop!(lshr))
617+
codegen_intrinsic_binop!(lshr)
618618
}
619619
}
620620
// "simd_shuffle#" => handled in an `if` preceding this match
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FAILURE\
2+
shift operand is negative
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Checks that `simd_shl` returns a failure if the operand is negative.
5+
//! Note: The "operand is negative" property isn't checked for `simd_shr`, only
6+
//! for `simd_shl`.
7+
#![feature(repr_simd, platform_intrinsics)]
8+
9+
#[repr(simd)]
10+
#[allow(non_camel_case_types)]
11+
#[derive(Clone, Copy, PartialEq, Eq)]
12+
pub struct i32x2(i32, i32);
13+
14+
extern "platform-intrinsic" {
15+
fn simd_shl<T>(x: T, y: T) -> T;
16+
}
17+
18+
#[kani::proof]
19+
fn test_simd_shl() {
20+
let value = kani::any();
21+
let values = i32x2(value, value);
22+
let shift = kani::any();
23+
kani::assume(shift >= 0);
24+
kani::assume(shift < 32);
25+
let shifts = i32x2(shift, shift);
26+
let _result = unsafe { simd_shl(values, shifts) };
27+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FAILURE\
2+
shift distance is negative
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Checks that `simd_shl` returns a failure if the shift distance is negative.
5+
#![feature(repr_simd, platform_intrinsics)]
6+
7+
#[repr(simd)]
8+
#[allow(non_camel_case_types)]
9+
#[derive(Clone, Copy, PartialEq, Eq)]
10+
pub struct i32x2(i32, i32);
11+
12+
extern "platform-intrinsic" {
13+
fn simd_shl<T>(x: T, y: T) -> T;
14+
}
15+
16+
#[kani::proof]
17+
fn test_simd_shl() {
18+
let value = kani::any();
19+
kani::assume(value >= 0);
20+
let values = i32x2(value, value);
21+
let shift = kani::any();
22+
kani::assume(shift < 32);
23+
let shifts = i32x2(shift, shift);
24+
let _result = unsafe { simd_shl(values, shifts) };
25+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FAILURE\
2+
shift distance too large
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Checks that `simd_shl` returns a failure if the shift distance is too large.
5+
#![feature(repr_simd, platform_intrinsics)]
6+
7+
#[repr(simd)]
8+
#[allow(non_camel_case_types)]
9+
#[derive(Clone, Copy, PartialEq, Eq)]
10+
pub struct i32x2(i32, i32);
11+
12+
extern "platform-intrinsic" {
13+
fn simd_shl<T>(x: T, y: T) -> T;
14+
}
15+
16+
#[kani::proof]
17+
fn test_simd_shl() {
18+
let value = kani::any();
19+
kani::assume(value >= 0);
20+
let values = i32x2(value, value);
21+
let shift = kani::any();
22+
kani::assume(shift >= 0);
23+
let shifts = i32x2(shift, shift);
24+
let _result = unsafe { simd_shl(values, shifts) };
25+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FAILURE\
2+
shift distance is negative
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Checks that `simd_shr` returns a failure if the shift distance is negative.
5+
#![feature(repr_simd, platform_intrinsics)]
6+
7+
#[repr(simd)]
8+
#[allow(non_camel_case_types)]
9+
#[derive(Clone, Copy, PartialEq, Eq)]
10+
pub struct i32x2(i32, i32);
11+
12+
extern "platform-intrinsic" {
13+
fn simd_shr<T>(x: T, y: T) -> T;
14+
}
15+
16+
#[kani::proof]
17+
fn test_simd_shr() {
18+
let value = kani::any();
19+
kani::assume(value >= 0);
20+
let values = i32x2(value, value);
21+
let shift = kani::any();
22+
kani::assume(shift < 32);
23+
let shifts = i32x2(shift, shift);
24+
let _result = unsafe { simd_shr(values, shifts) };
25+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FAILURE\
2+
shift distance too large
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Checks that `simd_shr` returns a failure if the shift distance is too large.
5+
#![feature(repr_simd, platform_intrinsics)]
6+
7+
#[repr(simd)]
8+
#[allow(non_camel_case_types)]
9+
#[derive(Clone, Copy, PartialEq, Eq)]
10+
pub struct i32x2(i32, i32);
11+
12+
extern "platform-intrinsic" {
13+
fn simd_shr<T>(x: T, y: T) -> T;
14+
}
15+
16+
#[kani::proof]
17+
fn test_simd_shr() {
18+
let value = kani::any();
19+
kani::assume(value >= 0);
20+
let values = i32x2(value, value);
21+
let shift = kani::any();
22+
kani::assume(shift >= 0);
23+
let shifts = i32x2(shift, shift);
24+
let _result = unsafe { simd_shr(values, shifts) };
25+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Checks that the `simd_shl` and `simd_shr` intrinsics are supported and they
5+
//! return the expected results.
6+
#![feature(repr_simd, platform_intrinsics)]
7+
8+
#[repr(simd)]
9+
#[allow(non_camel_case_types)]
10+
#[derive(Clone, Copy, PartialEq, Eq)]
11+
pub struct i32x2(i32, i32);
12+
13+
#[repr(simd)]
14+
#[allow(non_camel_case_types)]
15+
#[derive(Clone, Copy, PartialEq, Eq)]
16+
pub struct u32x2(u32, u32);
17+
18+
extern "platform-intrinsic" {
19+
fn simd_shl<T>(x: T, y: T) -> T;
20+
fn simd_shr<T>(x: T, y: T) -> T;
21+
}
22+
23+
#[kani::proof]
24+
fn test_simd_shl() {
25+
let value = kani::any();
26+
kani::assume(value >= 0);
27+
let values = i32x2(value, value);
28+
let shift = kani::any();
29+
kani::assume(shift >= 0);
30+
kani::assume(shift < 32);
31+
let shifts = i32x2(shift, shift);
32+
let normal_result = value << shift;
33+
let simd_result = unsafe { simd_shl(values, shifts) };
34+
assert_eq!(normal_result, simd_result.0);
35+
}
36+
37+
#[kani::proof]
38+
fn test_simd_shr_signed() {
39+
let value = kani::any();
40+
let values = i32x2(value, value);
41+
let shift = kani::any();
42+
kani::assume(shift >= 0);
43+
kani::assume(shift < 32);
44+
let shifts = i32x2(shift, shift);
45+
let normal_result = value >> shift;
46+
let simd_result = unsafe { simd_shr(values, shifts) };
47+
assert_eq!(normal_result, simd_result.0);
48+
}
49+
50+
#[kani::proof]
51+
fn test_simd_shr_unsigned() {
52+
let value = kani::any();
53+
let values = u32x2(value, value);
54+
let shift = kani::any();
55+
kani::assume(shift < 32);
56+
let shifts = u32x2(shift, shift);
57+
let normal_result = value >> shift;
58+
let simd_result = unsafe { simd_shr(values, shifts) };
59+
assert_eq!(normal_result, simd_result.0);
60+
}

0 commit comments

Comments
 (0)