"not" defined by matching vs "external"

Consider the following 2 definitions of not:

let external_not x = not x

let match_not = function true -> false | false -> true 

Godbolt https://godbolt.org/z/IJJAoU says we get different assembly:


camlExample__external_not_8:
        movq    %rax, %rbx
        movq    $4, %rax
        subq    %rbx, %rax
        ret
camlExample__match_not_15:
        cmpq    $1, %rax
        je      .L101
        movq    $1, %rax
        ret
.L101:
        movq    $3, %rax
        ret

Why is this?

Try this in godbolt

let t _ = true
let f _ = false

And I guess, you will answer you own question. Now, why booleans (and ints) are represented this way, is another question.

Short answer to differentiate them at runtime from pointers.

The not function from the standard library is implemented especially by the compiler backend so that more performant assembly is generated. The match_not function on the other hand is compiled according to the general compilation strategy that applies to any pattern matching (using branches), which results in slightly less efficient assembly.

to wit, stdlib.ml has:

external not : bool -> bool = "%boolnot"

The % in the external declaration indicates a compiler primitive.

https://github.com/ocaml/ocaml/pull/8547 and the other PRs it links seem related

1 Like