@ -16,35 +16,47 @@ new_theory "llvm_live";
numLib. prefer_num ( ) ;
numLib. prefer_num ( ) ;
Definition inc_pc_def :
Definition inc_pc_def :
inc_pc ip = ip with i := ip. i + 1
inc_pc ip = ip with i := inc_bip ip. i
End
End
(* T h e s e t o f p r o g r a m c o u n t e r s t h e g i v e n i n s t r u c t i o n a n d s t a r t i n g p o i n t c a n
(* T h e s e t o f p r o g r a m c o u n t e r s t h e g i v e n i n s t r u c t i o n a n d s t a r t i n g p o i n t c a n
* immediately reach , within a function * )
* immediately reach , within a function * )
Definition next_ips_def:
Definition instr_ next_ips_def:
( next_ips ( Ret _ ) ip = { } ) ∧
( instr_ next_ips ( Ret _ ) ip = { } ) ∧
( next_ips ( Br _ l1 l2 ) ip =
( instr_ next_ips ( Br _ l1 l2 ) ip =
{ <| f := ip. f ; b := Some l ; i := 0 |> | l | l ∈ { l1 ; l2 } } ) ∧
{ <| f := ip. f ; b := Some l ; i := Phi_ip ip. b |> | l | l ∈ { l1 ; l2 } } ) ∧
( next_ips ( Invoke _ _ _ _ l1 l2 ) ip =
( instr_ next_ips ( Invoke _ _ _ _ l1 l2 ) ip =
{ <| f := ip. f ; b := Some l ; i := 0 |> | l | l ∈ { l1 ; l2 } } ) ∧
{ <| f := ip. f ; b := Some l ; i := Phi_ip ip. b |> | l | l ∈ { l1 ; l2 } } ) ∧
( next_ips Unreachable ip = { } ) ∧
( instr_ next_ips Unreachable ip = { } ) ∧
( next_ips ( Sub _ _ _ _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Sub _ _ _ _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Extractvalue _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Extractvalue _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Insertvalue _ _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Insertvalue _ _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Alloca _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Alloca _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Load _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Load _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Store _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Store _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Gep _ _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Gep _ _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Ptrtoint _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Ptrtoint _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Inttoptr _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Inttoptr _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Icmp _ _ _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Icmp _ _ _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Call _ _ _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Call _ _ _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Cxa_allocate_exn _ _ ) ip = { inc_pc ip } ) ∧
( instr_ next_ips ( Cxa_allocate_exn _ _ ) ip = { inc_pc ip } ) ∧
(* T O D O : r e v i s i t t h r o w w h e n d e a l i n g w i t h e x c e p t i o n s *)
(* T O D O : r e v i s i t t h r o w w h e n d e a l i n g w i t h e x c e p t i o n s *)
( next_ips ( Cxa_throw _ _ _ ) ip = { } ) ∧
( instr_next_ips ( Cxa_throw _ _ _ ) ip = { } ) ∧
( next_ips ( Cxa_begin_catch _ _ ) ip = { inc_pc ip } ) ∧
( instr_next_ips ( Cxa_begin_catch _ _ ) ip = { inc_pc ip } ) ∧
( next_ips ( Cxa_end_catch ) ip = { inc_pc ip } ) ∧
( instr_next_ips ( Cxa_end_catch ) ip = { inc_pc ip } ) ∧
( next_ips ( Cxa_get_exception_ptr _ _ ) ip = { inc_pc ip } )
( instr_next_ips ( Cxa_get_exception_ptr _ _ ) ip = { inc_pc ip } )
End
Inductive next_ips :
( ∀prog ip i l.
get_instr prog ip ( Inl i ) ∧
l ∈ instr_next_ips i ip
⇒
next_ips prog ip l ) ∧
( ∀prog ip from_l phis.
get_instr prog ip ( Inr ( from_l , phis ) )
⇒
next_ips prog ip ( inc_pc ip ) )
End
End
(* T h e p a t h i s a l i s t o f p r o g r a m c o u n t e r s t h a t r e p r e s e n t a s t a t i c a l l y f e a s i b l e
(* T h e p a t h i s a l i s t o f p r o g r a m c o u n t e r s t h a t r e p r e s e n t a s t a t i c a l l y f e a s i b l e
@ -52,14 +64,13 @@ End
Inductive good_path :
Inductive good_path :
( ∀prog. good_path prog [ ] ) ∧
( ∀prog. good_path prog [ ] ) ∧
( ∀ ip i.
( ∀ prog ip i.
get_instr prog ip i
get_instr prog ip i
⇒
⇒
good_path prog [ ip ] ) ∧
good_path prog [ ip ] ) ∧
( ∀prog path ip1 i1 ip2.
( ∀prog path ip1 ip2.
get_instr prog ip1 i1 ∧
ip2 ∈ next_ips prog ip1 ∧
ip2 ∈ next_ips i1 ip1 ∧
good_path prog ( ip2 :: path )
good_path prog ( ip2 :: path )
⇒
⇒
good_path prog ( ip1 :: ip2 :: path ) )
good_path prog ( ip1 :: ip2 :: path ) )
@ -71,65 +82,102 @@ Definition arg_to_regs_def:
End
End
(* T h e r e g i s t e r s t h a t a n i n s t r u c t i o n u s e s *)
(* T h e r e g i s t e r s t h a t a n i n s t r u c t i o n u s e s *)
Definition uses_def:
Definition instr_ uses_def:
( uses ( Ret ( _ , a ) ) = arg_to_regs a ) ∧
( instr_ uses ( Ret ( _ , a ) ) = arg_to_regs a ) ∧
( uses ( Br a _ _ ) = arg_to_regs a ) ∧
( instr_ uses ( Br a _ _ ) = arg_to_regs a ) ∧
( uses ( Invoke _ _ a targs _ _ ) =
( instr_ uses ( Invoke _ _ a targs _ _ ) =
arg_to_regs a ∪ BIGUNION ( set ( map ( arg_to_regs o snd ) targs ) ) ) ∧
arg_to_regs a ∪ BIGUNION ( set ( map ( arg_to_regs o snd ) targs ) ) ) ∧
( uses Unreachable = { } ) ∧
( instr_ uses Unreachable = { } ) ∧
( uses ( Sub _ _ _ _ a1 a2 ) =
( instr_ uses ( Sub _ _ _ _ a1 a2 ) =
arg_to_regs a1 ∪ arg_to_regs a2 ) ∧
arg_to_regs a1 ∪ arg_to_regs a2 ) ∧
( uses ( Extractvalue _ ( _ , a ) _ ) = arg_to_regs a ) ∧
( instr_ uses ( Extractvalue _ ( _ , a ) _ ) = arg_to_regs a ) ∧
( uses ( Insertvalue _ ( _ , a1 ) ( _ , a2 ) _ ) =
( instr_ uses ( Insertvalue _ ( _ , a1 ) ( _ , a2 ) _ ) =
arg_to_regs a1 ∪ arg_to_regs a2 ) ∧
arg_to_regs a1 ∪ arg_to_regs a2 ) ∧
( uses ( Alloca _ _ ( _ , a ) ) = arg_to_regs a ) ∧
( instr_ uses ( Alloca _ _ ( _ , a ) ) = arg_to_regs a ) ∧
( uses ( Load _ _ ( _ , a ) ) = arg_to_regs a ) ∧
( instr_ uses ( Load _ _ ( _ , a ) ) = arg_to_regs a ) ∧
( uses ( Store ( _ , a1 ) ( _ , a2 ) ) =
( instr_ uses ( Store ( _ , a1 ) ( _ , a2 ) ) =
arg_to_regs a1 ∪ arg_to_regs a2 ) ∧
arg_to_regs a1 ∪ arg_to_regs a2 ) ∧
( uses ( Gep _ _ ( _ , a ) targs ) =
( instr_ uses ( Gep _ _ ( _ , a ) targs ) =
arg_to_regs a ∪ BIGUNION ( set ( map ( arg_to_regs o snd ) targs ) ) ) ∧
arg_to_regs a ∪ BIGUNION ( set ( map ( arg_to_regs o snd ) targs ) ) ) ∧
( uses ( Ptrtoint _ ( _ , a ) _ ) = arg_to_regs a ) ∧
( instr_ uses ( Ptrtoint _ ( _ , a ) _ ) = arg_to_regs a ) ∧
( uses ( Inttoptr _ ( _ , a ) _ ) = arg_to_regs a ) ∧
( instr_ uses ( Inttoptr _ ( _ , a ) _ ) = arg_to_regs a ) ∧
( uses ( Icmp _ _ _ a1 a2 ) =
( instr_ uses ( Icmp _ _ _ a1 a2 ) =
arg_to_regs a1 ∪ arg_to_regs a2 ) ∧
arg_to_regs a1 ∪ arg_to_regs a2 ) ∧
( uses ( Call _ _ _ targs ) =
( instr_ uses ( Call _ _ _ targs ) =
BIGUNION ( set ( map ( arg_to_regs o snd ) targs ) ) ) ∧
BIGUNION ( set ( map ( arg_to_regs o snd ) targs ) ) ) ∧
( uses ( Cxa_allocate_exn _ a ) = arg_to_regs a ) ∧
( instr_ uses ( Cxa_allocate_exn _ a ) = arg_to_regs a ) ∧
( uses ( Cxa_throw a1 a2 a3 ) =
( instr_ uses ( Cxa_throw a1 a2 a3 ) =
arg_to_regs a1 ∪ arg_to_regs a2 ∪ arg_to_regs a3 ) ∧
arg_to_regs a1 ∪ arg_to_regs a2 ∪ arg_to_regs a3 ) ∧
( uses ( Cxa_begin_catch _ a ) = arg_to_regs a ) ∧
( instr_uses ( Cxa_begin_catch _ a ) = arg_to_regs a ) ∧
( uses ( Cxa_end_catch ) = { } ) ∧
( instr_uses ( Cxa_end_catch ) = { } ) ∧
( uses ( Cxa_get_exception_ptr _ a ) = arg_to_regs a )
( instr_uses ( Cxa_get_exception_ptr _ a ) = arg_to_regs a )
End
Definition phi_uses_def :
phi_uses from_l ( Phi _ _ entries ) =
case alookup entries from_l of
| None => { }
| Some a => arg_to_regs a
End
Inductive uses :
( ∀prog ip i r.
get_instr prog ip ( Inl i ) ∧
r ∈ instr_uses i
⇒
uses prog ip r ) ∧
( ∀prog ip from_l phis r.
get_instr prog ip ( Inr ( from_l , phis ) ) ∧
r ∈ BIGUNION ( set ( map ( phi_uses from_l ) phis ) )
⇒
uses prog ip r )
End
End
(* T h e r e g i s t e r s t h a t a n i n s t r u c t i o n a s s i g n s *)
(* T h e r e g i s t e r s t h a t a n i n s t r u c t i o n a s s i g n s *)
Definition assigns_def :
Definition instr_assigns_def :
( assigns ( Invoke r _ _ _ _ _ ) = { r } ) ∧
( instr_assigns ( Invoke r _ _ _ _ _ ) = { r } ) ∧
( assigns ( Sub r _ _ _ _ _ ) = { r } ) ∧
( instr_assigns ( Sub r _ _ _ _ _ ) = { r } ) ∧
( assigns ( Extractvalue r _ _ ) = { r } ) ∧
( instr_assigns ( Extractvalue r _ _ ) = { r } ) ∧
( assigns ( Insertvalue r _ _ _ ) = { r } ) ∧
( instr_assigns ( Insertvalue r _ _ _ ) = { r } ) ∧
( assigns ( Alloca r _ _ ) = { r } ) ∧
( instr_assigns ( Alloca r _ _ ) = { r } ) ∧
( assigns ( Load r _ _ ) = { r } ) ∧
( instr_assigns ( Load r _ _ ) = { r } ) ∧
( assigns ( Gep r _ _ _ ) = { r } ) ∧
( instr_assigns ( Gep r _ _ _ ) = { r } ) ∧
( assigns ( Ptrtoint r _ _ ) = { r } ) ∧
( instr_assigns ( Ptrtoint r _ _ ) = { r } ) ∧
( assigns ( Inttoptr r _ _ ) = { r } ) ∧
( instr_assigns ( Inttoptr r _ _ ) = { r } ) ∧
( assigns ( Icmp r _ _ _ _ ) = { r } ) ∧
( instr_assigns ( Icmp r _ _ _ _ ) = { r } ) ∧
( assigns ( Call r _ _ _ ) = { r } ) ∧
( instr_assigns ( Call r _ _ _ ) = { r } ) ∧
( assigns ( Cxa_allocate_exn r _ ) = { r } ) ∧
( instr_assigns ( Cxa_allocate_exn r _ ) = { r } ) ∧
( assigns ( Cxa_begin_catch r _ ) = { r } ) ∧
( instr_assigns ( Cxa_begin_catch r _ ) = { r } ) ∧
( assigns ( Cxa_get_exception_ptr r _ ) = { r } ) ∧
( instr_assigns ( Cxa_get_exception_ptr r _ ) = { r } ) ∧
( assigns _ = { } )
( instr_assigns _ = { } )
End
Definition phi_assigns_def :
phi_assigns ( Phi r _ _ ) = { r }
End
Inductive assigns :
( ∀prog ip i r.
get_instr prog ip ( Inl i ) ∧
r ∈ instr_assigns i
⇒
assigns prog ip r ) ∧
( ∀prog ip from_l phis r.
get_instr prog ip ( Inr ( from_l , phis ) ) ∧
r ∈ BIGUNION ( set ( map phi_assigns phis ) )
⇒
assigns prog ip r )
End
End
Definition live_def :
Definition live_def :
live prog ip ⇔
live prog ip =
{ r | ∃path instr.
{ r | ∃path .
good_path prog ( ip :: path ) ∧
good_path prog ( ip :: path ) ∧
get_instr prog ( last ( ip :: path ) ) instr ∧
r ∈ uses prog ( last ( ip :: path ) ) ∧
r ∈ uses instr ∧
∀ip2. ip2 ∈ set ( front ( ip :: path ) ) ⇒ r ∉ assigns prog ip2 }
∀ip2 instr2. ip2 ∈ set ( front ( ip :: path ) ) ∧ get_instr prog ip2 instr2 ⇒ r ∉ assigns instr2 }
End
End
(*
Theorem get_instr_live :
Theorem get_instr_live :
∀prog ip instr.
∀prog ip instr.
get_instr prog ip instr
get_instr prog ip instr
@ -140,6 +188,7 @@ Proof
qexists_tac ` [ ] ` >> rw [ Once good_path_cases ] >>
qexists_tac ` [ ] ` >> rw [ Once good_path_cases ] >>
qexists_tac ` instr ` >> simp [ ] >> metis_tac [ IN_DEF ]
qexists_tac ` instr ` >> simp [ ] >> metis_tac [ IN_DEF ]
QED
QED
* )
Triviality set_rw :
Triviality set_rw :
! s P. (!x. x ∈ s ⇔ P x ) ⇔ s = P
! s P. (!x. x ∈ s ⇔ P x ) ⇔ s = P
@ -148,28 +197,24 @@ Proof
QED
QED
Theorem live_gen_kill :
Theorem live_gen_kill :
∀prog ip instr ip'.
∀prog ip ip'.
get_instr prog ip instr
live prog ip =
⇒
BIGUNION { live prog ip' | ip' | ip' ∈ next_ips prog ip } DIFF assigns prog ip ∪ uses prog ip
live prog ip = BIGUNION { live prog ip' | ip' ∈ next_ips instr ip } DIFF assigns instr ∪ uses instr
Proof
Proof
rw [ live_def , EXTENSION ] >> eq_tac >> rw [ ]
rw [ live_def , EXTENSION ] >> eq_tac >> rw [ ]
>- (
>- (
Cases_on ` path ` >> fs [ ]
Cases_on ` path ` >> fs [ ] >>
>- metis_tac [ get_instr_func ] >>
rename1 ` ip :: ip2 :: path ` >>
rename1 ` ip :: ip2 :: path ` >>
qpat_x_assum ` good_path _ _ ` mp_tac >> simp [ Once good_path_cases ] >> rw [ ] >>
qpat_x_assum ` good_path _ _ ` mp_tac >> simp [ Once good_path_cases ] >> rw [ ] >>
Cases_on ` x ∈ uses instr ` >> fs [ ] >> simp [ set_rw , PULL_EXISTS ] >>
Cases_on ` x ∈ uses prog ip ` >> fs [ ] >> simp [ set_rw , PULL_EXISTS ] >>
qexists_tac ` ip2 ` >> qexists_tac ` path ` >> qexists_tac ` instr' ` >> rw [ ] >>
qexists_tac ` ip2 ` >> qexists_tac ` path ` >> rw [ ] )
metis_tac [ get_instr_func ] )
>- (
>- (
fs [ ] >>
fs [ ] >>
qexists_tac ` ip' :: path ` >> qexists_tac ` instr' ` >> rw [ ]
qexists_tac ` ip' :: path ` >> rw [ ] >>
>- ( simp [ Once good_path_cases ] >> metis_tac [ ] ) >>
simp [ Once good_path_cases ] )
metis_tac [ get_instr_func ] )
>- (
>- (
qexists_tac ` [ ] ` >> qexists_tac ` instr ` >> rw [ ] >>
qexists_tac ` [ ] ` >> rw [ ] >>
simp [ Once good_path_cases ] >>
f s [ Once good_path_cases , uses_cases , IN_DEF ] >>
metis_tac [ ] )
metis_tac [ ] )
QED
QED