@@ -69,13 +69,11 @@ mod intrinsics {
69
69
}
70
70
71
71
#[ cfg( target_endian = "little" ) ]
72
- unsafe fn simd_bitmask_impl < T , const LANES : usize , const MASK_LEN : usize > (
73
- input : & [ T ; LANES ] ,
74
- ) -> [ u8 ; MASK_LEN ]
72
+ unsafe fn simd_bitmask_impl < T , const LANES : usize > ( input : & [ T ; LANES ] ) -> [ u8 ; mask_len ( LANES ) ]
75
73
where
76
74
T : MaskElement ,
77
75
{
78
- let mut mask_array = [ 0 ; MASK_LEN ] ;
76
+ let mut mask_array = [ 0 ; mask_len ( LANES ) ] ;
79
77
for lane in ( 0 ..input. len ( ) ) . rev ( ) {
80
78
let byte = lane / 8 ;
81
79
let mask = & mut mask_array[ byte] ;
@@ -101,13 +99,14 @@ mod intrinsics {
101
99
#[ rustc_diagnostic_item = "KaniModelSimdBitmask" ]
102
100
pub ( super ) unsafe fn simd_bitmask < T , U , E , const LANES : usize > ( input : T ) -> U
103
101
where
104
- [ u8 ; size_of :: < U > ( ) ] : Sized ,
102
+ [ u8 ; mask_len ( LANES ) ] : Sized ,
105
103
E : MaskElement ,
106
104
{
107
105
// These checks are compiler sanity checks to ensure we are not doing anything invalid.
108
- assert ! (
109
- size_of:: <U >( ) >= mask_len( LANES ) ,
110
- "Expected size of return type to be greater or equal to the mask lanes" ,
106
+ assert_eq ! (
107
+ size_of:: <U >( ) ,
108
+ size_of:: <[ u8 ; mask_len( LANES ) ] >( ) ,
109
+ "Expected size of return type and mask lanes to match" ,
111
110
) ;
112
111
assert_eq ! (
113
112
size_of:: <T >( ) ,
@@ -116,8 +115,8 @@ mod intrinsics {
116
115
) ;
117
116
118
117
let data = & * ( & input as * const T as * const [ E ; LANES ] ) ;
119
- let mask = simd_bitmask_impl :: < E , LANES , { size_of :: < U > ( ) } > ( data) ;
120
- ( & mask as * const [ u8 ; size_of :: < U > ( ) ] as * const U ) . read ( )
118
+ let mask = simd_bitmask_impl ( data) ;
119
+ ( & mask as * const [ u8 ; mask_len ( LANES ) ] as * const U ) . read ( )
121
120
}
122
121
123
122
/// Structure used for sanity check our parameters.
@@ -128,7 +127,7 @@ mod intrinsics {
128
127
#[ cfg( test) ]
129
128
mod test {
130
129
use super :: intrinsics as kani_intrinsic;
131
- use std:: { fmt:: Debug , mem :: size_of , simd:: * } ;
130
+ use std:: { fmt:: Debug , simd:: * } ;
132
131
133
132
extern "platform-intrinsic" {
134
133
fn simd_bitmask < T , U > ( x : T ) -> U ;
@@ -138,8 +137,8 @@ mod test {
138
137
/// masks with lanes represented using i16.
139
138
#[ test]
140
139
fn test_bitmask_i16 ( ) {
141
- check_portable_bitmask :: < _ , i16 , 16 > ( mask16x16:: splat ( false ) ) ;
142
- check_portable_bitmask :: < _ , i16 , 16 > ( mask16x16:: splat ( true ) ) ;
140
+ check_portable_bitmask :: < _ , i16 , 16 , u16 > ( mask16x16:: splat ( false ) ) ;
141
+ check_portable_bitmask :: < _ , i16 , 16 , u16 > ( mask16x16:: splat ( true ) ) ;
143
142
}
144
143
145
144
/// Tests that the model correctly fails if an invalid value is given.
@@ -156,23 +155,21 @@ mod test {
156
155
/// Tests that the model correctly fails if the size parameter of the mask doesn't match the
157
156
/// expected number of bytes in the representation.
158
157
#[ test]
159
- #[ should_panic(
160
- expected = "Expected size of return type to be greater or equal to the mask lanes"
161
- ) ]
158
+ #[ should_panic( expected = "Expected size of return type and mask lanes to match" ) ]
162
159
fn test_invalid_generics ( ) {
163
- let mask = mask32x32 :: splat ( false ) ;
164
- assert_eq ! ( unsafe { kani_intrinsic:: simd_bitmask:: <_, u8 , i32 , 32 >( mask) } , u8 :: MAX ) ;
160
+ let mask = mask32x16 :: splat ( false ) ;
161
+ assert_eq ! ( unsafe { kani_intrinsic:: simd_bitmask:: <_, u16 , i32 , 2 >( mask) } , u16 :: MAX ) ;
165
162
}
166
163
167
164
/// Test that the `simd_bitmask` model is equivalent to the intrinsic for a few random values.
168
165
/// These values shouldn't be symmetric and ensure that we also handle endianness correctly.
169
166
#[ test]
170
167
fn test_bitmask_i32 ( ) {
171
- check_portable_bitmask :: < _ , i32 , 8 > ( mask32x8:: from ( [
168
+ check_portable_bitmask :: < _ , i32 , 8 , u8 > ( mask32x8:: from ( [
172
169
true , true , false , true , false , false , false , true ,
173
170
] ) ) ;
174
171
175
- check_portable_bitmask :: < _ , i32 , 4 > ( mask32x4:: from ( [ true , false , false , true ] ) ) ;
172
+ check_portable_bitmask :: < _ , i32 , 4 , u8 > ( mask32x4:: from ( [ true , false , false , true ] ) ) ;
176
173
}
177
174
178
175
#[ repr( simd) ]
@@ -188,14 +185,16 @@ mod test {
188
185
}
189
186
190
187
/// Compare the value returned by our model and the portable simd representation.
191
- fn check_portable_bitmask < T , E , const LANES : usize > ( mask : Mask < T , LANES > )
188
+ fn check_portable_bitmask < T , E , const LANES : usize , M > ( mask : Mask < T , LANES > )
192
189
where
193
190
T : std:: simd:: MaskElement ,
194
191
LaneCount < LANES > : SupportedLaneCount ,
195
192
E : kani_intrinsic:: MaskElement ,
193
+ [ u8 ; kani_intrinsic:: mask_len ( LANES ) ] : Sized ,
194
+ u64 : From < M > ,
196
195
{
197
196
assert_eq ! (
198
- unsafe { kani_intrinsic:: simd_bitmask:: <_, u64 , E , LANES >( mask. clone( ) ) } ,
197
+ unsafe { u64 :: from ( kani_intrinsic:: simd_bitmask:: <_, M , E , LANES >( mask. clone( ) ) ) } ,
199
198
mask. to_bitmask( )
200
199
) ;
201
200
}
@@ -206,11 +205,26 @@ mod test {
206
205
T : Clone ,
207
206
U : PartialEq + Debug ,
208
207
E : kani_intrinsic:: MaskElement ,
209
- [ u8 ; size_of :: < U > ( ) ] : Sized ,
208
+ [ u8 ; kani_intrinsic :: mask_len ( LANES ) ] : Sized ,
210
209
{
211
210
assert_eq ! (
212
211
unsafe { kani_intrinsic:: simd_bitmask:: <_, U , E , LANES >( mask. clone( ) ) } ,
213
212
unsafe { simd_bitmask:: <T , U >( mask) }
214
213
) ;
215
214
}
215
+
216
+ /// Similar to portable simd_harness.
217
+ #[ test]
218
+ fn check_mask_harness ( ) {
219
+ // From array doesn't work either. Manually build [false, true, false, true]
220
+ let mut mask = mask32x4:: splat ( false ) ;
221
+ mask. set ( 1 , true ) ;
222
+ mask. set ( 3 , true ) ;
223
+ let bitmask = mask. to_bitmask ( ) ;
224
+ assert_eq ! ( bitmask, 0b1010 ) ;
225
+
226
+ let kani_mask = unsafe { u64:: from ( kani_intrinsic:: simd_bitmask :: < _ , u8 , u32 , 4 > ( mask. clone ( ) ) ) } ;
227
+ assert_eq ! ( kani_mask, bitmask) ;
228
+ }
229
+
216
230
}
0 commit comments