Theory Rewrites
subsection ‹Graph Rewriting›
theory
Rewrites
imports
Stuttering
begin
fun replace_usages :: "ID ⇒ ID ⇒ IRGraph ⇒ IRGraph" where
"replace_usages nid nid' g = replace_node nid (RefNode nid', stamp g nid') g"
lemma replace_usages_effect:
assumes "g' = replace_usages nid nid' g"
shows "kind g' nid = RefNode nid'"
using replace_usages.simps replace_node_lookup assms by blast
lemma replace_usages_changeonly:
assumes "nid ∈ ids g"
assumes "g' = replace_usages nid nid' g"
shows "changeonly {nid} g g'"
by (metis add_changed add_node_def replace_node_def replace_usages.simps assms(2))
lemma replace_usages_unchanged:
assumes "nid ∈ ids g"
assumes "g' = replace_usages nid nid' g"
shows "unchanged (ids g - {nid}) g g'"
using assms disjoint_change replace_usages_changeonly by presburger
fun nextNid :: "IRGraph ⇒ ID" where
"nextNid g = (Max (ids g)) + 1"
lemma max_plus_one:
fixes c :: "ID set"
shows "⟦finite c; c ≠ {}⟧ ⟹ (Max c) + 1 ∉ c"
by (meson Max_gr_iff less_add_one less_irrefl)
lemma ids_finite:
"finite (ids g)"
by simp
lemma nextNidNotIn:
"ids g ≠ {} ⟶ nextNid g ∉ ids g"
unfolding nextNid.simps using ids_finite max_plus_one by blast
fun bool_to_val_width1 :: "bool ⇒ Value" where
"bool_to_val_width1 True = (IntVal 1 1)" |
"bool_to_val_width1 False = (IntVal 1 0)"
fun constantCondition :: "bool ⇒ ID ⇒ IRNode ⇒ IRGraph ⇒ IRGraph" where
"constantCondition val nid (IfNode cond t f) g =
(let (g', nid') = Predicate.the (unrepE g (ConstantExpr (bool_to_val_width1 val))) in
replace_node nid (IfNode nid' t f, stamp g nid) g')" |
"constantCondition cond nid _ g = g"
inductive_cases unrepUnaryE:
"unrep g (UnaryExpr op e) (g', nid)"
inductive_cases unrepBinaryE:
"unrep g (BinaryExpr op e1 e2) (g', nid)"
inductive_cases unrepConditionalE:
"unrep g (ConditionalExpr c t f) (g', nid)"
inductive_cases unrepParamE:
"unrep g (ParameterExpr i s) (g', nid)"
inductive_cases unrepConstE:
"unrep g (ConstantExpr c) (g', nid)"
inductive_cases unrepLeafE:
"unrep g (LeafExpr n s) (g', nid)"
inductive_cases unrepVariableE:
"unrep g (VariableExpr v s) (g', nid)"
inductive_cases unrepConstVarE:
"unrep g (ConstantVar c) (g', nid)"
lemma uniqueDet:
assumes "unique g e (g'⇩1, nid⇩1)"
assumes "unique g e (g'⇩2, nid⇩2)"
shows "g'⇩1 = g'⇩2 ∧ nid⇩1 = nid⇩2"
using assms apply (induction)
apply (metis Pair_inject assms(1) assms(2) option.distinct(1) option.inject unique.cases)
by (metis Pair_inject assms(1) assms(2) option.discI option.inject unique.cases)
lemma unrepDet:
assumes "unrep g e (g'⇩1, nid⇩1)"
assumes "unrep g e (g'⇩2, nid⇩2)"
shows "g'⇩1 = g'⇩2 ∧ nid⇩1 = nid⇩2"
using assms proof (induction e arbitrary: g g'⇩1 nid⇩1 g'⇩2 nid⇩2)
case (UnaryExpr op e)
then show ?case
by (smt (verit, best) uniqueDet unrepUnaryE)
next
case (BinaryExpr x1 e1 e2)
then show ?case
by (smt (verit, best) uniqueDet unrepBinaryE)
next
case (ConditionalExpr e1 e2 e3)
then show ?case
by (smt (verit, best) uniqueDet unrepConditionalE)
next
case (ParameterExpr x1 x2)
then show ?case
by (smt (verit, best) uniqueDet unrepParamE)
next
case (LeafExpr x1 x2)
then show ?case
by (smt (verit, best) uniqueDet unrepLeafE)
next
case (ConstantExpr x)
then show ?case
by (smt (verit, best) uniqueDet unrepConstE)
next
case (ConstantVar x)
then show ?case
by (smt (verit, best) uniqueDet unrepConstVarE)
next
case (VariableExpr x1 x2)
then show ?case
by (smt (verit, best) uniqueDet unrepVariableE)
qed
lemma unwrapUnrepE:
assumes "unrep g e (g', nid')"
shows "(g', nid') = Predicate.the (unrepE g e)"
using assms unrepEI unrepDet unfolding Predicate.the_def
by (metis eval_usages.cases pred.sel the_equality unrepE_def)
lemma constantCondition_sem:
assumes "(unrep g (ConstantExpr (bool_to_val_width1 val)) (g', nid'))"
shows "constantCondition val nid (IfNode cond t f) g =
replace_node nid (IfNode nid' t f, stamp g nid) g'"
using assms unfolding constantCondition.simps
using unwrapUnrepE by auto
fun wf_insert :: "IRGraph ⇒ IRExpr ⇒ bool" where
"wf_insert g (LeafExpr n s) = is_preevaluated (kind g n)" |
"wf_insert g (VariableExpr v s) = False" |
"wf_insert g (ConstantVar v) = False" |
"wf_insert g _ = True"
lemma insertConstUnique:
"∃g' nid'. unique g (ConstantNode c, s) (g', nid')"
by (meson not_None_eq unique.simps)
lemma insertConst:
"∃g' nid'. unrep g (ConstantExpr c) (g', nid')"
using UnrepConstantNode insertConstUnique by blast
lemma constantConditionTrue:
assumes "kind g ifcond = IfNode cond t f"
assumes "g' = constantCondition True ifcond (kind g ifcond) g"
shows "g', p ⊢ (ifcond, m, h) → (t, m, h)"
proof -
have ifn: "⋀ c t f. IfNode c t f ≠ NoNode"
by simp
obtain g'' nid' where unrep: "unrep g (ConstantExpr (bool_to_val_width1 True)) (g'', nid')"
using insertConst by blast
then have "kind g'' nid' = ConstantNode (bool_to_val_width1 True)"
by (meson ConstUnrepE IRNode.distinct(1077) unique_kind)
also have "nid' ≠ ifcond"
by (metis ConstUnrepE IRNode.distinct(981) assms(1) calculation fresh_ids ids_some ifn unique.cases unrep unrepDet)
moreover have "g' = replace_node ifcond (IfNode nid' t f, stamp g ifcond) g''"
using assms constantCondition_sem unrep by presburger
moreover have "kind g' nid' = ConstantNode (bool_to_val_width1 True)"
using assms constantCondition.simps(1) replace_node_unchanged
by (metis DiffI calculation(1) calculation(2) calculation(3) emptyE insert_iff unrep unrep_contains)
moreover have if': "kind g' ifcond = IfNode nid' t f"
using ifn assms constantCondition.simps(1) replace_node_lookup
using calculation(3) by blast
have truedef: "bool_to_val True = (IntVal 32 1)"
by auto
from ifn have "ifcond ≠ (nextNid g)"
by (metis assms(1) emptyE ids_some nextNidNotIn)
moreover have "⋀ c. ConstantNode c ≠ NoNode"
by simp
ultimately have "kind g' nid' = ConstantNode (bool_to_val_width1 True)"
using add_changed
by fastforce
then have c': "kind g' nid' = ConstantNode (IntVal 1 1)"
by simp
have "valid_value (IntVal 1 1) (constantAsStamp (IntVal 1 1))"
by fastforce
then have "[g', m, p] ⊢ nid' ↦ IntVal 1 1"
using Value.distinct(1) ‹kind g' nid' = ConstantNode (bool_to_val_width1 True)›
by (metis bool_to_val_width1.simps(1) wf_value_def encodeeval.simps ConstantExpr ConstantNode)
from if' c' show ?thesis
by (metis (no_types, opaque_lifting) val_to_bool.simps(1) ‹[g',m,p] ⊢ nid' ↦ IntVal 1 1›
zero_neq_one IfNode)
qed
lemma constantConditionFalse:
assumes "kind g ifcond = IfNode cond t f"
assumes "g' = constantCondition False ifcond (kind g ifcond) g"
shows "g', p ⊢ (ifcond, m, h) → (f, m, h)"
proof -
have ifn: "⋀ c t f. IfNode c t f ≠ NoNode"
by simp
obtain g'' nid' where unrep: "unrep g (ConstantExpr (bool_to_val_width1 False)) (g'', nid')"
using insertConst by blast
also have "kind g'' nid' = ConstantNode (bool_to_val_width1 False)"
by (meson ConstUnrepE IRNode.distinct(1077) unique_kind unrep)
moreover have "nid' ≠ ifcond"
by (metis ConstUnrepE IRNode.distinct(981) assms(1) calculation(2) fresh_ids ids_some ifn unique.cases unrep unrepDet)
moreover have "g' = replace_node ifcond (IfNode nid' t f, stamp g ifcond) g''"
using assms(1) assms(2) constantCondition_sem unrep by presburger
moreover have "kind g' nid' = ConstantNode (bool_to_val_width1 False)"
using assms constantCondition.simps(1) replace_node_unchanged
by (metis DiffI calculation(2) calculation(3) calculation(4) emptyE insert_iff unrep unrep_contains)
moreover have if': "kind g' ifcond = IfNode nid' t f"
using ifn assms constantCondition.simps(1) replace_node_lookup
using calculation(4) by blast
have falsedef: "bool_to_val False = (IntVal 32 0)"
by auto
then have c': "kind g' nid' = ConstantNode (IntVal 1 0)"
by (simp add: calculation(5))
have "valid_value (IntVal 1 0) (constantAsStamp (IntVal 1 0))"
by auto
then have "[g', m, p] ⊢ nid' ↦ IntVal 1 0"
by (meson ConstantExpr ConstantNode c' encodeeval.simps wf_value_def)
from if' c' show ?thesis
by (meson IfNode ‹[g'::IRGraph,m::nat ⇒ Value,p::Value list] ⊢ nid'::nat ↦ IntVal (1::nat) (0::64 word)› encodeeval.simps val_to_bool.simps(1))
qed
lemma diff_forall:
assumes "∀n∈ids g - {nid}. cond n"
shows "∀n. n ∈ ids g ∧ n ∉ {nid} ⟶ cond n"
by (meson Diff_iff assms)
lemma replace_node_changeonly:
assumes "g' = replace_node nid node g"
shows "changeonly {nid} g g'"
by (metis add_changed add_node_def replace_node_def assms)
lemma add_node_changeonly:
assumes "g' = add_node nid node g"
shows "changeonly {nid} g g'"
by (metis Rep_IRGraph_inverse add_node.rep_eq assms replace_node.rep_eq replace_node_changeonly)
lemma constantConditionNoEffect:
assumes "¬(is_IfNode (kind g nid))"
shows "g = constantCondition b nid (kind g nid) g"
using assms constantCondition.simps
apply (cases "kind g nid")
prefer 15 prefer 16
apply (metis is_IfNode_def)
apply (metis)
by presburger+
lemma changeonly_ConstantExpr:
assumes "unrep g (ConstantExpr c) (g', nid)"
shows "changeonly {} g g'"
using assms
apply (cases "find_node_and_stamp g (ConstantNode c, constantAsStamp c) = None")
apply (smt (verit, ccfv_threshold) New add_node_as_set_eq changeonly.simps fresh_ids new_def not_excluded_keep_type order.refl uniqueDet unrepConstE unrep_preserves_contains)
by (metis changeonly.simps unique.cases unrepConstE unrepDet)
lemma constantCondition_changeonly:
assumes "nid ∈ ids g"
assumes "g' = constantCondition b nid (kind g nid) g"
shows "changeonly {nid} g g'"
proof (cases "is_IfNode (kind g nid)")
case True
obtain g'' nid' where unrep: "unrep g (ConstantExpr (bool_to_val_width1 b)) (g'', nid')"
using insertConst by blast
also have "changeonly {} g g''"
using changeonly_ConstantExpr unrep by blast
moreover have "∃t f ifcond. g' = replace_node nid (IfNode nid' t f, stamp g ifcond) g''"
using assms constantCondition_sem unrep
by (metis True is_IfNode_def)
then show ?thesis
using assms replace_node_changeonly add_node_changeonly unfolding changeonly.simps
by (metis calculation(2) changeonly.elims(2) empty_iff)
next
case False
have "g = g'"
using constantConditionNoEffect False assms(2) by presburger
then show ?thesis
by simp
qed
lemma constantConditionNoIf:
assumes "∀cond t f. kind g ifcond ≠ IfNode cond t f"
assumes "g' = constantCondition val ifcond (kind g ifcond) g"
shows "∃nid' .(g m p h ⊢ ifcond ↝ nid') ⟷ (g' m p h ⊢ ifcond ↝ nid')"
proof -
have "g' = g"
using constantConditionNoEffect assms is_IfNode_def by presburger
then show ?thesis
by simp
qed
lemma constantConditionValid:
assumes "kind g ifcond = IfNode cond t f"
assumes "[g, m, p] ⊢ cond ↦ v"
assumes "const = val_to_bool v"
assumes "g' = constantCondition const ifcond (kind g ifcond) g"
shows "∃nid' .(g m p h ⊢ ifcond ↝ nid') ⟷ (g' m p h ⊢ ifcond ↝ nid')"
proof (cases "const")
case True
have ifstep: "g, p ⊢ (ifcond, m, h) → (t, m, h)"
by (meson IfNode True assms(1,2,3) encodeeval.simps)
have ifstep': "g', p ⊢ (ifcond, m, h) → (t, m, h)"
using constantConditionTrue True assms(1,4) by presburger
from ifstep ifstep' show ?thesis
using StutterStep by blast
next
case False
have ifstep: "g, p ⊢ (ifcond, m, h) → (f, m, h)"
by (meson IfNode False assms(1,2,3) encodeeval.simps)
have ifstep': "g', p ⊢ (ifcond, m, h) → (f, m, h)"
using constantConditionFalse False assms(1,4) by presburger
from ifstep ifstep' show ?thesis
using StutterStep by blast
qed
end