Require Import Coqlib.
Require Import Maps.
Require Import Maps2.
Require Import AST.
Require Import Integers.
Require Import Values.
Require Import Events.
Require Import Memory.
Require Import Globalenvs.
Require Import Smallstep.
Require Import Op.
Require Import Registers.
Require Import Floats.
Require Import Kildall.
Require Import KildallComp.
Require Import SSA.
Require Import Utils.
Require Import Relation_Operators.
Require Import Classical.
Require Import OrderedType.
Require Import Ordered.
Require Import FSets.
Require Import DLib.
Require FSetAVL.
Decidable equalities over various types
Lemma zeq :
forall (
x y:
Z), {
x =
y} + {
x <>
y}.
Proof.
decide equality; decide equality.
Qed.
Lemma eq_memory_chunk:
forall (
x y:
memory_chunk), {
x=
y} + {
x<>
y}.
Proof.
decide equality.
Qed.
Lemma eq_addressing:
forall (
x y:
addressing), {
x=
y} + {
x<>
y}.
Proof.
Lemma eq_comparison:
forall (
x y:
comparison), {
x =
y} + {
x <>
y}.
Proof.
decide equality.
Qed.
Lemma eq_condition:
forall (
x y:
condition), {
x=
y} + {
x<>
y}.
Proof.
Lemma eq_typ:
forall (
x y:
typ), {
x=
y} + {
x<>
y}.
Proof.
decide equality.
Qed.
Lemma eq_signature:
forall (
x y:
signature), {
x=
y} + {
x<>
y}.
Proof.
Lemma eq_external_function:
forall (
x y:
external_function), {
x =
y} + {
x <>
y}.
Proof.
Utility lemmas about get_index_acc and get_index
Lemma get_index_acc_progress:
forall (
l:
list node) (
a b:
node)
acc k,
b <>
a ->
get_index_acc (
b::
l)
a acc =
Some k ->
get_index_acc l a (
acc+1) =
Some k.
Proof.
induction l;
intros.
inv H0.
destruct (
peq b a).
elim H ;
auto.
inv H2.
simpl in *.
destruct (
peq b a0).
elim H ;
auto.
auto.
Qed.
Lemma get_index_acc_ge_acc:
forall l e acc k,
get_index_acc l e acc =
Some k ->
ge k acc.
Proof.
induction l;
intros.
inv H.
simpl in H.
destruct (
peq a e).
inv H;
auto.
assert (
IHl' :=
IHl e (
acc+1)%
nat k H).
omega.
Qed.
Lemma get_index_acc_inv2 :
forall l a (
acc acc' :
nat)
x,
get_index_acc l a (
acc+
acc') =
Some (
x+
acc')%
nat ->
get_index_acc l a acc =
Some x.
Proof.
induction l;
intros.
inv H.
simpl in *.
destruct (
peq a a0).
inv H.
assert (
acc =
x)
by omega.
inv H1;
auto.
assert (
Hacc : (
acc+
acc'+1)%
nat = (
acc+1+
acc')%
nat)
by omega.
rewrite Hacc in *.
eapply IHl;
eauto.
Qed.
Lemma get_index_some_sn:
forall l a e k acc,
a <>
e ->
get_index_acc (
a ::
l)
e acc =
Some ((
k+1)%
nat) ->
get_index_acc l e acc =
Some k.
Proof.
Lemma get_index_some_in:
forall l e k,
get_index l e =
Some k ->
In e l.
Proof.
Lemma get_index_acc_inv :
forall l a (
acc acc' :
nat)
x,
get_index_acc l a acc =
Some x ->
get_index_acc l a (
acc+
acc') =
Some (
x+
acc')%
nat.
Proof.
induction l;
intros.
inv H.
simpl in *.
case_eq (
peq a a0);
intros.
rewrite H0 in H.
inversion H.
auto.
rewrite H0 in H.
assert ( (
acc +
acc' + 1)%
nat = (
acc + 1 +
acc')%
nat)
by omega.
rewrite H1.
eapply IHl ;
eauto.
Qed.
Lemma in_get_index_some:
forall l a,
In a l ->
exists k,
get_index l a =
Some k.
Proof.
Lemma get_index_progress:
forall l p pc0 k,
(
p <>
pc0) ->
get_index (
p::
l)
pc0 =
Some (
Datatypes.S k) ->
get_index l pc0 =
Some k.
Proof.
Lemma get_index_some :
forall l pc k,
get_index l pc =
Some k ->
(
k <
length l)%
nat.
Proof.
induction l ;
intros.
inv H.
destruct k ;
simpl in * ;
auto.
omega.
destruct (
peq a pc).
inv e.
unfold get_index in * ;
simpl in *.
rewrite peq_true in H ;
eauto.
inv H.
unfold get_index in *.
replace (
Datatypes.S k)
with (
k+1)%
nat in *;
try omega.
eapply get_index_some_sn in H ;
eauto.
exploit IHl ;
eauto.
intros.
omega.
Qed.
Lemma get_index_nth_error:
forall pc l k,
get_index l pc =
Some k ->
nth_error l k =
Some pc.
Proof.
Lemma get_index_acc_nth_okp_aux :
forall pc l k k',
SSA.get_index_acc l pc k' =
Some (
k'+
k)%
nat ->
nth_okp k l.
Proof.
induction l;
simpl.
congruence.
intros;
destruct peq.
assert (
k=
O).
inversion H.
omega.
subst;
constructor.
destruct k.
constructor.
replace (
k' +
Datatypes.S k)%
nat with ((
k'+1)+
k)%
nat in *
by omega.
constructor 2;
eauto.
Qed.
Lemma get_index_acc_nth_okp :
forall pc l k,
get_index l pc =
Some k ->
nth_okp k l.
Proof.
Utility lemmas about index_pred
Lemma index_pred_some :
forall pc t k pc0,
index_pred t pc0 pc =
Some k ->
(
k <
length (
t!!!
pc))%
nat.
Proof.
Lemma index_pred_some_nth:
forall pc t k pc0,
index_pred t pc0 pc =
Some k ->
nth_error (
t!!!
pc)
k =
Some pc0.
Proof.
Utility lemmas about successors
Lemma successors_instr_succs :
forall f pc pc'
instr,
(
fn_code f) !
pc =
Some instr ->
In pc' (
successors_instr instr) ->
exists succs, (
successors f) !
pc =
Some succs /\
In pc'
succs .
Proof.
Lemma succ_code_instr_succs :
forall f pc pc'
instr,
(
fn_code f) !
pc =
Some instr ->
In pc' (
successors_instr instr) ->
exists succs, (
successors f) !
pc =
Some succs /\
In pc'
succs .
Proof.
Lemma index_pred_instr_some :
forall instr pc'
f pc ,
(
fn_code f)!
pc =
Some instr ->
In pc' (
successors_instr instr) ->
(
exists k,
index_pred (
make_predecessors (
fn_code f)
successors_instr)
pc pc' =
Some k).
Proof.
Utility lemmas about wf_ssa_function
Lemma fn_phiargs:
forall f,
wf_ssa_function f ->
forall pc block x args pred k,
(
fn_phicode f) !
pc =
Some block ->
In (
Iphi args x)
block ->
index_pred (
Kildall.make_predecessors (
fn_code f)
successors_instr)
pred pc =
Some k ->
exists arg,
nth_error args k =
Some arg.
Proof.
Lemma fn_parablock:
forall f,
wf_ssa_function f ->
forall pc block,
(
fn_phicode f) !
pc =
Some block ->
NoDup block /\
True.
Proof.
intros.
exploit fn_ssa ;
eauto.
intros.
split ;
auto.
eapply H1 ;
eauto.
Qed.
Lemma fn_phicode_code :
forall f,
wf_ssa_function f ->
forall pc block,
(
fn_phicode f) !
pc =
Some block ->
exists ins, (
fn_code f) !
pc =
Some ins.
Proof.
Lemma fn_entrypoint_inv:
forall f,
wf_ssa_function f ->
(
exists i, (
f.(
fn_code) ! (
f.(
fn_entrypoint)) =
Some i)) /\
~
join_point f.(
fn_entrypoint)
f.
Proof.
Lemma def_at_entry_ext_params:
forall f r,
wf_ssa_function f ->
def f r (
fn_entrypoint f) ->
ext_params f r.
Proof.
Lemma fn_code_inv2:
forall f,
wf_ssa_function f ->
forall jp pc, (
join_point jp f) ->
In jp ((
successors f) !!!
pc) ->
f.(
fn_code) !
pc =
Some (
Inop jp).
Proof.
Lemma fn_phicode_inv1:
forall f,
wf_ssa_function f ->
forall phib jp i,
f.(
fn_code) !
jp =
Some i ->
f.(
fn_phicode) !
jp =
Some phib ->
join_point jp f.
Proof.
Lemma fn_phicode_inv2:
forall f,
wf_ssa_function f ->
forall jp i,
join_point jp f ->
f.(
fn_code) !
jp =
Some i ->
exists phib,
f.(
fn_phicode) !
jp =
Some phib.
Proof.
intros.
case_eq (
fn_phicode f) !
jp ;
intros ;
eauto.
destruct (
fn_phicode_inv f H jp) ;
eauto.
eapply H3 in H0.
congruence.
Qed.
Lemma ssa_def_unique2 :
forall f,
wf_ssa_function f ->
forall x pc1 pc2,
assigned_code_spec (
fn_code f)
pc1 x ->
assigned_phi_spec (
fn_phicode f)
pc2 x ->
False.
Proof.
intros.
inv H. inv fn_ssa.
generalize (H x pc1 pc2).
intuition.
Qed.
Lemma not_jnp_not_assigned_phi_spec:
forall f pc y,
wf_ssa_function f ->
~
join_point pc f ->
~
assigned_phi_spec (
fn_phicode f)
pc y.
Proof.
Lemma param_spec :
forall f,
wf_ssa_function f ->
forall pc pc'
k x args phiinstr,
index_pred (
make_predecessors (
fn_code f)
successors_instr)
pc pc' =
Some k ->
In (
Iphi args x)
phiinstr ->
(
fn_phicode f) !
pc' =
Some phiinstr ->
exists arg,
nth_error args k =
Some arg.
Proof.
Lemma ssa_def_dom_use :
forall f,
wf_ssa_function f ->
forall x u d,
use f x u ->
def f x d ->
dom f d u.
Proof.
Lemma ssa_use_exists_def :
forall f,
wf_ssa_function f ->
forall x u,
use f x u ->
exists d,
def f x d.
Proof.
Lemma wf_ssa_reached :
forall f,
wf_ssa_function f ->
forall pc ins,
(
fn_code f) !
pc =
Some ins ->
reached f pc.
Proof.
intros. inv H ; eauto.
Qed.
Hint Resolve wf_ssa_reached.
Lemma ssa_def_use_code_false :
forall f,
wf_ssa_function f ->
forall x pc,
use_code f x pc ->
assigned_code_spec (
fn_code f)
pc x ->
False.
Proof.
Lemma ssa_not_Inop_not_phi :
forall f,
wf_ssa_function f ->
forall pc x pc'
ins,
In pc' (
successors_instr ins) ->
(
fn_code f) !
pc =
Some ins ->
(
forall n,
ins <>
Inop n) ->
~
assigned_phi_spec (
fn_phicode f)
pc'
x.
Proof.
Lemma unique_def_spec_def :
forall f x d1 d2
(
HWF:
wf_ssa_function f),
def f x d1 ->
def f x d2 ->
d1 <>
d2 ->
False.
Proof.
intros.
destruct (
fn_ssa f)
as [
Hssa1 Hssa2];
auto.
generalize (
fn_entry f HWF) ;
intros.
destruct H2 as [
succ Hentry].
generalize (
fn_ssa_params f HWF);
intros Hparams.
inv H ;
inv H0;
inv H ;
inv H2;
try solve [
intuition
|
exploit Hparams ;
eauto
|
exploit Hparams ;
eauto ; (
intuition;
go)
|
exploit H3 ;
eauto
|
exploit H4 ;
eauto;
intuition
| (
eelim (
Hssa1 x d1 d2) ;
eauto;
intuition ;
eauto)].
Qed.
Lemma def_def_eq :
forall f x d1 d2
(
HWF:
wf_ssa_function f),
def f x d1 ->
def f x d2 ->
d1 =
d2.
Proof.
Ltac def_def f x pc pc' :=
match goal with
| [
HWF:
wf_ssa_function f |-
_ ] =>
(
exploit (
def_def_eq f x pc pc'
HWF);
eauto);
try (
econstructor ;
eauto);
try (
solve [
econstructor ;
eauto])
end.
Require RTL.
Ltac allinv :=
repeat
match goal with
| [
H1: (
fn_code ?
tf) ! ?
pc =
Some _ ,
H2: (
fn_code ?
tf) ! ?
pc =
Some _ |-
_ ] =>
rewrite H1 in H2;
inv H2
| [
H1: (
RTL.fn_code ?
tf) ! ?
pc =
Some _ ,
H2: (
RTL.fn_code ?
tf) ! ?
pc =
Some _ |-
_ ] =>
rewrite H1 in H2;
inv H2
| [
H1: (
fn_phicode ?
tf) ! ?
pc =
Some _ ,
H2: (
fn_phicode ?
tf) ! ?
pc =
Some _ |-
_ ] =>
rewrite H1 in H2;
inv H2
| [
H1: ?Γ ! ?
pc =
_ ,
H2: ?Γ ! ?
pc =
_ |-
_ ] =>
rewrite H1 in H2;
inv H2
| [
H1:
index_pred _ ?
pc ?
pc' =
Some _ ,
H2:
index_pred _ ?
pc ?
pc' =
Some _ |-
_ ] =>
rewrite H1 in H2;
inv H2
|
_ =>
idtac
end.
Lemma ssa_def_unique :
forall f x d1 d2,
wf_ssa_function f ->
def f x d1 ->
def f x d2 ->
d1 =
d2.
Proof.
intros.
def_def f x d1 d2.
Qed.
Lemma assigned_code_and_phi:
forall f,
wf_ssa_function f ->
forall r pc pc',
assigned_code_spec (
fn_code f)
pc r ->
assigned_phi_spec (
fn_phicode f)
pc'
r ->
False.
Proof.
intros f WFF r pc pc'
H1 H2.
destruct (
fn_ssa _ WFF)
as [
T _].
destruct (
T r pc pc');
intuition.
Qed.
Lemma assigned_code_unique :
forall f,
wf_ssa_function f ->
forall r pc pc',
assigned_code_spec (
fn_code f)
pc r ->
assigned_code_spec (
fn_code f)
pc'
r ->
pc=
pc'.
Proof.
intros f WFF r pc pc'
H1 H2.
destruct (
fn_ssa _ WFF)
as [
T _].
destruct (
T r pc pc');
intuition.
Qed.
Lemma assigned_phi_unique :
forall f,
wf_ssa_function f ->
forall r pc pc',
assigned_phi_spec (
fn_phicode f)
pc r ->
assigned_phi_spec (
fn_phicode f)
pc'
r ->
pc=
pc'.
Proof.
intros f WFF r pc pc'
H1 H2.
destruct (
fn_ssa _ WFF)
as [
T _].
destruct (
T r pc pc');
intuition.
Qed.
Lemma assigned_phi_spec_join_point :
forall f x pc,
wf_ssa_function f ->
assigned_phi_spec (
fn_phicode f)
pc x ->
join_point pc f.
Proof.
Lemma wf_ssa_use_and_def_same_pc :
forall f x pc,
wf_ssa_function f ->
use f x pc ->
def f x pc ->
assigned_phi_spec (
fn_phicode f)
pc x \/
ext_params f x.
Proof.
Properties and more lemmas about well-formed SSA functions
Section WF_SSA_PROP.
Variable f:
function.
Hypothesis HWF :
wf_ssa_function f.
Hint Resolve HWF.
Lemma elim_structural :
forall pc pc'
instr instr'
block,
(
fn_code f)!
pc =
Some instr ->
(
fn_code f)!
pc' =
Some instr' ->
(
fn_phicode f)!
pc' =
Some block ->
In pc' (
successors_instr instr) ->
instr =
Inop pc'.
Proof.
Lemma phicode_joinpoint:
forall pc block i,
(
fn_code f) !
pc =
Some i ->
(
fn_phicode f) !
pc =
Some block ->
join_point pc f.
Proof.
Lemma nophicode_nojoinpoint:
forall pc i,
(
fn_code f) !
pc =
Some i ->
(
fn_phicode f) !
pc =
None ->
~
join_point pc f.
Proof.
intros.
intro.
exploit (
fn_phicode_inv2 _ HWF);
eauto.
intros.
destruct H2.
simpl in *.
congruence.
Qed.
Lemma join_point_exclusive:
forall pc i,
(
fn_code f) !
pc =
Some i ->
~
join_point pc f \/
join_point pc f.
Proof.
Lemma use_ins_code :
forall pc x,
use f x pc ->
exists ins, (
fn_code f) !
pc =
Some ins.
Proof.
Lemma use_reached :
forall pc x,
use f x pc ->
reached f pc.
Proof.
intros.
exploit use_ins_code ;
eauto.
intros [
ins Hins].
inv HWF.
eapply fn_code_reached ;
eauto.
Qed.
End WF_SSA_PROP.
Auxiliary semantics for phi-blocks
This semantics is sequential, and it is equivalent to the parallel one
whenever the block is parallelizable
Definition phi_store_aux k phib (
rs:
SSA.regset) :=
List.fold_left (
fun rs phi =>
match phi with
| (
Iphi args dst) =>
match nth_error args k with
|
None =>
rs
|
Some r =>
rs #2
dst <- (
rs #2
r)
end
end
)
phib rs.
Lemmas about the sequential semantics of phiblocks
Lemma notin_cons_notin :
forall dst block a,
(
forall args, ~
In (
Iphi args dst) (
a::
block)) ->
forall args, ~
In (
Iphi args dst)
block.
Proof.
intros.
intro ; exploit (H args); eauto.
Qed.
Hint Resolve notin_cons_notin.
Lemma phi_store_notin_preserved_aux:
forall k block r v dst rs,
(
forall args, ~
In (
Iphi args dst)
block) ->
r <>
dst ->
(
phi_store k block (
rs#2
r <-
v))#2
dst =
rs#2
dst.
Proof.
induction block;
intros;
simpl.
*)
eapply P2Map.gso;
eauto.
*)
destruct a;
simpl.
case_eq (
nth_error l k);
intros ;
eauto.
*)
rewrite P2Map.gso ;
eauto.
intro Hcont.
inv Hcont.
eelim H ;
eauto.
Qed.
Lemma phi_store_notin_preserved:
forall k block rs dst,
(
forall args, ~ (
In (
Iphi args dst)
block)) ->
(
phi_store k block rs)#2
dst =
rs#2
dst.
Proof.
induction block;
intros.
*)
simpl;
auto.
*)
destruct a;
simpl.
case_eq (
nth_error l k);
intros;
eauto.
case some *)
rewrite P2Map.gso ;
eauto.
intro Hinv;
subst;
exploit (
H l);
eauto.
Qed.
Lemma phistore_compat:
forall k block (
rs1 rs2:
SSA.regset),
(
forall r,
rs1#2
r =
rs2#2
r) ->
(
forall r, (
phi_store k block rs1)#2
r = (
phi_store k block rs2)#2
r).
Proof.
induction block;
intros.
*)
simpl;
auto.
*)
destruct a;
simpl.
destruct (
nth_error l k);
eauto.
case some *)
rewrite H.
case_eq (
p2eq r r0);
intros ;
auto.
case eq *)
rewrite P2Map.gsspec.
rewrite H0.
rewrite P2Map.gsspec.
rewrite H0.
auto.
repeat (
rewrite P2Map.gso;
eauto).
Qed.
Lemma phi_store_copy_preserved:
forall k block rs dst arg ,
(
forall args,
not (
In (
Iphi args dst)
block)) ->
(
phi_store k block rs #2
dst <- (
rs #2
arg)) #2
dst =
rs #2
arg.
Proof.
How to compute the list of registers of a SSA function.
Module MiniOrderedTypeProd (
O1 O2:
OrderedType) <:
MiniOrderedType.
Module P1 :=
OrderedTypeFacts O1.
Module P2 :=
OrderedTypeFacts O2.
Definition t :
Type := (
O1.t *
O2.t)%
type.
Definition eq :
t ->
t ->
Prop :=
fun a b =>
O1.eq (
fst a) (
fst b) /\
O2.eq (
snd a) (
snd b).
Definition lt :
t ->
t ->
Prop :=
fun a b =>
O1.lt (
fst a) (
fst b) \/
(
O1.eq (
fst a) (
fst b) /\
O2.lt (
snd a) (
snd b)).
Lemma eq_refl :
forall x :
t,
eq x x.
Proof.
split; auto.
Qed.
Lemma eq_sym :
forall x y :
t,
eq x y ->
eq y x.
Proof.
intros x y H; inv H; split; auto.
Qed.
Lemma eq_trans :
forall x y z :
t,
eq x y ->
eq y z ->
eq x z.
Proof.
intros x y z H1 H2; inv H1; inv H2; split; eauto.
Qed.
Lemma lt_trans :
forall x y z :
t,
lt x y ->
lt y z ->
lt x z.
Proof.
intros x y z H1 H2; inv H1; inv H2.
left; eauto.
destruct H0; left; eauto.
destruct H; left; eauto.
destruct H; destruct H0; right; split; eauto.
Qed.
Lemma lt_not_eq :
forall x y :
t,
lt x y -> ~
eq x y.
Proof.
Definition compare :
forall x y :
t,
Compare lt eq x y.
Proof.
destruct x as [
x1 x2].
destruct y as [
y1 y2].
destruct (
O1.compare x1 y1).
constructor 1;
left;
auto.
destruct (
O2.compare x2 y2).
constructor 1;
right;
split;
simpl;
auto.
constructor 2;
split;
auto.
constructor 3;
right;
split;
simpl;
auto.
constructor 3;
left;
auto.
Defined.
End MiniOrderedTypeProd.
Module OrderedTypeProd (
O1 O2:
OrderedType) <:
OrderedType.
Module P :=
MiniOrderedTypeProd O1 O2.
Include MOT_to_OT P.
End OrderedTypeProd.
Module OP2 :=
OrderedTypeProd OrderedPositive OrderedPositive.
Module SSARegSet :=
FSetAVL.Make OP2.
Definition all_def (
c:
code) (
phic:
phicode) :
SSARegSet.t :=
PTree.fold
(
fun s _ ins =>
match ins with
|
Iop op args dst succ =>
SSARegSet.add dst s
|
Iload chunk addr args dst succ =>
SSARegSet.add dst s
|
Icall sig fn args dst succ =>
SSARegSet.add dst s
|
Ibuiltin fn args (
BR dst)
succ =>
SSARegSet.add dst s
|
_ =>
s
end)
c
(
PTree.fold
(
fun s _ phib =>
List.fold_left
(
fun s (
phi:
phiinstruction) =>
let (
_,
dst) :=
phi in SSARegSet.add dst s)
phib s)
phic SSARegSet.empty).
Definition param_set (
params:
list reg) :
SSARegSet.t :=
List.fold_right SSARegSet.add SSARegSet.empty params.
Definition all_uses (
c:
code) (
phic:
phicode) :
SSARegSet.t :=
PTree.fold
(
fun s _ ins =>
match ins with
|
Iop op args dst _ =>
fold_right SSARegSet.add s args
|
Iload chk adr args dst _ =>
fold_right SSARegSet.add s args
|
Icond cond args _ _ =>
fold_right SSARegSet.add s args
|
Ibuiltin ef args dst _ =>
fold_right SSARegSet.add s (
params_of_builtin_args args)
|
Istore chk adr args src _ =>
fold_right SSARegSet.add s (
src::
args)
|
Icall sig (
inl r)
args dst _ =>
fold_right SSARegSet.add s (
r::
args)
|
Itailcall sig (
inl r)
args =>
fold_right SSARegSet.add s (
r::
args)
|
Icall sig (
inr id)
args dst _ =>
fold_right SSARegSet.add s args
|
Itailcall sig (
inr id)
args =>
fold_right SSARegSet.add s args
|
Ijumptable arg tbl =>
SSARegSet.add arg s
|
Ireturn (
Some arg) =>
SSARegSet.add arg s
|
_ =>
s
end)
c
(
PTree.fold
(
fun s _ phib =>
fold_left
(
fun s (
phi:
phiinstruction) =>
let (
args,
dst) :=
phi in
fold_right SSARegSet.add s args)
phib s)
phic SSARegSet.empty).
Lemma In_fold_right_add1:
forall x l a,
In x l ->
SSARegSet.In x (
fold_right SSARegSet.add a l).
Proof.
Lemma In_fold_right_add2:
forall x l a,
SSARegSet.In x a ->
SSARegSet.In x (
fold_right SSARegSet.add a l).
Proof.
Lemma In_fold_right_add3:
forall x l a,
SSARegSet.In x (
fold_right SSARegSet.add a l) ->
SSARegSet.In x a \/
In x l.
Proof.
induction l;
simpl;
auto;
intros.
destruct (
p2eq x a);
subst;
auto.
destruct (
IHl a0);
auto.
eapply SSARegSet.add_3;
eauto.
destruct a;
destruct x;
simpl;
red;
destruct 1;
elim n;
subst;
auto.
Qed.
Lemma in_all_uses1:
forall x pc code s ins,
code!
pc =
Some ins ->
match ins with
|
Iop op args dst _ =>
In x args
|
Iload chk adr args dst _ =>
In x args
|
Icond cond args _ _ =>
In x args
|
Ibuiltin ef args dst _ =>
In x (
params_of_builtin_args args)
|
Istore chk adr args src _ =>
In x (
src::
args)
|
Icall sig (
inl r)
args dst _ =>
In x (
r::
args)
|
Itailcall sig (
inl r)
args =>
In x (
r::
args)
|
Icall sig (
inr id)
args dst _ =>
In x args
|
Itailcall sig (
inr id)
args =>
In x args
|
Ijumptable arg tbl =>
x =
arg
|
Ireturn (
Some arg) =>
x =
arg
|
_ =>
False
end ->
SSARegSet.In x
(
PTree.fold
(
fun s _ ins =>
match ins with
|
Iop op args dst _ =>
fold_right SSARegSet.add s args
|
Iload chk adr args dst _ =>
fold_right SSARegSet.add s args
|
Icond cond args _ _ =>
fold_right SSARegSet.add s args
|
Ibuiltin ef args dst _ =>
fold_right SSARegSet.add s (
params_of_builtin_args args)
|
Istore chk adr args src _ =>
fold_right SSARegSet.add s (
src::
args)
|
Icall sig (
inl r)
args dst _ =>
fold_right SSARegSet.add s (
r::
args)
|
Itailcall sig (
inl r)
args =>
fold_right SSARegSet.add s (
r::
args)
|
Icall sig (
inr id)
args dst _ =>
fold_right SSARegSet.add s args
|
Itailcall sig (
inr id)
args =>
fold_right SSARegSet.add s args
|
Ijumptable arg tbl =>
SSARegSet.add arg s
|
Ireturn (
Some arg) =>
SSARegSet.add arg s
|
_ =>
s
end)
code s).
Proof.
Lemma in_all_uses2:
forall x code s,
SSARegSet.In x s ->
SSARegSet.In x
(
PTree.fold
(
fun s _ ins =>
match ins with
|
Iop op args dst _ =>
fold_right SSARegSet.add s args
|
Iload chk adr args dst _ =>
fold_right SSARegSet.add s args
|
Icond cond args _ _ =>
fold_right SSARegSet.add s args
|
Ibuiltin ef args dst _ =>
fold_right SSARegSet.add s (
params_of_builtin_args args)
|
Istore chk adr args src _ =>
fold_right SSARegSet.add s (
src::
args)
|
Icall sig (
inl r)
args dst _ =>
fold_right SSARegSet.add s (
r::
args)
|
Itailcall sig (
inl r)
args =>
fold_right SSARegSet.add s (
r::
args)
|
Icall sig (
inr id)
args dst _ =>
fold_right SSARegSet.add s args
|
Itailcall sig (
inr id)
args =>
fold_right SSARegSet.add s args
|
Ijumptable arg tbl =>
SSARegSet.add arg s
|
Ireturn (
Some arg) =>
SSARegSet.add arg s
|
_ =>
s
end)
code s).
Proof.
Lemma in_all_uses3 :
forall x code s pc phib args dst,
code!
pc =
Some phib ->
In (
Iphi args dst)
phib ->
In x args ->
SSARegSet.In x
(
PTree.fold
(
fun (
s :
SSARegSet.t) (
_ :
positive) (
phib :
list phiinstruction) =>
fold_left
(
fun (
s0 :
SSARegSet.t) (
phi :
phiinstruction) =>
let (
args,
_) :=
phi in fold_right SSARegSet.add s0 args)
phib s)
code s).
Proof.
Definition ext_params_list (
c:
code) (
phic:
phicode) (
params:
list reg) :
list reg :=
SSARegSet.elements
(
SSARegSet.diff (
all_uses c phic)
(
SSARegSet.union (
all_def c phic) (
param_set params)))
++
params.
Lemma InA_In :
forall x (
l:
list reg),
InA (
fun a b :
OP2.P.t =>
fst a =
fst b /\
snd a =
snd b)
x l <->
In x l.
Proof.
induction l; simpl; split; intros; inv H.
destruct x; destruct a; simpl in *; destruct H1; left.
f_equal; auto.
rewrite IHl in H1; auto.
constructor 1 ;auto.
constructor 2; auto.
rewrite IHl; auto.
Qed.
Lemma In_param_set :
forall l x,
SSARegSet.In x (
param_set l) ->
In x l.
Proof.
Lemma use_In_all_usses :
forall f x pc,
use f x pc ->
SSARegSet.In x (
all_uses (
fn_code f) (
fn_phicode f)).
Proof.
Lemma In_all_def1:
forall x code s,
SSARegSet.In x
(
PTree.fold
(
fun (
s :
SSARegSet.t) (
_ :
positive) (
ins :
instruction) =>
match ins with
|
Inop _ =>
s
|
Iop _ _ dst _ =>
SSARegSet.add dst s
|
Iload _ _ _ dst _ =>
SSARegSet.add dst s
|
Istore _ _ _ _ _ =>
s
|
Icall _ _ _ dst _ =>
SSARegSet.add dst s
|
Itailcall _ _ _ =>
s
|
Ibuiltin _ _ (
BR dst)
_ =>
SSARegSet.add dst s
|
Ibuiltin _ _ _ _ =>
s
|
Icond _ _ _ _ =>
s
|
Ijumptable _ _ =>
s
|
Ireturn _ =>
s
end)
code s) ->
SSARegSet.In x s \/
exists pc :
node,
assigned_code_spec code pc x.
Proof.
intros x code s0.
apply PTree_Properties.fold_rec with (
P:=
fun code s =>
SSARegSet.In x s ->
SSARegSet.In x s0 \/ (
exists pc :
node,
assigned_code_spec code pc x)).
-
intros.
destruct (
H0 H1);
auto.
destruct H2 as [
pc H2];
right.
exists pc;
inv H2;
rewrite H in *;
eauto.
-
auto.
-
intros.
destruct v;
try destruct (
H1 H2);
auto.
+
destruct H3 as [
pc H3];
right;
exists pc.
inv H3.
*
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
*
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
*
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
*
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
destruct (
p2eq x r).
*
subst;
right;
exists k;
econstructor;
eauto.
rewrite PTree.gss;
eauto.
* {
elim H1;
auto.
-
destruct 1
as [
pc T].
right;
exists pc;
inv T.
+
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
-
eapply SSARegSet.add_3;
eauto.
destruct r;
destruct x;
simpl;
red;
destruct 1;
elim n0;
subst;
auto.
}
+
destruct (
p2eq x r).
subst;
right;
exists k;
econstructor 2;
eauto.
rewrite PTree.gss;
eauto.
elim H1;
auto.
destruct 1
as [
pc T].
right;
exists pc;
inv T.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
eapply SSARegSet.add_3;
eauto.
destruct r;
destruct x;
simpl;
red;
destruct 1;
elim n0;
subst;
auto.
+
destruct H3 as [
pc H3];
right;
exists pc.
inv H3.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
destruct (
p2eq x r).
subst;
right;
exists k;
econstructor 3;
eauto.
rewrite PTree.gss;
eauto.
elim H1;
auto.
destruct 1
as [
pc T].
right;
exists pc;
inv T.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
eapply SSARegSet.add_3;
eauto.
destruct r;
destruct x;
simpl;
red;
destruct 1;
elim n0;
subst;
auto.
+
destruct H3 as [
pc H3];
right;
exists pc.
inv H3.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
case_eq b;
intros;
subst.
*
destruct (
p2eq x0 x).
subst;
right;
exists k;
econstructor 4;
go.
rewrite PTree.gss;
go.
elim H1;
auto.
destruct 1
as [
pc T].
right;
exists pc;
inv T.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
eapply SSARegSet.add_3;
eauto.
destruct x0;
destruct x;
simpl;
red;
destruct 1;
elim n0;
subst;
auto.
*
elim H1;
auto.
destruct 1
as [
pc T].
right;
exists pc;
inv T.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
*
elim H1;
auto.
destruct 1
as [
pc T].
right;
exists pc;
inv T.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
elim H1;
auto.
destruct 1
as [
pc T].
right;
exists pc;
inv T.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
destruct H3 as [
pc H3];
right;
exists pc.
inv H3.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
+
destruct H3 as [
pc H3];
right;
exists pc.
inv H3.
econstructor 1;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 2;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 3;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
econstructor 4;
go;
rewrite PTree.gsspec;
destruct peq;
eauto;
subst;
congruence.
Qed.
Lemma In_fold_left_add1 :
forall x phib s,
SSARegSet.In x (
fold_left (
fun s0 (
phi:
phiinstruction) =>
let (
_,
dst) :=
phi in SSARegSet.add dst s0)
phib s) ->
SSARegSet.In x s \/
exists args,
In (
Iphi args x)
phib.
Proof.
induction phib;
simpl;
auto;
intros.
elim IHphib with (1:=
H);
clear IHphib;
intros.
destruct a.
destruct (
p2eq x r);
subst;
eauto.
left;
eapply SSARegSet.add_3;
eauto.
destruct r;
destruct x;
simpl;
red;
destruct 1;
elim n;
subst;
auto.
destruct H0;
eauto.
Qed.
Lemma In_all_def2:
forall x p s,
SSARegSet.In x
(
PTree.fold
(
fun (
s :
SSARegSet.t) (
_ :
positive) (
phib :
list phiinstruction) =>
fold_left
(
fun (
s0 :
SSARegSet.t) (
phi :
phiinstruction) =>
let (
_,
dst) :=
phi in SSARegSet.add dst s0)
phib s)
p
s) ->
SSARegSet.In x s \/
exists pc :
node,
assigned_phi_spec p pc x.
Proof.
Lemma In_all_def :
forall f x,
SSARegSet.In x (
all_def (
fn_code f) (
fn_phicode f)) ->
(
exists pc,
assigned_phi_spec (
fn_phicode f)
pc x)
\/ (
exists pc,
assigned_code_spec (
fn_code f)
pc x).
Proof.
Lemma ext_params_list_spec :
forall f x,
ext_params f x ->
In x (
ext_params_list (
fn_code f) (
fn_phicode f) (
fn_params f)).
Proof.
Lemma unique_def_elim1:
forall f pc pc'
x,
unique_def_spec f ->
assigned_code_spec (
fn_code f)
pc x ->
assigned_phi_spec (
fn_phicode f)
pc'
x ->
False.
Proof.
intros. inv H.
generalize (H2 x pc pc') ; intros Hcont.
intuition.
Qed.
Ltac ssa_def :=
let eq_pc pc1 pc2 :=
assert (
pc1 =
pc2)
by (
eapply ssa_def_unique;
eauto);
subst
in
match goal with
|
r :
reg |-
_ =>
match goal with
id:
def _ r ?
x,
id':
def _ r ?
y
|-
_ =>
eq_pc x y ;
try clear id'
end
|
x :
node,
y :
node |-
_ =>
match goal with
id:
def _ ?
r x,
id':
assigned_phi_spec_with_args _ y ?
r _ |-
_ =>
assert (
x =
y)
by (
repeat invh assigned_phi_spec_with_args;
eapply ssa_def_unique;
eauto);
subst
end
|
pc1:
node,
pc2:
node |-
_ =>
match goal with
id :
def _ ?
r pc1,
id':
assigned_phi_spec _ pc2 ?
r |-
_ =>
eq_pc pc1 pc2
end
|
pc1:
node,
pc2:
node |-
_ =>
match goal with
id:
assigned_phi_spec _ pc1 ?
r,
id':
assigned_phi_spec _ pc2 ?
r |-
_ =>
eq_pc pc1 pc2
end
|
id1:
assigned_phi_spec_with_args _ ?
pc1 ?
r _,
id2:
In (
Iphi _ ?
r) ?
phib,
id3:
_ ! ?
pc2 =
Some ?
phib |-
_ =>
assert (
pc1 =
pc2)
by (
inv id1;
eapply ssa_def_unique;
eauto);
subst
|
id :
_ ! ?
pc1 =
Some (
Iop _ _ ?
r _),
id' :
_ ! ?
pc2 =
Some (
Iop _ _ ?
r _)
|-
_ =>
match pc2 with
|
pc1 =>
fail 1
|
_ =>
idtac
end;
eq_pc pc1 pc2
|
id :
_ ! ?
pc1 =
Some (
Iop _ _ ?
r _),
id':
def _ ?
r ?
pc2 |-
_ =>
match pc2 with
|
pc1 =>
fail 1
|
_ =>
idtac
end;
eq_pc pc1 pc2
end.
Lemma wf_ssa_phidef_args :
forall f pc x args args',
wf_ssa_function f ->
assigned_phi_spec_with_args (
fn_phicode f)
pc x args ->
assigned_phi_spec_with_args (
fn_phicode f)
pc x args' ->
args =
args'.
Proof.
intros until args'.
intros WF ARGS ARGS'.
repeat invh assigned_phi_spec_with_args;
allinv.
exploit fn_ssa;
eauto.
intros UNIQ.
inv UNIQ.
exploit H3;
eauto;
intros;
invh and;
go.
Qed.
The is_edge predicate
Inductive is_edge (
tf:
SSA.function) :
node ->
node ->
Prop:=
|
Edge:
forall i j instr,
(
fn_code tf)!
i =
Some instr ->
In j (
successors_instr instr) ->
is_edge tf i j.
Lemma is_edge_succs_not_nil:
forall tf i j,
is_edge tf i j ->
exists succtfi, (
successors tf)!
i =
Some succtfi.
Proof.
Lemma is_edge_insuccs:
forall tf i j,
is_edge tf i j ->
(
exists succtfi, (
successors tf) !
i =
Some succtfi /\
In j succtfi).
Proof.
Lemma is_edge_pred:
forall tf i j,
is_edge tf i j ->
exists k,
index_pred (
make_predecessors (
fn_code tf)
successors_instr)
i j =
Some k.
Proof.
Lemma mk_pred_some_in:
forall tf i j ,
In j (
successors tf)!!!
i ->
exists instr, (
fn_code tf)!
i =
Some instr /\
In j (
successors_instr instr) .
Proof.
Lemma pred_is_edge_help:
forall tf i j k,
index_pred (
make_predecessors (
fn_code tf)
successors_instr)
i j =
Some k ->
(
is_edge tf i j).
Proof.
Lemma pred_is_edge:
forall tf i j k,
index_pred (
make_predecessors (
fn_code tf)
successors_instr)
i j =
Some k ->
is_edge tf i j.
Proof.
Inductive ssa_def :
Type :=
|
SDIop (
pc:
node)
|
SDPhi (
pc:
node) (
idx:
nat).
Inductive ssa_eq :
Type :=
|
EqIop (
op:
operation) (
args:
list reg) (
dst:
reg)
|
EqPhi (
dst:
reg) (
args:
list reg).
Definition ssa_eq_to_dst (
eq:
ssa_eq) :
reg :=
match eq with
|
EqIop _ _ dst =>
dst
|
EqPhi dst _ =>
dst
end.
Definition get_ssa_eq (
f:
function) (
d:
ssa_def) :
option ssa_eq :=
match d with
|
SDIop pc =>
match (
fn_code f)!
pc with
|
Some (
Iop op args dst _) =>
Some (
EqIop op args dst)
|
_ =>
None
end
|
SDPhi pc idx =>
match (
fn_phicode f)!
pc with
|
Some phi =>
match nth_error phi idx with
|
Some (
Iphi args dst) =>
Some (
EqPhi dst args)
|
None =>
None
end
|
_ =>
None
end
end.