We now describe some improvement to the classical compilation scheme. For simplicity, we present examples and defer the full presentation of our scheme to section 6. In all these examples, we focus on pattern-matching compilation, replacing potentially arbitrary actions more simple ones, such as integers or variables.
catch (catch (switch lx with case []: 1 default: exit) with (catch (switch ly with case []: 2 default: exit) with (catch (switch lx with case (::): (switch ly with case (::) : 3 default: exit) default: exit)))) with (failwith "Partial match")
catch (catch (switch* lx with case []: 1 case (::) : (switch ly with case (::): 3 default: exit)) with (switch ly with case []: 2 default: exit) with (failwith "Partial match")
let merge lx ly = match lx,ly with | [], _ -> 1 | _, [] -> 2 | x::xs, y::ys -> 3 |
(P → L) = |
|
|
|||||||||
|
|||||||||
|
(P' → L') = |
|
|
||||||||||||||
|
(switch ly with case []: 2
default: exit)
always succeeds (this switch is the last one performed by the optimized
code in figure 1).
Thus, we replace it by 2
.
We can also suppress the outermost trap. Hence, applying both
optimizations described up to now, compilation of P → L
finally yields:
catch (switch* lx with case []: 1 case (::): (switch ly with case []: 3 default: exit)) with 2 |
The two previous optimizations yield optimal code for the merge example. Hence we complicate the running example by considering a matching on objects of type t from section 2:
|
||||||||||||||||||||||||||||||||||||||||||||
The optimized mixture rule yields four matrices: | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
One
.(exit 3)
lies in trap handler number 2
(line 15) and
results from ly not being Nil, this gives us no direct information
on lx.
Now, looking upwards for (exit 2)
, we can infer that
trap handler number 2 is entered from two different points.
In the first case (line 9),
(lx ly) is fully known as
(Cons (v1, v2) Nil), in the second case
(line 11), only lx is know to be
One v.
As (exit 3)
on line 15 gets executed only when
ly is not Nil,
we can finally deduce that the first case never results in entering
trap handler number 3.
As a consequence, trap handler number 3 is executed in a context where
lx necessarily is One v, the switch it performs is
useless and line 16 can be simplified into
“3
”. This elimination of useless tests[4] is usually
performed at a lower level by combining dead code elimination[9] and
conditional constant propagation[21, 6].Trap number | Context | |||||||
2 |
|
|||||||
3 |
|
|||||||
4 |
|