Skip to content
This repository has been archived by the owner on Dec 22, 2021. It is now read-only.

Commit

Permalink
[interpreter] Implement i16x8.qmulr_sat_s (#463)
Browse files Browse the repository at this point in the history
* [interpreter] Implement i16x8.qmulr_sat_s

This was merged in #365.

* Update interpreter/exec/int.ml

Co-authored-by: Andreas Rossberg <rossberg@mpi-sws.org>

Co-authored-by: Andreas Rossberg <rossberg@mpi-sws.org>
  • Loading branch information
ngzhian and rossberg committed Feb 17, 2021
1 parent 2d191fe commit 2eb77e2
Show file tree
Hide file tree
Showing 13 changed files with 176 additions and 3 deletions.
1 change: 1 addition & 0 deletions interpreter/binary/decode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ let simd_prefix s =
| 0x99l -> i16x8_max_u
| 0x9al -> i16x8_extmul_low_i8x16_s
| 0x9bl -> i16x8_avgr_u
| 0x9cl -> i16x8_q15mulr_sat_s
| 0x9dl -> i16x8_extmul_high_i8x16_s
| 0x9el -> i16x8_extmul_low_i8x16_u
| 0x9fl -> i16x8_extmul_high_i8x16_u
Expand Down
1 change: 1 addition & 0 deletions interpreter/binary/encode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ let encode m =
| Binary (V128 V128Op.(I16x8 ExtMulHighS)) -> simd_op 0x9dl
| Binary (V128 V128Op.(I16x8 ExtMulLowU)) -> simd_op 0x9el
| Binary (V128 V128Op.(I16x8 ExtMulHighU)) -> simd_op 0x9fl
| Binary (V128 V128Op.(I16x8 Q15MulRSatS)) -> simd_op 0x9cl
| Binary (V128 V128Op.(I32x4 Add)) -> simd_op 0xael
| Binary (V128 V128Op.(I32x4 Sub)) -> simd_op 0xb1l
| Binary (V128 V128Op.(I32x4 MinS)) -> simd_op 0xb6l
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 @@ -111,6 +111,7 @@ module SimdOp (SXX : Simd.S) (Value : ValueType with type t = SXX.t) = struct
| I16x8 ExtMulHighS -> SXX.I16x8_convert.extmul_high_s
| I16x8 ExtMulLowU -> SXX.I16x8_convert.extmul_low_u
| I16x8 ExtMulHighU -> SXX.I16x8_convert.extmul_high_u
| I16x8 Q15MulRSatS -> SXX.I16x8.q15mulr_sat_s
| I32x4 Add -> SXX.I32x4.add
| I32x4 Sub -> SXX.I32x4.sub
| I32x4 MinS -> SXX.I32x4.min_s
Expand Down
9 changes: 9 additions & 0 deletions interpreter/exec/int.ml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ sig
val add_sat_u : t -> t -> t
val sub_sat_s : t -> t -> t
val sub_sat_u : t -> t -> t
val q15mulr_sat_s : t -> t -> t

val of_int_s : int -> t
val of_int_u : int -> t
Expand Down Expand Up @@ -289,6 +290,14 @@ struct
let sub_sat_s x y = saturate_s (sub x y)
let sub_sat_u x y = saturate_u (sub (as_unsigned x) (as_unsigned y))

let q15mulr_sat_s x y =
(* mul x64 y64 can overflow int64 when both are int32 min, but this is only
* used by i16x8, so we are fine for now. *)
assert (Rep.bitwidth < 32);
let x64 = Rep.to_int64 x in
let y64 = Rep.to_int64 y in
Rep.of_int64 Int64.((shift_right (add (mul x64 y64) 0x4000L) 15))

let to_int_s = Rep.to_int
let to_int_u i = Rep.to_int i land (Rep.to_int Rep.max_int lsl 1) lor 1

Expand Down
3 changes: 3 additions & 0 deletions interpreter/exec/simd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ sig
val add_sat_u : t -> t -> t
val sub_sat_s : t -> t -> t
val sub_sat_u : t -> t -> t
val q15mulr_sat_s : t -> t -> t
end

(* This signature defines the types and operations SIMD floats can expose. *)
Expand Down Expand Up @@ -353,6 +354,8 @@ struct
let add_sat_u = binop Int.add_sat_u
let sub_sat_s = binop Int.sub_sat_s
let sub_sat_u = binop Int.sub_sat_u
(* The intermediate will overflow lane.t, so have Int implement this. *)
let q15mulr_sat_s = binop Int.q15mulr_sat_s
end

module V8x16 = struct
Expand Down
2 changes: 1 addition & 1 deletion interpreter/syntax/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct
| Eq | Ne | LtS | LtU | LeS | LeU | GtS | GtU | GeS | GeU
| Swizzle | Shuffle of int list | NarrowS | NarrowU
| AddSatS | AddSatU | SubSatS | SubSatU
| DotI16x8S
| DotI16x8S | Q15MulRSatS
| ExtMulLowS | ExtMulHighS | ExtMulLowU | ExtMulHighU
type funop = Abs | Neg | Sqrt
| Ceil | Floor | Trunc | Nearest
Expand Down
1 change: 1 addition & 0 deletions interpreter/syntax/operators.ml
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ let i16x8_extmul_low_i8x16_s = Binary (V128 V128Op.(I16x8 ExtMulLowS))
let i16x8_extmul_high_i8x16_s = Binary (V128 V128Op.(I16x8 ExtMulHighS))
let i16x8_extmul_low_i8x16_u = Binary (V128 V128Op.(I16x8 ExtMulLowU))
let i16x8_extmul_high_i8x16_u = Binary (V128 V128Op.(I16x8 ExtMulHighU))
let i16x8_q15mulr_sat_s = Binary (V128 V128Op.(I16x8 Q15MulRSatS))

let i32x4_splat = Convert (V128 V128Op.(I32x4 Splat))
let i32x4_extract_lane imm = SimdExtract (V128Op.I32x4 (ZX, imm))
Expand Down
1 change: 1 addition & 0 deletions interpreter/text/arrange.ml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ struct
| I16x8 ExtMulHighS -> "i16x8.extmul_high_i8x16_s"
| I16x8 ExtMulLowU -> "i16x8.extmul_low_i8x16_u"
| I16x8 ExtMulHighU -> "i16x8.extmul_high_i8x16_u"
| I16x8 Q15MulRSatS -> "i16x8.q15mulr_sat_s"
| I32x4 Add -> "i32x4.add"
| I32x4 Sub -> "i32x4.sub"
| I32x4 Mul -> "i32x4.mul"
Expand Down
2 changes: 2 additions & 0 deletions interpreter/text/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,8 @@ rule token = parse
{ BINARY (ext s i64x2_extmul_low_i32x4_s i64x2_extmul_low_i32x4_u) }
| "i64x2.extmul_high_i32x4_"(sign as s)
{ BINARY (ext s i64x2_extmul_high_i32x4_s i64x2_extmul_high_i32x4_u) }
| "i16x8.q15mulr_sat_s"
{ BINARY i16x8_q15mulr_sat_s }

| (simd_shape as s) { SIMD_SHAPE (simd_shape s) }

Expand Down
1 change: 1 addition & 0 deletions test/core/simd/meta/gen_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
'simd_store_lane',
'simd_ext_mul',
'simd_int_to_int_widen',
'simd_i16x8_q15mulr_sat_s',
)


Expand Down
36 changes: 36 additions & 0 deletions test/core/simd/meta/simd_i16x8_q15mulr_sat_s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python3

from simd_arithmetic import SimdArithmeticCase


"""Generate test cases for i16x8.mulr_sat_s
"""
class SimdI16x8Q15MulRSatS(SimdArithmeticCase):
LANE_TYPE = 'i16x8'
UNARY_OPS = ()
BINARY_OPS = ('q15mulr_sat_s',)

@property
def full_bin_test_data(self):
return []

@property
def hex_binary_op_test_data(self):
return []

def get_combine_cases(self):
return ''

def gen_test_cases(self):
wast_filename = '../simd_i16x8_q15mulr_sat_s.wast'
with open(wast_filename, 'w') as fp:
fp.write(self.get_all_cases())


def gen_test_cases():
simd_i16x8_q16mulr_sat_s = SimdI16x8Q15MulRSatS()
simd_i16x8_q16mulr_sat_s.gen_test_cases()


if __name__ == '__main__':
gen_test_cases()
11 changes: 9 additions & 2 deletions test/core/simd/meta/simd_integer_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,9 @@ def binary_op(self, operand1, operand2, src_lane, dst_lane=None):
add, sub, mul,
add_sat_s, add_sat_u,
sub_sat_s, sub_sat_u,
min_s, min_u, max_s, max_u, avgr_u
ext_mul_s, ext_mul_u (same as mul)
min_s, min_u, max_s, max_u, avgr_u,
ext_mul_s, ext_mul_u (same as mul),
q15mulr_sat_s
:param operand1: the operand 1, integer or literal string in hex or decimal format
:param operand2: the operand 2, integer or literal string in hex or decimal format
Expand Down Expand Up @@ -170,6 +171,12 @@ def binary_op(self, operand1, operand2, src_lane, dst_lane=None):
i1 = self.get_valid_value(v1, src_lane, signed=False)
i2 = self.get_valid_value(v2, src_lane, signed=False)
value = i1 * i2
elif self.op == 'q15mulr_sat_s':
# This should be before 'sat' case.
i1 = ArithmeticOp.get_valid_value(v1, src_lane)
i2 = ArithmeticOp.get_valid_value(v2, src_lane)
result = (i1 * i2 + 0x4000) >> 15
return ArithmeticOp.get_valid_value(result, src_lane)
elif 'sat' in self.op:
value = self._saturate(v1, v2, src_lane)
if self.op.endswith('_u'):
Expand Down
110 changes: 110 additions & 0 deletions test/core/simd/simd_i16x8_q15mulr_sat_s.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
;; Tests for i16x8 arithmetic operations on major boundary values and all special values.


(module
(func (export "i16x8.q15mulr_sat_s") (param v128 v128) (result v128) (i16x8.q15mulr_sat_s (local.get 0) (local.get 1)))
)


;; i16x8.q15mulr_sat_s
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 0 0 0 0 0 0 0 0)
(v128.const i16x8 0 0 0 0 0 0 0 0))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 0 0 0 0 0 0 0 0)
(v128.const i16x8 1 1 1 1 1 1 1 1))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 1 1 1 1 1 1 1 1)
(v128.const i16x8 1 1 1 1 1 1 1 1))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 0 0 0 0 0 0 0 0)
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 1 1 1 1 1 1 1 1)
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1)
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 16383 16383 16383 16383 16383 16383 16383 16383)
(v128.const i16x8 16384 16384 16384 16384 16384 16384 16384 16384))
(v128.const i16x8 8192 8192 8192 8192 8192 8192 8192 8192))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 16384 16384 16384 16384 16384 16384 16384 16384)
(v128.const i16x8 16384 16384 16384 16384 16384 16384 16384 16384))
(v128.const i16x8 8192 8192 8192 8192 8192 8192 8192 8192))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -16383 -16383 -16383 -16383 -16383 -16383 -16383 -16383)
(v128.const i16x8 -16384 -16384 -16384 -16384 -16384 -16384 -16384 -16384))
(v128.const i16x8 8192 8192 8192 8192 8192 8192 8192 8192))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -16384 -16384 -16384 -16384 -16384 -16384 -16384 -16384)
(v128.const i16x8 -16384 -16384 -16384 -16384 -16384 -16384 -16384 -16384))
(v128.const i16x8 8192 8192 8192 8192 8192 8192 8192 8192))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -16385 -16385 -16385 -16385 -16385 -16385 -16385 -16385)
(v128.const i16x8 -16384 -16384 -16384 -16384 -16384 -16384 -16384 -16384))
(v128.const i16x8 8193 8193 8193 8193 8193 8193 8193 8193))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 32765 32765 32765 32765 32765 32765 32765 32765)
(v128.const i16x8 1 1 1 1 1 1 1 1))
(v128.const i16x8 1 1 1 1 1 1 1 1))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 32766 32766 32766 32766 32766 32766 32766 32766)
(v128.const i16x8 1 1 1 1 1 1 1 1))
(v128.const i16x8 1 1 1 1 1 1 1 1))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 32768 32768 32768 32768 32768 32768 32768 32768)
(v128.const i16x8 1 1 1 1 1 1 1 1))
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -32766 -32766 -32766 -32766 -32766 -32766 -32766 -32766)
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(v128.const i16x8 1 1 1 1 1 1 1 1))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -32767 -32767 -32767 -32767 -32767 -32767 -32767 -32767)
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(v128.const i16x8 1 1 1 1 1 1 1 1))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768)
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(v128.const i16x8 1 1 1 1 1 1 1 1))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 32767 32767 32767 32767 32767 32767 32767 32767)
(v128.const i16x8 32767 32767 32767 32767 32767 32767 32767 32767))
(v128.const i16x8 32766 32766 32766 32766 32766 32766 32766 32766))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768)
(v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768))
(v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768)
(v128.const i16x8 -32767 -32767 -32767 -32767 -32767 -32767 -32767 -32767))
(v128.const i16x8 32767 32767 32767 32767 32767 32767 32767 32767))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 65535 65535 65535 65535 65535 65535 65535 65535)
(v128.const i16x8 0 0 0 0 0 0 0 0))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 65535 65535 65535 65535 65535 65535 65535 65535)
(v128.const i16x8 1 1 1 1 1 1 1 1))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 65535 65535 65535 65535 65535 65535 65535 65535)
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(v128.const i16x8 0 0 0 0 0 0 0 0))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 65535 65535 65535 65535 65535 65535 65535 65535)
(v128.const i16x8 32767 32767 32767 32767 32767 32767 32767 32767))
(v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 65535 65535 65535 65535 65535 65535 65535 65535)
(v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768))
(v128.const i16x8 1 1 1 1 1 1 1 1))
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 65535 65535 65535 65535 65535 65535 65535 65535)
(v128.const i16x8 65535 65535 65535 65535 65535 65535 65535 65535))
(v128.const i16x8 0 0 0 0 0 0 0 0))

;; type check
(assert_invalid (module (func (result v128) (i16x8.q15mulr_sat_s (i32.const 0) (f32.const 0.0)))) "type mismatch")

;; Test operation with empty argument

(assert_invalid
(module
(func $i16x8.q15mulr_sat_s-1st-arg-empty (result v128)
(i16x8.q15mulr_sat_s (v128.const i16x8 0 0 0 0 0 0 0 0))
)
)
"type mismatch"
)
(assert_invalid
(module
(func $i16x8.q15mulr_sat_s-arg-empty (result v128)
(i16x8.q15mulr_sat_s)
)
)
"type mismatch"
)

0 comments on commit 2eb77e2

Please sign in to comment.