@@ -1777,6 +1777,7 @@ pub const FuncGen = struct {
17771777 .get_union_tag = > try self .airGetUnionTag (inst ),
17781778 .clz = > try self .airClzCtz (inst , "ctlz" ),
17791779 .ctz = > try self .airClzCtz (inst , "cttz" ),
1780+ .popcount = > try self .airPopCount (inst , "ctpop" ),
17801781
17811782 .atomic_store_unordered = > try self .airAtomicStore (inst , .Unordered ),
17821783 .atomic_store_monotonic = > try self .airAtomicStore (inst , .Monotonic ),
@@ -3679,6 +3680,40 @@ pub const FuncGen = struct {
36793680 }
36803681 }
36813682
3683+ fn airPopCount (self : * FuncGen , inst : Air.Inst.Index , prefix : [* :0 ]const u8 ) ! ? * const llvm.Value {
3684+ if (self .liveness .isUnused (inst )) return null ;
3685+
3686+ const ty_op = self .air .instructions .items (.data )[inst ].ty_op ;
3687+ const operand_ty = self .air .typeOf (ty_op .operand );
3688+ const operand = try self .resolveInst (ty_op .operand );
3689+ const target = self .dg .module .getTarget ();
3690+ const bits = operand_ty .intInfo (target ).bits ;
3691+
3692+ var fn_name_buf : [100 ]u8 = undefined ;
3693+ const llvm_fn_name = std .fmt .bufPrintZ (& fn_name_buf , "llvm.{s}.i{d}" , .{
3694+ prefix , bits ,
3695+ }) catch unreachable ;
3696+ const fn_val = self .dg .object .llvm_module .getNamedFunction (llvm_fn_name ) orelse blk : {
3697+ const operand_llvm_ty = try self .dg .llvmType (operand_ty );
3698+ const param_types = [_ ]* const llvm.Type {operand_llvm_ty };
3699+ const fn_type = llvm .functionType (operand_llvm_ty , & param_types , param_types .len , .False );
3700+ break :blk self .dg .object .llvm_module .addFunction (llvm_fn_name , fn_type );
3701+ };
3702+
3703+ const params = [_ ]* const llvm.Value {operand };
3704+ const wrong_size_result = self .builder .buildCall (fn_val , & params , params .len , .C , .Auto , "" );
3705+ const result_ty = self .air .typeOfIndex (inst );
3706+ const result_llvm_ty = try self .dg .llvmType (result_ty );
3707+ const result_bits = result_ty .intInfo (target ).bits ;
3708+ if (bits > result_bits ) {
3709+ return self .builder .buildTrunc (wrong_size_result , result_llvm_ty , "" );
3710+ } else if (bits < result_bits ) {
3711+ return self .builder .buildZExt (wrong_size_result , result_llvm_ty , "" );
3712+ } else {
3713+ return wrong_size_result ;
3714+ }
3715+ }
3716+
36823717 fn callFloor (self : * FuncGen , arg : * const llvm.Value , ty : Type ) ! * const llvm.Value {
36833718 return self .callFloatUnary (arg , ty , "floor" );
36843719 }
0 commit comments