Require Import Bool.
Require Import List.
Import ListNotations.
Require Import Sorting.
Require Import OrdersEx.
Require Import Relation_Operators.
Require Import Coqlib.
Require Import AST.
Require Import Maps.
Require Import Utils.
Require Import TrMaps2.
Require Import Kildall.
Require Import KildallComp.
Require Import SSA.
Require Import SSAutils.
Lemma fold_invariant :
forall {
A B} (
f :
A ->
B ->
A)
l a (
P:
A->
Prop),
P a ->
(
forall x t,
In x l ->
P t ->
P (
f t x)) ->
P (
fold_left f l a).
Proof.
intros A B f l.
induction l; intros.
-
simpl. assumption.
-
simpl. apply IHl.
+ apply H0.
left. reflexivity.
assumption.
+ intros. apply H0.
right. assumption.
assumption.
Qed.
Lemma fold_becomes_true_growing :
forall {
A B :
Type} (
f :
A ->
B ->
A)
l a (
P :
A ->
Prop),
Exists (
fun b =>
forall a,
P (
f a b))
l ->
forall (
f_growing :
forall x t,
In x l ->
P t ->
P (
f t x)),
P (
List.fold_left f l a).
Proof.
intros.
revert a.
induction H;
intros.
-
simpl.
apply fold_invariant.
apply H.
intros.
apply f_growing.
right;
assumption.
assumption.
-
apply IHExists.
intros.
apply f_growing.
right;
assumption.
assumption.
Qed.
Lemma fold_becomes_true_growing_with_invariant :
forall {
A B :
Type} (
f :
A ->
B ->
A)
l a (
P P0 :
A ->
Prop),
P0 a ->
(
forall x t,
In x l ->
P0 t ->
P0 (
f t x)) ->
Exists (
fun b =>
forall a,
P0 a ->
P (
f a b))
l ->
forall (
f_growing :
forall x t,
In x l ->
P0 t ->
P t ->
P (
f t x)),
P (
List.fold_left f l a).
Proof.
intros.
revert dependent a.
induction H1;
intros.
-
simpl.
assert (
P (
fold_left f l (
f a x)) /\
P0 (
fold_left f l (
f a x)))
as Ha;
[|
apply Ha].
apply fold_invariant.
+
split.
*
apply H.
assumption.
*
apply H0.
left;
reflexivity.
assumption.
+
intros.
destruct H3 as (
H31 &
H32).
split.
*
apply f_growing;
try assumption.
right;
assumption.
*
apply H0.
right;
assumption.
assumption.
-
apply IHExists.
+
intros.
apply H0.
right;
assumption.
assumption.
+
intros.
apply f_growing;
try assumption.
right;
assumption.
+
apply H0.
left;
reflexivity.
assumption.
Qed.
Definition option_union (
a b :
option unit) :
option unit :=
match a with
|
None =>
b
|
Some tt =>
Some tt
end.
Lemma union_strict_correct :
forall m1 m2 x,
(
PTree.combine_union_strict option_union m1 m2) !
x =
Some tt
<->
m1 !
x =
Some tt \/
m2 !
x =
Some tt.
Proof.
intros.
rewrite PTree.gcombine_union_strict.
-
destruct (
m1 !
x)
as [[]|], (
m2!
x)
as [[]|];
simpl;
tauto.
-
reflexivity.
-
destruct a as [[]|];
reflexivity.
Qed.
Lemma union_strict_wf :
forall m1 m2,
PTree.pt_wf m1 ->
PTree.pt_wf m2 ->
PTree.pt_wf (
PTree.combine_union_strict option_union m1 m2).
Proof.
Definition option_diff (
a b :
option unit) :
option unit :=
match b with
|
None =>
a
|
Some _ =>
None
end.
Lemma diff_correct :
forall m1 m2 x,
(
PTree.combine_diff option_diff m1 m2) !
x =
Some tt
<->
m1 !
x =
Some tt /\
m2 !
x =
None.
Proof.
intros.
rewrite PTree.gcombine_diff.
destruct (
m2 !
x);
simpl.
-
intuition congruence.
-
intuition.
-
destruct b;
reflexivity.
-
reflexivity.
Qed.
Definition is_included '(
a,
b) '(
c,
d) :=
(
c <=
a)%
positive /\ (
b <=
d)%
positive.
Lemma is_included_trans :
forall a b c d e f,
is_included (
a,
b) (
c,
d) ->
is_included (
c,
d) (
e,
f) ->
is_included (
a,
b) (
e,
f).
Proof.
Lemma is_included_dec :
forall a b c d,
is_included (
a,
b) (
c,
d) \/
~
is_included (
a,
b) (
c,
d).
Proof.
Definition test_is_included '(
a,
b) '(
c,
d) :=
Pos.leb c a &&
Pos.leb b d.
Lemma test_is_included_spec :
forall a b c d,
test_is_included (
a,
b) (
c,
d) =
true <->
is_included (
a,
b) (
c,
d).
Proof.
Definition can_reach r (
c:
PTree.t (
PTree.t unit))
u v :=
match r !
v with
|
None =>
false
|
Some i_v =>
match c !
u with
|
None =>
false
|
Some set =>
PTree.fold (
fun b w _ =>
b ||
match r !
w with
|
None =>
false
|
Some i_w =>
test_is_included i_v i_w
end
)
set false
end
end.
Module SortWithIndex (
X :
Orders.UsualOrderedType).
Section withIndex.
Context {
A :
Type}.
Context (
index :
A ->
X.t).
Fixpoint merge (
l1 l2 :
list (
A*
X.t)) :=
let fix merge_aux l2 :=
match l1,
l2 with
| [],
_ =>
l2
|
_, [] =>
l1
| (
_,
n1)
as a1::
l1', (
_,
n2)
as a2::
l2' =>
match X.compare n1 n2 with
|
Eq =>
merge_aux l2'
|
Lt =>
a1 ::
merge l1'
l2
|
Gt =>
a2 ::
merge_aux l2'
end
end
in merge_aux l2.
Fixpoint merge_list_to_stack stack l :=
match stack with
| [] => [
Some l]
|
None ::
stack' =>
Some l ::
stack'
|
Some l' ::
stack' =>
None ::
merge_list_to_stack stack' (
merge l'
l)
end.
Fixpoint merge_stack stack :=
match stack with
| [] => []
|
None ::
stack' =>
merge_stack stack'
|
Some l ::
stack' =>
merge l (
merge_stack stack')
end.
Fixpoint iter_merge stack l :=
match l with
| [] =>
merge_stack stack
|
a::
l' =>
iter_merge (
merge_list_to_stack stack [(
a,
index a)])
l'
end.
Definition sort_aux :=
iter_merge [].
Definition sort l :=
List.map fst (
sort_aux l).
Local Notation Sorted := (
LocallySorted (
fun '((
_,
n1) :
A *
X.t) '(
_,
n2) =>
X.lt n1 n2)) (
only parsing).
Fixpoint SortedStack stack :=
match stack with
| [] =>
True
|
None ::
stack' =>
SortedStack stack'
|
Some l ::
stack' =>
Sorted l /\
SortedStack stack'
end.
Local Ltac invert H :=
inversion H;
subst;
clear H.
Local Open Scope list_scope.
Fixpoint flatten_stack (
stack :
list (
option (
list (
A *
X.t)))) :=
match stack with
| [] => []
|
None ::
stack' =>
flatten_stack stack'
|
Some l ::
stack' =>
l ++
flatten_stack stack'
end.
Lemma Sorted_merge_aux :
forall x1 n1 l1 x2 n2 l2,
Sorted ((
x2,
n2) ::
l2) ->
exists x3 n3 l3,
merge ((
x1,
n1) ::
l1) ((
x2,
n2) ::
l2) = (
x3,
n3) ::
l3
/\ (
X.eq n3 n1 \/
X.eq n3 n2).
Proof.
intros.
induction l2 as [|(
x2',
n2')
l2].
-
simpl.
destruct (
X.compare_spec n1 n2).
+
eexists _,
_,
_.
split.
reflexivity.
left.
reflexivity.
+
eexists _,
_,
_.
split.
reflexivity.
left.
reflexivity.
+
eexists _,
_,
_.
split.
reflexivity.
right.
reflexivity.
-
simpl in *.
destruct (
X.compare_spec n1 n2).
+
destruct (
X.compare_spec n1 n2').
*
apply IHl2.
invert H.
contradiction (
RelationClasses.StrictOrder_Irreflexive _ H6).
*
eexists _,
_,
_.
split.
reflexivity.
left.
reflexivity.
*
rewrite H0 in H1.
invert H.
rewrite H1 in H6.
contradiction (
RelationClasses.StrictOrder_Irreflexive _ H6).
+
eexists _,
_,
_.
split.
reflexivity.
left.
reflexivity.
+
eexists _,
_,
_.
split.
reflexivity.
right;
reflexivity.
Qed.
Theorem Sorted_merge :
forall l1 l2,
Sorted l1 ->
Sorted l2 ->
Sorted (
merge l1 l2).
Proof.
induction l1 as [|(
x1,
n1)
l1];
induction l2 as [|(
x2,
n2)
l2];
intros;
simpl;
auto.
destruct (
X.compare_spec n1 n2).
-
eapply IHl2.
assumption.
invert H0.
constructor.
assumption.
-
invert H.
+
simpl.
constructor;
trivial.
+
destruct b as (
x3,
n3).
assert (
Sorted (
merge ((
x3,
n3)::
l) ((
x2,
n2)::
l2)))
by (
apply IHl1;
auto).
destruct (
Sorted_merge_aux x3 n3 l x2 n2 l2)
as (
x4 &
n4 &
l4 &
H61 &
H62).
assumption.
rewrite H61.
constructor.
rewrite <-
H61.
assumption.
destruct H62.
rewrite H2.
assumption.
rewrite H2.
assumption.
-
invert H0.
+
constructor;
trivial.
+
destruct b as (
x3,
n3).
assert (
Sorted (
merge ((
x1,
n1)::
l1) ((
x3,
n3)::
l)))
by (
apply IHl2;
auto).
destruct (
Sorted_merge_aux x1 n1 l1 x3 n3 l)
as (
x4 &
n4 &
l4 &
H61 &
H62).
assumption.
fold (
merge ((
x1,
n1) ::
l1) ((
x3,
n3) ::
l)).
simpl in H61.
rewrite H61.
constructor.
rewrite <-
H61.
assumption.
destruct H62.
rewrite H2.
assumption.
rewrite H2.
assumption.
Qed.
Theorem incl_merge :
forall l1 l2,
incl (
merge l1 l2) (
l1++
l2).
Proof.
induction l1 as [|(
x1,
n1)
l1];
simpl merge;
intro.
assert (
forall l, (
fix merge_aux (
l0 :
list _) :
list _ :=
l0)
l =
l)
as ->
by (
destruct l;
trivial).
apply incl_refl.
induction l2 as [|(
x2,
n2)
l2].
rewrite app_nil_r.
apply incl_refl.
destruct (
X.compare_spec n1 n2).
intros (
x3,
n3)
H1.
apply IHl2 in H1.
destruct H1.
left;
assumption.
right.
rewrite in_app_iff in H0 |- *.
destruct H0.
left;
assumption.
right;
right;
assumption.
apply incl_cons.
left;
reflexivity.
apply incl_tl.
apply IHl1.
intros (
x3,
n3)
H1.
destruct H1.
right.
rewrite in_app_iff.
right;
left.
assumption.
apply IHl2 in H0.
destruct H0.
left;
assumption.
right.
rewrite in_app_iff in H0 |- *.
destruct H0.
left;
assumption.
right;
right;
assumption.
Qed.
Theorem incl_merge_2 :
forall l1 l2 x n,
In (
x,
n) (
l1 ++
l2) ->
exists y,
In (
y,
n) (
merge l1 l2).
Proof.
intros l1 l2.
revert l1.
induction l2 as [|(
x2,
n2)
l2];
intros.
-
rewrite app_nil_r in H.
replace (
merge l1 [])
with l1 by (
destruct l1 as [|(?, ?) ?];
reflexivity).
eexists;
eassumption.
-
induction l1 as [|(
x1,
n1)
l1].
+
eexists;
eassumption.
+
simpl.
destruct (
X.compare_spec n1 n2).
*
subst n2.
rewrite in_app_iff in H.
destruct H.
--
eapply IHl2 with (
l1:=(
x1,
n1) ::
l1).
rewrite in_app_iff.
left;
eassumption.
--
destruct H.
++
inv H.
eapply IHl2 with (
l1:=(
x1,
n) ::
l1).
rewrite in_app_iff.
left;
left;
reflexivity.
++
eapply IHl2 with (
l1:=(
x1,
n1) ::
l1).
rewrite in_app_iff.
right;
eassumption.
*
destruct H.
--
inv H.
eexists.
left;
reflexivity.
--
apply IHl1 in H.
destruct H as (
y &
H).
exists y.
right;
assumption.
*
assert ((
x2,
n2) = (
x,
n) \/
In (
x,
n) (((
x1,
n1) ::
l1) ++
l2))
as Ha.
{
rewrite in_app_iff in H.
destruct H.
-
right.
rewrite in_app_iff.
left;
assumption.
-
destruct H.
left;
assumption.
right;
right.
rewrite in_app_iff.
right;
assumption.
}
destruct Ha.
--
eexists.
left.
eassumption.
--
apply IHl2 in H1.
destruct H1 as (
y &
H1).
exists y.
right.
assumption.
Qed.
Theorem incl_merge_2_inj :
forall l1 l2
(
number_inj :
forall x1 x2 n,
In (
x1,
n)
l1 ->
In (
x2,
n)
l2 ->
x1 =
x2),
incl (
l1 ++
l2) (
merge l1 l2).
Proof.
intros l1 l2 ? (
x,
n)
H.
revert dependent l1.
induction l2 as [|(
x2,
n2)
l2];
intros.
-
rewrite app_nil_r in H.
replace (
merge l1 [])
with l1 by (
destruct l1 as [|(?, ?) ?];
reflexivity).
assumption.
-
induction l1 as [|(
x1,
n1)
l1].
+
assumption.
+
simpl.
destruct (
X.compare_spec n1 n2).
*
subst n2.
assert (
x1 =
x2)
as Ha.
{
eapply number_inj;
left;
reflexivity. }
subst x2.
rewrite in_app_iff in H.
destruct H.
--
eapply IHl2 with (
l1:=(
x1,
n1) ::
l1);
eauto.
rewrite in_app_iff.
left;
eassumption.
--
destruct H.
++
inv H.
eapply IHl2 with (
l1:=(
x,
n) ::
l1);
eauto.
rewrite in_app_iff.
left;
left;
reflexivity.
++
eapply IHl2 with (
l1:=(
x1,
n1) ::
l1);
eauto.
rewrite in_app_iff.
right;
eassumption.
*
destruct H.
--
inv H.
left;
reflexivity.
--
apply IHl1 in H;
eauto.
*
assert ((
x2,
n2) = (
x,
n) \/
In (
x,
n) (((
x1,
n1) ::
l1) ++
l2))
as Ha.
{
rewrite in_app_iff in H.
destruct H.
-
right.
rewrite in_app_iff.
left;
assumption.
-
destruct H.
left;
assumption.
right;
right.
rewrite in_app_iff.
right;
assumption.
}
destruct Ha.
--
left.
assumption.
--
apply IHl2 in H1;
eauto.
Qed.
Theorem Sorted_merge_list_to_stack :
forall stack l,
SortedStack stack ->
Sorted l ->
SortedStack (
merge_list_to_stack stack l).
Proof.
induction stack as [|[|]];
intros;
simpl.
auto.
apply IHstack.
destruct H as (
_,
H1).
fold SortedStack in H1.
auto.
apply Sorted_merge;
auto;
destruct H;
auto.
auto.
Qed.
Theorem incl_merge_list_to_stack :
forall stack l,
incl (
flatten_stack (
merge_list_to_stack stack l)) (
l ++
flatten_stack stack).
Proof.
Theorem incl_merge_list_to_stack_2 :
forall stack l x n,
In (
x,
n) (
l ++
flatten_stack stack) ->
exists y,
In (
y,
n) (
flatten_stack (
merge_list_to_stack stack l)).
Proof.
Theorem incl_merge_list_to_stack_2_inj :
forall stack l
(
number_inj :
forall x1 x2 n,
In (
x1,
n) (
l ++
flatten_stack stack) ->
In (
x2,
n) (
l ++
flatten_stack stack) ->
x1 =
x2),
incl (
l ++
flatten_stack stack) (
flatten_stack (
merge_list_to_stack stack l)).
Proof.
Theorem Sorted_merge_stack :
forall stack,
SortedStack stack ->
Sorted (
merge_stack stack).
Proof.
induction stack as [|[|]];
simpl;
intros.
constructor;
auto.
apply Sorted_merge;
tauto.
auto.
Qed.
Theorem incl_merge_stack :
forall stack,
incl (
merge_stack stack) (
flatten_stack stack).
Proof.
induction stack as [|[]];
simpl.
apply incl_refl.
intros (
x,
n)
H.
apply incl_merge in H.
rewrite in_app_iff in H |- *.
destruct H.
left;
assumption.
right;
apply IHstack;
assumption.
assumption.
Qed.
Theorem incl_merge_stack_2 :
forall stack x n,
In (
x,
n) (
flatten_stack stack) ->
exists y,
In (
y,
n) (
merge_stack stack).
Proof.
intros.
induction stack as [|[]];
simpl.
-
contradiction.
-
simpl in H.
rewrite in_app_iff in H.
destruct H.
+
eapply incl_merge_2.
rewrite in_app_iff.
left;
eassumption.
+
apply IHstack in H.
destruct H as (
y &
H).
eapply incl_merge_2.
rewrite in_app_iff.
right;
eassumption.
-
simpl in H.
eauto.
Qed.
Theorem incl_merge_stack_2_inj :
forall stack
(
number_inj :
forall x1 x2 n,
In (
x1,
n) (
flatten_stack stack) ->
In (
x2,
n) (
flatten_stack stack) ->
x1 =
x2),
incl (
flatten_stack stack) (
merge_stack stack).
Proof.
intros.
intros (
x,
n)
H.
apply incl_merge_stack_2 in H as H0.
destruct H0 as (
y &
H0).
apply incl_merge_stack in H0 as H1.
specialize (
number_inj _ _ _ H H1).
subst y.
assumption.
Qed.
Theorem Sorted_iter_merge :
forall stack l,
SortedStack stack ->
Sorted (
iter_merge stack l).
Proof.
Theorem incl_iter_merge :
forall l stack,
incl (
iter_merge stack l)
(
flatten_stack stack ++
List.map (
fun a => (
a,
index a))
l).
Proof.
Theorem incl_iter_merge_2 :
forall l stack x n,
In (
x,
n) (
flatten_stack stack ++
List.map (
fun a => (
a,
index a))
l) ->
exists y,
In (
y,
n) (
iter_merge stack l).
Proof.
Theorem incl_iter_merge_2_inj :
forall l stack
(
number_inj :
forall x1 x2 n,
In (
x1,
n) (
flatten_stack stack ++
List.map (
fun a => (
a,
index a))
l) ->
In (
x2,
n) (
flatten_stack stack ++
List.map (
fun a => (
a,
index a))
l) ->
x1 =
x2),
incl (
flatten_stack stack ++
List.map (
fun a => (
a,
index a))
l)
(
iter_merge stack l).
Proof.
intros.
intros (
x,
n)
H.
apply incl_iter_merge_2 in H as H0.
destruct H0 as (
y &
H0).
apply incl_iter_merge in H0 as H1.
specialize (
number_inj _ _ _ H H1).
subst y.
assumption.
Qed.
Theorem Sorted_sort_aux :
forall l,
Sorted (
sort_aux l).
Proof.
Corollary LocallySorted_sort_aux :
forall l,
Sorted.Sorted (
fun '(
_,
n1) '(
_,
n2) =>
X.lt n1 n2) (
sort_aux l).
Proof.
Theorem incl_sort_aux :
forall l,
incl (
sort_aux l) (
List.map (
fun a => (
a,
index a))
l).
Proof.
Theorem incl_sort_aux_2 :
forall l x n,
In (
x,
n) (
List.map (
fun a => (
a,
index a))
l) ->
exists y,
In (
y,
n) (
sort_aux l).
Proof.
Theorem incl_sort_aux_2_inj :
forall l
(
number_inj :
forall x1 x2 n,
In (
x1,
n) (
List.map (
fun a => (
a,
index a))
l) ->
In (
x2,
n) (
List.map (
fun a => (
a,
index a))
l) ->
x1 =
x2),
incl (
List.map (
fun a => (
a,
index a))
l) (
sort_aux l).
Proof.
intros.
intros (
x,
n)
H.
apply incl_sort_aux_2 in H as H0.
destruct H0 as (
y &
H0).
apply incl_sort_aux in H0 as H1.
specialize (
number_inj _ _ _ H H1).
subst y.
assumption.
Qed.
Corollary StronglySorted_sort_aux :
forall l,
StronglySorted (
fun '(
_,
n1) '(
_,
n2) =>
X.lt n1 n2) (
sort_aux l).
Proof.
Theorem Sorted_sort :
forall l,
LocallySorted (
fun a b =>
X.lt (
index a) (
index b)) (
sort l).
Proof.
intros.
unfold sort.
pose proof (
Sorted_sort_aux l).
pose proof (
incl_sort_aux l).
induction H.
constructor.
constructor.
simpl.
constructor.
apply IHLocallySorted.
intros (
x,
n)
H2.
apply H0.
right;
assumption.
destruct a as (
x1,
n1),
b as (
x2,
n2).
simpl.
pose proof (
H0 (
x1,
n1) (
or_introl eq_refl)).
pose proof (
H0 (
x2,
n2) (
or_intror (
or_introl eq_refl))).
rewrite in_map_iff in H2,
H3.
destruct H2 as (
x1' &
H2 &
_).
destruct H3 as (
x2' &
H3 &
_).
congruence.
Qed.
Corollary LocallySorted_sort :
forall l,
Sorted.Sorted (
fun a b =>
X.lt (
index a) (
index b)) (
sort l).
Proof.
Theorem incl_sort :
forall l,
incl (
sort l)
l.
Proof.
intros.
intros a H.
unfold sort in H.
apply in_map_iff in H.
destruct H as ((
x,
n) &
H1 &
H2).
simpl in H1.
subst x.
apply incl_sort_aux in H2.
apply in_map_iff in H2.
destruct H2 as (
a' &
H21 &
H22).
invert H21.
assumption.
Qed.
Theorem incl_sort_2 :
forall l x,
In x l ->
exists y,
In y (
sort l) /\
index y =
index x.
Proof.
intros.
unfold sort.
assert (
In (
x,
index x) (
map (
fun a :
A => (
a,
index a))
l))
as Ha.
{
apply in_map_iff.
eexists.
split; [
reflexivity|
eassumption]. }
apply incl_sort_aux_2 in Ha.
destruct Ha as (
y &
Ha).
exists y.
split.
-
apply in_map_iff.
eexists (
_,
_).
split; [
reflexivity|
eassumption].
-
apply incl_sort_aux in Ha.
apply in_map_iff in Ha.
destruct Ha as (
y' &
Ha &
_).
inv Ha.
reflexivity.
Qed.
Theorem incl_sort_2_nearly_inj :
forall l wrong x
(
number_nearly_inj :
forall a b,
In a l ->
In b l ->
index a =
index b ->
a =
b \/
In (
index a)
wrong),
In x l -> ~
In (
index x)
wrong ->
In x (
sort l).
Proof.
intros.
apply incl_sort_2 in H as H1.
destruct H1 as (
y &
H11 &
H12).
apply incl_sort in H11 as H21.
specialize (
number_nearly_inj _ _ H21 H H12).
destruct number_nearly_inj;
congruence.
Qed.
Theorem incl_sort_2_inj :
forall l
(
number_inj :
forall a b,
In a l ->
In b l ->
index a =
index b ->
a =
b),
incl l (
sort l).
Proof.
intros.
intros x H.
apply incl_sort_2 in H as H0.
destruct H0 as (
y &
H01 &
H02).
apply incl_sort in H01 as H11.
specialize (
number_inj _ _ H11 H H02).
subst y.
assumption.
Qed.
Corollary StronglySorted_sort :
forall l,
StronglySorted (
fun a b =>
X.lt (
index a) (
index b)) (
sort l).
Proof.
End withIndex.
End SortWithIndex.
Module PosSortWithIndex :=
SortWithIndex OrdersEx.Positive_as_OT.
Module ZSortWithIndex :=
SortWithIndex Z.
Definition itv_strict_incl (
i1 i2:
itv) :
bool :=
if Z_lt_dec i2.(
pre)
i1.(
pre)
then
if Z_le_dec i1.(
post)
i2.(
post)
then true
else false
else false.
Definition itv_strict_Incl i1 i2 :=
i2.(
pre) <
i1.(
pre) /\
i1.(
post) <=
i2.(
post).
Lemma itv_strict_incl_spec :
forall i1 i2,
itv_strict_incl i1 i2 =
true <->
itv_strict_Incl i1 i2.
Proof.
Definition is_strict_ancestor (
dom :
PTree.t itv) (
n1 n2:
node) :
bool :=
match dom !
n1,
dom !
n2 with
|
Some itv1,
Some itv2 =>
itv_strict_incl itv2 itv1
|
_,
_ =>
false
end.
Definition sdom_test f :=
is_strict_ancestor f.(
fn_dom).
Lemma sdom_test_correct :
forall f (
wf :
wf_ssa_function f)
n d,
reached f n ->
sdom_test f d n =
true <->
sdom f d n.
Proof.
Definition du_chain :=
P2Map.t (
list node).
Construction
Definition regs_used_by (
i :
instruction) :
list reg :=
match i with
|
Iop _ l _ _ =>
l
|
Iload _ _ l _ _ =>
l
|
Istore _ _ l src _ =>
src::
l
|
Icall _ ros l _ _
|
Itailcall _ ros l =>
match ros with
|
inl r =>
r ::
l
|
inr _ =>
l
end
|
Ibuiltin _ l _ _ => (
params_of_builtin_args l)
|
Icond _ l _ _ =>
l
|
Ijumptable r _ =>
r ::
nil
|
Ireturn (
Some r) =>
r ::
nil
|
_ =>
nil
end.
Lemma regs_used_by_correct :
forall f pc i r,
f.(
fn_code) !
pc =
Some i ->
use_code f r pc ->
In r (
regs_used_by i).
Proof.
intros.
inv H0; rewrite H1 in H; inv H; simpl; auto.
Qed.
Lemma regs_used_by_complete :
forall f pc i r,
f.(
fn_code) !
pc =
Some i ->
In r (
regs_used_by i) ->
use_code f r pc.
Proof.
intros. destruct i; simpl in H0; try (econstructor; eassumption).
- contradiction.
- destruct s0.
+ econstructor; eassumption.
+ econstructor; eassumption.
- destruct s0.
+ econstructor; eassumption.
+ econstructor; eassumption.
- destruct H0 as [|[]]. subst.
econstructor; eassumption.
- destruct o.
+ destruct H0 as [|[]]. subst.
econstructor; eassumption.
+ contradiction.
Qed.
Definition handle_reg_list (
duc:
du_chain) (
pc :
node) (
rs:
list reg) :=
List.fold_left (
fun u r =>
P2Map.set r (
pc ::
u #2
r)
u)
rs duc.
Lemma handle_reg_list_correct_1 :
forall duc pc rs r pc',
In pc' (
duc #2
r) ->
In pc' ((
handle_reg_list duc pc rs) #2
r).
Proof.
Lemma handle_reg_list_correct_2 :
forall duc pc rs r,
In r rs ->
In pc ((
handle_reg_list duc pc rs) #2
r).
Proof.
Lemma handle_reg_list_complete_1 :
forall duc pc rs r,
In pc ((
handle_reg_list duc pc rs) #2
r) ->
~
In pc (
duc #2
r) ->
In r rs.
Proof.
Lemma handle_reg_list_complete_2 :
forall duc pc rs r pc',
In pc' ((
handle_reg_list duc pc rs) #2
r) ->
pc' <>
pc ->
In pc' (
duc #2
r).
Proof.
Definition def_use_1 duc c :=
PTree.fold (
fun u pc i =>
handle_reg_list u pc (
regs_used_by i))
c duc.
Lemma def_use_1_correct_1 :
forall duc c r pc,
In pc (
duc #2
r) ->
In pc ((
def_use_1 duc c) #2
r).
Proof.
Lemma def_use_1_correct_2 :
forall f duc r pc,
use_code f r pc ->
In pc ((
def_use_1 duc f.(
fn_code)) #2
r).
Proof.
Lemma def_use_1_complete :
forall f duc r pc,
In pc ((
def_use_1 duc f.(
fn_code)) #2
r) ->
~
In pc (
duc #2
r) ->
use_code f r pc.
Proof.
Definition handle_phi_block_k (
duc:
du_chain)
k pc pb :=
List.fold_left (
fun u pi =>
match pi with
|
Iphi args _ =>
match nth_error args k with
|
None =>
u
|
Some r =>
P2Map.set r (
pc ::
u #2
r)
u
end
end)
pb duc.
Lemma handle_phi_block_k_correct_1 :
forall duc k pc pb r pc',
In pc' (
duc #2
r) ->
In pc' ((
handle_phi_block_k duc k pc pb) #2
r).
Proof.
Lemma handle_phi_block_k_correct_2 :
forall duc k pc pb args dst r,
In (
Iphi args dst)
pb ->
nth_error args k =
Some r ->
In pc ((
handle_phi_block_k duc k pc pb) #2
r).
Proof.
Lemma handle_phi_block_k_complete_1 :
forall duc k pc pb r,
In pc ((
handle_phi_block_k duc k pc pb) #2
r) ->
~
In pc (
duc #2
r) ->
exists args dst,
In (
Iphi args dst)
pb /\
nth_error args k =
Some r.
Proof.
intros.
revert H.
unfold handle_phi_block_k.
apply fold_invariant.
-
contradiction.
-
intros pi duc'.
intros.
destruct pi as [
args dst].
destruct (
nth_error args k)
eqn:
Hnth.
+
rewrite P2Map.gsspec in H2.
destruct (
p2eq r r0).
*
subst.
eexists _,
_.
split;
eassumption.
*
auto.
+
auto.
Qed.
Section fold_left2.
Context {
A B C :
Type}.
Context (
f :
A ->
B ->
C ->
A).
Fixpoint fold_left2 (
l1 :
list B) (
l2 :
list C)
a :=
match l1,
l2 with
| [],
_ =>
a
|
_, [] =>
a
|
b ::
l1,
c ::
l2 =>
fold_left2 l1 l2 (
f a b c)
end.
Lemma fold_left2_invariant_nth :
forall l1 l2 a (
P:
A->
Prop),
P a ->
(
forall k b c t,
nth_error l1 k =
Some b ->
nth_error l2 k =
Some c ->
P t ->
P (
f t b c)) ->
P (
fold_left2 l1 l2 a).
Proof.
intros l1.
induction l1;
intros.
-
simpl.
assumption.
-
destruct l2.
+
simpl.
assumption.
+
simpl.
apply IHl1.
*
apply H0 with (
k:=0%
nat).
--
reflexivity.
--
reflexivity.
--
assumption.
*
intros.
apply H0 with (
k:=
S k);
assumption.
Qed.
Lemma fold_left2_invariant :
forall l1 l2 a (
P:
A->
Prop),
P a ->
(
forall b c t,
In b l1 ->
In c l2 ->
P t ->
P (
f t b c)) ->
P (
fold_left2 l1 l2 a).
Proof.
Lemma fold_left2_app :
forall l11 l12 l21 l22 a,
List.length l11 =
List.length l21 ->
fold_left2 (
l11 ++
l12) (
l21 ++
l22)
a
=
fold_left2 l12 l22 (
fold_left2 l11 l21 a).
Proof.
induction l11;
intros.
-
simpl in H.
symmetry in H.
apply length_zero_iff_nil in H.
subst.
reflexivity.
-
destruct l21 as [|
b l21].
+
simpl in H.
discriminate.
+
simpl.
apply IHl11.
simpl in H.
congruence.
Qed.
Lemma fold_left2_becomes_true_growing :
forall l1 l2 a (
P :
A ->
Prop)
k b c,
nth_error l1 k =
Some b ->
nth_error l2 k =
Some c ->
(
forall a,
P (
f a b c)) ->
forall (
f_growing :
forall b c t,
In b l1 ->
In c l2 ->
P t ->
P (
f t b c)),
P (
fold_left2 l1 l2 a).
Proof.
End fold_left2.
Definition handle_phi_instr (
duc :
du_chain)
preds pi :=
match pi with
|
Iphi args _ =>
fold_left2 (
fun c pc arg =>
P2Map.set arg (
pc ::
c #2
arg)
c)
preds args duc
end.
Lemma handle_phi_instr_correct_1 :
forall duc preds pi r pc,
In pc (
duc #2
r) ->
In pc ((
handle_phi_instr duc preds pi) #2
r).
Proof.
intros.
destruct pi as [
args dst].
simpl.
apply fold_left2_invariant.
-
assumption.
-
intros pc'
r'
duc'.
intros.
rewrite P2Map.gsspec.
destruct (
p2eq r r').
+
right;
congruence.
+
assumption.
Qed.
Lemma handle_phi_instr_correct_2 :
forall duc preds args dst k r pc,
nth_error preds k =
Some pc ->
nth_error args k =
Some r ->
In pc ((
handle_phi_instr duc preds (
Iphi args dst)) #2
r).
Proof.
Lemma handle_phi_instr_complete :
forall duc preds args dst r pc,
In pc ((
handle_phi_instr duc preds (
Iphi args dst)) #2
r) ->
~
In pc (
duc #2
r) ->
exists k,
nth_error preds k =
Some pc /\
nth_error args k =
Some r.
Proof.
Definition handle_phi_block (
duc :
du_chain)
preds (
pb :
phiblock) :=
fold_left (
fun u pi =>
handle_phi_instr u preds pi)
pb duc.
Lemma handle_phi_block_correct_1 :
forall duc preds pb r pc,
In pc (
duc #2
r) ->
In pc ((
handle_phi_block duc preds pb) #2
r).
Proof.
Lemma handle_phi_block_correct_2 :
forall duc preds pb args dst k r pc,
In (
Iphi args dst)
pb ->
nth_error args k =
Some r ->
nth_error preds k =
Some pc ->
In pc ((
handle_phi_block duc preds pb) #2
r).
Proof.
Lemma handle_phi_block_complete :
forall duc preds pb r pc,
In pc ((
handle_phi_block duc preds pb) #2
r) ->
~
In pc (
duc #2
r) ->
exists args dst k,
In (
Iphi args dst)
pb /\
nth_error preds k =
Some pc /\
nth_error args k =
Some r.
Proof.
intros.
revert H.
unfold handle_phi_block.
apply fold_invariant.
-
contradiction.
-
intros pi duc'.
intros.
destruct (
in_dec peq pc (
duc' #2
r)).
+
auto.
+
destruct pi as [
args dst].
exists args,
dst.
apply handle_phi_instr_complete in H2;
try assumption.
destruct H2 as (
k &
H21 &
H22).
exists k.
repeat (
split;
eauto).
Qed.
Definition def_use_2 duc c phic :=
let preds :=
make_predecessors c successors_instr in
PTree.fold (
fun u pc pb =>
match preds !
pc with
|
None =>
u
|
Some preds =>
handle_phi_block u preds pb
end)
phic duc.
Lemma def_use_2_correct_1 :
forall duc c phic r pc,
In pc (
duc #2
r) ->
In pc ((
def_use_2 duc c phic) #2
r).
Proof.
Lemma def_use_2_correct_2 :
forall f (
wf :
wf_ssa_function f)
duc r pc,
use_phicode f r pc ->
In pc ((
def_use_2 duc f.(
fn_code)
f.(
fn_phicode)) #2
r).
Proof.
Lemma make_predecessors_NoDup :
forall f (
wf :
wf_ssa_function f)
pc,
NoDup ((
make_predecessors f.(
fn_code)
successors_instr) !!!
pc).
Proof.
Lemma def_use_2_complete :
forall f (
wf :
wf_ssa_function f)
duc r pc,
In pc ((
def_use_2 duc f.(
fn_code)
f.(
fn_phicode)) #2
r) ->
~
In pc (
duc #2
r) ->
use_phicode f r pc.
Proof.
Definition make_du_chain f :
du_chain :=
let u :=
def_use_1 (
P2Map.init nil) (
fn_code f)
in
def_use_2 u f.(
fn_code)
f.(
fn_phicode).
Lemma make_du_chain_correct :
forall f (
wf :
wf_ssa_function f)
r pc,
use f r pc ->
In pc ((
make_du_chain f) #2
r).
Proof.
Lemma make_du_chain_complete :
forall f (
wf :
wf_ssa_function f)
r pc,
In pc ((
make_du_chain f) #2
r) ->
use f r pc.
Proof.
Definition defined_var ins :=
match ins with
|
Iop _ _ r _ =>
Some r
|
Iload _ _ _ r _ =>
Some r
|
Icall _ _ _ r _ =>
Some r
|
Ibuiltin _ _ (
BR r)
_ =>
Some r
|
_ =>
None
end.
Definition compute_code_def (
f :
function) :
P2Tree.t node ->
P2Tree.t node :=
PTree.fold
(
fun acc pc ins =>
match defined_var ins with
|
Some r =>
P2Tree.set r pc acc
|
None =>
acc
end)
(
fn_code f).
Definition compute_phi_def (
f :
function) :
P2Tree.t node ->
P2Tree.t node :=
PTree.fold
(
fun acc pc phib =>
fold_left
(
fun acc phi =>
match phi with
|
Iphi args dst =>
P2Tree.set dst pc acc
end)
phib acc)
(
fn_phicode f).
Definition get_all_def f :=
let defs :=
P2Tree.empty node in
let defs :=
compute_code_def f defs in
let defs :=
compute_phi_def f defs in
defs.
Definition compute_def (
f :
function)
all_defs :=
fun r =>
match all_defs !2
r with
|
Some d =>
d
|
None =>
fn_entrypoint f
end.
Lemma assigned_code_spec_defined_var :
forall f d r,
assigned_code_spec f.(
fn_code)
d r ->
exists i,
f.(
fn_code) !
d =
Some i /\
defined_var i =
Some r.
Proof.
intros. inv H; (eexists; split; [eassumption|reflexivity]).
Qed.
Lemma defined_var_assigned_code_spec :
forall f d i r,
f.(
fn_code) !
d =
Some i ->
defined_var i =
Some r ->
assigned_code_spec f.(
fn_code)
d r.
Proof.
intros. destruct i; inv H0; try (econstructor; eassumption).
destruct b; inv H2; econstructor; eassumption.
Qed.
Lemma compute_code_def_correct_1 :
forall f (
wf :
wf_ssa_function f)
defs r,
(
forall pc, ~
assigned_code_spec f.(
fn_code)
pc r) ->
(
compute_code_def f defs) !2
r =
defs !2
r.
Proof.
Lemma compute_code_def_correct_2 :
forall f (
wf :
wf_ssa_function f)
defs r d,
assigned_code_spec f.(
fn_code)
d r ->
(
compute_code_def f defs) !2
r =
Some d.
Proof.
Lemma compute_code_def_complete :
forall f (
wf :
wf_ssa_function f)
defs r d,
(
compute_code_def f defs) !2
r =
Some d ->
defs !2
r =
None ->
assigned_code_spec f.(
fn_code)
d r.
Proof.
Lemma compute_phi_def_correct_1 :
forall f (
wf :
wf_ssa_function f)
defs r,
(
forall pc, ~
assigned_phi_spec f.(
fn_phicode)
pc r) ->
(
compute_phi_def f defs) !2
r =
defs !2
r.
Proof.
Lemma compute_phi_def_correct_2 :
forall f (
wf :
wf_ssa_function f)
defs r d,
assigned_phi_spec f.(
fn_phicode)
d r ->
(
compute_phi_def f defs) !2
r =
Some d.
Proof.
Lemma compute_phi_def_complete :
forall f (
wf :
wf_ssa_function f)
defs r d,
(
compute_phi_def f defs) !2
r =
Some d ->
defs !2
r =
None ->
assigned_phi_spec f.(
fn_phicode)
d r.
Proof.
Lemma compute_def_correct :
forall f (
wf :
wf_ssa_function f)
r d,
def f r d ->
compute_def f (
get_all_def f)
r =
d.
Proof.
Lemma compute_def_complete :
forall f (
wf :
wf_ssa_function f)
r d
(
USE:
exists pc,
use f r pc),
compute_def f (
get_all_def f)
r =
d ->
def f r d.
Proof.
Definition collect_variables f :=
let defs :=
all_def f.(
fn_code)
f.(
fn_phicode)
in
let uses :=
all_uses f.(
fn_code)
f.(
fn_phicode)
in
let params :=
List.fold_left (
fun acc x =>
SSARegSet.add x acc)
f.(
fn_params)
SSARegSet.empty
in
SSARegSet.union (
SSARegSet.union defs uses)
params.
Definition ignore2 {
A B} (
x :
A) (
y :
B) :=
x.
Lemma clos_refl_trans_clos_trans :
forall {
A} (
R :
A ->
A ->
Prop)
x y,
clos_refl_trans _ R x y <->
x =
y \/
clos_trans _ R x y.
Proof.
split;
intros.
-
induction H.
+
right;
apply t_step;
assumption.
+
left;
reflexivity.
+
destruct IHclos_refl_trans1,
IHclos_refl_trans2.
*
left;
congruence.
*
right;
congruence.
*
right;
congruence.
*
right;
eauto using t_trans.
-
destruct H.
subst y.
apply rt_refl.
induction H.
+
apply rt_step;
assumption.
+
eauto using rt_trans.
Qed.