Suppose we have a when expression
```
15 if foo -> <b1>
b if bar -> <b2>
_ -> <b3>
```
that may have a decision tree like
```
15?
\true => foo?
\true => <b1>
\false => bar?
\true => <b2>
\false => <b3>
\false => bar?
\true => <b2>
\false => <b3>
```
In this case, the guard "bar?" appears twice in the compiled decision
tree. We need to materialize the guard expression in both locations in
the compiled tree, which means we cannot as-is stamp a compiled `bar?`
twice in each location. The reason is that
- the compiled joinpoint for each `bar?` guard needs to have a unique ID
- the guard expression might have call which needs unique call spec IDs,
or other joins that need unique joinpoint IDs.
So, save the expression as we build up the decision tree and materialize
the guard each time we need it. In practice the guards should be quite
small, so duplicating should be fine. We could avoid duplication, but
it's not clear to me how to do that exactly since the branches after the
guard might end up being different.
If we are jumping to a target branch, it is necessary that the target
branch has all required pattern symbols loaded in it. Usually this is
already the case, but there is an exception with guarded patterns.
Guarded patterns have their patterns loaded only right before the guard
is evaluated, which happens at some point further along the decision
tree. As such, when a guarded pattern jumps to its target destination,
it should append the loaded patterns as parameters on the target
joinpoint.
When we load a structure with a nested recursive pointer, the pointer
may be loaded opaquely. We need to refine it to the concrete type wanted
by the layout.
This conversion can be removed after we upgrade to LLVM 15.
Closes#5162