Require Import Coqlib.
Require Import Maps.
Require Import Classical.
Require Import Utils.
Require Import Relation_Operators.
Require Import Relations.Relation_Definitions.
Require Import DLib.
Formalization of Dominators
We formalize dominators on top of an abstract notion of graph,
parameterized by the node type, on which we assume a decidable
equality. In the CompCertSSA middle-end, node is positive.
Section Graph.
Context {
node :
Type}.
Variable peq :
forall x y:
node, {
x=
y}+{
x<>
y}.
Variable cfg :
node ->
node ->
Prop.
Variable exit :
node ->
Prop.
Variable entry :
node.
reached pc holds if node pc is reachable from entry
Definition reached (
pc:
node) :
Prop := (
cfg **)
entry pc.
Definition of paths in the CFG of a function
Inductive pstate :
Type :=
|
PState:
forall (
pc:
node),
pstate
|
PStop:
pstate.
Inductive path_step :
pstate ->
node ->
pstate ->
Prop :=
|
step_i:
forall pc pc'
(
CFG :
reached pc)
(
STEP:
cfg pc pc'),
path_step (
PState pc)
pc (
PState pc')
|
step_stop:
forall pc
(
CFG :
reached pc)
(
NOSTEP :
exit pc),
path_step (
PState pc)
pc PStop.
Inductive path :
pstate ->
list node ->
pstate ->
Prop :=
|
path_refl :
forall s,
path s nil s
|
path_cons :
forall s1 t s2 pc s3
(
STEP:
path_step s1 pc s2)
(
PATH:
path s2 t s3),
path s1 (
pc::
t)
s3.
Hint Constructors path_step path.
Useful lemmas about path
Lemma path_app :
forall p1 s1 s2 s3 p2,
path s1 p1 s2 ->
path s2 p2 s3 ->
path s1 (
p1++
p2)
s3.
Proof.
induction p1; intros.
inv H. simpl ; auto.
simpl.
inv H.
econstructor ; eauto.
Qed.
Lemma path_from_ret_nil :
forall p s,
path PStop p s ->
p =
nil.
Proof.
induction p ; intros. auto.
inv H ; auto.
inv STEP.
Qed.
Lemma path_from_ret_ret :
forall p s,
path PStop p s ->
s =
PStop.
Proof.
Lemma in_path_split :
forall (
pc pc'
pc'' :
node) (
p :
list node),
path (
PState pc)
p (
PState pc') ->
In pc''
p ->
exists p' :
list node,
exists p'' :
list node,
path (
PState pc)
p' (
PState pc'') /\
~
In pc''
p' /\
path (
PState pc'') (
pc'' ::
p'') (
PState pc').
Proof.
induction 1 ;
intros.
inv H.
inv STEP.
destruct (
peq pc''
pc0).
inv e.
exists nil ;
exists t ;
split ; (
econstructor ;
eauto).
inv H0.
congruence.
exploit IHpath ;
eauto.
intros [
p' [
p'' [
Hp' [
Hnotin Hp'']]]].
exists (
pc0::
p').
exists p''.
split.
econstructor 2 ;
eauto.
econstructor ;
eauto.
intro Hcont ;
inv Hcont ;
intuition.
exploit path_from_ret_nil ;
eauto.
intros Heq.
inv Heq.
inv H0.
inv H.
exists nil;
exists nil.
split; (
econstructor ;
eauto).
inv H2.
Qed.
Lemma in_path_split_app :
forall pc pc'
pc''
p,
path (
PState pc)
p (
PState pc') ->
In pc''
p ->
exists p',
exists p'',
path (
PState pc)
p' (
PState pc'')
/\ ~
In pc''
p'
/\
p =
p'++(
pc''::
p'').
Proof.
induction 1 ;
intros.
inv H.
inv STEP.
destruct (
peq pc''
pc0).
inv e.
clear H0.
exists nil.
exists t ;
split ;
econstructor ;
eauto.
inv H0.
congruence.
exploit IHpath ;
eauto.
intros [
p' [
p'' [
Hp' [
Hnotin Happ]]]].
rewrite Happ.
exists (
pc0::
p').
exists p''.
split.
econstructor 2 ;
eauto.
split.
intro Hcont.
inv Hcont.
elim n ;
auto.
elim Hnotin ;
auto.
simpl ;
auto.
exploit path_from_ret_nil ;
eauto.
intros.
inv H1.
inv H.
inv H0.
exists nil.
exists nil.
split.
econstructor ;
eauto.
split ;
auto.
elim H.
Qed.
Lemma in_path_split' :
forall (
pc pc'
pc'' :
node) (
p :
list node),
path (
PState pc)
p (
PState pc') ->
In pc''
p ->
exists p'
p'',
path (
PState pc)
p' (
PState pc'') /\
~
In pc''
p' /\
path (
PState pc'') (
pc'' ::
p'') (
PState pc') /\
p =
p' ++
pc'' ::
p''.
Proof.
intros.
remember (
PState pc)
as PC.
remember (
PState pc')
as PC'.
revert dependent pc'.
revert dependent pc.
induction H;
intros;
subst.
-
contradiction.
-
inv STEP; [|
inv H;
inv STEP].
destruct (
peq pc pc'').
+
subst.
exists nil,
t.
split; [
constructor|].
split; [
intros []|].
split.
*
econstructor; [|
eassumption].
constructor;
assumption.
*
reflexivity.
+
destruct H0; [
contradiction|].
destruct (
IHpath H0 pc'0
eq_refl pc'
eq_refl)
as (
p' &
p'' &
IH1 &
IH2 &
IH3 &
IH4).
exists (
pc ::
p'),
p''.
repeat split.
*
econstructor; [|
eassumption].
constructor;
assumption.
*
intros [
contra|
contra];
congruence.
*
assumption.
*
rewrite IH4.
reflexivity.
Qed.
Lemma path_first :
forall p pc pc',
path (
PState pc)
p (
PState pc') ->
pc <>
pc' ->
exists pc'',
exists p',
path (
PState pc)
p' (
PState pc'') /\
~
In pc'
p' /\
pc'' <>
pc' /\
path_step (
PState pc'')
pc'' (
PState pc').
Proof.
induction p ;
intros;
inv H.
congruence.
assert (
a =
pc)
by (
inv STEP;
auto).
inv H.
destruct s2.
destruct (
peq pc0 pc').
peq *)
inv e.
exists pc.
exists nil.
split;
auto.
diff *)
exploit IHp ;
eauto.
intros [
pc'' [
p' [
Hp' [
Hpc'' [
Hdiff Hnotin]]]]].
exists pc''.
exists (
pc::
p').
split ;
auto.
econstructor ;
eauto.
split ;
auto.
intro Hcont.
inv Hcont.
congruence.
elim Hpc'' ;
auto.
exploit path_from_ret_nil ;
eauto.
intros Heq;
subst.
inv PATH.
Qed.
Lemma cfg_path :
forall pc pc',
cfg**
pc pc' ->
reached pc ->
exists p,
path (
PState pc)
p (
PState pc').
Proof.
Lemma reached_path :
forall pc',
reached pc' ->
exists p,
path (
PState entry)
p (
PState pc').
Proof.
Dominance relation: dom pc pc' holds if node pc dominates node pc'
Inductive dom :
node ->
node ->
Prop :=
|
dom_eq :
forall pc,
dom pc pc
|
dom_path :
forall pc pc'
(
RPC' :
reached pc')
(
PATH :
forall p,
path (
PState entry)
p (
PState pc') ->
In pc p),
dom pc pc'.
Hint Constructors dom.
Dominance relation is reflexive
Lemma dom_refl :
forall pc,
dom pc pc.
Proof.
intros ; eauto.
Qed.
Dominance relation is transitive
Lemma dom_trans :
forall pc1 pc2 pc3,
dom pc1 pc2 ->
dom pc2 pc3 ->
dom pc1 pc3.
Proof.
intros;
inv H;
auto.
inv H0.
econstructor ;
eauto.
econstructor ;
eauto ;
intros.
exploit PATH0 ;
eauto ;
intros.
destruct (
peq entry pc2).
inv e.
eelim (
PATH nil) ;
eauto.
exploit in_path_split_app ;
eauto.
intros.
destruct H1 as [
p1 [
p2 [
Hpath [
Htrace Happ]]]].
inv Happ.
exploit PATH ;
eauto.
intros.
eapply in_app ;
eauto.
Qed.
Strict dominance sdom pc pc' holds if pc' strictly dominates pc
Inductive sdom (
pc pc' :
node) :
Prop :=
|
sdom_intro :
forall (
DOM : (
dom pc pc')) (
NEQ :
pc <>
pc'),
sdom pc pc'.
Lemma sdom_spec :
forall pc1 pc2,
sdom pc1 pc2 -> (
dom pc1 pc2) /\
pc1 <>
pc2.
Proof.
intros. inv H ; auto.
Qed.
Lemma not_sdom_spec :
forall pc1 pc2, ~
sdom pc1 pc2 ->
(
pc1 =
pc2) \/ (~
dom pc1 pc2).
Proof.
intros.
destruct (
peq pc1 pc2).
auto.
right.
intro Hcont.
elim H ;
auto.
econstructor ;
eauto.
Qed.
Lemma sdom_not_dom :
forall pc pc',
sdom pc pc' -> ~
dom pc'
pc.
Proof.
intros pc pc'
SDOM.
inv SDOM.
generalize DOM ;
inv DOM ;
intros DOM.
congruence.
exploit reached_path ;
eauto.
intros [
ppc'
Hppc'].
exploit PATH ;
eauto.
intros.
exploit in_path_split ;
eauto.
intros [
p' [
p'' [
Hp' [
Hnotin Happ]]]].
destruct (
In_dec peq pc'
p').
exploit (
in_path_split_app entry pc);
eauto.
intros [
p2 [
p3 [
Hp'' [
Hnotin'
Happ']]]].
inv Happ'.
exploit PATH ;
eauto.
intros.
elim Hnotin.
eapply in_app ;
eauto.
intro Hcont.
inv Hcont.
congruence.
exploit PATH0 ;
eauto.
Qed.
Dominance relation is antisymmetric
Lemma dom_antisym :
forall pc pc',
dom pc pc' ->
dom pc'
pc ->
pc =
pc'.
Proof.
intros.
case (
peq pc pc') ;
intros.
auto.
exploit sdom_not_dom ;
eauto.
split ;
auto.
intuition.
Qed.
Strict dominance is transitive
Lemma sdom_trans :
forall pc1 pc2 pc3,
sdom pc1 pc2 ->
sdom pc2 pc3 ->
sdom pc1 pc3.
Proof.
intros.
inv H.
inv H0.
econstructor ;
eauto.
eapply dom_trans;
eauto.
intro Hcont.
inv Hcont.
exploit dom_antisym ;
eauto.
Qed.
Lemma dom_sdom_trans :
forall pc1 pc2 pc3,
dom pc1 pc2 ->
sdom pc2 pc3 ->
sdom pc1 pc3.
Proof.
intros.
destruct (
peq pc1 pc2).
inv e.
auto.
eapply sdom_trans;
eauto.
econstructor ;
eauto.
Qed.
Dominance relation is an order
Lemma dom_order :
order node dom.
Proof.
Other utility lemmas about (strict) dominance
Lemma sdom_dom_pred :
forall pc pc'
pc'',
sdom pc pc'' ->
reached pc' ->
cfg pc'
pc'' ->
dom pc pc'.
Proof.
intros.
destruct (
peq pc pc').
-
inv e ;
econstructor ;
eauto.
-
econstructor ;
eauto.
intros.
inv H.
inv DOM;
try congruence.
exploit (
PATH (
p++(
pc'::
nil))).
+
eapply path_app;
eauto.
+
rewrite in_app_iff;
destruct 1;
auto.
simpl in H;
destruct H;
intuition.
Qed.
Lemma dom_eq_sdom :
forall pc pc',
dom pc pc' ->
pc =
pc' \/
sdom pc pc'.
Proof.
intros.
destruct (
peq pc pc').
inv e ;
auto.
right.
inv H.
congruence.
constructor ;
auto.
Qed.
Lemma entry_dom :
forall pc,
reached pc ->
dom entry pc.
Proof.
intros.
destruct (
peq pc entry).
inv e ;
constructor ;
auto.
constructor;
auto.
intros.
inv H0.
congruence.
inv STEP ;
eauto.
Qed.
Lemma dom_entry :
forall pc,
dom pc entry ->
pc =
entry.
Proof.
intros.
destruct (
peq pc entry).
inv e ;
constructor ;
auto.
inv H.
congruence.
exploit (
PATH nil) ;
eauto.
intros.
inv H.
Qed.
Lemma entry_sdom :
forall pc,
~
sdom pc entry.
Proof.
intros.
intro Hcont.
inv Hcont.
exploit dom_entry ;
eauto.
Qed.
Lemma not_dom_path_wo :
forall pc pc',
~
dom pc pc' ->
reached pc' ->
(
exists p,
path (
PState entry)
p (
PState pc') /\ ~
In pc p).
Proof.
intros.
destruct (
peq pc pc').
inv e.
elim H ;
econstructor ;
eauto.
eelim (
classic (
exists p,
path (
PState entry)
p (
PState pc') /\ ~
In pc p));
intros.
eauto.
elim H.
econstructor ;
eauto.
intros.
destruct (
In_dec peq pc p);
auto.
eelim H1.
exists p ;
eauto.
Qed.
Lemma sdom_dom_trans :
forall pc1 pc2 pc3,
sdom pc1 pc2 ->
dom pc2 pc3 ->
sdom pc1 pc3.
Proof.
intros.
destruct (
peq pc2 pc3).
-
go.
-
eapply sdom_trans;
go.
Qed.
Lemma elim_sdom_sdom :
forall pc1 pc2,
sdom pc1 pc2 ->
sdom pc2 pc1 ->
False.
Proof.
End Graph.