Require Import Coqlib.
Require Import Errors.
Require Import Maps.
Require Import AST.
Require Import Integers.
Require Import Values.
Require Import Globalenvs.
Require Import Smallstep.
Require Import Dom.
Require Import Op.
Require Import SSA.
Require Import SSAutils.
Require Import Utils.
Require Import CSSA.
Require RTLpar.
Require Import RTLpargen.
Require Import Kildall.
Require Import KildallComp.
Require Import DLib.
Require Import Events.
Require CSSAlive.
Require Import CSSAval.
Require Import CSSAninterf.
Require Import CSSAutils.
Require Import Classical.
Require Import CSSAdef.
Require Import Registers.
Unset Allow StrictProp.
Lemma compute_regrepr_correct :
forall f r r'
regrepr,
wf_cssa_function f ->
compute_regrepr f =
Errors.OK regrepr ->
regrepr r =
regrepr r' ->
(
exists d1,
def f r d1) ->
(
exists d2,
def f r'
d2) ->
ninterfere_spec f r r'.
Proof.
Lemma compute_regrepr_init :
forall f regrepr phib pc r r'
dst args,
compute_regrepr f =
Errors.OK regrepr ->
(
fn_phicode f) !
pc =
Some phib ->
In (
Iphi args dst)
phib ->
In r (
dst ::
args) ->
In r' (
dst ::
args) ->
regrepr r =
regrepr r'.
Proof.
intros until args.
intros Hregrepr Hphib Hphi Hinr Hinr'.
unfold compute_regrepr in Hregrepr.
flatten Hregrepr.
rewrite andb_true_iff in Eq1.
destruct Eq1 as [
Hclasses Hcssaphis].
unfold check_cssa_coalescing_in_phicode in Hcssaphis.
unfold check_cssa_coalescing_in_phib in Hcssaphis.
unfold check_phi_ressources_coalescing in Hcssaphis.
rewrite forallb_forall in Hcssaphis.
specialize (
Hcssaphis phib).
exploit Hcssaphis;
eauto.
exploit PTree.elements_correct;
eauto.
intros.
eapply In_Insnd_phib;
eauto.
intros Hcssaphi.
rewrite forallb_forall in Hcssaphi.
specialize (
Hcssaphi (
Iphi args dst)).
exploit Hcssaphi;
eauto.
intros Hcssaarg.
rewrite forallb_forall in Hcssaarg.
case_eq (
peq r dst);
intros;
case_eq (
peq r'
dst);
intros.
congruence.
exploit (
Hcssaarg r');
eauto.
inv Hinr';
auto.
congruence.
intros Eqr'
dst.
rewrite <-
e in Eqr'
dst.
destruct peq in Eqr'
dst;
go.
exploit (
Hcssaarg r);
eauto.
inv Hinr;
auto.
congruence.
intros Eqrdst.
rewrite e.
destruct peq in Eqrdst;
go.
exploit (
Hcssaarg r');
eauto.
inv Hinr';
auto.
congruence.
intros Eqr'
dst.
exploit (
Hcssaarg r);
eauto.
inv Hinr;
auto.
congruence.
intros Eqrdst.
destruct peq in Eqr'
dst;
destruct peq in Eqrdst;
go.
Qed.
Transformation spec
Variant transl_function_spec:
CSSA.function ->
RTLpar.function ->
Prop :=
|
transl_function_spec_intro:
forall f tf regrepr
(
RegRepr:
compute_regrepr f =
Errors.OK regrepr)
(
codeNone:
forall pc,
(
fn_code f) !
pc =
None ->
(
RTLpar.fn_code tf) !
pc =
None)
(
codeSome:
forall pc ins,
(
fn_code f) !
pc =
Some ins ->
(
RTLpar.fn_code tf) !
pc =
Some (
transl_instruction regrepr ins))
(
parcbNone:
forall pc,
(
fn_parcopycode f) !
pc =
None ->
(
RTLpar.fn_parcopycode tf) !
pc =
None)
(
parcbSome:
forall pc parcb,
(
fn_parcopycode f) !
pc =
Some parcb ->
(
RTLpar.fn_parcopycode tf) !
pc =
Some (
parcb_cleanup (
transl_parcb regrepr parcb))),
transl_function_spec f tf.
Variant tr_function:
CSSA.function ->
RTLpar.function ->
Prop :=
|
tr_function_intro:
forall f regrepr (
Regrepr:
compute_regrepr f =
Errors.OK regrepr),
tr_function
f
(
RTLpar.mkfunction
f.(
fn_sig)
(
map regrepr f.(
fn_params))
f.(
fn_stacksize)
(
transl_code regrepr f.(
fn_code))
(
parcopycode_cleanup (
transl_parcopycode regrepr f.(
fn_parcopycode)))
f.(
fn_entrypoint)).
Lemma transl_function_charact:
forall f tf,
wf_cssa_function f ->
transl_function f =
Errors.OK tf ->
tr_function f tf.
Proof.
Lemma transl_function_correct :
forall f tf,
tr_function f tf ->
transl_function_spec f tf.
Proof.
Definition transl_fundef (
f:
CSSA.fundef) :
res RTLpar.fundef :=
transf_partial_fundef transl_function f.
match_states
Variant lazydef (
f :
function) (
r :
reg) (
pc :
node) :
Prop :=
|
lazydef_phi:
assigned_phi_spec (
fn_phicode f)
pc r ->
lazydef f r pc
|
lazydef_parcb':
assigned_parcopy_spec (
fn_parcopycode f)
pc r ->
join_point pc f ->
lazydef f r pc.
Variant match_regset (
f :
CSSA.function) (
pc :
node) :
SSA.regset ->
SSA.regset ->
Prop :=
|
mrg_intro :
forall rs rs'
regrepr,
forall (
RegRepr:
compute_regrepr f =
Errors.OK regrepr),
(
forall r, (
cssalive_spec f r pc /\ ~
lazydef f r pc)
\/
lazydef f r pc ->
rs #
r =
rs' # (
regrepr r)) ->
match_regset f pc rs rs'.
Inductive match_stackframes :
list CSSA.stackframe ->
list RTLpar.stackframe ->
Prop :=
|
match_stackframes_nil:
match_stackframes nil nil
|
match_stackframes_cons:
forall res f sp pc rs rs'
s tf ts regrepr
(
STACK :
match_stackframes s ts )
(
SPEC:
transl_function f =
Errors.OK tf)
(
WFF:
wf_cssa_function f)
(
RegRepr:
compute_regrepr f =
Errors.OK regrepr)
(
MRs:
forall r,
(
cssalive_spec f r pc /\ ~
lazydef f r pc /\
r <>
res)
\/
lazydef f r pc ->
rs #
r =
rs' # (
regrepr r))
(
Hnotlive:
forall r,
regrepr r =
regrepr res ->
r <>
res ->
~
cssalive_spec f r pc)
(
Hnotlazydef:
forall r, ~
lazydef f r pc),
match_stackframes
(
Stackframe res f sp pc rs ::
s)
(
RTLpar.Stackframe (
regrepr res)
tf sp pc rs' ::
ts).
Global Hint Constructors match_stackframes:
core.
Set Implicit Arguments.
Require Import Linking.
Section PRESERVATION.
Definition match_prog (
p:
CSSA.program) (
tp:
RTLpar.program) :=
match_program (
fun cu f tf =>
transl_fundef f =
Errors.OK tf)
eq p tp.
Lemma transf_program_match:
forall p tp,
transl_program p =
OK tp ->
match_prog p tp.
Proof.
Section CORRECTNESS.
Variable prog:
CSSA.program.
Variable tprog:
RTLpar.program.
Let ge :=
Genv.globalenv prog.
Let tge :=
Genv.globalenv tprog.
Hypothesis TRANSF_PROG:
match_prog prog tprog.
Hypothesis WF_PROG :
wf_cssa_program prog.
Variant match_states:
CSSA.state ->
RTLpar.state ->
Prop :=
|
match_states_intro:
forall s ts sp pc rs rs'
m f tf
(
REACH:
reachable prog (
State s f sp pc rs m))
(
SPEC:
transl_function f =
Errors.OK tf)
(
STACK:
match_stackframes s ts)
(
WFF:
wf_cssa_function f)
(
MREG:
match_regset f pc rs rs'),
match_states
(
State s f sp pc rs m)
(
RTLpar.State ts tf sp pc rs'
m)
|
match_states_call:
forall s ts f tf args m
(
REACH:
reachable prog (
Callstate s f args m))
(
SPEC:
transl_fundef f =
Errors.OK tf)
(
STACK:
match_stackframes s ts)
(
WFF:
wf_cssa_fundef f),
match_states
(
Callstate s f args m)
(
RTLpar.Callstate ts tf args m)
|
match_states_return:
forall s ts v m
(
REACH:
reachable prog (
Returnstate s v m))
(
STACK:
match_stackframes s ts ),
match_states
(
Returnstate s v m)
(
RTLpar.Returnstate ts v m).
Hint Constructors match_states:
core.
Lemma parcb_transl_other :
forall parcb f r rs'
regrepr,
compute_regrepr f =
Errors.OK regrepr ->
(
forall src dst,
In (
Iparcopy src dst)
parcb ->
(
regrepr r) <> (
regrepr dst) \/
regrepr r =
regrepr dst /\
rs' # (
regrepr r) =
rs' # (
regrepr src)) ->
(
parcopy_store
(
parcb_cleanup (
transl_parcb regrepr parcb))
rs')
# (
regrepr r) =
rs' # (
regrepr r).
Proof.
induction parcb;
auto.
intros f r rs'
regrepr Hregrepr Hprops.
simpl in *.
destruct a.
flatten;
go.
simpl.
case_eq (
peq (
regrepr r)
(
regrepr r1));
intros.
+
rewrite e in *.
rewrite PMap.gss;
eauto.
exploit (
Hprops r0 r1).
go.
intros Hprop.
destruct Hprop;
go.
destruct H0;
go.
+
rewrite PMap.gso;
eauto.
Qed.
Lemma parcb_transl_store_in :
forall parcb f rs'
r src regrepr,
In (
Iparcopy src r)
parcb ->
NoDup (
map parc_dst parcb) ->
(
forall src'
dst,
In (
Iparcopy src'
dst)
parcb ->
(
regrepr r) <> (
regrepr dst) \/
rs' # (
regrepr src') =
rs' # (
regrepr src)) ->
compute_regrepr f =
Errors.OK regrepr ->
(
parcopy_store
(
parcb_cleanup (
transl_parcb regrepr parcb))
rs')
# (
regrepr r) =
rs' # (
regrepr src).
Proof.
induction parcb;
intros f rs'
r src regrepr Hin HNoDup Hprops Hregrepr;
simpl in *.
+
contradiction.
+
destruct a.
flatten;
go.
{
destruct Hin.
-
assert (
EQ1:
r1 =
r)
by congruence.
assert (
EQ2:
r0 =
src)
by congruence.
rewrite EQ1,
EQ2 in *.
rewrite <-
e.
rewrite parcb_transl_other with (
f :=
f);
go;
intros.
case_eq(
peq (
regrepr src) (
regrepr dst));
auto;
intros.
right.
split;
auto.
exploit Hprops;
go;
intros.
destruct H2;
go.
-
inv HNoDup.
eapply IHparcb;
go.
}
destruct Hin.
-
assert (
EQ1:
r1 =
r)
by congruence.
assert (
EQ2:
r0 =
src)
by congruence.
rewrite EQ1,
EQ2 in *.
simpl.
rewrite PMap.gss;
auto.
-
inv HNoDup.
case_eq (
peq (
regrepr r1) (
regrepr r));
intros;
simpl.
{
rewrite e in *.
rewrite PMap.gss.
exploit (
Hprops r0 r1);
auto;
intros.
destruct H1;
congruence. }
{
rewrite PMap.gso;
eauto. }
Qed.
Lemma no_successive_jp :
forall f pc pc',
wf_cssa_function f ->
join_point pc f ->
join_point pc'
f ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
False.
Proof.
Simulation lemmas
Lemma not_lazydef_in_pred :
forall f pc pc'
phib r,
wf_cssa_function f ->
(
fn_phicode f) !
pc' =
Some phib ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
~
lazydef f r pc.
Proof.
intros until r.
intros WF Hphib Hinop.
unfold not;
intros Hlazy.
assert ((
fn_phicode f) !
pc =
None).
eapply jp_not_preceded_by_jp;
eauto.
go.
inv Hlazy.
inv H0.
go.
inv H0.
induction WF.
assert ((
fn_phicode f) !
pc <>
None).
apply fn_phicode_inv;
auto.
congruence.
Qed.
Lemma not_use_and_def_in_jppred :
forall f pc parcb pc'
phib r src,
wf_cssa_function f ->
(
fn_parcopycode f) !
pc =
Some parcb ->
(
fn_phicode f) !
pc' =
Some phib ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
In (
Iparcopy src r)
parcb ->
~
def f src pc.
Proof.
Ltac eqregreprs regrepr0 regrepr :=
assert(
EQREGREPRS:
regrepr0 =
regrepr)
by congruence;
rewrite EQREGREPRS in *.
Lemma simul_parcb :
forall r f parcb'
phib parcb
rs rs'
regrepr pc pc'
s sp d m,
wf_cssa_function f ->
check_cssaval f (
compute_cssaval_function f)
(
get_ext_params f (
get_all_def f)) =
true ->
reachable prog (
State s f sp pc rs m) ->
compute_regrepr f =
Errors.OK regrepr ->
(
fn_phicode f) !
pc' =
Some phib ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
(
fn_parcopycode f) !
pc =
Some parcb ->
(
fn_parcopycode f) !
pc' =
Some parcb' ->
match_regset f pc rs rs' ->
def f r d ->
(
cssalive_spec f r pc' /\
~
assigned_parcopy_spec (
fn_parcopycode f)
pc r)
\/
assigned_parcopy_spec (
fn_parcopycode f)
pc r ->
(
parcopy_store parcb rs) !!
r =
(
parcopy_store (
parcb_cleanup (
transl_parcb regrepr parcb))
rs')
!! (
regrepr r).
Proof.
Lemma simul_parcbphib :
forall r f parcb'
phib k parcb
rs rs'
regrepr pc pc'
s sp d m,
wf_cssa_function f ->
check_cssaval f (
compute_cssaval_function f)
(
get_ext_params f (
get_all_def f)) =
true ->
reachable prog (
State s f sp pc rs m) ->
compute_regrepr f =
Errors.OK regrepr ->
(
fn_phicode f) !
pc' =
Some phib ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
(
fn_parcopycode f) !
pc =
Some parcb ->
(
fn_parcopycode f) !
pc' =
Some parcb' ->
index_pred (
get_preds f)
pc pc' =
Some k ->
(
cssalive_spec f r pc' /\
~
assigned_parcopy_spec (
fn_parcopycode f)
pc r /\
~
assigned_phi_spec (
fn_phicode f)
pc'
r)
\/
assigned_parcopy_spec (
fn_parcopycode f)
pc r
\/
assigned_phi_spec (
fn_phicode f)
pc'
r ->
match_regset f pc rs rs' ->
def f r d ->
(
phi_store k phib
(
parcopy_store parcb rs)) !!
r =
(
parcopy_store (
parcb_cleanup (
transl_parcb regrepr parcb))
rs') !! (
regrepr r).
Proof.
intros until m.
intros WF Wcssaval Reach Hregrepr Hphib Hinop Hparcb Hparcb'
Hindex
Hprops MR Hdef.
case_eq (
In_dst_phib r phib);
intros.
+
exploit In_dst_phib_true;
eauto;
intros.
destruct H0 as [
args Hin].
assert (
Harg:
exists arg,
nth_error args k =
Some arg).
eapply fn_phiargs;
eauto.
destruct Harg as [
arg Hnth].
assert (
regrepr arg =
regrepr r).
{
eapply compute_regrepr_init;
eauto.
induction WF;
auto.
constructor 2.
eapply nth_error_in;
eauto.
}
rewrite <-
H0.
erewrite phi_store_in;
eauto.
assert(
USE:
use f arg pc)
by go.
exploit exists_def;
eauto;
intros DEF;
destruct DEF as [
argdef DEF].
eapply simul_parcb;
eauto.
{
induction WF.
right;
auto.
exploit fn_jp_use_phib;
go.
}
+
assert (
Hnotin:
forall args, ~
In (
Iphi args r)
phib).
apply In_dst_phib_false;
auto.
rewrite <-
phi_store_other.
eapply simul_parcb;
go.
destruct Hprops as [
Hprops |
Hprops].
left.
destruct Hprops as [
MR1 [
MR2 MR3]].
split;
go.
right.
destruct Hprops.
auto.
inv H0.
destruct H2 as [
args Hin].
assert(
EQ:
phiinstr =
phib)
by congruence.
rewrite EQ in *.
assert(
Hnotinphib: ~
In (
Iphi args r)
phib).
apply In_dst_phib_false;
auto.
congruence.
intros.
unfold not;
intros.
assert (~
In (
Iphi args dst)
phib).
rewrite H1 in *.
apply Hnotin.
auto.
Qed.
Lemma liveinout_jp :
forall f pc r,
wf_cssa_function f ->
join_point pc f ->
cssalive_spec f r pc ->
cssaliveout_spec f r pc.
Proof.
intros f pc r WF Hjp Hlive.
assert (
exists succ, (
fn_code f) !
pc =
Some (
Inop succ)).
{
induction WF.
apply fn_inop_in_jp.
rewrite fn_phicode_inv in Hjp.
auto.
}
destruct H as [
succ Hinop].
inv Hlive.
inv H0.
+
inv H1;
go.
+
assert(
join_point succ f).
inv H1.
assert(
is_edge (
fn_code f)
pc pc0).
eapply pred_is_edge_help;
eauto.
inv H0.
assert(
EQ:
instr =
Inop succ)
by congruence.
rewrite EQ in *.
simpl in *.
destruct H2;
try contradiction.
rewrite <-
H0 in *.
induction WF;
apply fn_phicode_inv;
congruence.
induction WF;
intuition.
+
induction WF.
intuition.
+
eapply correspondance_outin;
eauto.
+
eapply correspondance_outin;
eauto.
Qed.
Lemma invariant_props_used_in_parcb' :
forall f pc pc'
phib parcb'
src r,
wf_cssa_function f ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
(
fn_phicode f) !
pc' =
Some phib ->
(
fn_parcopycode f) !
pc' =
Some parcb' ->
In (
Iparcopy src r)
parcb' ->
cssalive_spec f src pc' /\
~
assigned_parcopy_spec (
fn_parcopycode f)
pc src /\
~
assigned_phi_spec (
fn_phicode f)
pc'
src \/
assigned_parcopy_spec (
fn_parcopycode f)
pc src \/
assigned_phi_spec (
fn_phicode f)
pc'
src.
Proof.
intros until r.
intros WF Hinop Hphib Hparcb' Hin.
right. right.
induction WF.
apply fn_jp_use_parcb'.
apply fn_phicode_inv.
congruence. go.
Qed.
Lemma cssaval_props_used_in_parcb' :
forall f pc pc'
phib parcb'
src r,
wf_cssa_function f ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
(
fn_phicode f) !
pc' =
Some phib ->
(
fn_parcopycode f) !
pc' =
Some parcb' ->
In (
Iparcopy src r)
parcb' ->
cssadom f src pc /\
~
assigned_phi_spec (
fn_phicode f)
pc'
src /\
~
assigned_parcopy_spec (
fn_parcopycode f)
pc src /\
~
assigned_parcopy_spec (
fn_parcopycode f)
pc'
src \/
assigned_parcopy_spec (
fn_parcopycode f)
pc src \/
assigned_phi_spec (
fn_phicode f)
pc'
src.
Proof.
intros until r.
intros WF Hinop Hphib Hparcb' Hin.
right. right.
induction WF.
apply fn_jp_use_parcb'.
apply fn_phicode_inv.
congruence. go.
Qed.
Ltac do_not_jp_pred pc_2 pc'
_2 :=
eapply no_successive_jp with (
pc :=
pc_2) (
pc' :=
pc'
_2);
eauto;
rewrite fn_phicode_inv;
try congruence.
Lemma rewrite_with_cssaval_until_jp :
forall f pc'
phib pc parcb parcb'
src r k rs s sp m,
wf_cssa_function f ->
reachable prog (
State s f sp pc rs m) ->
check_cssaval f (
compute_cssaval_function f)
(
get_ext_params f (
get_all_def f)) =
true ->
(
fn_phicode f) !
pc' =
Some phib ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
(
fn_parcopycode f) !
pc =
Some parcb ->
(
fn_parcopycode f) !
pc' =
Some parcb' ->
In (
Iparcopy src r)
parcb' ->
index_pred (
get_preds f)
pc pc' =
Some k ->
cssaval_spec f (
compute_cssaval_function f) ->
(
phi_store k phib (
parcopy_store parcb rs)) !!
src =
(
phi_store k phib (
parcopy_store parcb rs))
!! (
compute_cssaval_function f src).
Proof.
Lemma simul_parcbphibparcb' :
forall r f parcb'
phib k parcb
rs rs'
regrepr pc pc'
s sp d m,
wf_cssa_function f ->
check_cssaval f (
compute_cssaval_function f)
(
get_ext_params f (
get_all_def f)) =
true ->
reachable prog (
State s f sp pc rs m) ->
compute_regrepr f =
Errors.OK regrepr ->
(
fn_phicode f) !
pc' =
Some phib ->
(
fn_code f) !
pc =
Some (
Inop pc') ->
(
fn_parcopycode f) !
pc =
Some parcb ->
(
fn_parcopycode f) !
pc' =
Some parcb' ->
index_pred (
get_preds f)
pc pc' =
Some k ->
match_regset f pc rs rs' ->
((
cssalive_spec f r pc' /\ ~
lazydef f r pc'
/\ ~
assigned_parcopy_spec (
fn_parcopycode f)
pc r)
\/
(
cssalive_spec f r pc' /\ ~
lazydef f r pc'
/\
assigned_parcopy_spec (
fn_parcopycode f)
pc r)
\/
lazydef f r pc') ->
def f r d ->
(
parcopy_store parcb'
(
phi_store k phib
(
parcopy_store parcb rs)))
!!
r =
(
parcopy_store (
parcb_cleanup (
transl_parcb regrepr parcb'))
(
parcopy_store (
parcb_cleanup (
transl_parcb regrepr parcb))
rs'))
!! (
regrepr r).
Proof.
Lemma registers_equal :
forall args (
rs rs' :
SSA.regset)
regrepr,
(
forall r,
In r args ->
rs !!
r =
rs' !! (
regrepr r)) ->
rs ##
args =
rs' ## (
map regrepr args).
Proof.
induction args; intros.
go.
simpl.
rewrite <- IHargs with (rs := rs).
rewrite H. auto. constructor; auto.
intros. auto.
Qed.
Lemma stacksize_preserved:
forall f tf,
transl_function f =
Errors.OK tf ->
fn_stacksize f =
RTLpar.fn_stacksize tf.
Proof.
Lemma symbols_preserved:
forall (
s:
ident),
Genv.find_symbol tge s =
Genv.find_symbol ge s.
Proof.
Lemma function_ptr_translated:
forall (
b:
Values.block) (
f:
CSSA.fundef),
Genv.find_funct_ptr ge b =
Some f ->
exists tf,
Genv.find_funct_ptr tge b =
Some tf
/\
transl_fundef f =
Errors.OK tf.
Proof.
Lemma sig_fundef_translated:
forall f tf,
wf_cssa_fundef f ->
transl_fundef f =
Errors.OK tf ->
RTLpar.funsig tf =
CSSA.funsig f.
Proof.
intros f tf.
intros.
case_eq f;
intros.
-
rewrite H1 in H0.
simpl in *.
Errors.monadInv H0.
eapply transl_function_charact in EQ ;
eauto.
simpl in *.
inv EQ.
inv H.
auto.
inv H.
auto.
-
rewrite H1 in H0.
go.
Qed.
Ltac split_but_remember :=
match goal with
| [
H:
_ |- ?
A /\ ?
B ] =>
assert(
Hstep:
A)
end.
Ltac do_reachability REACH x :=
inv REACH;
match goal with
| [
Hreach:
exists t :
trace,
_ |-
_ ] =>
destruct Hreach as [
t Hreach];
destruct Hreach as [
Hinit Hreachstep];
constructor 1
with (
x :=
x);
go;
exists t;
split;
auto;
eapply star_right;
go;
rewrite E0_right;
auto
end.
Lemma predecessors_preserved :
forall f tf,
wf_cssa_function f ->
transl_function f =
Errors.OK tf ->
make_predecessors (
RTLpar.fn_code tf)
successors_instr
=
make_predecessors (
fn_code f)
successors_instr.
Proof.
Lemma jp_preserved_1 :
forall f tf jp,
wf_cssa_function f ->
transl_function f =
Errors.OK tf ->
join_point jp f ->
RTLpar.join_point jp tf.
Proof.
Lemma jp_preserved_2 :
forall f tf jp,
wf_cssa_function f ->
transl_function f =
Errors.OK tf ->
RTLpar.join_point jp tf ->
join_point jp f.
Proof.
Lemma lazydef_spec :
forall f pc r,
lazydef f r pc \/ ~
lazydef f r pc.
Proof.
Lemma live_implies_use :
forall f pc r,
wf_cssa_function f ->
cssalive_spec f r pc ->
exists pc',
use f r pc'.
Proof.
intros f pc r WF Hlive.
induction Hlive; go.
Qed.
Lemma cssadom_dom :
forall f pc r d,
wf_cssa_function f ->
~
join_point pc f ->
def f r d ->
cssadom f r pc ->
dom f d pc.
Proof.
intros f pc r d WF Hnjp Hdef Hdom.
inv Hdom.
+
assert(
EQ:
d =
def_r).
eapply def_def_eq;
eauto.
rewrite EQ in *.
exploit (@
sdom_spec positive);
eauto.
intros Hsdom.
destruct Hsdom.
auto.
+
inv H.
induction WF.
assert(
Hphinotnone: (
fn_phicode f) !
pc <>
None)
by congruence.
rewrite <-
fn_phicode_inv in Hphinotnone.
congruence.
+
congruence.
Qed.
Lemma not_parcb_def_outside_inop :
forall f pc r,
wf_cssa_function f ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
~
assigned_parcopy_spec (
fn_parcopycode f)
pc r.
Proof.
intros f pc r WF Hnotinop.
unfold not;
intros Hassign.
inv Hassign.
assert(
Hinop:
exists s, (
fn_code f) !
pc =
Some (
Inop s)).
eapply parcb_inop;
eauto.
go.
destruct Hinop;
congruence.
Qed.
Lemma not_phi_def_outside_inop :
forall f pc r,
wf_cssa_function f ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
~
assigned_phi_spec (
fn_phicode f)
pc r.
Proof.
intros f pc r WF Hnotinop.
unfold not;
intros Hassign.
inv Hassign.
assert(
Hinop:
exists s, (
fn_code f) !
pc =
Some (
Inop s)).
eapply fn_inop_in_jp;
go.
destruct Hinop;
go.
Qed.
Lemma not_lazydef_outside_inop :
forall f pc r,
wf_cssa_function f ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
~
lazydef f r pc.
Proof.
Lemma not_lazydef_outside_jp :
forall f pc r,
wf_cssa_function f ->
~
join_point pc f ->
~
lazydef f r pc.
Proof.
intros f pc r WF Hnojp.
unfold not;
intros Hlazy.
inv Hlazy;
auto.
inv H.
induction WF.
rewrite fn_phicode_inv in Hnojp.
intuition congruence.
Qed.
Lemma use_usecode_outside_inop :
forall f pc r,
wf_cssa_function f ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
use f r pc ->
use_code f r pc.
Proof.
Hint Resolve ident_eq:
core.
Lemma cssaval_contradiction_in_Ioporbuiltin :
forall f pc args res pc'
r s sp rs m,
reachable prog (
State s f sp pc rs m) ->
wf_cssa_function f ->
(
exists op, (
fn_code f) !
pc =
Some (
Iop op args res pc')) \/
(
exists fd r0,
(
fn_code f) !
pc =
Some (
Icall (
funsig fd) (
inl r0)
args res pc')) \/
(
exists fd i,
(
fn_code f) !
pc =
Some (
Icall (
funsig fd) (
inr i)
args res pc')) \/
(
exists chunk addr,
(
fn_code f) !
pc =
Some (
Iload chunk addr args res pc')) \/
(
exists ef args, (
fn_code f) !
pc =
Some (
Ibuiltin ef args (
BR res)
pc')) ->
cssaval_spec f (
compute_cssaval_function f) ->
compute_cssaval_function f r =
compute_cssaval_function f res ->
compute_cssaval_function f res =
res ->
r <>
res ->
cssalive_spec f r pc ->
False.
Proof.
Lemma cssaval_contradiction_in_Iop :
forall f pc op args res pc'
r s sp rs m,
reachable prog (
State s f sp pc rs m) ->
wf_cssa_function f ->
(
fn_code f) !
pc =
Some (
Iop op args res pc') ->
cssaval_spec f (
compute_cssaval_function f) ->
compute_cssaval_function f r =
compute_cssaval_function f res ->
compute_cssaval_function f res =
res ->
r <>
res ->
cssalive_spec f r pc ->
False.
Proof.
Lemma cssaval_contradiction_in_Ibuiltin :
forall f pc ef args res pc'
r s sp rs m,
reachable prog (
State s f sp pc rs m) ->
wf_cssa_function f ->
(
fn_code f) !
pc =
Some (
Ibuiltin ef args (
BR res)
pc') ->
cssaval_spec f (
compute_cssaval_function f) ->
compute_cssaval_function f r =
compute_cssaval_function f res ->
compute_cssaval_function f res =
res ->
r <>
res ->
cssalive_spec f r pc ->
False.
Proof.
Lemma cssaval_contradiction_in_Icall :
forall f pc fd args res pc'
r r0 s sp rs m,
reachable prog (
State s f sp pc rs m) ->
wf_cssa_function f ->
(
fn_code f) !
pc =
Some (
Icall (
funsig fd) (
inl r0)
args res pc') ->
cssaval_spec f (
compute_cssaval_function f) ->
compute_cssaval_function f r =
compute_cssaval_function f res ->
compute_cssaval_function f res =
res ->
r <>
res ->
cssalive_spec f r pc ->
False.
Proof.
Lemma cssaval_contradiction_in_Icallinr :
forall f pc fd args res pc'
r i s sp rs m,
reachable prog (
State s f sp pc rs m) ->
wf_cssa_function f ->
(
fn_code f) !
pc =
Some (
Icall (
funsig fd) (
inr i)
args res pc') ->
cssaval_spec f (
compute_cssaval_function f) ->
compute_cssaval_function f r =
compute_cssaval_function f res ->
compute_cssaval_function f res =
res ->
r <>
res ->
cssalive_spec f r pc ->
False.
Proof.
Lemma cssaval_contradiction_in_Iload :
forall f pc args chunk addr dst pc'
r s sp rs m,
reachable prog (
State s f sp pc rs m) ->
wf_cssa_function f ->
(
fn_code f) !
pc =
Some (
Iload chunk addr args dst pc') ->
cssaval_spec f (
compute_cssaval_function f) ->
compute_cssaval_function f r =
compute_cssaval_function f dst ->
compute_cssaval_function f dst =
dst ->
r <>
dst ->
cssalive_spec f r pc ->
False.
Proof.
Lemma not_lazydef_after_noinop :
forall f pc pc'
r,
wf_cssa_function f ->
cfg f pc pc' ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
~
lazydef f r pc'.
Proof.
intros f pc pc'
r WF Hedge Hnotinop.
unfold not;
intros Hlazy.
inv Hlazy.
+
inv H.
assert(
Hinop: (
fn_code f) !
pc =
Some (
Inop pc')).
induction WF.
apply fn_normalized.
apply fn_phicode_inv.
congruence.
unfold successors_list;
unfold successors in *.
rewrite PTree.gmap1.
case_eq ((
fn_code f) !
pc);
intros;
try destruct i;
simpl;
flatten;
inv Hedge;
match goal with
| [
H : (
fn_code f) !
pc =
Some ?
i |-
_ ] =>
assert(
Hins:
ins =
i)
by congruence;
rewrite Hins in HCFG_in;
simpl in HCFG_in;
auto
|
_ =>
idtac
end.
go.
go.
+
assert(
Hinop: (
fn_code f) !
pc =
Some (
Inop pc')).
apply fn_normalized;
go.
unfold successors_list;
unfold successors in *.
rewrite PTree.gmap1.
case_eq ((
fn_code f) !
pc);
intros;
try destruct i;
simpl;
flatten;
inv Hedge;
match goal with
| [
H : (
fn_code f) !
pc =
Some ?
i |-
_ ] =>
assert(
Hins:
ins =
i)
by congruence;
rewrite Hins in HCFG_in;
simpl in HCFG_in;
auto
|
_ =>
idtac
end.
go.
go.
Qed.
Lemma live_in_pred_if_notdefined :
forall f r pc pc',
wf_cssa_function f ->
~
def f r pc ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
cfg f pc pc' ->
cssalive_spec f r pc' /\ ~
lazydef f r pc' \/
lazydef f r pc' ->
cssalive_spec f r pc.
Proof.
intros f r pc pc'
WF Hnotdef Hnotinop Hedge Hprops.
destruct Hprops as [
Hlive |
Hlazy].
+
constructor 2
with (
pc' :=
pc').
go.
unfold not;
intros Hdef.
inv Hdef;
go.
tauto.
+
contradict Hlazy.
eapply not_lazydef_after_noinop;
go.
Qed.
Lemma live_at_notinop_if_used :
forall f pc r,
wf_cssa_function f ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
use f r pc ->
cssalive_spec f r pc.
Proof.
Lemma not_usedanddef_outside_inop :
forall f pc r,
wf_cssa_function f ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
use f r pc ->
~
def f r pc.
Proof.
Lemma absurd_notinop_at_entry :
forall f,
wf_cssa_function f ->
(
forall s, (
fn_code f) ! (
fn_entrypoint f) <>
Some (
Inop s)) ->
False.
Proof.
Lemma ninterlive_outside_inop :
forall f r dst pc pc',
wf_cssa_function f ->
cssalive_spec f r pc' /\ ~
lazydef f r pc' \/
lazydef f r pc' ->
ninterlive_spec f r dst ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
def f dst pc ->
cfg f pc pc' ->
r <>
dst ->
False.
Proof.
Lemma live_props_outside_inop :
forall f r pc'
pc,
wf_cssa_function f ->
cfg f pc pc' ->
~
assigned_code_spec (
fn_code f)
pc r ->
cssalive_spec f r pc' /\ ~
lazydef f r pc' \/
lazydef f r pc' ->
(
forall s, (
fn_code f) !
pc <>
Some (
Inop s)) ->
cssalive_spec f r pc.
Proof.
Lemma functions_translated:
forall (
v:
val) (
f:
CSSA.fundef),
Genv.find_funct ge v =
Some f ->
exists tf,
Genv.find_funct tge v =
Some tf
/\
transl_fundef f =
Errors.OK tf.
Proof.
Lemma spec_ros_r_find_function:
forall rs rs'
f r regrepr,
rs #
r =
rs' # (
regrepr r) ->
CSSA.find_function ge (
inl _ r)
rs =
Some f ->
exists tf,
RTLpar.find_function tge (
inl _ (
regrepr r))
rs' =
Some tf
/\
transl_fundef f =
Errors.OK tf.
Proof.
Lemma spec_ros_id_find_function:
forall rs rs'
f id,
CSSA.find_function ge (
inr _ id)
rs =
Some f ->
exists tf,
RTLpar.find_function tge (
inr _ id)
rs' =
Some tf
/\
transl_fundef f =
Errors.OK tf.
Proof.
Lemma match_regset_args :
forall args regrepr rs (
rs' :
SSA.regset),
(
forall r,
In r args ->
rs #
r =
rs' # (
regrepr r)) ->
rs ##
args =
rs' ## (
map regrepr args).
Proof.
induction args; go.
intros.
simpl.
erewrite IHargs; eauto.
rewrite H. auto. auto.
Qed.
Lemma not_used_at_entry :
forall f r,
wf_cssa_function f ->
~
use f r (
fn_entrypoint f).
Proof.
Lemma no_jp_after_entry :
forall f pc,
wf_cssa_function f ->
(
fn_phicode f) !
pc <>
None ->
cfg f (
fn_entrypoint f)
pc ->
False.
Proof.
Lemma live_at_entry_def_aux:
forall f r pc',
wf_cssa_function f ->
cfg f (
fn_entrypoint f)
pc' ->
cssalive_spec f r pc' ->
def f r (
fn_entrypoint f).
Proof.
Lemma live_at_entry_def :
forall f r,
wf_cssa_function f ->
cssalive_spec f r (
fn_entrypoint f) ->
def f r (
fn_entrypoint f).
Proof.
Lemma init_regs_match :
forall params f r d args regrepr,
wf_cssa_function f ->
cssalive_spec f r (
fn_entrypoint f) ->
(
forall r',
In r'
params ->
In r' (
fn_params f)) ->
compute_regrepr f =
OK regrepr ->
def f r d ->
(
init_regs args params) !!
r =
(
init_regs args (
map regrepr params))
!! (
regrepr r).
Proof.
Lemma liveorlazydef_exists_def:
forall f r pc,
wf_cssa_function f ->
cssalive_spec f r pc /\ ~
lazydef f r pc \/
lazydef f r pc ->
exists d,
def f r d.
Proof.
intros f r pc WH Hrprops.
destruct Hrprops as [
Hrprops |
Hrprops];
auto.
destruct Hrprops.
exploit live_implies_use;
eauto;
intros Huse.
destruct Huse as [
u Huse].
exploit exists_def;
eauto.
inv Hrprops;
go.
Qed.
Lemma live_exists_def:
forall f r pc,
wf_cssa_function f ->
cssalive_spec f r pc ->
exists d,
def f r d.
Proof.
Lemma compute_regrepr_good_cssaval :
forall f regrepr,
compute_regrepr f =
Errors.OK regrepr ->
check_cssaval f (
compute_cssaval_function f)
(
get_ext_params f (
get_all_def f)) =
true.
Proof.
Lemma senv_preserved:
Senv.equiv (
Genv.to_senv ge) (
Genv.to_senv tge).
Proof.
Lemma transl_step_correct:
forall s1 t s2,
step ge s1 t s2 ->
forall s1' (
MS:
match_states s1 s1'),
exists s2',
RTLpar.step tge s1'
t s2' /\
match_states s2 s2'.
Proof.
Lemma transf_initial_states:
forall st1,
initial_state prog st1 ->
exists st2,
RTLpar.initial_state tprog st2
/\
match_states st1 st2.
Proof.
Lemma transf_final_states:
forall st1 st2 r,
match_states st1 st2
->
final_state st1 r
->
RTLpar.final_state st2 r.
Proof.
intros. inv H0. inv H.
inv STACK.
constructor.
Qed.
Theorem transf_program_correct:
forward_simulation (
CSSA.semantics prog) (
RTLpar.semantics tprog).
Proof.
End CORRECTNESS.
End PRESERVATION.
Section WF.
Variable prog:
CSSA.program.
Variable tprog:
RTLpar.program.
Hypothesis TRANSF_PROG:
match_prog prog tprog.
Hypothesis WF_TRANSF:
wf_cssa_program prog.
Lemma transl_function_inops :
forall f tf,
transl_function f =
Errors.OK tf ->
forall pc s,
(
fn_code f) !
pc =
Some (
Inop s) <->
(
RTLpar.fn_code tf) !
pc =
Some (
Inop s).
Proof.
unfold transl_function ;
intros f tf TRANS pc s.
flatten TRANS;
simpl.
unfold transl_code.
rewrite PTree.gmap1.
unfold option_map.
split.
-
intros INOP.
rewrite INOP;
auto.
-
flatten ;
destruct i ;
go ;
try solve [
simpl ;
flatten].
Qed.
Lemma transl_function_ins :
forall f tf,
transl_function f =
Errors.OK tf ->
forall pc ins,
(
fn_code f) !
pc =
Some ins ->
exists ins', (
RTLpar.fn_code tf) !
pc =
Some ins'.
Proof.
Lemma transl_function_ins_2 :
forall f tf,
transl_function f =
Errors.OK tf ->
forall pc ins,
(
RTLpar.fn_code tf) !
pc =
Some ins ->
exists ins', (
fn_code f) !
pc =
Some ins'.
Proof.
Lemma transl_function_parcb_2 :
forall f tf,
transl_function f =
Errors.OK tf ->
forall pc p,
(
RTLpar.fn_parcopycode tf) !
pc =
Some p ->
exists p, (
fn_parcopycode f) !
pc =
Some p.
Proof.
Lemma entry_point_preserved :
forall f tf,
transl_function f =
OK tf ->
RTLpar.fn_entrypoint tf =
fn_entrypoint f.
Proof.
Lemma successors_preserved :
forall f tf,
transl_function f =
Errors.OK tf ->
forall pc ins ins'
pc',
(
fn_code f) !
pc =
Some ins ->
(
RTLpar.fn_code tf) !
pc =
Some ins' ->
(
In pc' (
successors_instr ins) <->
In pc' (
successors_instr ins')).
Proof.
unfold transl_function ;
intros f tf TRANS pc ins ins'
pc'
CODE TCODE.
flatten TRANS;
simpl in *;
go.
unfold transl_code in *.
rewrite PTree.gmap1 in *.
unfold option_map in *.
rewrite CODE in *.
destruct ins ;
go;
try solve [
destruct s0 ;
go];
destruct o ;
go.
Qed.
Lemma successors_preserved_2 :
forall f tf,
transl_function f =
Errors.OK tf ->
forall pc pc',
In pc' (
successors f) !!!
pc <->
In pc' (
RTLpar.successors tf) !!!
pc.
Proof.
Lemma cfg_preserved :
forall f tf,
transl_function f =
Errors.OK tf ->
forall pc pc',
cfg f pc pc' <->
RTLpar.cfg tf pc pc'.
Proof.
Lemma is_wf_function :
forall f tf,
wf_cssa_function f ->
transl_function f =
Errors.OK tf ->
RTLpar.wf_function tf.
Proof.
Theorem is_wf_program :
RTLpar.wf_program tprog.
Proof.
red.
intros.
red in WF_TRANSF.
inv TRANSF_PROG.
intuition.
revert H0 H WF_TRANSF.
clear.
generalize (
prog_defs tprog).
induction 1;
intros.
-
inv H.
-
inv H1.
+
inv H.
inv H2.
{
destruct f1 ;
simpl in * ;
try constructor;
auto.
*
monadInv H5.
constructor.
eapply is_wf_function;
eauto.
destruct a1,
g.
exploit (
WF_TRANSF (
Internal f0)
i);
eauto.
simpl in * ;
eauto.
left.
inv H;
simpl in *;
auto.
intros.
inv H1;
auto.
simpl in *.
inv H.
*
monadInv H5.
constructor.
}
+
eapply IHlist_forall2;
eauto.
Qed.
End WF.