Skip to content

Commit

Permalink
[interpreter] Implement i8x16.popcnt (WebAssembly#451)
Browse files Browse the repository at this point in the history
Small fix to the test generation script, the order of applying operators
was incorrect.

Includes a fix to popcnt implementation that is upstream
(WebAssembly#1286).
  • Loading branch information
ngzhian authored Feb 9, 2021
1 parent 634be58 commit ef343cb
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 23 deletions.
1 change: 1 addition & 0 deletions interpreter/binary/decode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ let simd_prefix s =
| 0x78l -> i8x16_max_s
| 0x79l -> i8x16_max_u
| 0x7bl -> i8x16_avgr_u
| 0x7cl -> i8x16_popcnt
| 0x80l -> i16x8_abs
| 0x81l -> i16x8_neg
| 0x83l -> i16x8_all_true
Expand Down
1 change: 1 addition & 0 deletions interpreter/binary/encode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ let encode m =
| Unary (V128 V128Op.(V128 Not)) -> simd_op 0x4dl
| Unary (V128 V128Op.(I8x16 Abs)) -> simd_op 0x60l
| Unary (V128 V128Op.(I8x16 Neg)) -> simd_op 0x61l
| Unary (V128 V128Op.(I8x16 Popcnt)) -> simd_op 0x7cl
| Unary (V128 V128Op.(I16x8 Abs)) -> simd_op 0x80l
| Unary (V128 V128Op.(I16x8 Neg)) -> simd_op 0x81l
| Unary (V128 V128Op.(I16x8 WidenLowS)) -> simd_op 0x87l
Expand Down
1 change: 1 addition & 0 deletions interpreter/exec/eval_simd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module SimdOp (SXX : Simd.S) (Value : ValueType with type t = SXX.t) = struct
fun v -> match op with
| I8x16 Neg -> to_value (SXX.I8x16.neg (of_value 1 v))
| I8x16 Abs -> to_value (SXX.I8x16.abs (of_value 1 v))
| I8x16 Popcnt -> to_value (SXX.I8x16.popcnt (of_value 1 v))
| I16x8 Neg -> to_value (SXX.I16x8.neg (of_value 1 v))
| I16x8 Abs -> to_value (SXX.I16x8.abs (of_value 1 v))
| I16x8 WidenLowS -> to_value (SXX.I16x8_convert.widen_low_s (of_value 1 v))
Expand Down
2 changes: 1 addition & 1 deletion interpreter/exec/int.ml
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ struct

let popcnt x =
let rec loop acc i n =
if n = Rep.zero then
if i = 0 then
acc
else
let acc' = if and_ n Rep.one = Rep.one then acc + 1 else acc in
Expand Down
2 changes: 2 additions & 0 deletions interpreter/exec/simd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ sig
val ge_u : t -> t -> t
val abs : t -> t
val neg : t -> t
val popcnt : t -> t
val add : t -> t -> t
val sub : t -> t -> t
val min_s : t -> t -> t
Expand Down Expand Up @@ -319,6 +320,7 @@ struct
let ge_u = binop (cmp Int.ge_u)
let abs = unop Int.abs
let neg = unop Int.neg
let popcnt = unop Int.popcnt
let add = binop Int.add
let sub = binop Int.sub
let mul = binop Int.mul
Expand Down
1 change: 1 addition & 0 deletions interpreter/syntax/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module SimdOp =
struct
type iunop = Abs | Neg | TruncSatF32x4S | TruncSatF32x4U
| WidenLowS | WidenLowU | WidenHighS | WidenHighU
| Popcnt
type ibinop = Add | Sub | MinS | MinU | MaxS | MaxU | Mul | AvgrU
| Eq | Ne | LtS | LtU | LeS | LeU | GtS | GtU | GeS | GeU
| Swizzle | Shuffle of int list | NarrowS | NarrowU
Expand Down
1 change: 1 addition & 0 deletions interpreter/syntax/operators.ml
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ let i8x16_sub = Binary (V128 V128Op.(I8x16 Sub))
let i8x16_sub_sat_s = Binary (V128 V128Op.(I8x16 SubSatS))
let i8x16_sub_sat_u = Binary (V128 V128Op.(I8x16 SubSatU))
let i8x16_abs = Unary (V128 V128Op.(I8x16 Abs))
let i8x16_popcnt = Unary (V128 V128Op.(I8x16 Popcnt))
let i8x16_min_s = Binary (V128 V128Op.(I8x16 MinS))
let i8x16_min_u = Binary (V128 V128Op.(I8x16 MinU))
let i8x16_max_s = Binary (V128 V128Op.(I8x16 MaxS))
Expand Down
1 change: 1 addition & 0 deletions interpreter/text/arrange.ml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ struct
let unop xx (op : unop) = match op with
| I8x16 Neg -> "i8x16.neg"
| I8x16 Abs -> "i8x16.abs"
| I8x16 Popcnt -> "i8x16.popcnt"
| I16x8 Abs -> "i16x8.abs"
| I16x8 Neg -> "i16x8.neg"
| I16x8 WidenLowS -> "i16x8.widen_low_i8x16_s"
Expand Down
2 changes: 2 additions & 0 deletions interpreter/text/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,8 @@ rule token = parse
| (simd_shape as s)".abs"
{ only ["i8x16"; "i16x8"; "i32x4"; "f32x4"; "f64x2"] s lexbuf;
UNARY (simdop s i8x16_abs i16x8_abs i32x4_abs unreachable f32x4_abs f64x2_abs) }
| "i8x16.popcnt"
{ UNARY i8x16_popcnt }
| (simd_int_shape as s)".all_true"
{ only ["i8x16"; "i16x8"; "i32x4"] s lexbuf;
UNARY (simd_int_op s i8x16_all_true i16x8_all_true i32x4_all_true unreachable) }
Expand Down
5 changes: 3 additions & 2 deletions test/core/simd/meta/simd_int_arith2.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@ def gen_test_case_combination(self):
for op2 in unary_ops:
o2 = ArithmeticOp(op2)
result3 = []
ret3 = o1.unary_op('-1', self.LANE_VALUE)
ret3 = o2.unary_op(ret3, self.LANE_VALUE)
ret3 = o2.unary_op('-1', self.LANE_VALUE)
ret3 = o1.unary_op(ret3, self.LANE_VALUE)
result3.append(ret3)
cases += '\n' + str(AssertReturn('{lane_type}.{op1}-{lane_type}.{op2}'.format(lane_type=self.LANE_TYPE, op1=op1, op2=op2),
[SIMD.v128_const('-1', self.LANE_TYPE)],
Expand Down Expand Up @@ -543,6 +543,7 @@ class Simdi16x8Case(SimdLaneWiseInteger):
class Simdi8x16Case(SimdLaneWiseInteger):
LANE_TYPE = 'i8x16'

UNARY_OPS = ('abs','popcnt')
BINARY_OPS = ('min_s', 'min_u', 'max_s', 'max_u', 'avgr_u')
UNKNOWN_BINARY_OPS = ('i32x4.avgr_u', 'f32x4.avgr_u',
'i64x2.avgr_u', 'f64x2.avgr_u',
Expand Down
3 changes: 3 additions & 0 deletions test/core/simd/meta/simd_integer_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ def unary_op(self, operand, lane):
result = -result
if base == 16:
return hex(result)
elif self.op == 'popcnt':
result = self.get_valid_value(v, lane)
return str(bin(result % lane.mod).count('1'))
else:
raise Exception('Unknown unary operation')

Expand Down
Loading

0 comments on commit ef343cb

Please sign in to comment.