@@ -2336,7 +2336,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
23362336 }
23372337
23382338 // 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+ ) {
23402343 let vec_ty = bx. cx . type_vector (
23412344 match * in_elem. kind ( ) {
23422345 ty:: Int ( i) => bx. cx . type_int_from_ty ( i) ,
@@ -2354,31 +2357,38 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
23542357 sym:: simd_bswap => "bswap" ,
23552358 sym:: simd_bitreverse => "bitreverse" ,
23562359 sym:: simd_ctlz => "ctlz" ,
2360+ sym:: simd_ctpop => "ctpop" ,
23572361 sym:: simd_cttz => "cttz" ,
23582362 _ => unreachable ! ( ) ,
23592363 } ;
23602364 let int_size = in_elem. int_size_and_signed ( bx. tcx ( ) ) . 0 . bits ( ) ;
23612365 let llvm_intrinsic = & format ! ( "llvm.{}.v{}i{}" , intrinsic_name, in_len, int_size, ) ;
23622366
2363- return if name == sym :: simd_bswap && int_size == 8 {
2367+ return match name {
23642368 // 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+ // this fun bonus i1 arg means "poison if the arg vector contains zero"
2372+ let fn_ty = bx. type_func ( & [ vec_ty, bx. type_i1 ( ) ] , vec_ty) ;
2373+ let f = bx. declare_cfn ( llvm_intrinsic, llvm:: UnnamedAddr :: No , fn_ty) ;
2374+ Ok ( bx. call (
2375+ fn_ty,
2376+ None ,
2377+ None ,
2378+ f,
2379+ // simd_ctlz and simd_cttz are exposed to safe code, so let's not poison anything
2380+ & [ args[ 0 ] . immediate ( ) , bx. const_int ( bx. type_i1 ( ) , 0 ) ] ,
2381+ None ,
2382+ None ,
2383+ ) )
2384+ }
2385+ sym:: simd_bswap | simd:: simd_bitreverse | simd:: 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 ! ( ) ,
23822392 } ;
23832393 }
23842394
0 commit comments