(** Least upper bound *)
Definition vlub (v w: aval) : aval :=
match v, w with
| Vbot, _ => w
| _, Vbot => v
| I i1, I i2 =>
if Int.eq i1 i2 then v else
if Int.lt i1 Int.zero || Int.lt i2 Int.zero
then sgn Pbot (Z.max (ssize i1) (ssize i2))
else uns Pbot (Z.max (usize i1) (usize i2))
| I i, Uns p n | Uns p n, I i =>
if Int.lt i Int.zero
then sgn p (Z.max (ssize i) (n + 1))
else uns p (Z.max (usize i) n)
| I i, Sgn p n | Sgn p n, I i =>
sgn p (Z.max (ssize i) n)
| I i, (Ptr p | Ifptr p) | (Ptr p | Ifptr p), I i =>
if va_strict tt || Int.eq i Int.zero then Ifptr p else Vtop
| Uns p1 n1, Uns p2 n2 => Uns (plub p1 p2) (Z.max n1 n2)
| Uns p1 n1, Sgn p2 n2 => sgn (plub p1 p2) (Z.max (n1 + 1) n2)
| Sgn p1 n1, Uns p2 n2 => sgn (plub p1 p2) (Z.max n1 (n2 + 1))
| Sgn p1 n1, Sgn p2 n2 => sgn (plub p1 p2) (Z.max n1 n2)
| F f1, F f2 =>
if Float.eq_dec f1 f2 then v else ntop
| FS f1, FS f2 =>
if Float32.eq_dec f1 f2 then v else ntop
| L i1, L i2 =>
if Int64.eq i1 i2 then v else ntop
| Ptr p1, Ptr p2 => Ptr(plub p1 p2)
| Ptr p1, Ifptr p2 => Ifptr(plub p1 p2)
| Ifptr p1, Ptr p2 => Ifptr(plub p1 p2)
| Ifptr p1, Ifptr p2 => Ifptr(plub p1 p2)
| (Ptr p1 | Ifptr p1), (Uns p2 _ | Sgn p2 _) => Ifptr(plub p1 p2)
| (Uns p1 _ | Sgn p1 _), (Ptr p2 | Ifptr p2) => Ifptr(plub p1 p2)
| _, (Ptr p | Ifptr p) | (Ptr p | Ifptr p), _ => if va_strict tt then Ifptr p else Vtop
| _, _ => Vtop
end.

Lemma vmatch_lub_l:
forall v x y, vmatch v x -> vmatch v (vlub x y).