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

Commit 770ce64

Browse files
committed
Fix q15 saturating mul
Forgot to saturate the result in both test generation code and interpreter. This fixes both cases.
1 parent b4fde03 commit 770ce64

File tree

4 files changed

+14
-15
lines changed

4 files changed

+14
-15
lines changed

interpreter/exec/int.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ struct
296296
assert (Rep.bitwidth < 32);
297297
let x64 = Rep.to_int64 x in
298298
let y64 = Rep.to_int64 y in
299-
Rep.of_int64 Int64.((shift_right (add (mul x64 y64) 0x4000L) 15))
299+
saturate_s (Rep.of_int64 Int64.((shift_right (add (mul x64 y64) 0x4000L) 15)))
300300

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

test/core/simd/meta/simd_integer_op.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,7 @@ def _saturate(self, operand1: int, operand2: int, lane: LaneValue) -> int:
6868
if self.op.startswith('sub'):
6969
value = operand1 - operand2
7070

71-
if value > lane.max:
72-
return lane.max
73-
if value < lane.min:
74-
return lane.min
71+
return lane.sat_s(value)
7572

7673
if self.op.endswith('sat_u'):
7774
if operand1 < 0:
@@ -83,10 +80,7 @@ def _saturate(self, operand1: int, operand2: int, lane: LaneValue) -> int:
8380
if self.op.startswith('sub'):
8481
value = operand1 - operand2
8582

86-
if value > lane.mask:
87-
return lane.mask
88-
if value < 0:
89-
return 0
83+
return lane.sat_u(value)
9084

9185
return value
9286

@@ -122,10 +116,10 @@ def unary_op(self, operand, lane):
122116
return str(bin(result % lane.mod).count('1'))
123117
elif self.op == 'sat_s':
124118
# Don't call get_valid_value, it will truncate results.
125-
return max(lane.min, min(v, lane.max))
119+
return lane.sat_s(v)
126120
elif self.op == 'sat_u':
127121
# Don't call get_valid_value, it will truncate results.
128-
return max(0, min(v, lane.mask))
122+
return lane.sat_u(v)
129123
else:
130124
raise Exception('Unknown unary operation')
131125

@@ -181,8 +175,7 @@ def binary_op(self, operand1, operand2, src_lane, dst_lane=None):
181175
# This should be before 'sat' case.
182176
i1 = ArithmeticOp.get_valid_value(v1, src_lane)
183177
i2 = ArithmeticOp.get_valid_value(v2, src_lane)
184-
result = (i1 * i2 + 0x4000) >> 15
185-
return ArithmeticOp.get_valid_value(result, src_lane)
178+
return src_lane.sat_s((i1 * i2 + 0x4000) >> 15)
186179
elif 'sat' in self.op:
187180
value = self._saturate(v1, v2, src_lane)
188181
if self.op.endswith('_u'):

test/core/simd/meta/simd_lane_value.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,10 @@ def mod(self):
2929

3030
@property
3131
def quarter(self):
32-
return pow(2, self.lane_width - 2)
32+
return pow(2, self.lane_width - 2)
33+
34+
def sat_s(self, v):
35+
return max(self.min, min(v, self.max))
36+
37+
def sat_u(self, v):
38+
return max(0, min(v, self.mask))

test/core/simd/simd_i16x8_q15mulr_sat_s.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
(v128.const i16x8 32766 32766 32766 32766 32766 32766 32766 32766))
6464
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768)
6565
(v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768))
66-
(v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768))
66+
(v128.const i16x8 32767 32767 32767 32767 32767 32767 32767 32767))
6767
(assert_return (invoke "i16x8.q15mulr_sat_s" (v128.const i16x8 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768)
6868
(v128.const i16x8 -32767 -32767 -32767 -32767 -32767 -32767 -32767 -32767))
6969
(v128.const i16x8 32767 32767 32767 32767 32767 32767 32767 32767))

0 commit comments

Comments
 (0)