From 129da6c3631da14fa24fa557ebbc781a019af16e Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Mon, 27 Jul 2020 09:25:55 -0700 Subject: [PATCH] Implement SIMD splats using Convert (#274) i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 splats. Implemented using Convert ast as a splat essentially takes a value of every other type to V128. --- interpreter/exec/eval_numeric.ml | 13 +++++++++---- interpreter/exec/simd.ml | 14 +++++++++++++- interpreter/syntax/ast.ml | 3 ++- interpreter/syntax/operators.ml | 6 ++++++ interpreter/text/lexer.mll | 3 +++ interpreter/valid/valid.ml | 10 +++++++++- 6 files changed, 42 insertions(+), 7 deletions(-) diff --git a/interpreter/exec/eval_numeric.ml b/interpreter/exec/eval_numeric.ml index 51ccd5b708..72d173b678 100644 --- a/interpreter/exec/eval_numeric.ml +++ b/interpreter/exec/eval_numeric.ml @@ -293,12 +293,17 @@ end module V128CvtOp = struct - (* TODO open Ast.SimdOp - *) - (* FIXME *) - let cvtop op v = failwith "TODO v128" + let cvtop op v : value = + match op with + | I8x16 Splat -> V128 (V128.I8x16.splat (I32Op.of_value 1 v)) + | I16x8 Splat -> V128 (V128.I16x8.splat (I32Op.of_value 1 v)) + | I32x4 Splat -> V128 (V128.I32x4.splat (I32Op.of_value 1 v)) + | I64x2 Splat -> V128 (V128.I64x2.splat (I64Op.of_value 1 v)) + | F32x4 Splat -> V128 (V128.F32x4.splat (F32Op.of_value 1 v)) + | F64x2 Splat -> V128 (V128.F64x2.splat (F64Op.of_value 1 v)) + | _ -> assert false end let eval_extractop extractop v = V128Op.extractop extractop v diff --git a/interpreter/exec/simd.ml b/interpreter/exec/simd.ml index bca6447f44..8d0c28343d 100644 --- a/interpreter/exec/simd.ml +++ b/interpreter/exec/simd.ml @@ -46,6 +46,7 @@ sig type t type lane + val splat : lane -> t val extract_lane : int -> t -> lane val abs : t -> t val neg : t -> t @@ -67,6 +68,8 @@ sig type t type lane + val splat : lane -> t + val extract_lane : int -> t -> lane val abs : t -> t val neg : t -> t val sqrt : t -> t @@ -76,7 +79,6 @@ sig val div : t -> t -> t val min : t -> t -> t val max : t -> t -> t - val extract_lane : int -> t -> lane end module type Vec = @@ -148,6 +150,7 @@ struct module MakeFloat (Float : Float.S) (Convert : sig val to_shape : Rep.t -> Float.t list val of_shape : Float.t list -> Rep.t + val num_lanes : int end) : Float with type t = Rep.t and type lane = Float.t = struct type t = Rep.t @@ -163,16 +166,19 @@ struct let div = binop Float.div let min = binop Float.min let max = binop Float.max + let splat x = Convert.of_shape (List.init Convert.num_lanes (fun i -> x)) let extract_lane i s = List.nth (Convert.to_shape s) i end module MakeInt (Int : Int.S) (Convert : sig val to_shape : Rep.t -> Int.t list val of_shape : Int.t list -> Rep.t + val num_lanes : int end) : Int with type t = Rep.t and type lane = Int.t = struct type t = Rep.t type lane = Int.t + let splat x = Convert.of_shape (List.init Convert.num_lanes (fun i -> x)) let extract_lane i s = List.nth (Convert.to_shape s) i let unop f x = Convert.of_shape (List.map f (Convert.to_shape x)) let binop f x y = Convert.of_shape (List.map2 f (Convert.to_shape x) (Convert.to_shape y)) @@ -197,31 +203,37 @@ struct module I8x16 = MakeInt (I8) (struct let to_shape = Rep.to_i8x16 let of_shape = Rep.of_i8x16 + let num_lanes = lanes I8x16 end) module I16x8 = MakeInt (I16) (struct let to_shape = Rep.to_i16x8 let of_shape = Rep.of_i16x8 + let num_lanes = lanes I16x8 end) module I32x4 = MakeInt (I32) (struct let to_shape = Rep.to_i32x4 let of_shape = Rep.of_i32x4 + let num_lanes = lanes I32x4 end) module I64x2 = MakeInt (I64) (struct let to_shape = Rep.to_i64x2 let of_shape = Rep.of_i64x2 + let num_lanes = lanes I64x2 end) module F32x4 = MakeFloat (F32) (struct let to_shape = Rep.to_f32x4 let of_shape = Rep.of_f32x4 + let num_lanes = lanes F32x4 end) module F64x2 = MakeFloat (F64) (struct let to_shape = Rep.to_f64x2 let of_shape = Rep.of_f64x2 + let num_lanes = lanes F64x2 end) end diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index 97d8ed1aeb..2e6ee517e9 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -70,7 +70,8 @@ struct type testop = (vtestop, vtestop, vtestop, vtestop, vtestop, vtestop, vtestop) v128op type ternop = Bitselect type relop = TodoRelOp - type cvtop = TodoCvtOp + type vcvtop = Splat + type cvtop = (vcvtop, vcvtop, vcvtop, vcvtop, vcvtop, vcvtop, vcvtop) v128op type extractop = I32x4ExtractLane of int | F32x4ExtractLane of int end diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index d7a64a08ef..58a2c6f2b9 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -224,6 +224,7 @@ let v128_or = Binary (V128 (V128Op.V128 V128Op.Or)) let v128_xor = Binary (V128 (V128Op.V128 V128Op.Xor)) let v128_bitselect = Ternary (V128Op.Bitselect) +let i8x16_splat = Convert (V128 (V128Op.I8x16 V128Op.Splat)) let i8x16_neg = Unary (V128 (V128Op.I8x16 V128Op.Neg)) let i8x16_any_true = Test (V128 (V128Op.I8x16 V128Op.AnyTrue)) let i8x16_all_true = Test (V128 (V128Op.I8x16 V128Op.AllTrue)) @@ -236,6 +237,7 @@ let i8x16_max_s = Binary (V128 (V128Op.I8x16 V128Op.MaxS)) let i8x16_max_u = Binary (V128 (V128Op.I8x16 V128Op.MaxU)) let i8x16_avgr_u = Binary (V128 (V128Op.I8x16 V128Op.AvgrU)) +let i16x8_splat = Convert (V128 (V128Op.I16x8 V128Op.Splat)) let i16x8_neg = Unary (V128 (V128Op.I16x8 V128Op.Neg)) let i16x8_any_true = Test (V128 (V128Op.I16x8 V128Op.AnyTrue)) let i16x8_all_true = Test (V128 (V128Op.I16x8 V128Op.AllTrue)) @@ -249,6 +251,7 @@ let i16x8_max_s = Binary (V128 (V128Op.I16x8 V128Op.MaxS)) let i16x8_max_u = Binary (V128 (V128Op.I16x8 V128Op.MaxU)) let i16x8_avgr_u = Binary (V128 (V128Op.I16x8 V128Op.AvgrU)) +let i32x4_splat = Convert (V128 (V128Op.I32x4 V128Op.Splat)) let i32x4_extract_lane imm = ExtractLane (V128Op.I32x4ExtractLane imm) let i32x4_abs = Unary (V128 (V128Op.I32x4 V128Op.Abs)) let i32x4_neg = Unary (V128 (V128Op.I32x4 V128Op.Neg)) @@ -262,11 +265,13 @@ let i32x4_max_s = Binary (V128 (V128Op.I32x4 V128Op.MaxS)) let i32x4_max_u = Binary (V128 (V128Op.I32x4 V128Op.MaxU)) let i32x4_mul = Binary (V128 (V128Op.I32x4 V128Op.Mul)) +let i64x2_splat = Convert (V128 (V128Op.I64x2 V128Op.Splat)) let i64x2_neg = Unary (V128 (V128Op.I64x2 V128Op.Neg)) let i64x2_add = Binary (V128 (V128Op.I64x2 V128Op.Add)) let i64x2_sub = Binary (V128 (V128Op.I64x2 V128Op.Sub)) let i64x2_mul = Binary (V128 (V128Op.I64x2 V128Op.Mul)) +let f32x4_splat = Convert (V128 (V128Op.F32x4 V128Op.Splat)) let f32x4_extract_lane imm = ExtractLane (V128Op.F32x4ExtractLane imm) let f32x4_abs = Unary (V128 (V128Op.F32x4 V128Op.Abs)) let f32x4_neg = Unary (V128 (V128Op.F32x4 V128Op.Neg)) @@ -278,6 +283,7 @@ let f32x4_div = Binary (V128 (V128Op.F32x4 V128Op.Div)) let f32x4_min = Binary (V128 (V128Op.F32x4 V128Op.Min)) let f32x4_max = Binary (V128 (V128Op.F32x4 V128Op.Max)) +let f64x2_splat = Convert (V128 (V128Op.F64x2 V128Op.Splat)) let f64x2_neg = Unary (V128 (V128Op.F64x2 V128Op.Neg)) let f64x2_sqrt = Unary (V128 (V128Op.F64x2 V128Op.Sqrt)) let f64x2_add = Binary (V128 (V128Op.F64x2 V128Op.Add)) diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index b4e92f32d9..878d61330b 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -244,6 +244,9 @@ rule token = parse | "global.get" { GLOBAL_GET } | "global.set" { GLOBAL_SET } + | (simd_shape as s)".splat" + { SPLAT (simdop s i8x16_splat i16x8_splat i32x4_splat + i64x2_splat f32x4_splat f64x2_splat) } | (simd_shape as s)".extract_lane" { EXTRACT_LANE (fun imm -> simdop s unimplemented_simd unimplemented_simd i32x4_extract_lane diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 5216093d54..2e7d40b0f8 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -135,7 +135,15 @@ let type_cvtop at = function | PromoteF32 -> F32Type | DemoteF64 -> error at "invalid conversion" ), F64Type - | Values.V128 cvtop -> failwith "TODO v128" + | Values.V128 cvtop -> + let open V128Op in + (match cvtop with + | I8x16 Splat | I16x8 Splat | I32x4 Splat -> I32Type + | I64x2 Splat -> I64Type + | F32x4 Splat -> F32Type + | F64x2 Splat -> F64Type + | V128 Splat -> error at "invalid conversion" + ), V128Type (* Expressions *)