@@ -427,6 +427,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) {
427
427
return IrInstructionIdCtz;
428
428
}
429
429
430
+ static constexpr IrInstructionId ir_instruction_id(IrInstructionPopCount *) {
431
+ return IrInstructionIdPopCount;
432
+ }
433
+
430
434
static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) {
431
435
return IrInstructionIdUnionTag;
432
436
}
@@ -1725,6 +1729,15 @@ static IrInstruction *ir_build_ctz_from(IrBuilder *irb, IrInstruction *old_instr
1725
1729
return new_instruction;
1726
1730
}
1727
1731
1732
+ static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1733
+ IrInstructionPopCount *instruction = ir_build_instruction<IrInstructionPopCount>(irb, scope, source_node);
1734
+ instruction->value = value;
1735
+
1736
+ ir_ref_instruction(value, irb->current_basic_block);
1737
+
1738
+ return &instruction->base;
1739
+ }
1740
+
1728
1741
static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target_value,
1729
1742
IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime,
1730
1743
IrInstruction *switch_prongs_void)
@@ -3841,6 +3854,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
3841
3854
IrInstruction *ctz = ir_build_ctz(irb, scope, node, arg0_value);
3842
3855
return ir_lval_wrap(irb, scope, ctz, lval);
3843
3856
}
3857
+ case BuiltinFnIdPopCount:
3858
+ {
3859
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
3860
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
3861
+ if (arg0_value == irb->codegen->invalid_instruction)
3862
+ return arg0_value;
3863
+
3864
+ IrInstruction *instr = ir_build_pop_count(irb, scope, node, arg0_value);
3865
+ return ir_lval_wrap(irb, scope, instr, lval);
3866
+ }
3844
3867
case BuiltinFnIdClz:
3845
3868
{
3846
3869
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -15275,6 +15298,48 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC
15275
15298
}
15276
15299
}
15277
15300
15301
+ static TypeTableEntry *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstructionPopCount *instruction) {
15302
+ IrInstruction *value = instruction->value->other;
15303
+ if (type_is_invalid(value->value.type))
15304
+ return ira->codegen->builtin_types.entry_invalid;
15305
+
15306
+ if (value->value.type->id != TypeTableEntryIdInt && value->value.type->id != TypeTableEntryIdComptimeInt) {
15307
+ ir_add_error(ira, value,
15308
+ buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name)));
15309
+ return ira->codegen->builtin_types.entry_invalid;
15310
+ }
15311
+
15312
+ if (instr_is_comptime(value)) {
15313
+ ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
15314
+ if (!val)
15315
+ return ira->codegen->builtin_types.entry_invalid;
15316
+ if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) {
15317
+ size_t result = bigint_popcount_unsigned(&val->data.x_bigint);
15318
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
15319
+ bigint_init_unsigned(&out_val->data.x_bigint, result);
15320
+ return ira->codegen->builtin_types.entry_num_lit_int;
15321
+ }
15322
+ if (value->value.type->id == TypeTableEntryIdComptimeInt) {
15323
+ Buf *val_buf = buf_alloc();
15324
+ bigint_append_buf(val_buf, &val->data.x_bigint, 10);
15325
+ ir_add_error(ira, &instruction->base,
15326
+ buf_sprintf("@popCount on negative %s value %s",
15327
+ buf_ptr(&value->value.type->name), buf_ptr(val_buf)));
15328
+ return ira->codegen->builtin_types.entry_invalid;
15329
+ }
15330
+ size_t result = bigint_popcount_signed(&val->data.x_bigint, value->value.type->data.integral.bit_count);
15331
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
15332
+ bigint_init_unsigned(&out_val->data.x_bigint, result);
15333
+ return ira->codegen->builtin_types.entry_num_lit_int;
15334
+ }
15335
+
15336
+ IrInstruction *result = ir_build_pop_count(&ira->new_irb, instruction->base.scope,
15337
+ instruction->base.source_node, value);
15338
+ result->value.type = get_smallest_unsigned_int_type(ira->codegen, value->value.type->data.integral.bit_count);
15339
+ ir_link_new_instruction(result, &instruction->base);
15340
+ return result->value.type;
15341
+ }
15342
+
15278
15343
static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) {
15279
15344
if (type_is_invalid(value->value.type))
15280
15345
return ira->codegen->invalid_instruction;
@@ -20534,6 +20599,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
20534
20599
return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
20535
20600
case IrInstructionIdCtz:
20536
20601
return ir_analyze_instruction_ctz(ira, (IrInstructionCtz *)instruction);
20602
+ case IrInstructionIdPopCount:
20603
+ return ir_analyze_instruction_pop_count(ira, (IrInstructionPopCount *)instruction);
20537
20604
case IrInstructionIdSwitchBr:
20538
20605
return ir_analyze_instruction_switch_br(ira, (IrInstructionSwitchBr *)instruction);
20539
20606
case IrInstructionIdSwitchTarget:
@@ -20892,6 +20959,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
20892
20959
case IrInstructionIdUnwrapOptional:
20893
20960
case IrInstructionIdClz:
20894
20961
case IrInstructionIdCtz:
20962
+ case IrInstructionIdPopCount:
20895
20963
case IrInstructionIdSwitchVar:
20896
20964
case IrInstructionIdSwitchTarget:
20897
20965
case IrInstructionIdUnionTag:
0 commit comments