@@ -2336,7 +2336,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
2336
2336
}
2337
2337
2338
2338
// Unary integer intrinsics
2339
- if matches ! ( name, sym:: simd_bswap | sym:: simd_bitreverse | sym:: simd_ctlz | sym:: simd_cttz) {
2339
+ if matches ! (
2340
+ name,
2341
+ sym:: simd_bswap | sym:: simd_bitreverse | sym:: simd_ctlz | sym:: simd_ctpop | sym:: simd_cttz
2342
+ ) {
2340
2343
let vec_ty = bx. cx . type_vector (
2341
2344
match * in_elem. kind ( ) {
2342
2345
ty:: Int ( i) => bx. cx . type_int_from_ty ( i) ,
@@ -2354,31 +2357,38 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
2354
2357
sym:: simd_bswap => "bswap" ,
2355
2358
sym:: simd_bitreverse => "bitreverse" ,
2356
2359
sym:: simd_ctlz => "ctlz" ,
2360
+ sym:: simd_ctpop => "ctpop" ,
2357
2361
sym:: simd_cttz => "cttz" ,
2358
2362
_ => unreachable ! ( ) ,
2359
2363
} ;
2360
2364
let int_size = in_elem. int_size_and_signed ( bx. tcx ( ) ) . 0 . bits ( ) ;
2361
2365
let llvm_intrinsic = & format ! ( "llvm.{}.v{}i{}" , intrinsic_name, in_len, int_size, ) ;
2362
2366
2363
- return if name == sym :: simd_bswap && int_size == 8 {
2367
+ return match name {
2364
2368
// byte swap is no-op for i8/u8
2365
- Ok ( args[ 0 ] . immediate ( ) )
2366
- } else if matches ! ( name, sym:: simd_ctlz | sym:: simd_cttz) {
2367
- let fn_ty = bx. type_func ( & [ vec_ty, bx. type_i1 ( ) ] , vec_ty) ;
2368
- let f = bx. declare_cfn ( llvm_intrinsic, llvm:: UnnamedAddr :: No , fn_ty) ;
2369
- Ok ( bx. call (
2370
- fn_ty,
2371
- None ,
2372
- None ,
2373
- f,
2374
- & [ args[ 0 ] . immediate ( ) , bx. const_int ( bx. type_i1 ( ) , 0 ) ] ,
2375
- None ,
2376
- None ,
2377
- ) )
2378
- } else {
2379
- let fn_ty = bx. type_func ( & [ vec_ty] , vec_ty) ;
2380
- let f = bx. declare_cfn ( llvm_intrinsic, llvm:: UnnamedAddr :: No , fn_ty) ;
2381
- Ok ( bx. call ( fn_ty, None , None , f, & [ args[ 0 ] . immediate ( ) ] , None , None ) )
2369
+ sym:: simd_bswap if int_size == 8 => Ok ( args[ 0 ] . immediate ( ) ) ,
2370
+ sym:: simd_ctlz | sym:: simd_cttz => {
2371
+ // for the (int, i1 immediate) pair, the second arg adds `(0, true) => poison`
2372
+ let fn_ty = bx. type_func ( & [ vec_ty, bx. type_i1 ( ) ] , vec_ty) ;
2373
+ let dont_poison_on_zero = bx. const_int ( bx. type_i1 ( ) , 0 ) ;
2374
+ let f = bx. declare_cfn ( llvm_intrinsic, llvm:: UnnamedAddr :: No , fn_ty) ;
2375
+ Ok ( bx. call (
2376
+ fn_ty,
2377
+ None ,
2378
+ None ,
2379
+ f,
2380
+ & [ args[ 0 ] . immediate ( ) , dont_poison_on_zero] ,
2381
+ None ,
2382
+ None ,
2383
+ ) )
2384
+ }
2385
+ sym:: simd_bswap | sym:: simd_bitreverse | sym:: simd_ctpop => {
2386
+ // simple unary argument cases
2387
+ let fn_ty = bx. type_func ( & [ vec_ty] , vec_ty) ;
2388
+ let f = bx. declare_cfn ( llvm_intrinsic, llvm:: UnnamedAddr :: No , fn_ty) ;
2389
+ Ok ( bx. call ( fn_ty, None , None , f, & [ args[ 0 ] . immediate ( ) ] , None , None ) )
2390
+ }
2391
+ _ => unreachable ! ( ) ,
2382
2392
} ;
2383
2393
}
2384
2394
0 commit comments