authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-26 19:15:27-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-07-26 19:15:27-04:00
logfc105f268149b195ea4a4189da59d40e96e455b4
tree8047cbd1e68974cac6de857424d930d650edcc9a
parenta9a4fd3200f6f40c1e66a5f8c9e3742639098b9c
parentdd796154be57da69c0b8467495e9029bb52cb897
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9458 from SuperAuguste/popcount-ctz-clz

Vector support for `@popCount`, `@ctz`, and `@clz`

7 files changed, 258 insertions(+), 49 deletions(-)

doc/langref.html.in+19-13
......@@ -7366,18 +7366,20 @@ pub const CallOptions = struct {
73667366 {#header_close#}
73677367
73687368 {#header_open|@clz#}
7369 <pre>{#syntax#}@clz(comptime T: type, integer: T){#endsyntax#}</pre>
7369 <pre>{#syntax#}@clz(comptime T: type, operand: T){#endsyntax#}</pre>
7370 <p>{#syntax#}T{#endsyntax#} must be an integer type.</p>
7371 <p>{#syntax#}operand{#endsyntax#} may be an {#link|integer|Integers#} or {#link|vector|Vectors#}.</p>
73707372 <p>
7371 This function counts the number of most-significant (leading in a big-Endian sense) zeroes in {#syntax#}integer{#endsyntax#}.
7373 This function counts the number of most-significant (leading in a big-Endian sense) zeroes in an integer.
73727374 </p>
73737375 <p>
7374 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},
7376 If {#syntax#}operand{#endsyntax#} is a {#link|comptime#}-known integer,
73757377 the return type is {#syntax#}comptime_int{#endsyntax#}.
7376 Otherwise, the return type is an unsigned integer with the minimum number
7378 Otherwise, the return type is an unsigned integer or vector of unsigned integers with the minimum number
73777379 of bits that can represent the bit count of the integer type.
73787380 </p>
73797381 <p>
7380 If {#syntax#}integer{#endsyntax#} is zero, {#syntax#}@clz{#endsyntax#} returns the bit width
7382 If {#syntax#}operand{#endsyntax#} is zero, {#syntax#}@clz{#endsyntax#} returns the bit width
73817383 of integer type {#syntax#}T{#endsyntax#}.
73827384 </p>
73837385 {#see_also|@ctz|@popCount#}
......@@ -7509,18 +7511,20 @@ test "main" {
75097511 {#header_close#}
75107512
75117513 {#header_open|@ctz#}
7512 <pre>{#syntax#}@ctz(comptime T: type, integer: T){#endsyntax#}</pre>
7514 <pre>{#syntax#}@ctz(comptime T: type, operand: T){#endsyntax#}</pre>
7515 <p>{#syntax#}T{#endsyntax#} must be an integer type.</p>
7516 <p>{#syntax#}operand{#endsyntax#} may be an {#link|integer|Integers#} or {#link|vector|Vectors#}.</p>
75137517 <p>
7514 This function counts the number of least-significant (trailing in a big-Endian sense) zeroes in {#syntax#}integer{#endsyntax#}.
7518 This function counts the number of least-significant (trailing in a big-Endian sense) zeroes in an integer.
75157519 </p>
75167520 <p>
7517 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},
7521 If {#syntax#}operand{#endsyntax#} is a {#link|comptime#}-known integer,
75187522 the return type is {#syntax#}comptime_int{#endsyntax#}.
7519 Otherwise, the return type is an unsigned integer with the minimum number
7523 Otherwise, the return type is an unsigned integer or vector of unsigned integers with the minimum number
75207524 of bits that can represent the bit count of the integer type.
75217525 </p>
75227526 <p>
7523 If {#syntax#}integer{#endsyntax#} is zero, {#syntax#}@ctz{#endsyntax#} returns
7527 If {#syntax#}operand{#endsyntax#} is zero, {#syntax#}@ctz{#endsyntax#} returns
75247528 the bit width of integer type {#syntax#}T{#endsyntax#}.
75257529 </p>
75267530 {#see_also|@clz|@popCount#}
......@@ -8105,12 +8109,14 @@ test "@wasmMemoryGrow" {
81058109 {#header_close#}
81068110
81078111 {#header_open|@popCount#}
8108 <pre>{#syntax#}@popCount(comptime T: type, integer: T){#endsyntax#}</pre>
8112 <pre>{#syntax#}@popCount(comptime T: type, operand: T){#endsyntax#}</pre>
8113 <p>{#syntax#}T{#endsyntax#} must be an integer type.</p>
8114 <p>{#syntax#}operand{#endsyntax#} may be an {#link|integer|Integers#} or {#link|vector|Vectors#}.</p>
81098115 <p>Counts the number of bits set in an integer.</p>
81108116 <p>
8111 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#},
8117 If {#syntax#}operand{#endsyntax#} is a {#link|comptime#}-known integer,
81128118 the return type is {#syntax#}comptime_int{#endsyntax#}.
8113 Otherwise, the return type is an unsigned integer with the minimum number
8119 Otherwise, the return type is an unsigned integer or vector of unsigned integers with the minimum number
81148120 of bits that can represent the bit count of the integer type.
81158121 </p>
81168122 {#see_also|@ctz|@clz#}
src/stage1/all_types.hpp+3
......@@ -1907,12 +1907,15 @@ struct ZigLLVMFnKey {
19071907 union {
19081908 struct {
19091909 uint32_t bit_count;
1910 uint32_t vector_len; // 0 means not a vector
19101911 } ctz;
19111912 struct {
19121913 uint32_t bit_count;
1914 uint32_t vector_len; // 0 means not a vector
19131915 } clz;
19141916 struct {
19151917 uint32_t bit_count;
1918 uint32_t vector_len; // 0 means not a vector
19161919 } pop_count;
19171920 struct {
19181921 BuiltinFnId op;
src/stage1/analyze.cpp+6-3
......@@ -7883,11 +7883,14 @@ bool type_id_eql(TypeId const *a, TypeId const *b) {
78837883uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey const *x) {
78847884 switch (x->id) {
78857885 case ZigLLVMFnIdCtz:
7886 return (uint32_t)(x->data.ctz.bit_count) * (uint32_t)810453934;
7886 return (uint32_t)(x->data.ctz.bit_count) * (uint32_t)810453934 +
7887 (uint32_t)(x->data.ctz.vector_len) * (((uint32_t)x->id << 5) + 1025);
78877888 case ZigLLVMFnIdClz:
7888 return (uint32_t)(x->data.clz.bit_count) * (uint32_t)2428952817;
7889 return (uint32_t)(x->data.clz.bit_count) * (uint32_t)2428952817 +
7890 (uint32_t)(x->data.clz.vector_len) * (((uint32_t)x->id << 5) + 1025);
78897891 case ZigLLVMFnIdPopCount:
7890 return (uint32_t)(x->data.clz.bit_count) * (uint32_t)101195049;
7892 return (uint32_t)(x->data.pop_count.bit_count) * (uint32_t)101195049 +
7893 (uint32_t)(x->data.pop_count.vector_len) * (((uint32_t)x->id << 5) + 1025);
78917894 case ZigLLVMFnIdFloatOp:
78927895 return (uint32_t)(x->data.floating.bit_count) * ((uint32_t)x->id + 1025) +
78937896 (uint32_t)(x->data.floating.vector_len) * (((uint32_t)x->id << 5) + 1025) +
src/stage1/codegen.cpp+1
......@@ -5070,6 +5070,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFn
50705070 n_args = 1;
50715071 key.id = ZigLLVMFnIdPopCount;
50725072 key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
5073 key.data.pop_count.vector_len = vector_len;
50735074 } else if (fn_id == BuiltinFnIdBswap) {
50745075 fn_name = "bswap";
50755076 n_args = 1;
src/stage1/ir.cpp+168-14
......@@ -15945,85 +15945,239 @@ static Stage1AirInst *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
1594515945}
1594615946
1594715947static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCtz *instruction) {
15948 Error err;
15949
1594815950 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
1594915951 if (type_is_invalid(int_type))
1595015952 return ira->codegen->invalid_inst_gen;
1595115953
15952 Stage1AirInst *op = ir_implicit_cast(ira, instruction->op->child, int_type);
15954 Stage1AirInst *uncasted_op = instruction->op->child;
15955 if (type_is_invalid(uncasted_op->value->type))
15956 return ira->codegen->invalid_inst_gen;
15957
15958 uint32_t vector_len = UINT32_MAX; // means not a vector
15959 if (uncasted_op->value->type->id == ZigTypeIdArray) {
15960 bool can_be_vec_elem;
15961 if ((err = is_valid_vector_elem_type(ira->codegen, uncasted_op->value->type->data.array.child_type,
15962 &can_be_vec_elem)))
15963 {
15964 return ira->codegen->invalid_inst_gen;
15965 }
15966 if (can_be_vec_elem) {
15967 vector_len = uncasted_op->value->type->data.array.len;
15968 }
15969 } else if (uncasted_op->value->type->id == ZigTypeIdVector) {
15970 vector_len = uncasted_op->value->type->data.vector.len;
15971 }
15972
15973 bool is_vector = (vector_len != UINT32_MAX);
15974 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
15975
15976 Stage1AirInst *op = ir_implicit_cast(ira, uncasted_op, op_type);
1595315977 if (type_is_invalid(op->value->type))
1595415978 return ira->codegen->invalid_inst_gen;
1595515979
1595615980 if (int_type->data.integral.bit_count == 0)
1595715981 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, 0);
1595815982
15983 ZigType *smallest_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
15984
1595915985 if (instr_is_comptime(op)) {
1596015986 ZigValue *val = ir_resolve_const(ira, op, UndefOk);
1596115987 if (val == nullptr)
1596215988 return ira->codegen->invalid_inst_gen;
1596315989 if (val->special == ConstValSpecialUndef)
1596415990 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
15965 size_t result_usize = bigint_ctz(&op->value->data.x_bigint, int_type->data.integral.bit_count);
15966 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result_usize);
15991
15992 if (is_vector) {
15993 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
15994 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type);
15995 expand_undef_array(ira->codegen, val);
15996 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(smallest_vec_type->data.vector.len);
15997 for (unsigned i = 0; i < smallest_vec_type->data.vector.len; i += 1) {
15998 ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
15999 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
16000 op_elem_val, UndefOk)))
16001 {
16002 return ira->codegen->invalid_inst_gen;
16003 }
16004 ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i];
16005 result_elem_val->type = smallest_type;
16006 result_elem_val->special = op_elem_val->special;
16007 if (op_elem_val->special == ConstValSpecialUndef)
16008 continue;
16009 size_t value = bigint_ctz(&op_elem_val->data.x_bigint, int_type->data.integral.bit_count);
16010 bigint_init_unsigned(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint, value);
16011 }
16012 return result;
16013 } else {
16014 size_t result_usize = bigint_ctz(&op->value->data.x_bigint, int_type->data.integral.bit_count);
16015 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result_usize);
16016 }
1596716017 }
1596816018
15969 ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
16019 ZigType *return_type = is_vector ? get_vector_type(ira->codegen, vector_len, smallest_type) : smallest_type;
1597016020 return ir_build_ctz_gen(ira, instruction->base.scope, instruction->base.source_node, return_type, op);
1597116021}
1597216022
1597316023static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstClz *instruction) {
16024 Error err;
16025
1597416026 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
1597516027 if (type_is_invalid(int_type))
1597616028 return ira->codegen->invalid_inst_gen;
1597716029
15978 Stage1AirInst *op = ir_implicit_cast(ira, instruction->op->child, int_type);
16030 Stage1AirInst *uncasted_op = instruction->op->child;
16031 if (type_is_invalid(uncasted_op->value->type))
16032 return ira->codegen->invalid_inst_gen;
16033
16034 uint32_t vector_len = UINT32_MAX; // means not a vector
16035 if (uncasted_op->value->type->id == ZigTypeIdArray) {
16036 bool can_be_vec_elem;
16037 if ((err = is_valid_vector_elem_type(ira->codegen, uncasted_op->value->type->data.array.child_type,
16038 &can_be_vec_elem)))
16039 {
16040 return ira->codegen->invalid_inst_gen;
16041 }
16042 if (can_be_vec_elem) {
16043 vector_len = uncasted_op->value->type->data.array.len;
16044 }
16045 } else if (uncasted_op->value->type->id == ZigTypeIdVector) {
16046 vector_len = uncasted_op->value->type->data.vector.len;
16047 }
16048
16049 bool is_vector = (vector_len != UINT32_MAX);
16050 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
16051
16052 Stage1AirInst *op = ir_implicit_cast(ira, uncasted_op, op_type);
1597916053 if (type_is_invalid(op->value->type))
1598016054 return ira->codegen->invalid_inst_gen;
1598116055
1598216056 if (int_type->data.integral.bit_count == 0)
1598316057 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, 0);
1598416058
16059 ZigType *smallest_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
16060
1598516061 if (instr_is_comptime(op)) {
1598616062 ZigValue *val = ir_resolve_const(ira, op, UndefOk);
1598716063 if (val == nullptr)
1598816064 return ira->codegen->invalid_inst_gen;
1598916065 if (val->special == ConstValSpecialUndef)
1599016066 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
15991 size_t result_usize = bigint_clz(&op->value->data.x_bigint, int_type->data.integral.bit_count);
15992 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result_usize);
16067
16068 if (is_vector) {
16069 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
16070 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type);
16071 expand_undef_array(ira->codegen, val);
16072 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(smallest_vec_type->data.vector.len);
16073 for (unsigned i = 0; i < smallest_vec_type->data.vector.len; i += 1) {
16074 ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
16075 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
16076 op_elem_val, UndefOk)))
16077 {
16078 return ira->codegen->invalid_inst_gen;
16079 }
16080 ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i];
16081 result_elem_val->type = smallest_type;
16082 result_elem_val->special = op_elem_val->special;
16083 if (op_elem_val->special == ConstValSpecialUndef)
16084 continue;
16085 size_t value = bigint_clz(&op_elem_val->data.x_bigint, int_type->data.integral.bit_count);
16086 bigint_init_unsigned(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint, value);
16087 }
16088 return result;
16089 } else {
16090 size_t result_usize = bigint_clz(&op->value->data.x_bigint, int_type->data.integral.bit_count);
16091 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result_usize);
16092 }
1599316093 }
1599416094
15995 ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
16095 ZigType *return_type = is_vector ? get_vector_type(ira->codegen, vector_len, smallest_type) : smallest_type;
1599616096 return ir_build_clz_gen(ira, instruction->base.scope, instruction->base.source_node, return_type, op);
1599716097}
1599816098
1599916099static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1ZirInstPopCount *instruction) {
16100 Error err;
16101
1600016102 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
1600116103 if (type_is_invalid(int_type))
1600216104 return ira->codegen->invalid_inst_gen;
1600316105
16004 Stage1AirInst *op = ir_implicit_cast(ira, instruction->op->child, int_type);
16106 Stage1AirInst *uncasted_op = instruction->op->child;
16107 if (type_is_invalid(uncasted_op->value->type))
16108 return ira->codegen->invalid_inst_gen;
16109
16110 uint32_t vector_len = UINT32_MAX; // means not a vector
16111 if (uncasted_op->value->type->id == ZigTypeIdArray) {
16112 bool can_be_vec_elem;
16113 if ((err = is_valid_vector_elem_type(ira->codegen, uncasted_op->value->type->data.array.child_type,
16114 &can_be_vec_elem)))
16115 {
16116 return ira->codegen->invalid_inst_gen;
16117 }
16118 if (can_be_vec_elem) {
16119 vector_len = uncasted_op->value->type->data.array.len;
16120 }
16121 } else if (uncasted_op->value->type->id == ZigTypeIdVector) {
16122 vector_len = uncasted_op->value->type->data.vector.len;
16123 }
16124
16125 bool is_vector = (vector_len != UINT32_MAX);
16126 ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
16127
16128 Stage1AirInst *op = ir_implicit_cast(ira, uncasted_op, op_type);
1600516129 if (type_is_invalid(op->value->type))
1600616130 return ira->codegen->invalid_inst_gen;
1600716131
1600816132 if (int_type->data.integral.bit_count == 0)
1600916133 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, 0);
1601016134
16135 ZigType *smallest_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
16136
1601116137 if (instr_is_comptime(op)) {
1601216138 ZigValue *val = ir_resolve_const(ira, op, UndefOk);
1601316139 if (val == nullptr)
1601416140 return ira->codegen->invalid_inst_gen;
1601516141 if (val->special == ConstValSpecialUndef)
1601616142 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
16143
16144 if (is_vector) {
16145 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
16146 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type);
16147 expand_undef_array(ira->codegen, val);
16148 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(smallest_vec_type->data.vector.len);
16149 for (unsigned i = 0; i < smallest_vec_type->data.vector.len; i += 1) {
16150 ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
16151 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
16152 op_elem_val, UndefOk)))
16153 {
16154 return ira->codegen->invalid_inst_gen;
16155 }
16156 ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i];
16157 result_elem_val->type = smallest_type;
16158 result_elem_val->special = op_elem_val->special;
16159 if (op_elem_val->special == ConstValSpecialUndef)
16160 continue;
1601716161
16018 if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) {
16019 size_t result = bigint_popcount_unsigned(&val->data.x_bigint);
16162 if (bigint_cmp_zero(&op_elem_val->data.x_bigint) != CmpLT) {
16163 size_t value = bigint_popcount_unsigned(&op_elem_val->data.x_bigint);
16164 bigint_init_unsigned(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint, value);
16165 }
16166 size_t value = bigint_popcount_signed(&op_elem_val->data.x_bigint, int_type->data.integral.bit_count);
16167 bigint_init_unsigned(&result->value->data.x_array.data.s_none.elements[i].data.x_bigint, value);
16168 }
16169 return result;
16170 } else {
16171 if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) {
16172 size_t result = bigint_popcount_unsigned(&val->data.x_bigint);
16173 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result);
16174 }
16175 size_t result = bigint_popcount_signed(&val->data.x_bigint, int_type->data.integral.bit_count);
1602016176 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result);
1602116177 }
16022 size_t result = bigint_popcount_signed(&val->data.x_bigint, int_type->data.integral.bit_count);
16023 return ir_const_unsigned(ira, instruction->base.scope, instruction->base.source_node, result);
1602416178 }
1602516179
16026 ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count);
16180 ZigType *return_type = is_vector ? get_vector_type(ira->codegen, vector_len, smallest_type) : smallest_type;
1602716181 return ir_build_pop_count_gen(ira, instruction->base.scope, instruction->base.source_node, return_type, op);
1602816182}
1602916183
test/behavior/math.zig+34-14
......@@ -123,16 +123,27 @@ test "@clz" {
123123}
124124
125125fn testClz() !void {
126 try expect(clz(u8, 0b10001010) == 0);
127 try expect(clz(u8, 0b00001010) == 4);
128 try expect(clz(u8, 0b00011010) == 3);
129 try expect(clz(u8, 0b00000000) == 8);
130 try expect(clz(u128, 0xffffffffffffffff) == 64);
131 try expect(clz(u128, 0x10000000000000000) == 63);
126 try expect(@clz(u8, 0b10001010) == 0);
127 try expect(@clz(u8, 0b00001010) == 4);
128 try expect(@clz(u8, 0b00011010) == 3);
129 try expect(@clz(u8, 0b00000000) == 8);
130 try expect(@clz(u128, 0xffffffffffffffff) == 64);
131 try expect(@clz(u128, 0x10000000000000000) == 63);
132132}
133133
134fn clz(comptime T: type, x: T) usize {
135 return @clz(T, x);
134test "@clz vectors" {
135 try testClzVectors();
136 comptime try testClzVectors();
137}
138
139fn testClzVectors() !void {
140 @setEvalBranchQuota(10_000);
141 try expectEqual(@clz(u8, @splat(64, @as(u8, 0b10001010))), @splat(64, @as(u4, 0)));
142 try expectEqual(@clz(u8, @splat(64, @as(u8, 0b00001010))), @splat(64, @as(u4, 4)));
143 try expectEqual(@clz(u8, @splat(64, @as(u8, 0b00011010))), @splat(64, @as(u4, 3)));
144 try expectEqual(@clz(u8, @splat(64, @as(u8, 0b00000000))), @splat(64, @as(u4, 8)));
145 try expectEqual(@clz(u128, @splat(64, @as(u128, 0xffffffffffffffff))), @splat(64, @as(u8, 64)));
146 try expectEqual(@clz(u128, @splat(64, @as(u128, 0x10000000000000000))), @splat(64, @as(u8, 63)));
136147}
137148
138149test "@ctz" {
......@@ -141,14 +152,23 @@ test "@ctz" {
141152}
142153
143154fn testCtz() !void {
144 try expect(ctz(u8, 0b10100000) == 5);
145 try expect(ctz(u8, 0b10001010) == 1);
146 try expect(ctz(u8, 0b00000000) == 8);
147 try expect(ctz(u16, 0b00000000) == 16);
155 try expect(@ctz(u8, 0b10100000) == 5);
156 try expect(@ctz(u8, 0b10001010) == 1);
157 try expect(@ctz(u8, 0b00000000) == 8);
158 try expect(@ctz(u16, 0b00000000) == 16);
159}
160
161test "@ctz vectors" {
162 try testClzVectors();
163 comptime try testClzVectors();
148164}
149165
150fn ctz(comptime T: type, x: T) usize {
151 return @ctz(T, x);
166fn testCtzVectors() !void {
167 @setEvalBranchQuota(10_000);
168 try expectEqual(@ctz(u8, @splat(64, @as(u8, 0b10100000))), @splat(64, @as(u4, 5)));
169 try expectEqual(@ctz(u8, @splat(64, @as(u8, 0b10001010))), @splat(64, @as(u4, 1)));
170 try expectEqual(@ctz(u8, @splat(64, @as(u8, 0b00000000))), @splat(64, @as(u4, 8)));
171 try expectEqual(@ctz(u16, @splat(64, @as(u16, 0b00000000))), @splat(64, @as(u5, 16)));
152172}
153173
154174test "assignment operators" {
test/behavior/popcount.zig+27-5
......@@ -1,11 +1,14 @@
1const expect = @import("std").testing.expect;
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const Vector = std.meta.Vector;
25
3test "@popCount" {
4 comptime try testPopCount();
5 try testPopCount();
6test "@popCount integers" {
7 comptime try testPopCountIntegers();
8 try testPopCountIntegers();
69}
710
8fn testPopCount() !void {
11fn testPopCountIntegers() !void {
912 {
1013 var x: u32 = 0xffffffff;
1114 try expect(@popCount(u32, x) == 32);
......@@ -41,3 +44,22 @@ fn testPopCount() !void {
4144 try expect(@popCount(i128, 0b11111111000110001100010000100001000011000011100101010001) == 24);
4245 }
4346}
47
48test "@popCount vectors" {
49 // https://github.com/ziglang/zig/issues/3317
50 if (std.Target.current.cpu.arch == .mipsel or std.Target.current.cpu.arch == .mips) return error.SkipZigTest;
51
52 comptime try testPopCountVectors();
53 try testPopCountVectors();
54}
55
56fn testPopCountVectors() !void {
57 {
58 var x: Vector(8, u32) = [1]u32{0xffffffff} ** 8;
59 try expectEqual([1]u6{32} ** 8, @as([8]u6, @popCount(u32, x)));
60 }
61 {
62 var x: Vector(8, i16) = [1]i16{-1} ** 8;
63 try expectEqual([1]u5{16} ** 8, @as([8]u5, @popCount(i16, x)));
64 }
65}