theory SSA_CFG imports Graph_path "HOL-Library.Sublist" begin
subsection‹CFG›
locale CFG_base = graph_Entry_base αe αn invar inEdges' Entry for
αe :: "'g ==> ('node::linorder × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"and
Entry :: "'g ==> 'node" + fixes"defs" :: "'g ==> 'node ==> 'var::linorder set" fixes"uses" :: "'g ==> 'node ==> 'var set" begin definition"vars g ≡ fold (∪) (map (uses g) (αn g)) {}" definition defAss' :: "'g ==> 'node ==> 'var ==> bool"where "defAss' g m v ⟷ (∀ns. g ⊨ Entry g-ns→m ⟶ (∃n ∈ set ns. v ∈ defs g n))"
definition defAss'Uses :: "'g ==> bool"where "defAss'Uses g ≡∀m ∈ set (αn g). ∀v ∈ uses g m. defAss' g m v" end
locale CFG = CFG_base αe αn invar inEdges' Entry "defs""uses"
+ graph_Entry αe αn invar inEdges' Entry for
αe :: "'g ==> ('node::linorder × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"and
Entry :: "'g ==> 'node"and "defs" :: "'g ==> 'node ==> 'var::linorder set"and "uses" :: "'g ==> 'node ==> 'var set" + assumes defs_uses_disjoint: "n ∈ set (αn g) ==> defs g n ∩ uses g n = {}" assumes defs_finite[simp]: "finite (defs g n)" assumes uses_in_αn: "v ∈ uses g n ==> n ∈ set (αn g)" assumes uses_finite[simp, intro!]: "finite (uses g n)" assumes invar[intro!]: "invar g" begin lemma vars_finite[simp]: "finite (vars g)" by (auto simp:vars_def)
lemma Entry_no_predecessor[simp]: "predecessors g (Entry g) = []" using Entry_unreachable by (auto simp:predecessors_def)
lemma uses_in_vars[elim, simp]: "v ∈ uses g n ==> v ∈ vars g" by (auto simp add:vars_def uses_in_αn intro!: fold_union_elemI)
lemma varsE: assumes"v ∈ vars g" obtains n where"n ∈ set (αn g)""v ∈ uses g n" using assms by (auto simp:vars_def elim!:fold_union_elem)
lemma defs_uses_disjoint'[simp]: "n ∈ set (αn g) ==> v ∈ defs g n ==> v ∈ uses g n ==> False" using defs_uses_disjoint by auto end
context CFG begin lemma defAss'E: assumes"defAss' g m v""g ⊨ Entry g-ns→m" obtains n where"n ∈ set ns""v ∈ defs g n" using assms unfolding defAss'_defby auto
lemma defAss'_extend: assumes"defAss' g m v" assumes"g ⊨ n-ns→m""∀n ∈ set (tl ns). v ∉ defs g n" shows"defAss' g n v" unfolding defAss'_defproof (rule allI, rule impI) fix ns' assume"g ⊨ Entry g-ns'→n" with assms(2) have"g ⊨ Entry g-ns'@tl ns→m"by auto with assms(1) obtain n' where n': "n' ∈ set (ns'@tl ns)""v ∈ defs g n'"by -(erule defAss'E) with assms(3) have"n' ∉ set (tl ns)"by auto with n' show"∃n ∈ set ns'. v ∈ defs g n"by auto qed end
text‹A CFG is well-formed if it satisfies definite assignment.›
locale CFG_SSA_base = CFG_base αe αn invar inEdges' Entry "defs""uses" for
αe :: "'g ==> ('node::linorder × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"and
Entry::"'g ==> 'node"and "defs" :: "'g ==> 'node ==> 'val::linorder set"and "uses" :: "'g ==> 'node ==> 'val set" + fixes phis :: "'g ==> ('node, 'val) phis" begin definition"phiDefs g n ≡ {v. (n,v) ∈ dom (phis g)}" definition[code]: "allDefs g n ≡ defs g n ∪ phiDefs g n"
definition[code]: "phiUses g n ≡ ∪n' ∈ set (successors g n). ∪v' ∈ phiDefs g n'. snd ` Set.filter (λ(n'',v). n'' = n) (set (zip (predecessors g n') (the (phis g (n',v')))))" definition[code]: "allUses g n ≡ uses g n ∪ phiUses g n" definition[code]: "allVars g ≡∪n ∈ set (αn g). allDefs g n ∪ allUses g n"
definition defAss :: "'g ==> 'node ==> 'val ==> bool"where "defAss g m v ⟷ (∀ns. g ⊨ Entry g-ns→m ⟶ (∃n ∈ set ns. v ∈ allDefs g n))"
lemmas CFG_SSA_defs = phiDefs_def allDefs_def phiUses_def allUses_def allVars_def defAss_def end
locale CFG_SSA = CFG αe αn invar inEdges' Entry "defs""uses" + CFG_SSA_base αe αn invar inEdges' Entry "defs""uses" phis for
αe :: "'g ==> ('node::linorder × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"and
Entry::"'g ==> 'node"and "defs" :: "'g ==> 'node ==> 'val::linorder set"and "uses" :: "'g ==> 'node ==> 'val set"and
phis :: "'g ==> ('node, 'val) phis" + assumes phis_finite: "finite (dom (phis g))" assumes phis_in_αn: "phis g (n,v) = Some vs ==> n ∈ set (αn g)" assumes phis_wf: "phis g (n,v) = Some args ==> length (predecessors g n) = length args" assumes simpleDefs_phiDefs_disjoint: "n ∈ set (αn g) ==> defs g n ∩ phiDefs g n = {}" assumes allDefs_disjoint: "[n ∈ set (αn g); m ∈ set (αn g); n ≠ m]==> allDefs g n ∩ allDefs g m = {}" begin lemma phis_disj: assumes"phis g (n,v) = Some vs" and"phis g (n',v) = Some vs'" shows"n = n'"and"vs = vs'" proof - from assms have"n ∈ set (αn g)"and"n' ∈ set (αn g)" by (auto dest: phis_in_αn) from allDefs_disjoint [OF this] assms show"n = n'" by (auto simp: allDefs_def phiDefs_def) with assms show"vs = vs'"by simp qed
lemma allDefs_disjoint': "[n ∈ set (αn g); m ∈ set (αn g); v ∈ allDefs g n; v ∈ allDefs g m]==> n = m" using allDefs_disjoint by auto
lemma phiUsesI: assumes"n' ∈ set (αn g)""phis g (n',v') = Some vs""(n,v) ∈ set (zip (predecessors g n') vs)" shows"v ∈ phiUses g n" proof- from assms(3) have"n ∈ set (predecessors g n')"by auto hence1: "n' ∈ set (successors g n)"using assms(1) by simp from assms(2) have2: "v' ∈ phiDefs g n'"by (auto simp add:phiDefs_def) from assms(2) have3: "the (phis g (n',v')) = vs"by simp with assms(3) show ?thesis apply (simp only: phiUses_def) using1apply (rule UN_I) using2apply (rule UN_I) apply auto done qed
lemma phiUsesE: assumes"v ∈ phiUses g n" obtains n' v' vs where"n' ∈ set (successors g n)""(n,v) ∈ set (zip (predecessors g n') vs)""phis g (n', v') = Some vs" proof- from assms(1) obtain n' v' where"n'∈set (successors g n)""v'∈phiDefs g n'" "v ∈ snd ` Set.filter (λ(n'', v). n'' = n) (set (zip (predecessors g n') (the (phis g (n', v')))))"by (auto simp:phiUses_def) thus ?thesis by - (rule that[of n' "the (phis g (n',v'))" v'], auto simp:phiDefs_def) qed
lemma defs_in_allDefs[simp]: "v ∈ defs g n ==> v ∈ allDefs g n"by (simp add:allDefs_def) lemma phiDefs_in_allDefs[simp, elim]: "v ∈ phiDefs g n ==> v ∈ allDefs g n"by (simp add:allDefs_def) lemma uses_in_allUses[simp]: "v ∈ uses g n ==> v ∈ allUses g n"by (simp add:allUses_def) lemma phiUses_in_allUses[simp]: "v ∈ phiUses g n ==> v ∈ allUses g n"by (simp add:allUses_def) lemma allDefs_in_allVars[simp, intro]: "[v ∈ allDefs g n; n ∈ set (αn g)]==> v ∈ allVars g"by (auto simp:allVars_def) lemma allUses_in_allVars[simp, intro]: "[v ∈ allUses g n; n ∈ set (αn g)]==> v ∈ allVars g"by (auto simp:allVars_def)
lemma phiDefs_finite[simp]: "finite (phiDefs g n)" unfolding phiDefs_def proof (rule finite_surj[where f=snd], rule phis_finite[where g=g]) have"∧x y. phis g (n,x) = Some y ==> x ∈ snd ` dom (phis g)"by (metis domI imageI snd_conv) thus"{v. (n, v) ∈ dom (phis g)} ⊆ snd ` dom (phis g)"by auto qed
lemma phiUses_finite[simp]: assumes"n ∈ set (αn g)" shows"finite (phiUses g n)" by (auto simp: phiUses_def)
lemma allDefs_finite[simp]: "n ∈ set (αn g) ==> finite (allDefs g n)"by (auto simp add:allDefs_def) lemma allUses_finite[simp]: "n ∈ set (αn g) ==> finite (allUses g n)"by (auto simp add:allUses_def) lemma allVars_finite[simp]: "finite (allVars g)"by (auto simp add:allVars_def)
lemma defAss_extend: assumes"defAss g m v" assumes"g ⊨ n-ns→m""∀n ∈ set (tl ns). v ∉ allDefs g n" shows"defAss g n v" unfolding defAss_def proof (rule allI, rule impI) fix ns' assume"g ⊨ Entry g-ns'→n" with assms(2) have"g ⊨ Entry g-ns'@tl ns→m"by auto with assms(1) obtain n' where n': "n' ∈ set (ns'@tl ns)""v ∈ allDefs g n'"by (auto dest:defAssD) with assms(3) have"n' ∉ set (tl ns)"by auto with n' show"∃n ∈ set ns'. v ∈ allDefs g n"by auto qed
lemma defAss_dominating: assumes[simp]: "n ∈ set (αn g)" shows"defAss g n v ⟷ (∃m ∈ set (αn g). dominates g m n ∧ v ∈ allDefs g m)" proof assume asm: "defAss g n v" obtain ns where ns: "g ⊨ Entry g-ns→n"by (atomize, auto) from defAssD[OF asm this] obtain m where m: "m ∈ set ns""v ∈ allDefs g m"by auto have"dominates g m n" proof fix ns' assume ns': "g ⊨ Entry g-ns'→n" from defAssD[OF asm this] obtain m' where m': "m' ∈ set ns'""v ∈ allDefs g m'"by auto with m ns ns' have"m' = m"by - (rule allDefs_disjoint', auto) with m' show"m ∈ set ns'"by simp qed simp with m ns show"∃m∈set (αn g). dominates g m n ∧ v ∈ allDefs g m"by auto next assume"∃m ∈ set (αn g). dominates g m n ∧ v ∈ allDefs g m" thenobtain m where[simp]: "m ∈ set (αn g)"and m: "dominates g m n""v ∈ allDefs g m"by auto show"defAss g n v" proof (rule defAssI) fix ns assume"g ⊨ Entry g-ns→n" with m(1) have"m ∈ set ns"by - (rule dominates_mid, auto) with m(2) show"∃n∈set ns. v ∈ allDefs g n"by auto qed qed end
locale CFG_SSA_wf_base = CFG_SSA_base αe αn invar inEdges' Entry "defs""uses" phis for
αe :: "'g ==> ('node::linorder × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"and
Entry::"'g ==> 'node"and "defs" :: "'g ==> 'node ==> 'val::linorder set"and "uses" :: "'g ==> 'node ==> 'val set"and
phis :: "'g ==> ('node, 'val) phis" begin text‹Using the SSA properties, we can map every value to its unique defining node and
remove the @{typ 'node} parameter of the @{term phis} map.›
definition defNode :: "'g ==> 'val ==> 'node"where
defNode_code [code]: "defNode g v ≡ hd [n ← αn g. v ∈ allDefs g n]"
abbreviation"def_dominates g v' v ≡ dominates g (defNode g v') (defNode g v)" abbreviation"strict_def_dom g v' v ≡ defNode g v' ≠ defNode g v ∧ def_dominates g v' v"
definition"phi g v = phis g (defNode g v,v)" definition[simp]: "phiArg g v v' ≡∃vs. phi g v = Some vs ∧ v' ∈ set vs"
definition[code]: "isTrivialPhi g v v' ⟷ v' ≠ v ∧ (case phi g v of Some vs ==> set vs = {v,v'} ∨ set vs = {v'} | None ==> False)" definition[code]: "trivial g v ≡∃v' ∈ allVars g. isTrivialPhi g v v'" definition[code]: "redundant g ≡∃v ∈ allVars g. trivial g v"
definition"defAssUses g ≡∀n ∈ set (αn g). ∀v ∈ allUses g n. defAss g n v"
text‹'liveness' of an SSA value is defined inductively starting from simple uses so that
a circle of \pf s is not considered live.›
declare [[inductive_internals]] inductive liveVal :: "'g ==> 'val ==> bool" for g :: 'g where
liveSimple: "[n ∈ set (αn g); val ∈ uses g n]==> liveVal g val"
| livePhi: "[liveVal g v; phiArg g v v']==> liveVal g v'"
definition"pruned g = (∀n ∈ set (αn g). ∀val. val ∈ phiDefs g n ⟶ liveVal g val)"
locale CFG_SSA_wf = CFG_SSA αe αn invar inEdges' Entry "defs""uses" phis + CFG_SSA_wf_base αe αn invar inEdges' Entry "defs""uses" phis for
αe :: "'g ==> ('node::linorder × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"and
Entry::"'g ==> 'node"and "defs" :: "'g ==> 'node ==> 'val::linorder set"and "uses" :: "'g ==> 'node ==> 'val set"and
phis :: "'g ==> ('node, 'val) phis" + assumes allUses_def_ass: "[v ∈ allUses g n; n ∈ set (αn g)]==> defAss g n v" assumes Entry_no_phis[simp]: "phis g (Entry g,v) = None" begin lemma allVars_in_allDefs: "v ∈ allVars g ==>∃n ∈ set (αn g). v ∈ allDefs g n" unfolding allVars_def apply auto apply (drule(1) allUses_def_ass) apply (clarsimp simp: defAss_def) apply (drule Entry_reaches) apply auto[1] by fastforce
lemma phiDefs_Entry_empty[simp]: "phiDefs g (Entry g) = {}" by (auto simp: phiDefs_def)
lemma phi_Entry_empty[simp]: "defNode g v = Entry g ==> phi g v = None" by (simp add:phi_def)
lemma defNode_ex1: assumes"v ∈ allVars g" shows"∃!n. n ∈ set (αn g) ∧ v ∈ allDefs g n" proof (rule ex_ex1I) show"∃n. n ∈ set (αn g) ∧ v ∈ allDefs g n" proof- from assms(1) obtain n where n: "n ∈ set (αn g)""v ∈ allDefs g n ∨ v ∈ allUses g n"by (auto simp:allVars_def) thus ?thesis proof (cases "v ∈ allUses g n") case True from n(1) obtain ns where ns: "g ⊨ Entry g-ns→n"by (atomize_elim, rule Entry_reaches, auto) with allUses_def_ass[OF True n(1)] obtain m where m: "m ∈ set ns""v ∈ allDefs g m"by - (drule defAssD, auto) from ns this(1) have"m ∈ set (αn g)"by (rule path2_in_αn) with n(1) m show ?thesis by auto qed auto qed show"∧n m. n ∈ set (αn g) ∧ v ∈ allDefs g n ==> m ∈ set (αn g) ∧ v ∈ allDefs g m ==> n = m"using allDefs_disjoint by auto qed
lemma defNode_def: "v ∈ allVars g ==> defNode g v = (THE n. n ∈ set (αn g) ∧ v ∈ allDefs g n)" unfolding defNode_code by (rule the1_list[symmetric], rule defNode_ex1)
lemma defNode[simp]: assumes"v ∈ allVars g" shows"(defNode g v) ∈ set (αn g)""v ∈ allDefs g (defNode g v)" apply (atomize(full)) unfolding defNode_def[OF assms] using assms by - (rule theI', rule defNode_ex1)
lemma defNode_eq[intro]: assumes"n ∈ set (αn g)""v ∈ allDefs g n" shows"defNode g v = n" apply (subst defNode_def, rule allDefs_in_allVars[OF assms(2) assms(1)]) by (rule the1_equality, rule defNode_ex1, rule allDefs_in_allVars[where n=n], simp_all add:assms)
lemma defNode_cases[consumes 1]: assumes"v ∈ allVars g" obtains (simpleDef) "v ∈ defs g (defNode g v)"
| (phi) "phi g v ≠ None" proof (cases "v ∈ defs g (defNode g v)") case True thus thesis by (rule simpleDef) next case False with assms[THEN defNode(2)] show thesis by - (rule phi, auto simp: allDefs_def phiDefs_def phi_def) qed
lemma phi_phiDefs[simp]: "phi g v = Some vs ==> v ∈ phiDefs g (defNode g v)"by (auto simp:phiDefs_def phi_def)
lemma simpleDef_not_phi: assumes"n ∈ set (αn g)""v ∈ defs g n" shows"phi g v = None" proof- from assms have"defNode g v = n"by auto with assms show ?thesis using simpleDefs_phiDefs_disjoint by (auto simp: phi_def phiDefs_def) qed
lemma phi_wf: "phi g v = Some vs ==> length (predecessors g (defNode g v)) = length vs" by (rule phis_wf) (simp add:phi_def)
lemma phi_finite: "finite (dom (phi g))" proof- let ?f = "λv. (defNode g v,v)" have"phi g = phis g ∘ ?f"by (auto simp add:phi_def) moreoverhave"inj ?f"by (auto intro:injI) hence"finite (dom (phis g ∘ ?f))"by - (rule finite_dom_comp, auto simp add:phis_finite inj_on_def) ultimatelyshow ?thesis by simp qed
lemma phiUses_exI: assumes"m ∈ set (predecessors g n)""phis g (n,v) = Some vs""n ∈ set (αn g)" obtains v' where"v' ∈ phiUses g m""v' ∈ set vs" proof- from assms(1) obtain i where i: "m = predecessors g n ! i""i < length (predecessors g n)"by (metis in_set_conv_nth) with assms(2) phis_wf have[simp]: "i < length vs"by (auto simp add:phi_def) from i assms(2,3) have"vs ! i ∈ phiUses g m"by - (rule phiUsesI, auto simp add:phiUses_def phi_def set_zip) thus thesis by (rule that) (auto simp add:i(2) phis_wf) qed
lemma phiArg_exI: assumes"m ∈ set (predecessors g (defNode g v))""phi g v ≠ None"and[simp]: "v ∈ allVars g" obtains v' where"v' ∈ phiUses g m""phiArg g v v'" proof- from assms(2) obtain vs where"phi g v = Some vs"by auto with assms(1) show thesis by - (rule phiUses_exI, auto intro!:that simp: phi_def) qed
lemma phiUses_exI': assumes"phiArg g p q"and[simp]: "p ∈ allVars g" obtains m where"q ∈ phiUses g m""m ∈ set (predecessors g (defNode g p))" proof- let ?n = "defNode g p" from assms(1) obtain i vs where vs: "phi g p = Some vs"and i: "q = vs ! i""i < length vs"by (metis in_set_conv_nth phiArg_def) with phis_wf have[simp]: "i < length (predecessors g ?n)"by (auto simp add:phi_def) from vs i have"q ∈ phiUses g (predecessors g ?n ! i)"by - (rule phiUsesI, auto simp add:phiUses_def phi_def set_zip) thus thesis by (rule that) (auto simp add:i(2) phis_wf) qed
lemma phiArg_in_allVars[simp]: assumes"phiArg g v v'" shows"v' ∈ allVars g" proof- let ?n = "defNode g v" from assms(1) obtain vs where vs: "phi g v = Some vs""v' ∈ set vs"by auto thenobtain m where m: "(m,v') ∈ set (zip (predecessors g ?n) vs)"by - (rule set_zip_leftI, rule phi_wf) from vs(1) have n: "?n ∈ set (αn g)"by (simp add: phi_def phis_in_αn) with m have[simp]: "m ∈ set (αn g)"by auto from n m vs have"v' ∈ phiUses g m"by - (rule phiUsesI, simp_all add:phi_def) thus ?thesis by - (rule allUses_in_allVars, auto simp:allUses_def) qed
lemma defAss_defNode: assumes"defAss g m v""v ∈ allVars g""g ⊨ Entry g-ns→m" shows"defNode g v ∈ set ns" proof- from assms obtain n where n: "n ∈ set ns""v ∈ allDefs g n"by (auto simp:defAss_def) with assms(3) have"n = defNode g v"by - (rule defNode_eq[symmetric], auto) with n show"defNode g v ∈ set ns"by (simp add:defAss_def) qed
lemma defUse_path_ex: assumes"v ∈ allUses g m""m ∈ set (αn g)" obtains ns where"g ⊨ defNode g v-ns→m""EntryPath g ns" proof- from assms have"defAss g m v"by - (rule allUses_def_ass, auto) moreoverfrom assms obtain ns where ns: "g ⊨ Entry g-ns→m""EntryPath g ns" by - (atomize_elim, rule Entry_reachesE, auto) ultimatelyhave"defNode g v ∈ set ns"using assms(1) by - (rule defAss_defNode, auto) with ns(1) obtain ns' where"g ⊨ defNode g v-ns'→m""suffix ns' ns" by (rule path2_split_ex', auto simp: Sublist.suffix_def) thus thesis using ns(2) by - (rule that, assumption, rule EntryPath_suffix, auto) qed
lemma defUse_path_dominated: assumes"g ⊨ defNode g v-ns→n""defNode g v ∉ set (tl ns)""v ∈ allUses g n""n' ∈ set ns" shows"dominates g (defNode g v) n'" proof (rule dominatesI) fix es assume asm: "g ⊨ Entry g-es→n'" from assms(1,4) obtain ns' where ns': "g ⊨ n'-ns'→n""suffix ns' ns" by - (rule path2_split_ex, auto simp: Sublist.suffix_def) from assms have"defAss g n v"by - (rule allUses_def_ass, auto) with asm ns'(1) assms(3) have"defNode g v ∈ set (es@tl ns')"by - (rule defAss_defNode, auto) with suffix_tl_subset[OF ns'(2)] assms(2) show"defNode g v ∈ set es"by auto next show"n' ∈ set (αn g)"using assms(1,4) by auto qed
lemma allUses_dominated: assumes"v ∈ allUses g n""n ∈ set (αn g)" shows"dominates g (defNode g v) n" proof- from assms obtain ns where"g ⊨ defNode g v-ns→n""defNode g v ∉ set (tl ns)" by - (rule defUse_path_ex, auto elim: simple_path2) with assms(1) show ?thesis by - (rule defUse_path_dominated, auto) qed
lemma phiArg_path_ex': assumes"phiArg g p q"and[simp]: "p ∈ allVars g" obtains ns m where"g ⊨ defNode g q-ns→m""EntryPath g ns""q ∈ phiUses g m""m ∈ set (predecessors g (defNode g p))" proof- from assms obtain m where m: "q ∈ phiUses g m""m ∈ set (predecessors g (defNode g p))" by (rule phiUses_exI') thenobtain ns where"g ⊨ defNode g q-ns→m""EntryPath g ns"by - (rule defUse_path_ex, auto) with m show thesis by - (rule that) qed
lemma phiArg_path_ex: assumes"phiArg g p q"and[simp]: "p ∈ allVars g" obtains ns where"g ⊨ defNode g q-ns→defNode g p""length ns > 1" by (rule phiArg_path_ex'[OF assms], rule, auto)
lemma phiArg_tranclp_path_ex: assumes"r++ p q""p ∈ allVars g"and[simp]: "∧p q. r p q ==> phiArg g p q" obtains ns where"g ⊨ defNode g q-ns→defNode g p""length ns > 1" "∀n ∈ set (butlast ns). ∃p q m ns'. r p q ∧ g ⊨ defNode g q-ns'→m ∧ (defNode g q)∉ set (tl ns') ∧ q ∈ phiUses g m ∧ m ∈ set (predecessors g (defNode g p)) ∧ n ∈set ns' ∧ set ns' ⊆ set ns ∧ defNode g p ∈ set ns" using assms(1,2) proof (induction rule: converse_tranclp_induct) case (base p) from base.hyps base.prems(2) obtain ns' m where ns': "g ⊨ defNode g q-ns'→m""defNode g q ∉ set (tl ns')""m ∈ set (predecessors g (defNode g p))""q ∈ phiUses g m" by - (rule phiArg_path_ex', rule assms(3), auto intro: simple_path2) hence ns: "g ⊨ defNode g q-ns'@[defNode g p]→defNode g p""length (ns'@[defNode g p]) > 1"by auto
show ?case proof (rule base.prems(1)[OF ns, rule_format], rule exI, rule exI, rule exI, rule exI) fix n assume"n ∈ set (butlast (ns' @ [defNode g p]))" with base.hyps ns' show"r p q ∧ g ⊨ defNode g q-ns'→m ∧ defNode g q ∉ set (tl ns') ∧ q ∈ phiUses g m ∧ m ∈ set (predecessors g (defNode g p)) ∧ n ∈ set ns' ∧ set ns' ⊆ set (ns' @ [defNode g p]) ∧ defNode g p ∈ set (ns' @ [defNode g p])" by auto qed next case (step p p') from step.prems(2) step.hyps(1) obtain ns'2 m where ns'2: "g ⊨ defNode g p'-ns'2→m""m ∈ set (predecessors g (defNode g p))""defNode g p' ∉ set (tl ns'2)""p' ∈ phiUses g m" by - (rule phiArg_path_ex', rule assms(3), auto intro: simple_path2) thenobtain ns2where ns2: "g ⊨ defNode g p'-ns2→defNode g p""length ns2 > 1""ns2 = ns'2@[defNode g p]"by (atomize_elim, auto)
show thesis proof (rule step.IH) fix ns assume ns: "g ⊨ defNode g q-ns→defNode g p'""1 < length ns" assume IH: "∀n∈set (butlast ns). ∃p q m ns'. r p q ∧ g ⊨ defNode g q-ns'→m ∧ defNode g q ∉ set (tl ns') ∧ q ∈ phiUses g m ∧ m ∈ set (predecessors g (defNode g p)) ∧ n ∈ set ns' ∧ set ns'⊆ set ns ∧ defNode g p ∈ set ns"
let ?path = "ns@tl ns2" have ns_ns2: "g ⊨ defNode g q-?path→defNode g p""1 < length ?path"using ns ns2(1,2) by auto show thesis proof (rule step.prems(1)[OF ns_ns2, rule_format]) fix n assume n: "n ∈ set (butlast ?path)" show"∃p q m ns'a. r p q ∧ g ⊨ defNode g q-ns'a→m ∧ defNode g q ∉ set (tl ns'a) ∧ q ∈ phiUses g m ∧ m ∈ set (predecessors g (defNode g p)) ∧ n ∈ set ns'a ∧ set ns'a ⊆ set ?path ∧ defNode g p ∈ set ?path" proof (cases "n ∈ set (butlast ns)") case True with IH obtain p q m ns' where" r p q ∧ g ⊨ defNode g q-ns'→m ∧ defNode g q ∉ set (tl ns') ∧ q ∈ phiUses g m ∧ m ∈ set (predecessors g (defNode g p)) ∧ n ∈ set ns' ∧ set ns'⊆ set ns ∧ defNode g p ∈ set ns"by auto thus ?thesis by - (rule exI, rule exI, rule exI, rule exI, auto) next case False from ns ns2have1: "?path = butlast ns@ns2" by - (rule concat_join[symmetric], auto simp: path2_def) from ns2(1) n False 1have"n ∈ set (butlast ns2)"by (auto simp: butlast_append path2_not_Nil) with step.hyps ns'2 ns2(3) show ?thesis by - (subst 1, rule exI[where x=p], rule exI[where x=p'], rule exI, rule exI, auto simp: path2_not_Nil) qed qed next show"p' ∈ allVars g"using step.prems(2) step.hyps(1)[THEN assms(3)] by auto qed qed
lemma non_dominated_predecessor: assumes"n ∈ set (αn g)""n ≠ Entry g" obtains m where"m ∈ set (predecessors g n)""¬dominates g n m" proof- obtain ns where"g ⊨ Entry g-ns→n" by (atomize_elim, rule Entry_reaches, auto simp add:assms(1)) thenobtain ns' where ns': "g ⊨ Entry g-ns'→n""n ∉ set (butlast ns')" by (rule simple_path2) let ?m = "last (butlast ns')" from ns'(1) assms(2) obtain m: "g ⊨ Entry g-butlast ns'→?m""?m ∈ set (predecessors g n)" by - (rule path2_unsnoc, auto) with m(1) ns'(2) show thesis by - (rule that, auto elim:dominatesE) qed
lemma liveVal_in_allVars[simp]: "liveVal g v ==> v ∈ allVars g" by (induction rule: liveVal.induct, auto intro!: allUses_in_allVars)
lemma phi_no_closed_loop: assumes[simp]: "p ∈ allVars g"and"phi g p = Some vs" shows"set vs ≠ {p}" proof (cases "defNode g p = Entry g") case True with assms(2) show ?thesis by auto next case False show ?thesis proof assume[simp]: "set vs = {p}" let ?n = "defNode g p" obtain ns where ns: "g ⊨ Entry g-ns→?n""?n ∉ set (butlast ns)"by (rule simple_Entry_path, auto) let ?m = "last (butlast ns)" from ns False obtain m: "g ⊨ Entry g-butlast ns→?m""?m ∈ set (predecessors g ?n)" by - (rule path2_unsnoc, auto) hence"p ∈ phiUses g ?m"using assms(2) by - (rule phiUses_exI, auto simp:phi_def) hence"defAss g ?m p"using m by - (rule allUses_def_ass, auto) thenobtain l where l: "l ∈ set (butlast ns)""p ∈ allDefs g l"using m by - (drule defAssD, auto) with assms(2) m have"l = ?n"by - (rule allDefs_disjoint', auto) with ns l m show False by auto qed qed
lemma phis_phi: "phis g (n, v) = Some vs ==> phi g v = Some vs" unfolding phi_def apply (subst defNode_eq) by (auto simp: allDefs_def phi_def phiDefs_def intro: phis_in_αn)
lemma trivial_phi: "trivial g v ==> phi g v ≠ None" by (auto simp: trivial_def isTrivialPhi_def split: option.splits)
lemma trivial_finite: "finite {v. trivial g v}" by (rule finite_subset[OF _ phi_finite]) (auto dest: trivial_phi)
lemma trivial_in_allVars: "trivial g v ==> v ∈ allVars g" by (drule trivial_phi, auto simp: allDefs_def phiDefs_def image_def phi_def intro: phis_in_αn intro!: allDefs_in_allVars)
declare phiArg_def [simp del] end
subsection‹Bundling of CFG and Equivalent SSA CFG›
locale CFG_SSA_Transformed = CFG_SSA_Transformed_base αe αn invar inEdges' Entry oldDefs oldUses "defs""uses" phis var
+ old: CFG_wf αe αn invar inEdges' Entry oldDefs oldUses + CFG_SSA_wf αe αn invar inEdges' Entry "defs""uses" phis for
αe :: "'g ==> ('node::linorder × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"and
Entry::"'g ==> 'node"and
oldDefs :: "'g ==> 'node ==> 'var::linorder set"and
oldUses :: "'g ==> 'node ==> 'var set"and "defs" :: "'g ==> 'node ==> 'val::linorder set"and "uses" :: "'g ==> 'node ==> 'val set"and
phis :: "'g ==> ('node, 'val) phis"and
var :: "'g ==> 'val ==> 'var" + assumes oldDefs_def: "oldDefs g n = var g ` defs g n" assumes oldUses_def: "n ∈ set (αn g) ==> oldUses g n = var g ` uses g n" assumes conventional: " \<lbrakk>g ⊨ n-ns→m; n ∉ set (tl ns); v ∈ allDefs g n; v ∈ allUses g m; x ∈ set (tl ns); v' ∈ allDefs g x]==> var g v' ≠ var g v" assumes phis_same_var[elim]: "phis g (n,v) = Some vs ==> v' ∈ set vs ==> var g v' = var g v" assumes allDefs_var_disjoint: "[n ∈ set (αn g); v ∈ allDefs g n; v' ∈ allDefs g n; v ≠ v']==> var g v' ≠ var g v" begin lemma conventional': "[g ⊨ n-ns→m; n ∉ set (tl ns); v ∈ allDefs g n; v ∈ allUses g m; v' ∈ allDefs g x; var g v' = var g v]==> x ∉ set (tl ns)" using conventional by auto
lemma conventional'': "[g ⊨ defNode g v-ns→m; defNode g v ∉ set (tl ns); v ∈ allUses g m; var g v' = var g v; v ∈ allVars g; v' ∈ allVars g]==> defNode g v' ∉ set (tl ns)" by (rule conventional'[where v=v and v'=v'], auto)
lemma phiArg_same_var: "phiArg g p q ==> var g q = var g p" by (metis phiArg_def phi_def phis_same_var)
lemma oldDef_defAss: assumes"v ∈ allUses g n""g ⊨ Entry g-ns→n" obtains m where"m ∈ set ns""var g v ∈ oldDefs g m" using assms proof (induction ns arbitrary: v n rule: length_induct) case (1 ns) from"1.prems"(2-) have2: "defNode g v ∈ set ns" by - (rule defAss_defNode, rule allUses_def_ass, auto) let ?V = "defNode g v" from"1.prems"(2,3) have[simp]: "v ∈ allVars g"by auto thus ?case proof (cases v rule: defNode_cases) case simpleDef with2show thesis by - (rule "1.prems"(1), auto simp: oldDefs_def) next case phi thenobtain vs where vs: "phi g v = Some vs"by auto from"1.prems"(3) 2obtain ns' where ns': "g ⊨ Entry g-ns'→?V""prefix ns' ns" by (rule old.path2_split_ex, auto) let ?V' = "last (butlast ns')" from ns' phi have nontriv: "length ns' ≥ 2" by - (rule old.path2_nontrivial, auto) hence3: "g ⊨ Entry g-butlast ns'→?V'""?V' ∈ set (old.predecessors g ?V)" using ns'(1) by (auto intro: old.path2_unsnoc) with phi vs obtain v' where v': "v' ∈ phiUses g ?V'""var g v' = var g v" by - (rule phiArg_exI, auto simp: phi_def phis_same_var phiArg_def) show thesis proof (rule "1.IH"[rule_format]) show"length (butlast ns') < length ns"using ns' by (cases ns', auto simp: old.path2_not_Nil2 dest: prefix_length_le) show"v' ∈ allUses g ?V'"using v'(1) by simp next fix n assume"n ∈ set (butlast ns')""var g v' ∈ oldDefs g n" thus thesis using ns'(2)[THEN set_mono_prefix] v'(2) by - (rule "1.prems"(1)[of n], auto dest: in_set_butlastD) qed (rule 3(1)) qed qed
lemma allDef_path_from_simpleDef: assumes[simp]: "v ∈ allVars g" obtains n ns where"g ⊨ n-ns→defNode g v""old.EntryPath g ns""var g v ∈ oldDefs g n" proof- let ?V = "defNode g v" from assms obtain ns where ns: "g ⊨ Entry g-ns→?V""old.EntryPath g ns" by - (rule old.Entry_reachesE, auto) from assms show thesis proof (cases v rule: defNode_cases) case simpleDef thus thesis by - (rule that, auto simp: oldDefs_def) next case phi thenobtain vs where vs: "phi g v = Some vs"by auto let ?V' = "last (butlast ns)" from ns phi have nontriv: "length ns ≥ 2" by - (rule old.path2_nontrivial, auto) hence3: "g ⊨ Entry g-butlast ns→?V'""?V' ∈ set (old.predecessors g ?V)" using ns(1) by (auto intro: old.path2_unsnoc) with phi vs obtain v' where v': "v' ∈ phiUses g ?V'""var g v' = var g v" by - (rule phiArg_exI, auto simp: phi_def phis_same_var phiArg_def) with3(1) obtain n where n: "n ∈ set (butlast ns)""var g v' ∈ oldDefs g n" by - (rule oldDef_defAss[of v' g], auto) with ns obtain ns' where"g ⊨ n-ns'→?V""suffix ns' ns" by - (rule old.path2_split_ex'[OF ns(1)], auto intro: in_set_butlastD simp: Sublist.suffix_def) with n(2) v'(2) ns(2) show thesis by - (rule that, assumption, erule old.EntryPath_suffix, auto) qed qed
lemma defNode_var_disjoint: assumes"p ∈ allVars g""q ∈ allVars g""p ≠ q""defNode g p = defNode g q" shows"var g p ≠ var g q" proof- have"q ∈ allDefs g (defNode g p)"using assms(2) assms(4) by (auto) thus ?thesis using assms(1-3) by - (rule allDefs_var_disjoint[of "defNode g p" g], auto) qed
lemma phiArg_distinct_nodes: assumes"phiArg g p q""p ≠ q"and[simp]: "p ∈ allVars g" shows"defNode g p ≠ defNode g q" proof have"p ∈ allDefs g (defNode g p)"by simp moreoverassume"defNode g p = defNode g q" ultimatelyhave"var g p ≠ var g q"using assms by - (rule defNode_var_disjoint, auto) moreover from assms(1) have"var g q = var g p"by (rule phiArg_same_var) ultimatelyshow False by simp qed
lemma phiArgs_def_distinct: assumes"phiArg g p q""phiArg g p r""q ≠ r""p ∈ allVars g" shows"defNode g q ≠ defNode g r" proof (rule) assume"defNode g q = defNode g r" hence"var g q ≠ var g r"using assms by - (rule defNode_var_disjoint, auto) thus False using phiArg_same_var[OF assms(1)] phiArg_same_var[OF assms(2)] by simp qed
lemma defNode_not_on_defUse_path: assumes p: "g ⊨ defNode g p-ns→n""defNode g p ∉ set (tl ns)""p ∈ allUses g n" assumes[simp]: "q ∈ allVars g""p ≠ q""var g p = var g q" shows"defNode g q ∉ set ns" proof- let ?P = "defNode g p" let ?Q = "defNode g q"
have[simp]: "p ∈ allVars g"using p(1,3) by auto have"?P ≠ ?Q"using defNode_var_disjoint[of p g q] by auto moreoverhave"?Q ∉ set (tl ns)"using p(2,3) by - (rule conventional'[OF p(1), of p q], auto) ultimatelyshow ?thesis using p(1) by (cases ns, auto simp: old.path2_def) qed
lemma defUse_paths_disjoint: assumes p: "g ⊨ defNode g p-ns→n""defNode g p ∉ set (tl ns)""p ∈ allUses g n" assumes q: "g ⊨ defNode g q-ms→m""defNode g q ∉ set (tl ms)""q ∈ allUses g m" assumes[simp]: "p ≠ q""var g p = var g q" shows"set ns ∩ set ms = {}" proof (rule equals0I) fix y assume y: "y ∈ set ns ∩ set ms"
{ fix p ns n assume p: "g ⊨ defNode g p-ns→n""defNode g p ∉ set (tl ns)""p ∈ allUses g n" assume y: "y ∈ set ns" from p(1,3) have dom: "old.dominates g (defNode g p) n"by - (rule allUses_dominated, auto) moreover obtain ns' where"g ⊨ y-ns'→n""suffix ns' ns" by (rule old.path2_split_first_last[OF p(1) y], auto) ultimatelyhave"old.dominates g (defNode g p) y"using suffix_tl_subset[of ns' ns] p(2) by - (rule old.dominates_extend[where ms=ns'], auto)
} with assms y have dom: "old.dominates g (defNode g p) y""old.dominates g (defNode g q) y"by auto
{ fix p ns n q ms m let ?P = "defNode g p" let ?Q = "defNode g q"
assume p: "g ⊨ defNode g p-ns→n""defNode g p ∉ set (tl ns)""p ∈ allUses g n""old.dominates g ?P y""y ∈ set ns" assume q: "g ⊨ defNode g q-ms→m""defNode g q ∉ set (tl ms)""q ∈ allUses g m""old.dominates g ?Q y""y ∈ set ms" assume[simp]: "p ≠ q""var g p = var g q" assume dom: "old.dominates g ?P ?Q" thenobtain pqs where pqs: "g ⊨ ?P-pqs→?Q""?P ∉ set (tl pqs)"by (rule old.dominates_path, auto intro: old.simple_path2) from p obtain ns2where ns2: "g ⊨ y-ns2→n""suffix ns2 ns"by - (rule old.path2_split_first_last, auto) from q obtain ms1where ms1: "g ⊨ ?Q-ms1→y""prefix ms1 ms"by - (rule old.path2_split_first_last, auto) have"var g q ≠ var g p" proof (rule conventional[OF _ _ _ p(3)]) let ?path = "(pqs@tl ms1)@tl ns2" show"g ⊨ ?P-?path→n"using pqs ms1 ns2 by (auto simp del:append_assoc intro:old.path2_app) have"?P ∉ set (tl ns2)"using p(2) ns2(2)[THEN suffix_tl_subset, THEN subsetD] by auto moreover have[simp]: "q ∈ allVars g""p ∈ allVars g"using p q by auto have"?P ∉ set (tl ms)"using q by - (rule conventional'[where v'=p and v=q], auto) hence"?P ∉ set (tl ms1)"using ms1(2)[simplified, THEN prefix_tl_subset] by auto ultimately show"?P ∉ set (tl ?path)"using pqs(2) by - (rule notI, auto dest: subsetD[OF set_tl_append']) show"p ∈ allDefs g (defNode g p)"by auto have"?P ≠ ?Q"using defNode_var_disjoint[of p g q] by auto hence1: "length pqs > 1"using pqs by - (rule old.path2_nontriv) hence"?Q ∈ set (tl pqs)"using pqs unfolding old.path2_def by (auto intro:last_in_tl) moreoverfrom1have"pqs ≠ []"by auto ultimatelyshow"?Q ∈ set (tl ?path)"by simp show"q ∈ allDefs g ?Q"by simp qed hence False by simp
} from this[OF p _ _ q] this[OF q _ _ p] y dom show False by - (rule old.dominates_antitrans[OF _ dom], auto) qed
lemma oldDefsI: "v ∈ defs g n ==> var g v ∈ oldDefs g n"by (simp add: oldDefs_def)
lemma simpleDefs_phiDefs_var_disjoint: assumes"v ∈ phiDefs g n""n ∈ set (αn g)" shows"var g v ∉ oldDefs g n" proof from assms have[simp]: "v ∈ allVars g"by auto assume"var g v ∈ oldDefs g n" thenobtain v'' where v'': "v'' ∈ defs g n""var g v'' = var g v" by (auto simp: oldDefs_def) from this(1) assms have"v'' ≠ v" using simpleDefs_phiDefs_disjoint[of n g] by (auto simp: phiArg_def) with v'' assms show False using allDefs_var_disjoint[of n g v'' v] by auto qed
lemma liveVal_use_path: assumes"liveVal g v" obtains ns m where"g ⊨ defNode g v-ns→m""var g v ∈ oldUses g m" "∧x. x ∈ set (tl ns) ==> var g v ∉ oldDefs g x" using assms proof (induction) case (liveSimple m v) from liveSimple.hyps have[simp]: "v ∈ allVars g" by - (rule allUses_in_allVars, auto) from liveSimple.hyps obtain ns where ns: "g ⊨ defNode g v-ns→m""defNode g v ∉ set (tl ns)" by - (rule defUse_path_ex, auto intro!: uses_in_allUses elim: old.simple_path2) from this(1) show thesis proof (rule liveSimple.prems) show"var g v ∈ oldUses g m"using liveSimple.hyps by (auto simp: oldUses_def)
{ fix x assume asm: "x ∈ set (tl ns)""var g v ∈ oldDefs g x" thenobtain v' where"v' ∈ defs g x""var g v' = var g v" by (auto simp: oldDefs_def) with asm liveSimple.hyps have False by - (rule conventional[OF ns, of v x v', THENnotE], auto)
} thus"∧x. x ∈ set (tl ns) ==> var g v ∉ oldDefs g x"by auto qed next case (livePhi v v') from livePhi.hyps have[simp]: "v ∈ allVars g""v' ∈ allVars g""var g v' = var g v" by (auto intro: phiArg_same_var) show thesis proof (rule livePhi.IH) fix ns m assume asm: "g ⊨ defNode g v-ns→m""var g v ∈ oldUses g m" "∧x. x ∈ set (tl ns) ==> var g v ∉ oldDefs g x" from livePhi.hyps(2) obtain ns' m' where ns': "g ⊨ defNode g v'-ns'→m'""v' ∈ phiUses g m'" "m' ∈ set (old.predecessors g (defNode g v))""defNode g v' ∉ set (tl ns')" by (rule phiArg_path_ex', auto elim: old.simple_path2) show thesis proof (rule livePhi.prems) show"g ⊨ defNode g v'-(ns'@[defNode g v])@tl ns→m" apply (rule old.path2_app) apply (rule old.path2_snoc[OF ns'(1,3)]) by (rule asm(1)) show"var g v' ∈ oldUses g m"using asm(2) by simp
{ fix x assume asm: "x ∈ set (tl ns')""var g v ∈ oldDefs g x" thenobtain v'' where"v'' ∈ defs g x""var g v'' = var g v" by (auto simp: oldDefs_def) with asm ns'(2) have False by - (rule conventional[OF ns'(1,4), of v' x v'', THENnotE], auto)
} thenshow"∧x. x ∈ set (tl ((ns'@[defNode g v])@tl ns)) ==> var g v' ∉ oldDefs g x" using simpleDefs_phiDefs_var_disjoint[of v g "defNode g v"] livePhi.hyps(2) by (auto dest!: set_tl_append'[THEN subsetD] asm(3) simp: phiArg_def) qed qed qed end
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.