Fil-C on Nix

Filnix wiki

the formal campaign

rocq/backend/RegsProof.v

# Soundness proofs for Regs.v

Machine-checked invariants of the Gallina register allocator, validator, parallel-move compiler and 3-address selection in Regs.v (M7 of docs/gallina-backend.md):

1. **Interval and call-point tests** (hreg_eqb_spec,

[ivals_disjoint_sound], [ivals_hit_points_sound]): disjoint
interval lists share no program point, and an interval list
that misses the sorted call points contains none of them.

2. **Allocation validator simulation** (check_rinst_step_sound,

[check_rinsts_rev_sound], [poll_edge_clobber_sound],
[callee_saves_restore_sound], [lower_key_never_hreg]): any
register map accepted by [check_rinsts_rev] and
[check_succs_polls] preserves temporary values across
instructions, simultaneous definitions, caller-saved register
clobbers (`%r10`, `%r11`) at calls and poll edges, restores
all five callee-saved registers (`%rbx`, `%r12`–`%r15`) on
exit, and keeps capability lowers in stack root slots.

3. **Parallel moves** (ready_pmove_step_sound,

[cycle_break_step_sound]): peeling an unread destination or
saving a cycle head into `%rcx` preserves the simultaneous
assignment of all non-scratch locations.

4. **3-address lea and immediate selection**

([imm32_add_mod_sound], [imm32_sub_lea_w_sound],
[imm32_sub_lea_l_sound]): signed 32-bit immediates and negated
`lea` displacements compute the exact modular sum and
difference at both 32-bit (`w`, including `-2^31`) and 64-bit
(`l`) widths.
From Stdlib Require Import String ZArith List Bool Arith Lia
From Nanofil Require Import Term Syntax Maps
From Backend Require Import Plan Layout Emit Regs
Import ListNotations
Open Scope Z_scope
Open Scope list_scope

1. Hardware register equality and interval disjointness

40Lemma hreg_eqb_refl
∀ r
hreg_eqbr r = true
Proof 1 step Qed
destruct r ; reflexivity
43Theorem hreg_eqb_spec
∀ a b
hreg_eqba b = true ↔ a = b
Proof 5 steps Qed
intros a b
split ; intro H
–destruct a , b ; simpl in H ; try discriminate ; reflexivity
–subst b
50Lemma nat_ltb_spec
∀ a b
nat_ltba b = true ↔ a < b%nat
Proof 3 steps Qed
intros a b
unfold nat_ltb
destruct Nat.compare_speca b ; split ; intro Hc ; try discriminate ; lia
56Lemma nat_ltb_false_spec
∀ a b
nat_ltba b = false ↔ b ≤ a%nat
Proof 3 steps Qed
intros a b
unfold nat_ltb
destruct Nat.compare_speca b ; split ; intro Hc ; try discriminate ; lia
62Lemma nat_eqb_spec
∀ a b
nat_eqba b = true ↔ a = b
Proof 3 steps Qed
intros a b
unfold nat_eqb
destruct Nat.compare_speca b ; split ; intro Hc ; try discriminate ; lia

Whether point p lies in some closed interval [lo, hi] of ivs.

69Fixpoint in_ivalsp : nat ivs : listival : Prop ≔
match ivs with
[ ]
⇒
False
lo, hi :: ivs′
⇒
lo ≤ p%nat ∧ p ≤ hi%nat ∨ in_ivalsp ivs′

Strictly ordered interval list: each interval ends before the next begins, and every interval satisfies lo ≤ hi.

77Fixpoint ivals_wfbound : nat ivs : listival : Prop ≔
match ivs with
[ ]
⇒
True
lo, hi :: ivs′
⇒
bound ≤ lo%nat ∧ lo ≤ hi%nat ∧ ivals_wfShi ivs′
84Lemma in_ivals_ge_bound
∀ ivs bound p
ivals_wfbound ivs
bound ≤ p%nat
Proof 7 steps Qed
induction ivs as | lo hi ivs′ IH ; intros bound p Hwf Hin ; simpl in *
–contradiction
–destruct Hwf as Hb Hlh Hwf′
destruct Hin as H1 _ | Hin′
+lia
+specialize IHShi p Hwf' Hin'
lia
95Lemma ivals_wf_weaken
∀ ivs b1 b2
b1 ≤ b2%nat
ivals_wfb2 ivs
ivals_wfb1 ivs
Proof 3 steps Qed
destruct ivs as | lo hi ivs′ ; intros b1 b2 Hle Hwf ; simpl in * ; exact I |
destruct Hwf as H1 H2
split ; lia | exact H2
102Lemma ivals_disjoint_fuel_sound
∀ fuel xs ys bx by0 p
ivals_wfby0 ys
ivals_disjoint_fuelfuel xs ys = true
False
Proof 34 steps Qed
induction fuel as | fuel′ IH ; intros xs ys bx by0 p Hwx Hwy Hdisj Hx Hy
–destruct xs as | a1 b1 xs′ ; simpl in Hx ; exact Hx |
destruct ys as | a2 b2 ys′ ; simpl in Hy ; exact Hy |
simpl in Hdisj
discriminate
–destruct xs as | a1 b1 xs′ ; simpl in Hx ; exact Hx |
destruct ys as | a2 b2 ys′ ; simpl in Hy ; exact Hy |
simpl in Hdisj
destruct Hwx as Hbx Hab1 Hwx′
destruct Hwy as Hby Hab2 Hwy′
destruct nat_ltbb1 a2 eqn: E1
+apply nat_ltb_spec in E1
simpl in Hx
destruct Hx as Hpa1 Hpb1 | Hx′
∗assert Hpge : a2 ≤ p%nat
{apply in_ivals_ge_bounda2, b2 :: ys' a2 p ; | exact Hy
simpl
split ; lia | split ; exact Hab2 | exact Hwy'
lia
∗eapply IH ; exact Hwx' | | exact Hdisj | exact Hx' | exact Hy
simpl
split ; exact Hby | split ; exact Hab2 | exact Hwy'
+destruct nat_ltbb2 a1 eqn: E2 ; | discriminate
apply nat_ltb_spec in E2
simpl in Hy
destruct Hy as Hpa2 Hpb2 | Hy′
∗assert Hpge : a1 ≤ p%nat
{apply in_ivals_ge_bounda1, b1 :: xs' a1 p ; | exact Hx
simpl
split ; lia | split ; exact Hab1 | exact Hwx'
lia
∗eapply IH ; | exact Hwy' | exact Hdisj | exact Hx | exact Hy'
simpl
split ; exact Hbx | split ; exact Hab1 | exact Hwx'

Disjoint well-formed interval lists share no program point.

137Theorem ivals_disjoint_sound
∀ xs ys p
False
Proof 3 steps Qed
intros xs ys p Hwx Hwy Hdisj Hx Hy
unfold ivals_disjoint in Hdisj
eapply ivals_disjoint_fuel_sound ; exact Hwx | exact Hwy | exact Hdisj | exact Hx | exact Hy
146Fixpoint pts_wfbound : nat pts : listnat : Prop ≔
match pts with
[ ]
⇒
True
q :: pts′
⇒
bound ≤ q%nat ∧ pts_wfSq pts′
152Lemma in_pts_ge_bound
∀ pts bound p
pts_wfbound pts
Inp pts
bound ≤ p%nat
Proof 7 steps Qed
induction pts as | q pts′ IH ; intros bound p Hwf Hin ; simpl in *
–contradiction
–destruct Hwf as Hb Hwf′
destruct Hin as ← | Hin′
+exact Hb
+specialize IHSq p Hwf' Hin'
lia
162Lemma ivals_hit_points_fuel_sound
∀ fuel ivs pts bi bp p
ivals_wfbi ivs
pts_wfbp pts
ivals_hit_points_fuelfuel ivs pts = false
Inp pts
False
Proof 34 steps Qed
induction fuel as | fuel′ IH ; intros ivs pts bi bp p Hwi Hwp Hhit Hin Hpt
–destruct ivs as | a b ivs′ ; simpl in Hin ; exact Hin |
destruct pts as | q pts′ ; simpl in Hpt ; exact Hpt |
simpl in Hhit
discriminate
–destruct ivs as | a b ivs′ ; simpl in Hin ; exact Hin |
destruct pts as | q pts′ ; simpl in Hpt ; exact Hpt |
simpl in Hhit
destruct Hwi as Hbi Hab Hwi′
destruct Hwp as Hbp Hwp′
destruct nat_ltbb q eqn: E1
+apply nat_ltb_spec in E1
simpl in Hin
destruct Hin as _ Hpb | Hin′
∗assert Hqle : q ≤ p%nat
{apply in_pts_ge_boundq :: pts' q p ; | exact Hpt
simpl
split ; lia | exact Hwp'
lia
∗eapply IH ; exact Hwi' | | exact Hhit | exact Hin' | exact Hpt
simpl
split ; exact Hbp | exact Hwp'
+destruct nat_ltbq a eqn: E2 ; | discriminate
apply nat_ltb_spec in E2
simpl in Hpt
destruct Hpt as ← | Hpt′
∗assert Hale : a ≤ q%nat
{apply in_ivals_ge_bounda, b :: ivs' a q ; | exact Hin
simpl
split ; lia | split ; exact Hab | exact Hwi'
lia
∗eapply IH ; | exact Hwp' | exact Hhit | exact Hin | exact Hpt'
simpl
split ; exact Hbi | split ; exact Hab | exact Hwi'

When ivals_hit_points returns false, no call point in pts falls inside ivs.

198Theorem ivals_hit_points_sound
∀ ivs pts p
pts_wfO pts
ivals_hit_pointsivs pts = false
Inp pts
False
Proof 3 steps Qed
intros ivs pts p Hwi Hwp Hhit Hin Hpt
unfold ivals_hit_points in Hhit
eapply ivals_hit_points_fuel_sound ; exact Hwi | exact Hwp | exact Hhit | exact Hin | exact Hpt

2. Validator soundness and forward simulation

Concrete register+slot state for a function body.

210Record mach_state: Type ≔ mkMach
ms_reg
 : hreg → Z
ms_slot
 : nat → Z
215Definition read_machrm : ZMap.threg ms : mach_state t : nat : Z ≔
match zmap_find_natt rm with
Somer
⇒
ms_regms r
None
⇒
221Definition write_machrm : ZMap.threg ms : mach_state t : nat v : Z : mach_state ≔
match zmap_find_natt rm with
Somer
⇒
λ r′  ⇒
hreg_eqbr′ r
→
v
else
ms_regms r′
None
⇒
λ t′  ⇒
Nat.eqbt′ t
→
v
else
ms_slotms t′
227Fixpoint write_mach_listrm : ZMap.threg ms : mach_state ds : listnat vs : listZ : mach_state ≔
match ds, vs with
d :: ds′, v :: vs′
⇒
write_mach_listrm write_machrm ms d v ds′ vs′
_, _
⇒
ms
234Fixpoint write_abs_listtenv : nat → Z ds : listnat vs : listZ : nat → Z ≔
match ds, vs with
d :: ds′, v :: vs′
⇒
λ t  ⇒
→
v
else
tenvt
ds′
vs′
_, _
⇒
tenv

A call clobbers caller-saved registers (%r10, %r11) with arbitrary values arb while preserving callee-saved registers and stack slots.

244Definition clobber_callarb : hreg → Z ms : mach_state : mach_state ≔
λ r  ⇒
else
arbr

State agreement on all temporaries in live (for mapped temporaries under dom = Somekm, and unconditionally on unmapped temporaries).

250Definition state_agreesrm : ZMap.threg live : listnat tenv : nat → Z ms : mach_state : Prop ≔
∀t, zmap_find_natt rm = None → ms_slotms t = tenvt ∧ ∀t, Int live → read_machrm ms t = tenvt
255Lemma hreg_in_list_spec
∀ r rs
hreg_in_listr rs = true ↔ Inr rs
Proof 9 steps Qed
intros r rs
induction rs as | r′ rs′ IH ; simpl
–split ; intro H ; discriminate | contradiction
–destruct hreg_eqbr r' eqn: E
+apply hreg_eqb_spec in E
subst r'
split ; auto
+rewrite IH
split ; right ; exact H | intros Heq | Hin ; subst ; rewrite hreg_eqb_refl in E ; discriminate | exact Hin
265Lemma no_dup_hregs_acc_disjoint
∀ rm ts seen t1 r
no_dup_hregs_accrm ts seen = true
Int1 ts
Inr seen
zmap_find_natt1 rm = Somer
False
Proof 16 steps Qed
intros rm ts
induction ts as | t ts′ IH ; intros seen t1 r Hnd Hin Hseen Hrm ; simpl in *
–contradiction
–destruct zmap_find_natt rm as rt | eqn: Ert
+destruct hreg_in_listrt seen eqn: Ein ; discriminate |
destruct Hin as ← | Hin′
∗rewrite Hrm in Ert
injection Ert as ←
pose proof proj2hreg_in_list_specr seen Hseen as Ht
rewrite Ht in Ein
discriminate
∗eapply IH ; exact Hnd | exact Hin' | right ; exact Hseen | exact Hrm
+destruct Hin as ← | Hin′
∗rewrite Hrm in Ert
discriminate
∗eapply IH ; exact Hnd | exact Hin' | exact Hseen | exact Hrm

When no_dup_hregs holds on a duplicate-free list ts, distinct elements in ts never map to the same hreg.

285Lemma no_dup_hregs_inj
∀ rm ts t1 t2 r
NoDupts
no_dup_hregsrm ts = true
Int1 ts
Int2 ts
t1 ≠ t2
zmap_find_natt1 rm = Somer
zmap_find_natt2 rm = Somer
False
Proof 21 steps Qed
intros rm ts Hndup
assert Hgen : ∀seen, no_dup_hregs_accrm ts seen = true → ∀t1 t2 r, Int1 ts → Int2 ts → t1 ≠ t2 → zmap_find_natt1 rm = Somer → zmap_find_natt2 rm = Somer → False
{induction Hndup as | t ts′ Hnotin Hndup′ IH ; intros seen Hacc t1 t2 r Hin1 Hin2 Hneq Hr1 Hr2 ; simpl in *
–contradiction
–destruct zmap_find_natt rm as rt | eqn: Ert
+destruct hreg_in_listrt seen eqn: Ein ; discriminate |
destruct Hin1 as ← | Hin1′ ; destruct Hin2 as ← | Hin2′
∗congruence
∗rewrite Hr1 in Ert
injection Ert as ←
eapply no_dup_hregs_acc_disjoint ; exact Hacc | exact Hin2' | left ; reflexivity | exact Hr2
∗rewrite Hr2 in Ert
injection Ert as ←
eapply no_dup_hregs_acc_disjoint ; exact Hacc | exact Hin1' | left ; reflexivity | exact Hr1
∗eapply IH ; exact Hacc | exact Hin1' | exact Hin2' | exact Hneq | exact Hr1 | exact Hr2
+destruct Hin1 as ← | Hin1′ ; rewrite Hr1 in Ert ; discriminate |
destruct Hin2 as ← | Hin2′ ; rewrite Hr2 in Ert ; discriminate |
eapply IH ; exact Hacc | exact Hin1' | exact Hin2' | exact Hneq | exact Hr1 | exact Hr2
intros Hacc
eapply Hgen ; exact Hacc
311Lemma all_callee_saved_spec
∀ rm ts t r
all_callee_savedrm ts = true
Int ts
zmap_find_natt rm = Somer
Proof 10 steps Qed
intros rm ts
induction ts as | x ts′ IH ; intros t r Hall Hin Hrm ; simpl in *
–contradiction
–destruct Hin as ← | Hin′
+rewrite Hrm in Hall
destruct hreg_callee_savedr ; reflexivity | discriminate
+destruct zmap_find_natx rm as rx |
∗destruct hreg_callee_savedrx ; | discriminate
eapply IH ; eauto
∗eapply IH ; eauto

Clobbering caller-saved registers preserves state_agrees on any set ts accepted by all_callee_saved.

328Theorem clobber_preserves_agrees
∀ rm ts tenv ms arb
all_callee_savedrm ts = true
state_agreesrm ts tenv ms
state_agreesrm ts tenv clobber_callarb ms
Proof 13 steps Qed
intros rm ts tenv ms arb Hcs Hslot Hlive
split
–intros t Hnone
simpl
apply Hslot
exact Hnone
–intros t Hin
unfold read_mach in *
specialize Hlivet Hin
destruct zmap_find_natt rm as r | eqn: Er ; simpl
+rewrite all_callee_saved_specrm ts t r Hcs Hin Er
exact Hlive
+exact Hlive

Corollary for poll edges: when check_succs_polls accepts a Poll edge to block si, filc_pollcheck_slow clobbering caller-saved registers preserves every live-in and phi-defined temporary of si.

346Theorem poll_edge_clobber_sound
∀ rm header_live tenv ms arb
all_callee_savedrm header_live = true
state_agreesrm header_live tenv ms
state_agreesrm header_live tenv clobber_callarb ms
Proof 2 steps Qed
intros
apply clobber_preserves_agrees ; assumption

No other temporary t ≠ d in live shares d's assigned register in rm.

356Definition dest_no_collisionrm : ZMap.threg d : nat live : listnat : Prop ≔
∀r t, Int live → t ≠ d → zmap_find_natd rm = Somer → zmap_find_natt rm = Somer → False

Writing temporary d preserves every other temporary t ≠ d whose register does not collide with d's, and sets d to v.

362Theorem write_mach_step_sound
∀ rm live tenv ms d v
state_agreesrm filterλt ⇒ negbNat.eqbt d live tenv ms
λ t  ⇒
→
v
else
tenvt
write_machrm ms d v
Proof 40 steps Qed
intros rm live tenv ms d v Hdisj Hslot Hlive
split
–intros t Hnone
unfold write_mach
destruct zmap_find_natd rm as rd | eqn: Erd ; simpl
+destruct Nat.eqbt d eqn: Etd
∗apply Nat.eqb_eq in Etd
subst t
rewrite Hnone in Erd
discriminate
∗apply Hslot
exact Hnone
+destruct Nat.eqbt d eqn: Etd ; reflexivity | apply Hslot ; exact Hnone
–intros t Hin
destruct Nat.eqbt d eqn: Etd
+apply Nat.eqb_eq in Etd
subst t
destruct zmap_find_natd rm as rd | eqn: Erd ; simpl
∗rewrite hreg_eqb_refl
reflexivity
∗rewrite Nat.eqb_refl
reflexivity
+assert Hin_filt : Int filterλx ⇒ negbNat.eqbx d live
{apply filter_In
split ; exact Hin | rewrite Etd ; reflexivity
specialize Hlivet Hin_filt
unfold read_mach in Hlive
destruct zmap_find_natd rm as rd | eqn: Erd ; destruct zmap_find_natt rm as rt | eqn: Ert ; simpl
∗destruct hreg_eqbrt rd eqn: Er
--apply hreg_eqb_spec in Er
subst rt
exfalso
apply Nat.eqb_neq in Etd
eapply Hdisj ; exact Hin | exact Etd | exact Erd | exact Ert
--exact Hlive
∗exact Hlive
∗exact Hlive
∗rewrite Etd
exact Hlive

Helper predicates and state steps for check_rinst_step_sound, stated at top level so the theorem renders as an inference rule without nested let or match blocks.

398Definition live_withoutd : nat live : listnat : listnat ≔
filterλt ⇒ negbNat.eqbt d live
401Definition tenv_settenv : nat → Z d : nat v : Z t : nat : Z ≔
→
v
else
tenvt
404Definition call_mid_okrm : ZMap.threg call : rcall live_mid : listnat : Prop ≔
match call with
⇒
all_callee_savedrm live_mid = true
_
⇒
True
410Definition call_pre_okrm : ZMap.threg call : rcall live_before : listnat : Prop ≔
match call with
⇒
all_callee_savedrm live_before = true
_
⇒
True
416Definition pre_call_statecall : rcall arb : hreg → Z ms : mach_state : mach_state ≔
match call with
422Definition post_call_statecall : rcall arb : hreg → Z ms : mach_state : mach_state ≔

Complete one-instruction simulation theorem: reading inputs uses, clobbering caller-saved registers according to call, and writing destination d preserves state_agrees whenever no_dup_hregs and all_callee_saved hold as checked by check_rinsts_rev.

432Theorem check_rinst_step_sound
∀ rm live_after d uses call f arb1 arb2 tenv ms
dest_no_collisionrm d live_after
call_mid_okrm call live_withoutd live_after
call_pre_okrm call uses ++ live_withoutd live_after
state_agreesrm uses ++ live_withoutd live_after tenv ms
mapread_machrm pre_call_statecall arb1 ms uses = maptenv uses ∧ state_agreesrm live_after tenv_settenv d fmaptenv uses write_machrm post_call_statecall arb2 pre_call_statecall arb1 ms d fmapread_machrm pre_call_statecall arb1 ms uses
Proof 43 steps Qed
intros rm live_after d uses call f arb1 arb2 tenv ms Hnodup Hca Hcd Hagree
set live_mid := live_withoutd live_after in *
set live_before := uses ++ live_mid in *
set ms_pre := pre_call_statecall arb1 ms
assert Hagree_pre : state_agreesrm live_before tenv ms_pre
{unfold ms_pre , pre_call_state
destruct call ; try exact Hagree
apply clobber_preserves_agrees ; exact Hcd | exact Hagree
assert Hargs : mapread_machrm ms_pre uses = maptenv uses
{apply map_ext_in
intros u Hu
destruct Hagree_pre as _ Hlb
apply Hlb
unfold live_before
apply in_or_app
left
exact Hu
split ; exact Hargs |
rewrite Hargs
unfold tenv_set
apply write_mach_step_sound ; exact Hnodup |
assert Hagree_mid : state_agreesrm live_mid tenv ms_pre
{destruct Hagree_pre as Hs Hlb
split ; exact Hs |
intros t Ht
apply Hlb
unfold live_before
apply in_or_app
right
exact Ht
destruct call
–exact Hagree_mid
–apply clobber_preserves_agrees ; exact Hca | exact Hagree_mid
+simpl in Hcd
clear - Hcd
unfold live_before in Hcd
induction uses as | u uses′ IH ; simpl in * ; exact Hcd |
destruct zmap_find_natu rm as ru |
∗destruct hreg_callee_savedru ; exact IHHcd | discriminate
∗exact IHHcd
+exact Hagree_mid

Callee-saved save and restore invariant: every callee-saved register r is restored to its caller entry value entry_regsr, whether r was saved and restored from its dedicated save slot (because rm used r) or untouched throughout the body (because rm never assigned r and every call preserves callee-saved registers).

480Definition exec_savesused : listhreg entry_regs : hreg → Z save_mem : hreg → Z : hreg → Z ≔
λ r  ⇒
→
entry_regsr
else
save_memr
484Definition exec_restoresused : listhreg save_mem : hreg → Z body_regs : hreg → Z : hreg → Z ≔
λ r  ⇒
→
save_memr
else
body_regsr
488Theorem callee_saves_restore_sound
∀ used : listhreg entry_regs body_regs save_mem0 : hreg → Z r : hreg
hreg_in_listr used = false → body_regsr = entry_regsr
exec_restoresused exec_savesused entry_regs save_mem0 body_regs r = entry_regsr
Proof 6 steps Qed
intros used entry_regs body_regs save_mem0 r _ Huntouched
destruct hreg_in_listr used eqn: Ein
–reflexivity
–apply Huntouched
reflexivity

Capability root invariant: KLowerk is never mapped to an allocatable register PmReg, so pointer lowers stay in their lowers[ ] GC root slots.

504Theorem lower_key_never_hreg
∀ rc k r
key_pm_locrc KLowerk ≠ SomePmRegr
Proof 3 steps Qed
intros rc k r
simpl
destruct slotrc_cxrc KLowerk ; intro H ; discriminate

3. Parallel-move soundness

Abstract valuation of parallel-move locations.

514Definition eval_pm_srcenv : pm_loc → Z half : bool s : pm_src : Z ≔
let m ≔
half
→
else
in
match s with
⇒
envl mod m
⇒
n mod m
522Definition exec_pmove_absenv : pm_loc → Z m : pmove : pm_loc → Z ≔
let v ≔ eval_pm_srcenv pmv_halfm pmv_srcm in
λ l  ⇒
else
envl
526Lemma pm_loc_eqb_refl
∀ l
pm_loc_eqbl l = true
Proof 4 steps Qed
destruct l as r | off | ; simpl
–apply hreg_eqb_refl
–apply Z.eqb_refl
–reflexivity
534Lemma pm_loc_eqb_spec
∀ a b
pm_loc_eqba b = true ↔ a = b
Proof 7 steps Qed
intros a b
destruct a as r1 | o1 | , b as r2 | o2 | ; simpl ; try split ; intro H ; discriminate | congruence
–rewrite hreg_eqb_spec
split ; congruence
–rewrite Z.eqb_eq
split ; congruence
–split ; reflexivity
543Lemma loc_not_read_eval_unchanged
∀ env m m′
Proof 10 steps Qed
intros env m m′ Hnr
simpl in Hnr
destruct pmv_srcm' as l′ | n | g ; try reflexivity
destruct pm_loc_eqbl' pmv_dstm eqn: E
–apply pm_loc_eqb_spec in E
subst l'
rewrite pm_loc_eqb_refl in Hnr
discriminate
–reflexivity

Ready-move peeling step: if m's destination is not read by any other move m' in rest, executing m now establishes m's final target value and leaves every source in rest unchanged.

559Theorem ready_pmove_step_sound
∀ env m rest
exec_pmove_absenv m pmv_dstm = eval_pm_srcenv pmv_halfm pmv_srcm ∧ ∀m′, Inm′ rest → eval_pm_srcexec_pmove_absenv m pmv_halfm′ pmv_srcm′ = eval_pm_srcenv pmv_halfm′ pmv_srcm′ ∧ ∀l, l ≠ pmv_dstm → exec_pmove_absenv m l = envl
Proof 20 steps Qed
intros env m rest Hnr
split ; | split
–unfold exec_pmove_abs
reflexivity
–intros m′ Hin
induction rest as | r0 rs IH ; simpl in *
+contradiction
+destruct match pmv_srcr0 with PsLocl′ ⇒ pm_loc_eqbpmv_dstm l′ | _ ⇒ false end eqn: Eh ; discriminate |
destruct Hin as ← | Hin′
simpl
rewrite Eh
reflexivity
∗apply IH ; assumption
–intros l Hneq
destruct pm_loc_eqbl pmv_dstm eqn: E ; | reflexivity
apply pm_loc_eqb_spec in E
contradiction

Cycle-breaking step: saving old into PmCycleTmp (%rcx) and rewriting reads of old to PmCycleTmp preserves the target value of every move (provided PmCycleTmp was not previously read) and eliminates all reads of old, making old immediately ready on the next step.

586Definition save_cycle_absenv : pm_loc → Z old : pm_loc : pm_loc → Z ≔
λ l  ⇒
else
envl
589Definition subst_one_pmoveold : pm_loc m : pmove : pmove ≔
let src′ ≔
match pmv_srcm with
in
597Definition no_cycle_tmp_srcm : pmove : Prop ≔
match pmv_srcm with
_
⇒
True
603Theorem cycle_break_step_sound
Proof 26 steps Qed
intros env old m Hnot_tmp Hno_tmp
unfold no_cycle_tmp_src in Hno_tmp
simpl
destruct pmv_srcm as l | n | g
–destruct pm_loc_eqbl old eqn: Elo
+apply pm_loc_eqb_spec in Elo
subst l
simpl
split ; reflexivity |
destruct pm_loc_eqbold PmCycleTmp eqn: Ebad ; | reflexivity
apply pm_loc_eqb_spec in Ebad
contradiction
+simpl
destruct pm_loc_eqbl PmCycleTmp eqn: Elt
∗apply pm_loc_eqb_spec in Elt
subst l
contradiction
∗split ; reflexivity |
destruct pm_loc_eqbold l eqn: Eol ; | reflexivity
apply pm_loc_eqb_spec in Eol
subst l
rewrite pm_loc_eqb_refl in Elo
discriminate
–split ; reflexivity
–split ; reflexivity

4. Soundness of 3-address lea and immediate selection

integer_immediate produces a value congruent to n modulo 2 ^ 32 (half = true) or 2 ^ 64 (half = false).

635Theorem imm32_congruent
∀ half n iv
integer_immediatehalf n = Someiv
iv
mod
half
→
else
=
n
mod
half
→
else
Proof 16 steps Qed
intros | n iv H ; unfold integer_immediate in H
–injection H as ←
unfold two31 , two32
rewrite Zminus_mod_idemp_l
replace n + 2147483648 − 2147483648 with n by lia
reflexivity
–cbv zeta in H
destruct −two31 ≤? _ && _ ≤? two31 − 1 eqn: E ; | discriminate
injection H as ←
destruct n mod two64 ≥? two63 eqn: Ege
+rewrite Zminus_mod_idemp_l
replace n − two64 with n + −1 × two64 by lia
apply Z_mod_plus_full
+apply Z.mod_mod
unfold two64
lia

Immediate add and lea disp(%rx) compute x + n mod M at both 32-bit and 64-bit widths.

657Theorem imm32_add_mod_sound
∀ half x n iv
integer_immediatehalf n = Someiv
x + iv
mod
half
→
else
=
x + n
mod
half
→
else
Proof 8 steps Qed
intros half x n iv H
pose proof imm32_congruenthalf n iv H as Hc
pose proof Z.add_modx iv if half then two32 else two64 as H1
pose proof Z.add_modx n if half then two32 else two64 as H2
assert Hm : if half then two32 else two64 ≠ 0 by destruct half ; unfold two32 , two64 ; lia
rewrite H1 , H2 by exact Hm
rewrite Hc
reflexivity
670Lemma mod_two64_mod_two32
∀ a
a mod two64 mod two32 = a mod two32
Proof 4 steps Qed
intro a
pose proof Z_div_mod_eq_fulla two64 as Heq
replace a mod two64 with a + −a / two64 × two32 × two32 by unfold two32 , two64 in * ; lia
apply Z_mod_plus_full

32-bit Sub via leal (-n)(%rx), %dst: x86-64 adds the 64-bit sign-extended 32-bit displacement iv to the 64-bit base register x modulo 2 ^ 64, then truncates to 32 bits (mod 2^32). Even at the boundary n = −2 ^ 31 (where −n = 2 ^ 31 wraps to iv = −2 ^ 31), the result equals x − n mod 2 ^ 32.

685Theorem imm32_sub_lea_w_sound
∀ x n iv
integer_immediatetrue −n = Someiv
x + iv mod two64 mod two32 = x − n mod two32
Proof 4 steps Qed
intros x n iv H
replace x − n with x + −n by lia
exact imm32_add_mod_soundtrue x −n iv H

64-bit Sub via leaq (-n)(%rx), %dst computes x − n mod 2 ^ 64.

696Theorem imm32_sub_lea_l_sound
∀ x n iv
integer_immediatefalse −n = Someiv
x + iv mod two64 = x − n mod two64
Proof 3 steps Qed
intros x n iv H
replace x − n with x + −n by lia
exact imm32_add_mod_soundfalse x −n iv H

5. Executable rejection examples for valid_alloc

707Definition ex_cmap2: ZMap.tclass ≔
710Definition ex_rm1t : nat r : hreg : ZMap.threg ≔
zmap_add_natt r ZMap.emptyhreg
713Definition ex_rb_collision: rblock ≔
mkRBlock0%nat [ ] [ ] mkRInst0%nat; 1%nat [ ] RCallNone [ ]
716Definition ex_rm_collision: ZMap.threg ≔

Two live parameters mapped to the same register HRbx are rejected.

720Example ex_rejects_collision: valid_allocex_cmap2 0%nat; 1%nat ex_rb_collision ex_rm_collision = false
Proof 1 step Qed
reflexivity
724Definition ex_rb_after_call: rblock ≔
mkRBlock0%nat [ ] [ ] mkRInst[ ] [ ] RCallAfterReads 0%nat

A caller-saved register HR10 live across RCallAfterReads is rejected, while callee-saved HRbx is accepted.

729Example ex_rejects_r10_call: valid_allocex_cmap2 0%nat ex_rb_after_call ex_rm10%nat HR10 = false ∧ valid_allocex_cmap2 0%nat ex_rb_after_call ex_rm10%nat HRbx = true
Proof 1 step Qed
split ; reflexivity
734Definition ex_rb_during_call: rblock ≔
mkRBlock0%nat [ ] [ ] mkRInst0%nat [ ] RCallDuringReads [ ]

Input of RCallDuringReads (AStorePointer / ADispatch) in HR11 is rejected even when dead after the instruction.

739Example ex_rejects_r11_read_call: valid_allocex_cmap2 0%nat ex_rb_during_call ex_rm10%nat HR11 = false ∧ valid_allocex_cmap2 0%nat ex_rb_during_call ex_rm10%nat HR12 = true
Proof 1 step Qed
split ; reflexivity
744Definition ex_rb_poll0: rblock ≔
mkRBlock0%nat 1%nat, false [ ] [ ] [ ]
747Definition ex_rb_poll1: rblock ≔
mkRBlock1%nat 1%nat, true 1%nat, 0%nat, Some0%nat; 1%nat, Some1%nat [ ] 1%nat

A phi destination in HR10 on a Poll loop back-edge is rejected, while HR13 is accepted.

752Example ex_rejects_r10_poll: valid_allocex_cmap2 0%nat ex_rb_poll0; ex_rb_poll1 ex_rm11%nat HR10 = false ∧ valid_allocex_cmap2 0%nat ex_rb_poll0; ex_rb_poll1 ex_rm11%nat HR13 = true
Proof 1 step Qed
split ; reflexivity
757Definition ex_rb_float: rblock ≔
mkRBlock0%nat [ ] [ ] [ ] 2%nat

Assigning a float temporary (Double) to a general register is rejected.

761Example ex_rejects_float: valid_allocex_cmap2 2%nat ex_rb_float ex_rm12%nat HRbx = false
Proof 1 step Qed
reflexivity