Skip to content

implementation and tests for clz, ctz, and popcnt #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions ml-proto/src/spec/arithmetic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ sig
val shift_right : t -> int -> t
val shift_right_logical : t -> int -> t
val to_int : t -> int
val of_int : int -> t
val of_int32 : int32 -> t
val of_int64 : int64 -> t
val to_float : t -> float
Expand All @@ -42,6 +43,8 @@ sig
val of_big_int_u : Big_int.big_int -> t
val to_value : t -> value
val of_value : int -> value -> t
val zero : t
val one : t
end

let to_big_int_u_for size to_big_int i =
Expand Down Expand Up @@ -118,11 +121,35 @@ struct
let unsigned big_op i j = big_op (Int.to_big_int_u i) (Int.to_big_int_u j)

let unop op =
let open Int in
let f = match op with
| Clz -> fun i -> i (* TODO *)
| Ctz -> fun i -> i (* TODO *)
| Popcnt -> fun i -> i (* TODO *)
in fun v -> Int.to_value (f (Int.of_value 1 v))
| Clz ->
let rec loop acc n =
if n = zero then
size
else if logand n (shift_left one (size - 1)) <> zero then
acc
else
loop (1 + acc) (shift_left n 1)
in loop 0
| Ctz ->
let rec loop acc n =
if n = zero then
size
else if logand n one = one then
acc
else
loop (1 + acc) (shift_right_logical n 1)
in loop 0
| Popcnt ->
let rec loop acc i n =
if n = zero then
acc
else
let acc' = if logand n one = one then acc + 1 else acc in
loop acc' (i - 1) (shift_right_logical n 1)
in loop 0 size
in fun v -> to_value (of_int (f (of_value 1 v)))

let binop op =
let f = match op with
Expand Down
37 changes: 37 additions & 0 deletions ml-proto/test/int32.wasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
(; Int arith operations ;)

(module
(func $clz (param $x i32) (result i32)
(i32.clz (get_local $x))
)

(func $ctz (param $x i32) (result i32)
(i32.ctz (get_local $x))
)

(func $popcnt (param $x i32) (result i32)
(i32.popcnt (get_local $x))
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice to keep the function name identical to the opcode name.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On 16 September 2015 at 01:36, Dan Gohman [email protected] wrote:

In ml-proto/test/int32.wasm
#50 (comment):

@@ -0,0 +1,37 @@
+(; Int arith operations ;)
+
+(module

  • (func $clz32 (param $x i32) (result i32)
  • (i32.clz (get_local $x))
  • )
  • (func $ctz32 (param $x i32) (result i32)
  • (i32.ctz (get_local $x))
  • )
  • (func $pcnt32 (param $x i32) (result i32)
  • (i32.popcnt (get_local $x))
  • )

It'd be nice to keep the function name identical to the opcode name.

Btw, despite it being what Intel picked on a bad day, popcnt really is an
odd name out. It is both inconsistent with the other count operators, and
it sounds like some kind of stack operator.

Would anybody mind if we changed it? For example, how about cnz (count
non-zeros), which would be in line with the other count operators. (If you
say it's a worthwhile idea I can create an issue or PR.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be wrong, but IIRC, the “population count” terminology long precedes Intel. It is used in GHC base package, GCC, Sparc, Cray, and CDC (the latter ones long before Intel). Even the Mark I had it but called it Sideways Add.

From: rossberg-chromium [mailto:[email protected]]
Sent: Wednesday, September 16, 2015 12:33 AM
To: WebAssembly/spec
Cc: Kuan, George
Subject: Re: [spec] implementation and tests for clz, ctz, and popcnt (#50)

In ml-proto/test/int32.wasmhttps://github.com//pull/50#discussion_r39600610:

@@ -0,0 +1,37 @@

+(; Int arith operations ;)

+(module

  • (func $clz32 (param $x i32) (result i32)
  • (i32.clz (get_local $x))
  • )
  • (func $ctz32 (param $x i32) (result i32)
  • (i32.ctz (get_local $x))
  • )
  • (func $pcnt32 (param $x i32) (result i32)
  • (i32.popcnt (get_local $x))
  • )
    On 16 September 2015 at 01:36, Dan Gohman [email protected] wrote: In ml-proto/test/int32.wasm implementation and tests for clz, ctz, and popcnt #50 (comment): > @@ -0,0 +1,37 @@ > +(; Int arith operations ;) > + > +(module > + (func $clz32 (param $x i32) (result i32) > + (i32.clz (get_local $x)) > + ) > + > + (func $ctz32 (param $x i32) (result i32) > + (i32.ctz (get_local $x)) > + ) > + > + (func $pcnt32 (param $x i32) (result i32) > + (i32.popcnt (get_local $x)) > + ) It'd be nice to keep the function name identical to the opcode name.
    Btw, despite it being what Intel picked on a bad day, popcnt really is an odd name out. It is both inconsistent with the other count operators, and it sounds like some kind of stack operator. Would anybody mind if we changed it? For example, how about cnz (count non-zeros), which would be in line with the other count operators. (If you say it's a worthwhile idea I can create an issue or PR.)


Reply to this email directly or view it on GitHubhttps://github.com//pull/50/files#r39600610.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On UltraSparc, it is known as POPC if that is any better.

From: rossberg-chromium [mailto:[email protected]]
Sent: Wednesday, September 16, 2015 12:33 AM
To: WebAssembly/spec
Cc: Kuan, George
Subject: Re: [spec] implementation and tests for clz, ctz, and popcnt (#50)

In ml-proto/test/int32.wasmhttps://github.com//pull/50#discussion_r39600610:

@@ -0,0 +1,37 @@

+(; Int arith operations ;)

+(module

  • (func $clz32 (param $x i32) (result i32)
  • (i32.clz (get_local $x))
  • )
  • (func $ctz32 (param $x i32) (result i32)
  • (i32.ctz (get_local $x))
  • )
  • (func $pcnt32 (param $x i32) (result i32)
  • (i32.popcnt (get_local $x))
  • )
    On 16 September 2015 at 01:36, Dan Gohman [email protected] wrote: In ml-proto/test/int32.wasm implementation and tests for clz, ctz, and popcnt #50 (comment): > @@ -0,0 +1,37 @@ > +(; Int arith operations ;) > + > +(module > + (func $clz32 (param $x i32) (result i32) > + (i32.clz (get_local $x)) > + ) > + > + (func $ctz32 (param $x i32) (result i32) > + (i32.ctz (get_local $x)) > + ) > + > + (func $pcnt32 (param $x i32) (result i32) > + (i32.popcnt (get_local $x)) > + ) It'd be nice to keep the function name identical to the opcode name.
    Btw, despite it being what Intel picked on a bad day, popcnt really is an odd name out. It is both inconsistent with the other count operators, and it sounds like some kind of stack operator. Would anybody mind if we changed it? For example, how about cnz (count non-zeros), which would be in line with the other count operators. (If you say it's a worthwhile idea I can create an issue or PR.)


Reply to this email directly or view it on GitHubhttps://github.com//pull/50/files#r39600610.


(export "clz" $clz)
(export "ctz" $ctz)
(export "popcnt" $popcnt)
)

(assert_eq (invoke "clz" (i32.const -1)) (i32.const 0)) ;; 0xFFFFFFFF
(assert_eq (invoke "clz" (i32.const 0)) (i32.const 32))
(assert_eq (invoke "clz" (i32.const 32768)) (i32.const 16)) ;; 0x00008000
(assert_eq (invoke "clz" (i32.const 255)) (i32.const 24)) ;; 0xFF
(assert_eq (invoke "clz" (i32.const -2147483648)) (i32.const 0)) ;; 0x80000000
(assert_eq (invoke "clz" (i32.const 1)) (i32.const 31))
(assert_eq (invoke "clz" (i32.const 2)) (i32.const 30))

(assert_eq (invoke "ctz" (i32.const -1)) (i32.const 0))
(assert_eq (invoke "ctz" (i32.const 0)) (i32.const 32))
(assert_eq (invoke "ctz" (i32.const 32768)) (i32.const 15)) ;; 0x00008000
(assert_eq (invoke "ctz" (i32.const 65536)) (i32.const 16)) ;; 0x00010000
(assert_eq (invoke "ctz" (i32.const -2147483648)) (i32.const 31)) ;; 0x80000000

(assert_eq (invoke "popcnt" (i32.const -1)) (i32.const 32))
(assert_eq (invoke "popcnt" (i32.const 0)) (i32.const 0))
(assert_eq (invoke "popcnt" (i32.const 32768)) (i32.const 1)) ;; 0x00008000