diff --git a/.browser_info/index.json b/.browser_info/index.json index 1b36c77d..8086074d 100644 --- a/.browser_info/index.json +++ b/.browser_info/index.json @@ -11,6 +11,8 @@ {"name": "Proofs", "description": "Supporting proof theories and definitions"}, {"name": "Semantics", "description": "Semantics of the GraalVM IR"}, + {"name": "SemanticsPaper", + "description": "Content for IR semantics description paper"}, {"name": "Snippets", "description": "Additional commands to enable the generation of LaTeX snippets of theories"}, diff --git a/Canonicalizations/.browser_info/build_uuid b/Canonicalizations/.browser_info/build_uuid index a3f9c8fa..c84274f9 100644 --- a/Canonicalizations/.browser_info/build_uuid +++ b/Canonicalizations/.browser_info/build_uuid @@ -1 +1 @@ -94b2d873-b4be-4e0a-9045-3603d668dae4 \ No newline at end of file +9410185a-1397-4e37-823e-e573c61b1bda \ No newline at end of file diff --git a/Canonicalizations/AbsPhase.html b/Canonicalizations/AbsPhase.html index cbd12b85..30baa6f1 100644 --- a/Canonicalizations/AbsPhase.html +++ b/Canonicalizations/AbsPhase.html @@ -12,27 +12,27 @@

Theory AbsPhase

-
subsection AbsNode Phase
+
subsection ‹AbsNode Phase›
 
 theory AbsPhase
   imports
     Common Proofs.StampEvalThms
 begin
 
-phase AbsNode
+phase AbsNode
   terminating size
 begin
 
-text 
-Note:
-
-We can't use @{const word_sless} for reasoning about @{const intval_less_than}.
+text ‹
+Note:
+
+We can't use @{const word_sless} for reasoning about @{const intval_less_than}.
 @{const word_sless} will always treat the $64^{th}$ bit as the sign flag
-while @{const intval_less_than} uses the $b^{th}$ bit depending on the size of the word.
-
+while @{const intval_less_than} uses the $b^{th}$ bit depending on the size of the word.
+›
 
-value "val[new_int 32 0 < new_int 32 4294967286]" ― ‹0 < -10 = False
-value "(0::int64) <s 4294967286" ― ‹0 < 4294967286 = True
+value "val[new_int 32 0 < new_int 32 4294967286]" ― ‹0 < -10 = False›
+value "(0::int64) <s 4294967286" ― ‹0 < 4294967286 = True›
 
 
 lemma signed_eqiv:
@@ -64,15 +64,15 @@ 

Theory AbsPhase

by (metis min_def nle_le take_bit_take_bit) -text -A special value exists for the maximum negative integer as its negation is itself. -We can define the value as @{term "(set_bit (b - 1) 0)::int64"} for any bit-width, b. - +text ‹ +A special value exists for the maximum negative integer as its negation is itself. +We can define the value as @{term "(set_bit (b - 1) 0)::int64"} for any bit-width, b. +› -value "(set_bit 1 0)::2 word" ― ‹2 -value "-(set_bit 1 0)::2 word" ― ‹2 -value "(set_bit 31 0)::32 word" ― ‹2147483648 -value "-(set_bit 31 0)::32 word" ― ‹2147483648 +value "(set_bit 1 0)::2 word" ― ‹2› +value "-(set_bit 1 0)::2 word" ― ‹2› +value "(set_bit 31 0)::32 word" ― ‹2147483648› +value "-(set_bit 31 0)::32 word" ― ‹2147483648› lemma negative_def: @@ -89,7 +89,7 @@

Theory AbsPhase

using assms by (simp add: bit_last_iff word_sless_alt) -(* +(* lemma invert1: fixes v :: "'a::len word" assumes "v <s 0" @@ -137,7 +137,7 @@

Theory AbsPhase

assumes "v ≠ (2^(LENGTH('a) - 1))" shows "0 <s (-v)" using invert1 assms negative_lower_bound order_less_le by blast -
*)
+*)
lemma negative_lower_bound: fixes v :: "'a::len word" @@ -154,14 +154,14 @@

Theory AbsPhase

shows "2^(LENGTH('a) - 1) <s x" using assms sorry -(* +(* lemma min_int: fixes x :: "'a::len word" assumes "x <s 0 ∧ 0 <s x" shows "x = 2^(LENGTH('a) - 1)" using assms using signed.less_asym by blast -*) +*) lemma negate_min_int: fixes v :: "'a::len word" @@ -195,7 +195,7 @@

Theory AbsPhase

qed qed -text We need to do the same proof at the value level. +text ‹We need to do the same proof at the value level.› lemma invert_intval: assumes "int_signed_value b v < 0" @@ -289,7 +289,7 @@

Theory AbsPhase

shows "intval_abs x UndefVal" using assms by force -(* Value level proofs *) +(* Value level proofs *) lemma val_abs_idem: assumes "valid_value x (IntegerStamp b l h)" assumes "val[abs(abs(x))] UndefVal" @@ -327,14 +327,14 @@

Theory AbsPhase

qed qed -paragraph Optimisations +paragraph ‹Optimisations› -(* +(* optimization AbsIdempotence: "abs(abs(x)) ⟼ abs(x) when wf_stamp x ∧ stamp_expr x = IntegerStamp b l h" using val_abs_idem using wf_stamp_def by fastforce -*) +*) end diff --git a/Canonicalizations/AddPhase.html b/Canonicalizations/AddPhase.html index 151ba70c..a94c8067 100644 --- a/Canonicalizations/AddPhase.html +++ b/Canonicalizations/AddPhase.html @@ -12,14 +12,14 @@

Theory AddPhase

-
subsection AddNode Phase
+
subsection ‹AddNode Phase›
 
 theory AddPhase
   imports
     Common
 begin
 
-phase AddNode 
+phase AddNode 
   terminating size
 begin
 
@@ -28,7 +28,7 @@ 

Theory AddPhase

shows "bin_eval BinAdd x y = bin_eval BinAdd y x" by (simp add: intval_add_sym) -(* horrible backward proof - needs improving *) +(* horrible backward proof - needs improving *) optimization AddShiftConstantRight: "((const v) + y) y + (const v) when ¬(is_ConstantExpr y)" apply (metis add_2_eq_Suc' less_Suc_eq plus_1_eq_Suc size.simps(11) size_non_add) using le_expr_def binadd_commute by blast @@ -36,16 +36,16 @@

Theory AddPhase

optimization AddShiftConstantRight2: "((const v) + y) y + (const v) when ¬(is_ConstantExpr y)" using AddShiftConstantRight by auto -(* TODO: define is_neutral and then lemmas like this: +(* TODO: define is_neutral and then lemmas like this: lemma simp_neutral: assumes n: "is_neutral op (IntVal32 n)" shows "bin_eval op x (IntVal32 n) = x" apply (induction op) unfolding is_neutral.simps using n apply auto -*) +*) -(* poor-mans is_neutral lemma *) +(* poor-mans is_neutral lemma *) lemma is_neutral_0 [simp]: assumes "val[(IntVal b x) + (IntVal b 0)] UndefVal" shows "val[(IntVal b x) + (IntVal b 0)] = (new_int b x)" @@ -54,7 +54,7 @@

Theory AddPhase

lemma AddNeutral_Exp: shows "exp[(e + (const (IntVal 32 0)))] exp[e]" apply auto - subgoal premises p for m p x + subgoal premises p for m p x proof - obtain ev where ev: "[m,p] e ev" using p by auto @@ -87,7 +87,7 @@

Theory AddPhase

lemma RedundantSubAdd_Exp: shows "exp[((a - b) + b)] a" apply auto - subgoal premises p for m p y xa ya + subgoal premises p for m p y xa ya proof - obtain bv where bv: "[m,p] b bv" using p(1) by auto @@ -111,7 +111,7 @@

Theory AddPhase

optimization RedundantSubAdd: "((e1 - e2) + e2) e1" using RedundantSubAdd_Exp by blast -(* a little helper lemma for using universal quantified assumptions *) +(* a little helper lemma for using universal quantified assumptions *) lemma allE2: "(x y. P x y) (P a b R) R" by simp @@ -126,7 +126,7 @@

Theory AddPhase

by (smt (z3) NeutralLeftSubVal evalDet eval_unused_bits_zero intval_add_sym intval_sub.elims new_int.simps well_formed_equal_defn) -(* Demonstration of our FOUR levels of expression rewrites: +(* Demonstration of our FOUR levels of expression rewrites: ======================================================= level 1 (Java-like): "-e + y ⟼ y - e" level 2 (expr trees): "rewrite_preservation @@ -157,21 +157,21 @@

Theory AddPhase

([m,p] ⊢ e ↦ ya) ∧ v = intval_sub x ya ∧ v ≠ UndefVal)" level 4 (Word library): "-ev + yv = yv - ev" (twice, for 32-bit and 64-bit) -
*)
+*)
-(* The LowLevel version, intval_*, of this helper lemma is much easier +(* The LowLevel version, intval_*, of this helper lemma is much easier to prove than the bin_eval level. And equally easy to use in AddToSub. - *) + *) lemma AddToSubHelperLowLevel: shows "val[-e + y] = val[y - e]" (is "?x = ?y") by (induction y; induction e; auto) print_phases -(* ----- Starts here ----- *) +(* ----- Starts here ----- *) -(* +(* AddNode has 8 optimisations total Currently *6* optimisations are verified. @@ -191,9 +191,9 @@

Theory AddPhase

- MergeSignExtendAdd - MergeZeroExtendAdd -
*)
+*)
-(* Value level proofs *) +(* Value level proofs *) lemma val_redundant_add_sub: assumes "a = new_int bb ival" assumes "val[b + a] UndefVal" @@ -205,7 +205,7 @@

Theory AddPhase

shows "val[x + (-e)] = val[x - e]" by (cases x; cases e; auto simp: assms) -(* Exp level proofs *) +(* Exp level proofs *) lemma exp_add_left_negate_to_sub: "exp[-e + y] exp[y - e]" by (cases e; cases y; auto simp: AddToSubHelperLowLevel) @@ -213,7 +213,7 @@

Theory AddPhase

lemma RedundantAddSub_Exp: shows "exp[(b + a) - b] a" apply auto - subgoal premises p for m p y xa ya + subgoal premises p for m p y xa ya proof - obtain bv where bv: "[m,p] b bv" using p(1) by auto @@ -235,7 +235,7 @@

Theory AddPhase

qed done -text Optimisations +text ‹Optimisations› optimization RedundantAddSub: "(b + a) - b a" using RedundantAddSub_Exp by blast @@ -250,17 +250,17 @@

Theory AddPhase

numeral_2_eq_2 plus_1_eq_Suc size.simps(1) size.simps(11) size_binary_const size_non_add) using exp_add_left_negate_to_sub by simp -(* ----- Ends here ----- *) +(* ----- Ends here ----- *) end -(* Isabelle Isar Questions: +(* Isabelle Isar Questions: Why doesn't subgoal handle \forall and ⟶ ? Then this pattern might become just a single subgoal? subgoal premises p1 apply ((rule allI)+; rule impI) subgoal premises p2 for m p v -*) +*) end
diff --git a/Canonicalizations/AndPhase.html b/Canonicalizations/AndPhase.html index b2cd3361..5689f9c7 100644 --- a/Canonicalizations/AndPhase.html +++ b/Canonicalizations/AndPhase.html @@ -12,7 +12,7 @@

Theory AndPhase

-
subsection AndNode Phase
+
subsection ‹AndNode Phase›
 
 theory AndPhase
   imports
@@ -34,7 +34,7 @@ 

Theory AndPhase

lemma AndRightFallthrough: "(((and (not ( x)) ( y)) = 0)) exp[x & y] exp[y]" apply simp apply (rule impI; (rule allI)+; rule impI) - subgoal premises p for m p v + subgoal premises p for m p v proof - obtain xv where xv: "[m, p] x xv" using p(2) by blast @@ -64,11 +64,11 @@

Theory AndPhase

end -phase AndNode +phase AndNode terminating size begin -(* Word level proofs *) +(* Word level proofs *) lemma bin_and_nots: "(~x & ~y) = (~(x | y))" by simp @@ -77,7 +77,7 @@

Theory AndPhase

"(x & ~False) = x" by simp -(* Value level proofs *) +(* Value level proofs *) lemma val_and_equal: assumes "x = new_int b v" and "val[x & x] UndefVal" @@ -94,8 +94,8 @@

Theory AndPhase

shows "val[x & ~(new_int b' 0)] = x" using assms apply (simp add: take_bit_eq_mask) by presburger -(* Not sure if this one is written correctly *) -(* +(* Not sure if this one is written correctly *) +(* lemma val_and_sign_extend: assumes "e = (1 << In)-1" shows "val[(intval_sign_extend In Out x) & (IntVal b e)] = intval_zero_extend In Out x" @@ -106,19 +106,19 @@

Theory AndPhase

assumes "e = (1 << In)-1 ∧ intval_and (intval_sign_extend In Out x) (IntVal 32 e) ≠ UndefVal" shows "val[(intval_sign_extend In Out x) & (IntVal 32 e)] = intval_zero_extend In Out x" using assms apply (cases x; auto) - sorry
*)
+ sorry*)
-(* Extras which were missing *) +(* Extras which were missing *) lemma val_and_zero: assumes "x = new_int b v" shows "val[x & (IntVal b 0)] = IntVal b 0" by (auto simp: assms) -(* Exp level proofs *) +(* Exp level proofs *) lemma exp_and_equal: "exp[x & x] exp[x]" apply auto - subgoal premises p for m p xv yv + subgoal premises p for m p xv yv proof- obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -155,7 +155,7 @@

Theory AndPhase

(ConstantExpr (new_int b e)) (UnaryExpr (UnaryZeroExtend In Out) x)" apply auto - subgoal premises p for m p va + subgoal premises p for m p va proof - obtain va where va: "[m,p] x va" using p(2) by auto @@ -170,9 +170,9 @@

Theory AndPhase

then have 3: "b (64::nat)" using eval_bits_1_64 p(4) by blast then have 4: "- ((2::int) ^ b div (2::int)) sint (signed_take_bit (b - Suc (0::nat)) (take_bit b e))" - by (simp add: "21" int_power_div_base signed_take_bit_int_greater_eq_minus_exp_word) + by (simp add: "21" int_power_div_base signed_take_bit_int_greater_eq_minus_exp_word) then have 5: "sint (signed_take_bit (b - Suc (0::nat)) (take_bit b e)) < (2::int) ^ b div (2::int)" - by (simp add: "21" "3" Suc_le_lessD int_power_div_base signed_take_bit_int_less_exp_word) + by (simp add: "21" "3" Suc_le_lessD int_power_div_base signed_take_bit_int_less_exp_word) then have 6: "[m,p] UnaryExpr (UnaryZeroExtend In Out) x intval_and (intval_sign_extend In Out va) (IntVal b (take_bit b e))" apply (cases va; simp) @@ -189,7 +189,7 @@

Theory AndPhase

assumes "stamp_expr x = IntegerStamp b lo hi" shows "exp[(x & ~(const (IntVal b 0)))] x" using assms apply auto - subgoal premises p for m p xa + subgoal premises p for m p xa proof- obtain xv where xv: "[m,p] x xv" using p(3) by auto @@ -203,7 +203,7 @@

Theory AndPhase

qed done -(*lemma exp_and_neutral: +(*lemma exp_and_neutral: "exp[x & ~(const (new_int b 0))] ≥ x" apply auto using val_and_neutral eval_unused_bits_zero sorry (* apply (cases x; simp) using val_and_neutral bin_eval.simps(4) @@ -217,14 +217,14 @@

Theory AndPhase

intval_not.simps(2) unfold_const64) using val_and_neutral_64 bin_eval.simps(4) unary_eval.simps(3) bin_and_neutral unfold_const64 intval_and.elims intval_not.simps(2) - sorry*)
*)
+ sorry*)*)
-(* Helpers *) +(* Helpers *) lemma val_and_commute[simp]: "val[x & y] = val[y & x]" by (cases x; cases y; auto simp: word_bw_comms(1)) -text Optimisations +text ‹Optimisations› optimization AndEqual: "x & x x" using exp_and_equal by blast @@ -237,7 +237,7 @@

Theory AndPhase

by (metis add_2_eq_Suc' less_SucI less_add_Suc1 not_less_eq size_binary_const size_non_add exp_and_nots)+ -(* Need to prove exp_sign_extend*) +(* Need to prove exp_sign_extend*) optimization AndSignExtend: "BinaryExpr BinAnd (UnaryExpr (UnarySignExtend In Out) (x)) (const (new_int b e)) (UnaryExpr (UnaryZeroExtend In Out) (x)) @@ -256,9 +256,9 @@

Theory AndPhase

when (((and (not (IRExpr_down y)) (IRExpr_up x)) = 0))"
by (simp add: IRExpr_down_def IRExpr_up_def) -end (* End of AndPhase *) +end (* End of AndPhase *) -end (* End of file *)
+
end (* End of file *)
\ No newline at end of file diff --git a/Canonicalizations/BinaryNode.html b/Canonicalizations/BinaryNode.html index 6032c81c..7a577be6 100644 --- a/Canonicalizations/BinaryNode.html +++ b/Canonicalizations/BinaryNode.html @@ -12,23 +12,23 @@

Theory BinaryNode

-
subsection BinaryNode Phase
+
subsection ‹BinaryNode Phase›
 
 theory BinaryNode
   imports
     Common
 begin
 
-phase BinaryNode 
+phase BinaryNode 
   terminating size
 begin
 
 optimization BinaryFoldConstant: "BinaryExpr op (const v1) (const v2)  ConstantExpr (bin_eval op v1 v2)"
   unfolding le_expr_def
   apply (rule allI impI)+
-  subgoal premises bin for m p v
+  subgoal premises bin for m p v
     apply (rule BinaryExprE[OF bin])
-    subgoal premises prems for x y
+    subgoal premises prems for x y
     proof -
       have x: "x = v1" 
         using prems by auto
diff --git a/Canonicalizations/Common.html b/Canonicalizations/Common.html
index abf60130..f5bf7b2c 100644
--- a/Canonicalizations/Common.html
+++ b/Canonicalizations/Common.html
@@ -12,7 +12,7 @@
 

Theory Common

-
section Canonicalization Optimizations
+
section ‹Canonicalization Optimizations›
 
 theory Common
   imports 
@@ -22,7 +22,7 @@ 

Theory Common

lemma size_pos[size_simps]: "0 < size y" apply (induction y; auto?) - subgoal for op + subgoal for op apply (cases op) by (smt (z3) gr0I one_neq_zero pos2 size.elims trans_less_add2)+ done diff --git a/Canonicalizations/ConditionalPhase.html b/Canonicalizations/ConditionalPhase.html index 97b3445c..90743edb 100644 --- a/Canonicalizations/ConditionalPhase.html +++ b/Canonicalizations/ConditionalPhase.html @@ -12,7 +12,7 @@

Theory ConditionalPhase

-
subsection ConditionalNode Phase
+
subsection ‹ConditionalNode Phase›
 
 theory ConditionalPhase
   imports
@@ -20,7 +20,7 @@ 

Theory ConditionalPhase

Proofs.StampEvalThms begin -phase ConditionalNode +phase ConditionalNode terminating size begin @@ -46,7 +46,7 @@

Theory ConditionalPhase

optimization NegateConditionFlipBranches: "((!e) ? x : y) (e ? y : x)" apply simp apply (rule allI; rule allI; rule allI; rule impI) - subgoal premises p for m p v + subgoal premises p for m p v proof - obtain ev where ev: "[m,p] e ev" using p by blast @@ -78,9 +78,9 @@

Theory ConditionalPhase

when (stamp_under (stamp_expr v) (stamp_expr u) wf_stamp u wf_stamp v)" using stamp_under_defn_inverse by fastforce -(** Start of new proofs **) +(** Start of new proofs **) -(* Value-level proofs *) +(* Value-level proofs *) lemma val_optimise_integer_test: assumes "v. x = IntVal 32 v" shows "val[((x & (IntVal 32 1)) eq (IntVal 32 0)) ? (IntVal 32 0) : (IntVal 32 1)] = @@ -103,7 +103,7 @@

Theory ConditionalPhase

shows "xv. v = IntVal b xv" using assms by (simp add: IRTreeEvalThms.valid_value_elims(3)) -(* Optimisations *) +(* Optimisations *) lemma intval_self_is_true: assumes "yv UndefVal" @@ -132,7 +132,7 @@

Theory ConditionalPhase

(alwaysDistinct (stamp_expr x) (stamp_expr y)) isBoolean c"
apply (metis Canonicalization.cond_size add_lessD1 size_binary_lhs) apply auto - subgoal premises p for m p cExpr xv cond + subgoal premises p for m p cExpr xv cond proof - obtain cond where cond: "[m,p] c cond" using p by blast @@ -161,7 +161,7 @@

Theory ConditionalPhase

qed done -(* Helpers *) +(* Helpers *) lemma negation_preserve_eval0: assumes "[m, p] exp[e] v" assumes "isBoolean e" @@ -203,7 +203,7 @@

Theory ConditionalPhase

apply (smt (verit) not_add_less1 max_less_iff_conj max.absorb3 linorder_less_linear add_2_eq_Suc' add_less_cancel_right size_binary_lhs add_lessD1 Canonicalization.cond_size) apply auto - subgoal premises p for m p cExpr yv cond trE faE + subgoal premises p for m p cExpr yv cond trE faE proof - obtain cond where cond: "[m,p] c cond" using p by blast @@ -247,7 +247,7 @@

Theory ConditionalPhase

have eqEvalFalse: "intval_equals yv xv = (IntVal 32 0)" unfolding xvv yvv apply auto by (metis (mono_tags) bool_to_val.simps(2) yxDiff yvv xvv) have trueEvalEquiv: "[m,p] exp[BinaryExpr BinIntegerEquals (c ? x : y) (y)] notCond" - apply (cases notCond) prefer 2 + apply (cases notCond) prefer 2 apply (metis IntVal0 Value.distinct(1) eqEvalFalse evalDet evaltree_not_undef falseEval p(6) intval_commute intval_logic_negation.simps(1) intval_self_is_true logic_negate_def negation_preserve_eval2 notCond trueEvalCond yvv cNotRange cond) @@ -266,7 +266,7 @@

Theory ConditionalPhase

optimization ConditionalExtractCondition2: "exp[(c ? false : true)] !c when isBoolean c" apply auto - subgoal premises p for m p cExpr cond + subgoal premises p for m p cExpr cond proof- obtain cond where cond: "[m,p] c cond" using p(2) by auto @@ -293,7 +293,7 @@

Theory ConditionalPhase

optimization ConditionalEqualIsRHS: "((x eq y) ? x : y) y" apply auto - subgoal premises p for m p v true false xa ya + subgoal premises p for m p v true false xa ya proof- obtain xv where xv: "[m,p] x xv" using p(8) by auto @@ -323,13 +323,13 @@

Theory ConditionalPhase

qed done -(* todo not sure if this is done properly *) +(* todo not sure if this is done properly *) optimization normalizeX: "((x eq const (IntVal 32 0)) ? (const (IntVal 32 0)) : (const (IntVal 32 1))) x when stamp_expr x = IntegerStamp 32 0 1 wf_stamp x isBoolean x" apply auto - subgoal premises p for m p v + subgoal premises p for m p v proof - obtain xa where xa: "[m,p] x xa" using p by blast @@ -346,19 +346,19 @@

Theory ConditionalPhase

qed done -(* todo not sure if this is done properly *) +(* todo not sure if this is done properly *) optimization normalizeX2: "((x eq (const (IntVal 32 1))) ? (const (IntVal 32 1)) : (const (IntVal 32 0))) x when (x = ConstantExpr (IntVal 32 0) | (x = ConstantExpr (IntVal 32 1)))" . -(* todo not sure if this is done properly *) +(* todo not sure if this is done properly *) optimization flipX: "((x eq (const (IntVal 32 0))) ? (const (IntVal 32 1)) : (const (IntVal 32 0))) x (const (IntVal 32 1)) when (x = ConstantExpr (IntVal 32 0) | (x = ConstantExpr (IntVal 32 1)))" . -(* todo not sure if this is done properly *) +(* todo not sure if this is done properly *) optimization flipX2: "((x eq (const (IntVal 32 1))) ? (const (IntVal 32 0)) : (const (IntVal 32 1))) x (const (IntVal 32 1)) when (x = ConstantExpr (IntVal 32 0) | @@ -376,7 +376,7 @@

Theory ConditionalPhase

x & (const (IntVal 32 1)) when (stamp_expr x = default_stamp wf_stamp x)"
apply (simp; rule impI; (rule allI)+; rule impI) - subgoal premises eval for m p v + subgoal premises eval for m p v proof - obtain xv where xv: "[m, p] x xv" using eval by fast @@ -401,22 +401,22 @@

Theory ConditionalPhase

qed done -(* todo not sure if this is done properly *) +(* todo not sure if this is done properly *) optimization opt_optimise_integer_test_2: "(((x & (const (IntVal 32 1))) eq (const (IntVal 32 0))) ? (const (IntVal 32 0)) : (const (IntVal 32 1))) x when (x = ConstantExpr (IntVal 32 0) | (x = ConstantExpr (IntVal 32 1)))" . -(* +(* optimization opt_conditional_eliminate_known_less: "((x < y) ? x : y) ⟼ x when (((stamp_under (stamp_expr x) (stamp_expr y)) | ((stpi_upper (stamp_expr x)) = (stpi_lower (stamp_expr y)))) ∧ wf_stamp x ∧ wf_stamp y)" apply auto using stamp_under_defn apply simp sorry -*) +*) -(* +(* optimization opt_normalize_x_original: "((BinaryExpr BinIntegerEquals x (ConstantExpr (IntVal32 0))) ? (ConstantExpr (IntVal32 0)) : (ConstantExpr (IntVal32 1))) ⟼ x when (stamp_expr x = IntegerStamp 32 0 1 ∧ @@ -425,9 +425,9 @@

Theory ConditionalPhase

using wf_stamp_def apply (cases x; simp) sorry -
*)
+*)
-(** End of new proofs **) +(** End of new proofs **) end diff --git a/Canonicalizations/MulPhase.html b/Canonicalizations/MulPhase.html index 584067b9..78919733 100644 --- a/Canonicalizations/MulPhase.html +++ b/Canonicalizations/MulPhase.html @@ -12,7 +12,7 @@

Theory MulPhase

-
subsection MulNode Phase
+
subsection ‹MulNode Phase›
 
 theory MulPhase
   imports
@@ -31,11 +31,11 @@ 

Theory MulPhase

"mul_size (ConstantVar c) = 2" | "mul_size (VariableExpr x s) = 2" -phase MulNode +phase MulNode terminating mul_size begin -(* Word level proofs *) +(* Word level proofs *) lemma bin_eliminate_redundant_negative: "uminus (x :: 'a::len word) * uminus (y :: 'a::len word) = x * y" by simp @@ -56,7 +56,7 @@

Theory MulPhase

"(x:: 'a::len word) * (2^j) = x << j" by simp -(* Helper *) +(* Helper *) lemma take_bit64[simp]: fixes w :: "int64" shows "take_bit 64 w = w" @@ -67,7 +67,7 @@

Theory MulPhase

by (metis lt2p_lem mask_eq_iff take_bit_eq_mask verit_comp_simplify1(2) wsst_TYs(3)) qed -(* TODO: merge this with val_eliminate_redundant_negative *) +(* TODO: merge this with val_eliminate_redundant_negative *) lemma mergeTakeBit: fixes a :: "nat" fixes b c :: "64 word" @@ -75,7 +75,7 @@

Theory MulPhase

take_bit a (b * c)" by (smt (verit, ccfv_SIG) take_bit_mult take_bit_of_int unsigned_take_bit_eq word_mult_def) -(* Value level proofs *) +(* Value level proofs *) lemma val_eliminate_redundant_negative: assumes "val[-x * -y] UndefVal" shows "val[-x * -y] = val[x * y]" @@ -97,7 +97,7 @@

Theory MulPhase

unfolding assms(1) apply auto by (metis bin_multiply_negative mergeTakeBit take_bit_minus_one_eq_mask) -(* x * 2^i = x << i*) +(* x * 2^i = x << i*) lemma val_MulPower2: fixes i :: "64 word" assumes "y = IntVal 64 (2 ^ unat(i))" @@ -106,7 +106,7 @@

Theory MulPhase

and "val[x * y] UndefVal" shows "val[x * y] = val[x << IntVal 64 i]" using assms apply (cases x; cases y; auto) - subgoal premises p for x2 + subgoal premises p for x2 proof - have 63: "(63 :: int64) = mask 6" by eval @@ -122,7 +122,7 @@

Theory MulPhase

qed by presburger -(* x * ((2 ^ j) + 1) = (x << j) + x *) +(* x * ((2 ^ j) + 1) = (x << j) + x *) lemma val_MulPower2Add1: fixes i :: "64 word" assumes "y = IntVal 64 ((2 ^ unat(i)) + 1)" @@ -132,7 +132,7 @@

Theory MulPhase

and "val_to_bool(val[IntVal 64 0 < y])" shows "val[x * y] = val[(x << IntVal 64 i) + x]" using assms apply (cases x; cases y; auto) - subgoal premises p for x2 + subgoal premises p for x2 proof - have 63: "(63 :: int64) = mask 6" by eval @@ -147,7 +147,7 @@

Theory MulPhase

qed using val_to_bool.simps(2) by presburger -(* x * ((2 ^ j) - 1) = (x << j) - x *) +(* x * ((2 ^ j) - 1) = (x << j) - x *) lemma val_MulPower2Sub1: fixes i :: "64 word" assumes "y = IntVal 64 ((2 ^ unat(i)) - 1)" @@ -157,7 +157,7 @@

Theory MulPhase

and "val_to_bool(val[IntVal 64 0 < y])" shows "val[x * y] = val[(x << IntVal 64 i) - x]" using assms apply (cases x; cases y; auto) - subgoal premises p for x2 + subgoal premises p for x2 proof - have 63: "(63 :: int64) = mask 6" by eval @@ -172,7 +172,7 @@

Theory MulPhase

qed using val_to_bool.simps(2) by presburger -(* Value level helpers *) +(* Value level helpers *) lemma val_distribute_multiplication: assumes "x = IntVal b xx q = IntVal b qq a = IntVal b aa" assumes "val[x * (q + a)] UndefVal" @@ -188,7 +188,7 @@

Theory MulPhase

using assms apply (cases x; cases q; cases a; auto) using distrib_left by blast -(* x * ((2 ^ j) + (2 ^ k)) = (x << j) + (x << k) *) +(* x * ((2 ^ j) + (2 ^ k)) = (x << j) + (x << k) *) lemma val_MulPower2AddPower2: fixes i j :: "64 word" assumes "y = IntVal 64 ((2 ^ unat(i)) + (2 ^ unat(j)))" @@ -205,11 +205,11 @@

Theory MulPhase

by eval then have n: "IntVal 64 ((2 ^ unat(i)) + (2 ^ unat(j))) = val[(IntVal 64 (2 ^ unat(i))) + (IntVal 64 (2 ^ unat(j)))]" - (* x * (2^i + 2^j)*) + (* x * (2^i + 2^j)*) by auto then have 1: "val[x * ((IntVal 64 (2 ^ unat(i))) + (IntVal 64 (2 ^ unat(j))))] = val[(x * IntVal 64 (2 ^ unat(i))) + (x * IntVal 64 (2 ^ unat(j)))]" - (* (x * 2^i) + (x * 2^j)*) + (* (x * 2^i) + (x * 2^j)*) using assms val_distribute_multiplication64 by simp then have 2: "val[(x * IntVal 64 (2 ^ unat(i)))] = val[x << IntVal 64 i]" by (metis (no_types, opaque_lifting) Value.distinct(1) intval_mul.simps(1) new_int.simps @@ -221,11 +221,11 @@

Theory MulPhase

thm_oracles val_MulPower2AddPower2 -(* Exp-level proofs *) +(* Exp-level proofs *) lemma exp_multiply_zero_64: shows "exp[x * (const (IntVal b 0))] ConstantExpr (IntVal b 0)" apply auto - subgoal premises p for m p xa + subgoal premises p for m p xa proof - obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -247,7 +247,7 @@

Theory MulPhase

lemma exp_multiply_neutral: "exp[x * (const (IntVal b 1))] x" apply auto - subgoal premises p for m p xa + subgoal premises p for m p xa proof - obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -267,7 +267,7 @@

Theory MulPhase

lemma exp_multiply_negative: "exp[x * -(const (IntVal b 1))] exp[-x]" apply auto - subgoal premises p for m p xa + subgoal premises p for m p xa proof - obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -330,7 +330,7 @@

Theory MulPhase

shows "exp[x * y] exp[(x << ConstantExpr (IntVal 64 i)) + (x << ConstantExpr (IntVal 64 j))]" using ConstantExprE equiv_exprs_def unfold_binary assms by fastforce -(* Exp level helpers *) +(* Exp level helpers *) lemma greaterConstant: fixes a b :: "64 word" @@ -351,7 +351,7 @@

Theory MulPhase

assumes "wf_stamp y" shows "exp[(x * q) + (x * y)] exp[x * (q + y)]" apply auto - subgoal premises p for m p xa qa xb aa + subgoal premises p for m p xa qa xb aa proof - obtain xv where xv: "[m,p] x xv" using p by simp @@ -375,7 +375,7 @@

Theory MulPhase

qed done -text Optimisations +text ‹Optimisations› optimization EliminateRedundantNegative: "-x * -y x * y" apply auto @@ -431,7 +431,7 @@

Theory MulPhase

64 > i y = exp[const (IntVal 64 (2 ^ unat(i)))])" apply simp apply (rule impI; (rule allI)+; rule impI) - subgoal premises eval for m p v + subgoal premises eval for m p v proof - obtain xv where xv: "[m, p] x xv" using eval(2) by blast @@ -463,7 +463,7 @@

Theory MulPhase

64 > i y = ConstantExpr (IntVal 64 ((2 ^ unat(i)) + 1)) )" apply simp apply (rule impI; (rule allI)+; rule impI) - subgoal premises p for m p v + subgoal premises p for m p v proof - obtain xv where xv: "[m, p] x xv" using p by fast @@ -497,13 +497,13 @@

Theory MulPhase

qed done -(* Need to prove exp_MulPower2Sub1 *) +(* Need to prove exp_MulPower2Sub1 *) optimization MulPower2Sub1: "x * y (x << const (IntVal 64 i)) - x when (i > 0 stamp_expr x = IntegerStamp 64 xl xh wf_stamp x 64 > i y = ConstantExpr (IntVal 64 ((2 ^ unat(i)) - 1)) )" apply simp apply (rule impI; (rule allI)+; rule impI) - subgoal premises p for m p v + subgoal premises p for m p v proof - obtain xv where xv: "[m,p] x xv" using p by fast @@ -533,9 +533,9 @@

Theory MulPhase

qed done -end (* End of MulPhase *) +end (* End of MulPhase *) -end (* End of file *) +end (* End of file *)
diff --git a/Canonicalizations/NegatePhase.html b/Canonicalizations/NegatePhase.html index 8ec5869c..2c220c3e 100644 --- a/Canonicalizations/NegatePhase.html +++ b/Canonicalizations/NegatePhase.html @@ -12,23 +12,23 @@

Theory NegatePhase

-
subsection NegateNode Phase
+
subsection ‹NegateNode Phase›
 
 theory NegatePhase
   imports
     Common
 begin
 
-phase NegateNode
+phase NegateNode
   terminating size
 begin
 
-(* Word level proofs *)
+(* Word level proofs *)
 lemma bin_negative_cancel:
  "-1 * (-1 * ((x::('a::len) word))) = x"
   by auto
 
-(* Value level proofs *)
+(* Value level proofs *)
 lemma val_negative_cancel:
   assumes "val[-(new_int b v)]  UndefVal"
   shows   "val[-(-(new_int b v))] = val[new_int b v]"
@@ -39,7 +39,7 @@ 

Theory NegatePhase

shows "val[-(x - y)] = val[y - x]" by (cases x; cases y; auto) -(* Exp level proofs *) +(* Exp level proofs *) lemma exp_distribute_sub: shows "exp[-(x - y)] exp[y - x]" by (auto simp: val_distribute_sub evaltree_not_undef) @@ -57,7 +57,7 @@

Theory NegatePhase

and "unat y = (b' - 1)" shows "exp[-(x >> (const (new_int b y)))] exp[x >>> (const (new_int b y))]" apply auto - subgoal premises p for m p xa + subgoal premises p for m p xa proof - obtain xa where xa: "[m,p] x xa" using p(2) by auto @@ -66,7 +66,7 @@

Theory NegatePhase

then have 2: "val[xa >> (IntVal b (take_bit b y))] UndefVal" by auto then have 4: "sint (signed_take_bit (b - Suc (0::nat)) (take_bit b y)) < (2::int) ^ b div (2::int)" - by (metis Suc_le_lessD Suc_pred eval_bits_1_64 int_power_div_base p(4) zero_less_numeral + by (metis Suc_le_lessD Suc_pred eval_bits_1_64 int_power_div_base p(4) zero_less_numeral signed_take_bit_int_less_exp_word size64 unfold_const wsst_TYs(3)) then have 5: "(0::nat) < b" using eval_bits_1_64 p(4) by blast @@ -77,7 +77,7 @@

Theory NegatePhase

intval_negate (intval_right_shift xa (IntVal b (take_bit b y)))" apply (cases y; auto) - subgoal premises p for n + subgoal premises p for n proof - have sg1: "y = word_of_nat n" by (simp add: p(1)) @@ -99,12 +99,12 @@

Theory NegatePhase

done -text Optimisations +text ‹Optimisations› optimization NegateCancel: "-(-(x)) x" using exp_negative_cancel by blast -(* FloatStamp condition is omitted. Not 100% sure. *) +(* FloatStamp condition is omitted. Not 100% sure. *) optimization DistributeSubtraction: "-(x - y) (y - x)" apply (smt (verit, best) add.left_commute add_2_eq_Suc' add_diff_cancel_left' is_ConstantExpr_def less_Suc_eq_0_disj plus_1_eq_Suc size.simps(11) size_binary_const size_non_add @@ -113,14 +113,14 @@

Theory NegatePhase

zero_less_Suc) using exp_distribute_sub by simp -(* Need to prove exp_negative_shift *) +(* Need to prove exp_negative_shift *) optimization NegativeShift: "-(x >> (const (new_int b y))) x >>> (const (new_int b y)) when (stamp_expr x = IntegerStamp b' lo hi unat y = (b' - 1))" using exp_negative_shift by simp -end (* End of NegatePhase *) +end (* End of NegatePhase *) -end (* End of file *) +end (* End of file *)
diff --git a/Canonicalizations/NewAnd.html b/Canonicalizations/NewAnd.html index d75ccd5d..4e4a2412 100644 --- a/Canonicalizations/NewAnd.html +++ b/Canonicalizations/NewAnd.html @@ -12,7 +12,7 @@

Theory NewAnd

-
subsection Experimental AndNode Phase
+
subsection ‹Experimental AndNode Phase›
 
 theory NewAnd
   imports
@@ -83,14 +83,14 @@ 

Theory NewAnd

using intval_xor_associative by fastforce lemma intval_and_absorb_or: - assumes "b v . x = new_int b v" (* TODO: required? *) + assumes "b v . x = new_int b v" (* TODO: required? *) assumes "val[x & (x | y)] UndefVal" shows "val[x & (x | y)] = val[x]" using assms apply (cases x; cases y; auto) by (metis (full_types) intval_and.simps(6)) lemma intval_or_absorb_and: - assumes "b v . x = new_int b v" (* TODO: required? *) + assumes "b v . x = new_int b v" (* TODO: required? *) assumes "val[x | (x & y)] UndefVal" shows "val[x | (x & y)] = val[x]" using assms apply (cases x; cases y; auto) @@ -99,7 +99,7 @@

Theory NewAnd

lemma exp_and_absorb_or: "exp[x & (x | y)] exp[x]" apply auto - subgoal premises p for m p xa xaa ya + subgoal premises p for m p xa xaa ya proof- obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -121,7 +121,7 @@

Theory NewAnd

lemma exp_or_absorb_and: "exp[x | (x & y)] exp[x]" apply auto - subgoal premises p for m p xa xaa ya + subgoal premises p for m p xa xaa ya proof- obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -145,26 +145,26 @@

Theory NewAnd

shows "x + y = or x y" by (simp add: assms) -(* +(* lemma fixes x y :: "64 word" assumes "∃e. n = 2^e" assumes "and y n = 0" shows "x + y = (or (and x n) (and y n)) + ((x >> n) + (y >> n) << n)" -*) +*) lemma no_overlap_or: assumes "and x y = 0" shows "x + y = or x y" by (metis bit_and_iff bit_xor_iff disjunctive_add xor_self_eq assms) -(*lemma no_carry_zero_bit: +(*lemma no_carry_zero_bit: assumes "¬(bit y j)" assumes "¬(bit y (Suc j))" shows "bit (x + y) (Suc j) = bit x (Suc j)" - using assms sorry*) + using assms sorry*) -(* +(* lemma fixes x y :: "'a :: len word" assumes "(and y (mask (Suc j))) = 0" @@ -212,8 +212,8 @@

Theory NewAnd

then show ?case sorry qed - using assms bit_and_iff bit_xor_iff disjunctive_add xor_self_eq sorry
*)
- (* + using assms bit_and_iff bit_xor_iff disjunctive_add xor_self_eq sorry*) + (* using assms proof (induction j) case 0 then show ?case @@ -226,9 +226,9 @@

Theory NewAnd

by (simp add: Suc.prems) show ?case using j0 sj0 no_overlap_or by blast -qed
*)
+qed *)
-(* +(* lemma packed_bits: fixes a :: "64 word" assumes "numberOfLeadingZeros a + bitCount a = 64" @@ -280,7 +280,7 @@

Theory NewAnd

using j by (simp add: less order_le_less) qed -
*)
+*)
context stamp_mask begin @@ -298,7 +298,7 @@

Theory NewAnd

lemma exp_eliminate_y: "and (y) (z) = 0 exp[(x | y) & z] exp[x & z]" apply simp apply (rule impI; rule allI; rule allI; rule allI) - subgoal premises p for m p v apply (rule impI) subgoal premises e + subgoal premises p for m p v apply (rule impI) subgoal premises e proof - obtain xv where xv: "[m,p] x xv" using e by auto @@ -334,7 +334,7 @@

Theory NewAnd

by (smt (verit, ccfv_SIG) highestOneBit_def int_nat_eq int_ops(6) less_imp_of_nat_less size64 max_set_bit zerosAboveHighestOne assms numberOfLeadingZeros_def) -no_notation LogicNegationNotation ("!_") +no_notation LogicNegationNotation ("!_") lemma zero_horner: "horner_sum of_bool 2 (map (λx. False) xs) = 0" @@ -498,7 +498,7 @@

Theory NewAnd

assumes "numberOfLeadingZeros (z) + numberOfTrailingZeros (y) 64" shows "exp[(x + y) & z] exp[x & z]" apply simp apply ((rule allI)+; rule impI) - subgoal premises eval for m p v + subgoal premises eval for m p v proof - obtain n where n: "n = 64 - numberOfLeadingZeros (z)" by simp @@ -533,7 +533,7 @@

Theory NewAnd

using L2 n zv yv assms by auto also have "... = and (xv mod 2^n) zv" by (smt (verit, best) and.idem take_bit_eq_mask take_bit_eq_mod word_bw_assocs(1) - mod_mod_trivial) + mod_mod_trivial) also have "... = and xv zv" by (metis L1 n zv) finally show ?thesis @@ -556,7 +556,7 @@

Theory NewAnd

thm_oracles improved_opt -(* +(* lemma falseBelowN_nBelowLowest: assumes "n ≤ Nat.size a" assumes "∀ i < n. ¬(bit a i)" @@ -663,9 +663,9 @@

Theory NewAnd

then show ?thesis using n by blast qed -
*)
+*)
-(* +(* lemma consumes: assumes "numberOfLeadingZeros (↑z) + bitCount (↑z) = 64" and "↑z ≠ 0" @@ -807,12 +807,12 @@

Theory NewAnd

qed done done -
*)
+*)
end -phase NewAnd +phase NewAnd terminating size begin @@ -832,10 +832,10 @@

Theory NewAnd

when (((and (IRExpr_up x) (IRExpr_up z)) = 0))" by (simp add: IRExpr_up_def)+ -(* +(* optimization redundant_lhs_add: "((x + y) & z) ⟼ x & z when ((and (IRExpr_up y) (IRExpr_down z)) = 0)" -*) +*) end diff --git a/Canonicalizations/NotPhase.html b/Canonicalizations/NotPhase.html index 60a3063f..d9141931 100644 --- a/Canonicalizations/NotPhase.html +++ b/Canonicalizations/NotPhase.html @@ -12,33 +12,33 @@

Theory NotPhase

-
subsection NotNode Phase
+
subsection ‹NotNode Phase›
 
 theory NotPhase
   imports
     Common
 begin
 
-phase NotNode
+phase NotNode
   terminating size
 begin
 
-(* Word level proofs *)
+(* Word level proofs *)
 lemma bin_not_cancel:
  "bin[¬(¬(e))] = bin[e]"
   by auto
 
-(* Value level proofs *)
+(* Value level proofs *)
 lemma val_not_cancel:
   assumes "val[~(new_int b v)]  UndefVal"
   shows   "val[~(~(new_int b v))] = (new_int b v)"
   by (simp add: take_bit_not_take_bit)
 
-(* Exp level proofs *)
+(* Exp level proofs *)
 lemma exp_not_cancel:
    "exp[~(~a)]  exp[a]" 
   apply auto
-  subgoal premises p for m p x
+  subgoal premises p for m p x
   proof -
     obtain av where av: "[m,p]  a  av"
       using p(2) by auto
@@ -51,14 +51,14 @@ 

Theory NotPhase

qed done -text Optimisations +text ‹Optimisations› optimization NotCancel: "exp[~(~a)] a" by (metis exp_not_cancel) -end (* End of NotPhase *) +end (* End of NotPhase *) -end (* End of file *) +end (* End of file *)
diff --git a/Canonicalizations/OrPhase.html b/Canonicalizations/OrPhase.html index 3db1f2c7..f7bc8097 100644 --- a/Canonicalizations/OrPhase.html +++ b/Canonicalizations/OrPhase.html @@ -12,7 +12,7 @@

Theory OrPhase

-
subsection OrNode Phase
+
subsection ‹OrNode Phase›
 
 theory OrPhase
   imports
@@ -22,32 +22,32 @@ 

Theory OrPhase

context stamp_mask begin -text -Taking advantage of the truth table of or operations. - -\begin{center} -\begin{tabular}{ c c c c } -\# & x & y & $x | y$ \\ -1 & 0 & 0 & 0 \\ -2 & 0 & 1 & 1 \\ -3 & 1 & 0 & 1 \\ -4 & 1 & 1 & 1 -\end{tabular} -\end{center} - -If row 2 never applies, that is, canBeZero x \& canBeOne y = 0, -then $(x | y) = x$. - -Likewise, if row 3 never applies, canBeZero y \& canBeOne x = 0, -then $(x | y) = y$. - +text ‹ +Taking advantage of the truth table of or operations. + +\begin{center} +\begin{tabular}{ c c c c } +\# & x & y & $x | y$ \\ +1 & 0 & 0 & 0 \\ +2 & 0 & 1 & 1 \\ +3 & 1 & 0 & 1 \\ +4 & 1 & 1 & 1 +\end{tabular} +\end{center} + +If row 2 never applies, that is, canBeZero x \& canBeOne y = 0, +then $(x | y) = x$. + +Likewise, if row 3 never applies, canBeZero y \& canBeOne x = 0, +then $(x | y) = y$. +› lemma OrLeftFallthrough: assumes "(and (not (x)) (y)) = 0" shows "exp[x | y] exp[x]" using assms apply simp apply ((rule allI)+; rule impI) - subgoal premises eval for m p v + subgoal premises eval for m p v proof - obtain b vv where e: "[m, p] exp[x | y] IntVal b vv" by (metis BinaryExprE bin_eval_new_int new_int.simps eval(2)) @@ -73,7 +73,7 @@

Theory OrPhase

shows "exp[x | y] exp[y]" using assms apply simp apply ((rule allI)+; rule impI) - subgoal premises eval for m p v + subgoal premises eval for m p v proof - obtain b vv where e: "[m, p] exp[x | y] IntVal b vv" by (metis BinaryExprE bin_eval_new_int new_int.simps eval(2)) @@ -96,11 +96,11 @@

Theory OrPhase

end -phase OrNode +phase OrNode terminating size begin -(* Word level proofs *) +(* Word level proofs *) lemma bin_or_equal: "bin[x | x] = bin[x]" by simp @@ -113,7 +113,7 @@

Theory OrPhase

"(~x | ~y) = (~(x & y))" by simp -(* Value level proofs *) +(* Value level proofs *) lemma val_or_equal: assumes "x = new_int b v" and "val[x | x] UndefVal" @@ -134,11 +134,11 @@

Theory OrPhase

"val[~x | ~y] = val[~(x & y)]" by (cases x; cases y; auto simp: take_bit_not_take_bit) -(* Exp level proofs *) +(* Exp level proofs *) lemma exp_or_equal: "exp[x | x] exp[x]" apply auto[1] - subgoal premises p for m p xa ya + subgoal premises p for m p xa ya proof- obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -160,7 +160,7 @@

Theory OrPhase

lemma exp_elim_redundant_false: "exp[x | false] exp[x]" apply auto[1] - subgoal premises p for m p xa + subgoal premises p for m p xa proof- obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -181,7 +181,7 @@

Theory OrPhase

qed done -text Optimisations +text ‹Optimisations› optimization OrEqual: "x | x x" by (meson exp_or_equal) @@ -205,10 +205,10 @@

Theory OrPhase

"x | y y when ((and (not (IRExpr_down y)) (IRExpr_up x)) = 0)" using simple_mask.OrRightFallthrough by blast -end (* End of OrPhase *) +end (* End of OrPhase *) -end (* End of file *) +end (* End of file *)
diff --git a/Canonicalizations/ProofStatus.html b/Canonicalizations/ProofStatus.html index 779e18f9..7862dbc2 100644 --- a/Canonicalizations/ProofStatus.html +++ b/Canonicalizations/ProofStatus.html @@ -19,7 +19,7 @@

Theory ProofStatus

AndPhase ConditionalPhase MulPhase - (*NarrowPhase*) + (*NarrowPhase*) NegatePhase NewAnd NotPhase @@ -41,9 +41,9 @@

Theory ProofStatus

print_theorems thm opt_add_left_negate_to_sub -(*thm_oracles AbsNegate*) +(*thm_oracles AbsNegate*) -export_phases Full +export_phases ‹Full› end
diff --git a/Canonicalizations/ShiftPhase.html b/Canonicalizations/ShiftPhase.html index e4e484b6..030c6a80 100644 --- a/Canonicalizations/ShiftPhase.html +++ b/Canonicalizations/ShiftPhase.html @@ -12,14 +12,14 @@

Theory ShiftPhase

-
subsection ShiftNode Phase
+
subsection ‹ShiftNode Phase›
 
 theory ShiftPhase
   imports 
     Common
 begin
 
-phase ShiftNode
+phase ShiftNode
   terminating size
 begin
 
@@ -53,8 +53,8 @@ 

Theory ShiftPhase

next case False then have " v . val_c = IntVal 64 v" - sorry (* no longer true - by (metis ‹n = intval_log2 val_c ∧ in_bounds n 0 32› in_bounds.simps(3) intval_log2.elims)*) + sorry (* no longer true + by (metis ‹n = intval_log2 val_c ∧ in_bounds n 0 32› in_bounds.simps(3) intval_log2.elims)*) then obtain vc where "val_c = IntVal 64 vc" by auto then have "n = IntVal 64 (word_of_int (SOME e. vc=2^e))" diff --git a/Canonicalizations/SignedDivPhase.html b/Canonicalizations/SignedDivPhase.html index 61d6d254..d5580c4d 100644 --- a/Canonicalizations/SignedDivPhase.html +++ b/Canonicalizations/SignedDivPhase.html @@ -12,33 +12,33 @@

Theory SignedDivPhase

-
subsection SignedDivNode Phase
+
subsection ‹SignedDivNode Phase›
 
 theory SignedDivPhase
   imports
     Common
 begin
 
-phase SignedDivNode
+phase SignedDivNode
   terminating size
 begin
 
-(* Value level proofs *)
+(* Value level proofs *)
 lemma val_division_by_one_is_self_32:
   assumes "x = new_int 32 v"
   shows "intval_div x (IntVal 32 1) = x"
   using assms apply (cases x; auto)
   by (simp add: take_bit_signed_take_bit)
 
-(* Optimizations*)
-(*
+(* Optimizations*)
+(*
 optimization opt_DivisionByOneIsSelf32: "x / ConstantExpr (IntVal32 1) ⟼ x"
    apply unfold_optimization unfolding le_expr_def
-  sorry*)
+  sorry*)
 
-end (* end of phase *)
+end (* end of phase *)
 
-end (* end of file *)
+end (* end of file *)
 
diff --git a/Canonicalizations/SignedRemPhase.html b/Canonicalizations/SignedRemPhase.html index 932da38c..bf662ba6 100644 --- a/Canonicalizations/SignedRemPhase.html +++ b/Canonicalizations/SignedRemPhase.html @@ -12,14 +12,14 @@

Theory SignedRemPhase

-
subsection SignedRemNode Phase
+
subsection ‹SignedRemNode Phase›
 
 theory SignedRemPhase
   imports
     Common
 begin
 
-phase SignedRemNode
+phase SignedRemNode
   terminating size
 begin
 
@@ -31,9 +31,9 @@ 

Theory SignedRemPhase

value "word_of_int (sint (x2::32 word) smod 1)" -end (* End of SignedRedPhase *) +end (* End of SignedRedPhase *) -end (* End of file *)
+
end (* End of file *)
\ No newline at end of file diff --git a/Canonicalizations/SubPhase.html b/Canonicalizations/SubPhase.html index 9f8f176b..c9af2c93 100644 --- a/Canonicalizations/SubPhase.html +++ b/Canonicalizations/SubPhase.html @@ -12,7 +12,7 @@

Theory SubPhase

-
subsection SubNode Phase
+
subsection ‹SubNode Phase›
 
 theory SubPhase
   imports
@@ -20,11 +20,11 @@ 

Theory SubPhase

Proofs.StampEvalThms begin -phase SubNode +phase SubNode terminating size begin -(* Word level proofs *) +(* Word level proofs *) lemma bin_sub_after_right_add: shows "((x::('a::len) word) + (y::('a::len) word)) - y = x" by simp @@ -57,7 +57,7 @@

Theory SubPhase

"(x :: 'a::len word) - (-(y :: 'a::len word)) = x + y" by simp -(* Value level proofs *) +(* Value level proofs *) lemma val_sub_after_right_add_2: assumes "x = new_int b v" assumes "val[(x + y) - y] UndefVal" @@ -111,11 +111,11 @@

Theory SubPhase

shows "val[x - (-y)] = val[x + y]" by (cases x; simp add: assms) -(* Exp level proofs *) +(* Exp level proofs *) lemma exp_sub_after_right_add: shows "exp[(x + y) - y] x" apply auto - subgoal premises p for m p ya xa yaa + subgoal premises p for m p ya xa yaa proof- obtain xv where xv: "[m,p] x xv" using p(3) by auto @@ -144,7 +144,7 @@

Theory SubPhase

lemma exp_sub_negative_value: "exp[x - (-y)] exp[x + y]" apply auto - subgoal premises p for m p xa ya + subgoal premises p for m p xa ya proof - obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -160,7 +160,7 @@

Theory SubPhase

lemma exp_sub_then_left_sub: "exp[x - (x - y)] y" using val_sub_then_left_sub apply auto - subgoal premises p for m p xa xaa ya + subgoal premises p for m p xa xaa ya proof- obtain xa where xa: "[m, p] x xa" using p(2) by blast @@ -185,7 +185,7 @@

Theory SubPhase

lemma SubtractZero_Exp: "exp[(x - (const IntVal b 0))] x" apply auto - subgoal premises p for m p xa + subgoal premises p for m p xa proof- obtain xv where xv: "[m,p] x xv" using p(1) by auto @@ -208,7 +208,7 @@

Theory SubPhase

assumes "¬(is_ConstantExpr x)" shows "exp[(const IntVal b 0) - x] exp[-x]" using assms apply auto - subgoal premises p for m p xa + subgoal premises p for m p xa proof- obtain xv where xv: "[m,p] x xv" using p(4) by auto @@ -222,7 +222,7 @@

Theory SubPhase

qed done -text Optimisations +text ‹Optimisations› optimization SubAfterAddRight: "((x + y) - y) x" using exp_sub_after_right_add by blast @@ -251,12 +251,12 @@

Theory SubPhase

thm_oracles SubtractZero -(* Doesn't have any subgoals? *) -(* +(* Doesn't have any subgoals? *) +(* optimization SubNegativeConstant: "(x - (const (IntVal b y))) ⟼ x + (const (IntVal b y)) when (y < 0)" done -*) +*) optimization SubNegativeValue: "(x - (-y)) x + y" apply (metis add_2_eq_Suc' less_SucI less_add_Suc1 not_less_eq size_binary_const size_non_add) @@ -269,7 +269,7 @@

Theory SubPhase

shows "x = val[-(-x)]" by (auto simp: assms is_IntVal_def) -(* +(* lemma remove_sub_preserve_take_bit: fixes v :: "64 word" assumes "b > 0 ∧ b ≤ 64" @@ -342,14 +342,14 @@

Theory SubPhase

by (metis eval evalDet lhsdef rhsdef) qed sorry -
*)
+*)
-(*Additional check for not constant for termination *) +(*Additional check for not constant for termination *) optimization ZeroSubtractValue: "((const IntVal b 0) - x) (-x) when (wf_stamp x stamp_expr x = IntegerStamp b lo hi ¬(is_ConstantExpr x))" using size_flip_binary ZeroSubtractValue_Exp by simp+ -(* +(* fun forPrimitive :: "Stamp ⇒ int64 ⇒ IRExpr" where "forPrimitive (IntegerStamp b lo hi) v = ConstantExpr (if take_bit b v = v then (IntVal b v) else UndefVal)" | "forPrimitive _ _ = ConstantExpr UndefVal" @@ -402,7 +402,7 @@

Theory SubPhase

then show ?thesis sorry qed done -
*)
+*)
optimization SubSelfIsZero: "(x - x) const IntVal b 0 when (wf_stamp x stamp_expr x = IntegerStamp b lo hi)" @@ -411,9 +411,9 @@

Theory SubPhase

take_bit_of_0 val_sub_self_is_zero validDefIntConst valid_int wf_stamp_def One_nat_def evalDet) -end (* End of SubPhase *) +end (* End of SubPhase *) -end (* End of file *) +end (* End of file *)
diff --git a/Canonicalizations/TacticSolving.html b/Canonicalizations/TacticSolving.html index 0b950701..3b460112 100644 --- a/Canonicalizations/TacticSolving.html +++ b/Canonicalizations/TacticSolving.html @@ -29,22 +29,22 @@

Theory TacticSolving

lemma size_pos[simp]: "0 < size y" apply (induction y; auto?) - subgoal premises prems for op a b + subgoal premises prems for op a b using prems by (induction op; auto) done -phase TacticSolving +phase TacticSolving terminating size begin -subsection AddNode -(*lemma val_add_left_negate_to_sub: +subsection ‹AddNode› +(*lemma val_add_left_negate_to_sub: "val[-x + y] ≈ val[y - x]" apply simp by (cases x; cases y; auto) lemma exp_add_left_negate_to_sub: "exp[-x + y] ≥ exp[y - x]" - using val_add_left_negate_to_sub by auto*) + using val_add_left_negate_to_sub by auto*) lemma value_approx_implies_refinement: assumes "lhs rhs" @@ -68,38 +68,38 @@

Theory TacticSolving

method solve for lhs rhs x y :: Value = (match conclusion in "size _ < size _" simp)?, - (match conclusion in "(elhs::IRExpr) (erhs::IRExpr)" for elhs erhs + (match conclusion in "(elhs::IRExpr) (erhs::IRExpr)" for elhs erhs (obtain_approx_eq lhs rhs x y)?) print_methods -(* +(* (simp del: well_formed_equal_def le_expr_def)?; - ((rule allI)+)?›)*) + ((rule allI)+)?›)*) thm BinaryExprE optimization opt_add_left_negate_to_sub: "-x + y y - x" - (*defer apply simp apply (rule allI)+ apply (rule impI) + (*defer apply simp apply (rule allI)+ apply (rule impI) apply (subgoal_tac "∀x1. [m, p] ⊢ exp[-x + y] ↦ x1") defer - *) + *) apply (solve "val[-x1 + y1]" "val[y1 - x1]" x1 y1) apply simp apply auto using evaltree_not_undef sorry -(* +(* apply (obtain_eval "exp[-x + y]" "val[-x1 + y1]") apply (rule BinaryExprE) apply (rule allI)+ sorry - apply (auto simp: unfold_evaltree) sorry*) - (* + apply (auto simp: unfold_evaltree) sorry*) + (* defer apply (test "val[-x1 + y1]" "val[y1 - x1]" x1 y1) apply (rule meta_mp[where P="val[-x1 + y1] ≈ val[y1 - x1]"]) prefer 2 apply (cases x1; cases y1; auto) apply (subgoal_tac "val[-x1 + y1] ≈ val[y1 - x1]") apply (cases x1; cases y1; auto) using exp_add_left_negate_to_sub apply simp - unfolding size.simps by simp*) + unfolding size.simps by simp*) -subsection NegateNode +subsection ‹NegateNode› lemma val_distribute_sub: "val[-(x-y)] val[y-x]" @@ -149,7 +149,7 @@

Theory TacticSolving

"exp[x & y] exp[y & x]" by auto -text --- --- New Optimisations - submitted and added into Graal --- +text ‹--- --- New Optimisations - submitted and added into Graal ---› lemma OrInverseVal: assumes "n = IntVal 32 v" shows "val[n | ~n] new_int 32 (-1)" @@ -159,7 +159,7 @@

Theory TacticSolving

optimization OrInverse: "exp[n | ~n] (const (new_int 32 (not 0))) when (stamp_expr n = IntegerStamp 32 l h wf_stamp n)" apply (auto simp: Suc_lessI) - subgoal premises p for m p xa xaa + subgoal premises p for m p xa xaa proof - obtain nv where nv: "[m,p] n nv" using p(3) by auto @@ -197,7 +197,7 @@

Theory TacticSolving

optimization XorInverse: "exp[n ~n] (const (new_int 32 (not 0))) when (stamp_expr n = IntegerStamp 32 l h wf_stamp n)" apply (auto simp: Suc_lessI) - subgoal premises p for m p xa xaa + subgoal premises p for m p xa xaa proof- obtain xv where xv: "[m,p] n xv" using p(3) by auto @@ -257,7 +257,7 @@

Theory TacticSolving

assumes "wf_stamp y" shows "exp[(~x) (~y)] exp[x y]" apply auto - subgoal premises p for m p xa xb + subgoal premises p for m p xa xb proof - obtain xa where xa: "[m,p] x xa" using p by blast @@ -277,14 +277,14 @@

Theory TacticSolving

end -text --- New optimisations - submitted, not added into Graal yet --- +text ‹--- New optimisations - submitted, not added into Graal yet ---› context stamp_mask begin -(* Extension to old Or optimisation +(* Extension to old Or optimisation x | y ↦ -1 when (downMask x | downMask y == -1) -*) +*) lemma ExpIntBecomesIntValArbitrary: assumes "stamp_expr x = IntegerStamp b xl xh" @@ -304,7 +304,7 @@

Theory TacticSolving

assumes "(or (x) (y)) = not 0" shows "exp[x | y] exp[(const (new_int b (not 0)))]" using assms apply auto - subgoal premises p for m p xvv yvv + subgoal premises p for m p xvv yvv proof - obtain xv where xv: "[m, p] x IntVal b xv" by (metis p(1,3,9) valid_int wf_stamp_def) @@ -328,13 +328,13 @@

Theory TacticSolving

done end -phase TacticSolving +phase TacticSolving terminating size begin -(* Add +(* Add x + ~x ↦ -1 -*) +*) lemma constEvalIsConst: assumes "wf_value n" @@ -355,7 +355,7 @@

Theory TacticSolving

assumes "wf_stamp n" shows "exp[n + (~n)] exp[(const (new_int b (not 0)))]" apply auto - subgoal premises p for m p x xa + subgoal premises p for m p x xa proof - have xaDef: "[m,p] n xa" by (simp add: p) @@ -386,9 +386,9 @@

Theory TacticSolving

when (stamp_expr n = IntegerStamp b l h wf_stamp n)"
apply (simp add: Suc_lessI) using AddNot ExpAddCommute by simp -(* +(* ~e == e ↦ false - *) + *) lemma TakeBitNotSelf: "(take_bit 32 (not e) = e) = False" @@ -413,7 +413,7 @@

Theory TacticSolving

shows "exp[BinaryExpr BinIntegerEquals (¬x) x] exp[(const (bool_to_val False))]" using assms apply auto - subgoal premises p for m p xa xaa + subgoal premises p for m p xa xaa proof - obtain xa where xa: "[m,p] x xa" using p(5) by auto @@ -441,13 +441,13 @@

Theory TacticSolving

when (stamp_expr x = IntegerStamp 32 xl xh wf_stamp x)" apply (simp add: Suc_lessI) using ExpNeverNotSelf by force -text --- New optimisations - not submitted / added into Graal yet --- -(* +text ‹--- New optimisations - not submitted / added into Graal yet ---› +(* (x ^ y) == x ↦ y == 0 x == (x ^ y) ↦ y == 0 (x ^ y) == y ↦ x == 0 y == (x ^ y) ↦ x == 0 - *) + *) lemma BinXorFallThrough: shows "bin[(x y) = x] bin[y = 0]" by (metis xor.assoc xor.left_neutral xor_self_eq) @@ -499,7 +499,7 @@

Theory TacticSolving

shows "exp[BinaryExpr BinIntegerEquals (x y) x] exp[BinaryExpr BinIntegerEquals y (const (new_int b 0))]" using assms apply auto - subgoal premises p for m p xa xaa ya + subgoal premises p for m p xa xaa ya proof - obtain b xv where xa: "[m,p] x new_int b xv" using intval_equals.elims @@ -556,13 +556,13 @@

Theory TacticSolving

context stamp_mask begin -(* Ian's optimisation, and it's Or equivalent +(* Ian's optimisation, and it's Or equivalent x & y ↦ x when x.up ∈ y.Down x | y ↦ y when x.up ∈ y.Down x.up ∈ y.Down means (x.up & y.Down = x.up), equiv to (x.up | y.Down = y.Down) -*) +*) lemma inEquivalence: assumes "[m, p] y IntVal b yv" @@ -576,13 +576,13 @@

Theory TacticSolving

shows "(and (x) (y)) = (x) (or (x) (y)) = (y)" by (metis word_ao_absorbs(3) word_ao_absorbs(4)) -(* x | y ↦ y when x.up ∈ y.Down *) +(* x | y ↦ y when x.up ∈ y.Down *) lemma RemoveLHSOrMask: assumes "(and (x) (y)) = (x)" assumes "(or (x) (y)) = (y)" shows "exp[x | y] exp[y]" using assms apply auto - subgoal premises p for m p v + subgoal premises p for m p v proof - obtain b ev where exp: "[m, p] exp[x | y] IntVal b ev" by (metis BinaryExpr bin_eval.simps(7) p(3,4,5) bin_eval_new_int new_int.simps) @@ -601,13 +601,13 @@

Theory TacticSolving

qed done -(* x & y ↦ x when x.up ∈ y.Down *) +(* x & y ↦ x when x.up ∈ y.Down *) lemma RemoveRHSAndMask: assumes "(and (x) (y)) = (x)" assumes "(or (x) (y)) = (y)" shows "exp[x & y] exp[x]" using assms apply auto - subgoal premises p for m p v + subgoal premises p for m p v proof - obtain b ev where exp: "[m, p] exp[x & y] IntVal b ev" by (metis BinaryExpr bin_eval.simps(6) p(3,4,5) new_int.simps bin_eval_new_int) @@ -625,9 +625,9 @@

Theory TacticSolving

qed done -(* Ian's new And optimisation +(* Ian's new And optimisation x & y ↦ 0 when x.up & y.up = 0 -*) +*) lemma ReturnZeroAndMask: assumes "stamp_expr x = IntegerStamp b xl xh" assumes "stamp_expr y = IntegerStamp b yl yh" @@ -638,7 +638,7 @@

Theory TacticSolving

assumes "(and (x) (y)) = 0" shows "exp[x & y] exp[const (new_int b 0)]" using assms apply auto - subgoal premises p for m p v + subgoal premises p for m p v proof - obtain yv where yv: "[m, p] y IntVal b yv" by (metis valid_int wf_stamp_def assms(2,5) p(2,4,10) wf_stamp_def) @@ -661,17 +661,17 @@

Theory TacticSolving

end -phase TacticSolving +phase TacticSolving terminating size begin -(* +(* (x ^ y) == (x ^ z) ↦ y == z (x ^ y) == (z ^ x) ↦ y == z (y ^ x) == (x ^ z) ↦ y == z (y ^ x) == (z ^ x) ↦ y == z - *) + *) lemma binXorIsEqual: "bin[((x y) = (x z))] bin[(y = z)]" @@ -751,7 +751,7 @@

Theory TacticSolving

assumes "val[x z] UndefVal" shows "val[intval_equals (x y) (x z)] = val[intval_equals y z]" using assms apply (cases x; cases y; cases z; auto) - subgoal premises p for yv zv apply (cases "(yv = zv)"; simp) + subgoal premises p for yv zv apply (cases "(yv = zv)"; simp) subgoal premises p proof - have isFalse: "bool_to_val (yv = zv) = bool_to_val False" @@ -801,7 +801,7 @@

Theory TacticSolving

shows "exp[BinaryExpr BinIntegerEquals (x y) (x z)] exp[BinaryExpr BinIntegerEquals y z]" using assms apply auto - subgoal premises p for m p x1 y1 x2 z1 + subgoal premises p for m p x1 y1 x2 z1 proof - obtain xVal where xVal: "[m,p] x xVal" using p(8) by simp @@ -819,7 +819,7 @@

Theory TacticSolving

qed done -(* 64 bit versions *) +(* 64 bit versions *) optimization XorIsEqual_64_1: "exp[BinaryExpr BinIntegerEquals (x y) (x z)] exp[BinaryExpr BinIntegerEquals y z] when (stamp_expr x = IntegerStamp 64 xl xh wf_stamp x) @@ -848,10 +848,10 @@

Theory TacticSolving

(stamp_expr z = IntegerStamp 64 zl zh wf_stamp z)"
by (meson dual_order.trans mono_binary exp_xor_commutative expXorIsEqual_64) -(* +(* XorEqZero (x ^ y) == 0 ↦ (x == y) - *) + *) lemma unwrap_bool_to_val: shows "(bool_to_val a = bool_to_val b) = (a = b)" @@ -881,7 +881,7 @@

Theory TacticSolving

shows "exp[BinaryExpr BinIntegerEquals (x y) (const (IntVal 64 0))] exp[BinaryExpr BinIntegerEquals (x) (y)]" using assms apply auto - subgoal premises p for m p x1 y1 + subgoal premises p for m p x1 y1 proof - obtain xv where xv: "[m,p] x xv" using p by blast @@ -905,10 +905,10 @@

Theory TacticSolving

(stamp_expr y = IntegerStamp 64 yl yh wf_stamp y)" using expXorEqZero_64 by fast -(* +(* XorEqNeg1 (x ^ y) == -1 ↦ (x == ¬y) - *) + *) lemma xorNeg1IsEq: "bin[(xor xv yv) = (not 0)] = bin[xv = not yv]" @@ -930,7 +930,7 @@

Theory TacticSolving

shows "exp[BinaryExpr BinIntegerEquals (x y) (const (IntVal 64 (not 0)))] exp[BinaryExpr BinIntegerEquals (x) (¬y)]" using assms apply auto - subgoal premises p for m p x1 y1 + subgoal premises p for m p x1 y1 proof - obtain xv where xv: "[m,p] x xv" using p by blast @@ -960,7 +960,7 @@

Theory TacticSolving

exp[BinaryExpr BinIntegerEquals (x) (¬y)] when (stamp_expr x = IntegerStamp 64 xl xh wf_stamp x) (stamp_expr y = IntegerStamp 64 yl yh wf_stamp y)" - using expXorEqNeg1_64 apply auto (* termination proof *) sorry + using expXorEqNeg1_64 apply auto (* termination proof *) sorry end diff --git a/Canonicalizations/XorPhase.html b/Canonicalizations/XorPhase.html index d8d490a8..b45918a4 100644 --- a/Canonicalizations/XorPhase.html +++ b/Canonicalizations/XorPhase.html @@ -12,7 +12,7 @@

Theory XorPhase

-
subsection XorNode Phase
+
subsection ‹XorNode Phase›
 
 theory XorPhase
   imports
@@ -20,11 +20,11 @@ 

Theory XorPhase

Proofs.StampEvalThms begin -phase XorNode +phase XorNode terminating size begin -(* Word level proofs *) +(* Word level proofs *) lemma bin_xor_self_is_false: "bin[x x] = 0" by simp @@ -37,7 +37,7 @@

Theory XorPhase

"bin[x 0] = bin[x]" by simp -(* Value level proofs *) +(* Value level proofs *) lemma val_xor_self_is_false: assumes "val[x x] UndefVal" shows "val_to_bool (val[x x]) = False" @@ -49,7 +49,7 @@

Theory XorPhase

shows "val[x x] = bool_to_val False" by (auto simp: assms) -(* Not sure if I need this; Optimization uses ConstantExpr False which is IntVal32 0 *) +(* Not sure if I need this; Optimization uses ConstantExpr False which is IntVal32 0 *) lemma val_xor_self_is_false_3: assumes "val[x x] UndefVal x = IntVal 64 v" shows "val[x x] = IntVal 64 0" @@ -65,12 +65,12 @@

Theory XorPhase

shows "val[x (bool_to_val False)] = x" using assms by (auto; meson) -(* Exp level proofs *) +(* Exp level proofs *) lemma exp_xor_self_is_false: assumes "wf_stamp x stamp_expr x = default_stamp" shows "exp[x x] exp[false]" using assms apply auto - subgoal premises p for m p xa ya + subgoal premises p for m p xa ya proof- obtain xv where xv: "[m,p] x xv" using p(3) by auto @@ -94,7 +94,7 @@

Theory XorPhase

lemma exp_eliminate_redundant_false: shows "exp[x false] exp[x]" using val_eliminate_redundant_false apply auto - subgoal premises p for m p xa + subgoal premises p for m p xa proof - obtain xa where xa: "[m, p] x xa" using p(2) by blast @@ -107,7 +107,7 @@

Theory XorPhase

qed done -text Optimisations +text ‹Optimisations› optimization XorSelfIsFalse: "(x x) false when (wf_stamp x stamp_expr x = default_stamp)" @@ -119,20 +119,20 @@

Theory XorPhase

optimization EliminateRedundantFalse: "(x false) x" using exp_eliminate_redundant_false by auto -(* BW: this doesn't seem right *) -(* Doesn't have any subgoals *) -(* +(* BW: this doesn't seem right *) +(* Doesn't have any subgoals *) +(* optimization MaskOutRHS: "(x ⊕ y) ⟼ ~x when (is_ConstantExpr y ∧ (stamp_expr (BinaryExpr BinXor x y) = IntegerStamp stampBits l h) ∧ (BinaryExpr BinAnd y (ConstantExpr (new_int stampBits (not 0))) = ConstantExpr (new_int stampBits (not 0))))" sorry -*) +*) -end (* End of XorPhase *) +end (* End of XorPhase *) -end (* End of file *) +end (* End of file *)
diff --git a/Canonicalizations/document.pdf b/Canonicalizations/document.pdf index e6472853..80c5f91e 100644 Binary files a/Canonicalizations/document.pdf and b/Canonicalizations/document.pdf differ diff --git a/Canonicalizations/index.html b/Canonicalizations/index.html index bc789e46..92d879a0 100644 --- a/Canonicalizations/index.html +++ b/Canonicalizations/index.html @@ -3,7 +3,7 @@ -Session Canonicalizations (Isabelle2022) +Session Canonicalizations (Isabelle2023) diff --git a/Canonicalizations/session_graph.pdf b/Canonicalizations/session_graph.pdf index 810c8a5c..4db8bbef 100644 Binary files a/Canonicalizations/session_graph.pdf and b/Canonicalizations/session_graph.pdf differ diff --git a/ConditionalElimination/.browser_info/build_uuid b/ConditionalElimination/.browser_info/build_uuid index 319f466b..c84274f9 100644 --- a/ConditionalElimination/.browser_info/build_uuid +++ b/ConditionalElimination/.browser_info/build_uuid @@ -1 +1 @@ -8417bd2f-3930-4566-ada4-a0910a7d5117 \ No newline at end of file +9410185a-1397-4e37-823e-e573c61b1bda \ No newline at end of file diff --git a/ConditionalElimination/CFG.html b/ConditionalElimination/CFG.html new file mode 100644 index 00000000..b9e9ac8a --- /dev/null +++ b/ConditionalElimination/CFG.html @@ -0,0 +1,472 @@ + + + + + +Theory CFG + + + + +
+

Theory CFG

+
+ +
theory CFG
+  imports Graph.IRGraph
+begin
+
+(*
+ * CFG based on the org.graalvm.compiler.nodes.cfg.ControlFlowGraph
+ * Page 2 on //notes/CFGNotes.pdf contains notes on the construction
+ *)
+
+datatype Block =
+  BasicBlock (start_node: ID) (end_node: ID) |
+  NoBlock
+
+(* TODO: prove termination *)
+function findEnd :: "IRGraph  ID  ID list  ID" where
+  "findEnd g nid [next] = findEnd g next (successors_of (kind g next))" |
+  "findEnd g nid succs = nid"
+  sorry termination sorry
+
+(* TODO: prove termination *)
+function findStart :: "IRGraph  ID  ID list  ID" where
+  "findStart g nid [pred] =
+    (if is_AbstractBeginNode (kind g nid) then
+      nid
+    else
+      (findStart g pred (sorted_list_of_set (predecessors g nid))))" |
+  "findStart g nid preds = nid"
+  sorry termination sorry
+
+fun blockOf :: "IRGraph  ID  Block" where
+  "blockOf g nid = (
+    let end = (findEnd g nid (sorted_list_of_set (succ g nid))) in
+    let start = (findStart g nid (sorted_list_of_set (predecessors g nid))) in
+    if (start = end  start = nid) then NoBlock else
+    BasicBlock start end
+  )"
+
+fun succ_from_end :: "IRGraph  ID  IRNode  Block set" where
+  "succ_from_end g e EndNode = {blockOf g (any_usage g e)}" |
+  "succ_from_end g e (IfNode c tb fb) = {blockOf g tb, blockOf g fb}" |
+  "succ_from_end g e (LoopEndNode begin) = {blockOf g begin}" |
+  "succ_from_end g e _ = (if (is_AbstractEndNode (kind g e))
+    then (set (map (blockOf g) (successors_of (kind g e))))
+    else {})"
+
+fun succ :: "IRGraph  Block  Block set" where
+  "succ g (BasicBlock start end) = succ_from_end g end (kind g end)" |
+  "succ g _ = {}"
+
+fun register_by_pred :: "IRGraph  ID  Block option" where
+  "register_by_pred g nid = (
+    case kind g (end_node (blockOf g nid)) of
+    (IfNode c tb fb)  Some (blockOf g nid) |
+    k  (if (is_AbstractEndNode k) then Some (blockOf g nid) else None)
+  )"
+
+fun pred_from_start :: "IRGraph  ID  IRNode  Block set" where
+  "pred_from_start g s (MergeNode ends _ _) = set (map (blockOf g) ends)" |
+  "pred_from_start g s (LoopBeginNode ends _ _ _) = set (map (blockOf g) ends)" |
+  "pred_from_start g s (LoopEndNode begin) = {blockOf g begin}" |
+  "pred_from_start g s _ = set (List.map_filter (register_by_pred g) (sorted_list_of_set (predecessors g s)))"
+
+fun pred :: "IRGraph  Block  Block set" where
+  "pred g (BasicBlock start end) = pred_from_start g start (kind g start)" |
+  "pred g _ = {}"
+
+inductive dominates :: "IRGraph  Block  Block  bool" ("_  _ ≥≥ _" 20) where
+  "(d = n)  ((pred g n  {})  (p  pred g n . (g  d ≥≥ p)))  dominates g d n"
+code_pred [show_modes] dominates .
+
+inductive postdominates :: "IRGraph  Block  Block  bool" ("_  _ ≤≤ _" 20) where
+  "(z = n)  ((succ g n  {})  (s  succ g n . (g  z ≤≤ s)))  postdominates g z n"
+code_pred [show_modes] postdominates .
+
+inductive strictly_dominates :: "IRGraph  Block  Block  bool" ("_  _ >> _" 20) where
+  "(g  d ≥≥ n); (d  n)  strictly_dominates g d n"
+code_pred [show_modes] strictly_dominates .
+
+inductive strictly_postdominates :: "IRGraph  Block  Block  bool" ("_  _ << _" 20) where
+  "(g  d ≤≤ n); (d  n)  strictly_postdominates g d n"
+code_pred [show_modes] strictly_postdominates .
+
+lemma "pred g nid = {}  ¬( d . (d  nid)  (g  d ≥≥ nid))"
+  using dominates.cases by blast
+
+lemma "succ g nid = {}  ¬( d . (d  nid)  (g  d ≤≤ nid))"
+  using postdominates.cases by blast
+
+lemma "pred g nid = {}  ¬( d . (g  d >> nid))"
+  using dominates.simps strictly_dominates.simps by presburger
+
+lemma "succ g nid = {}  ¬( d . (g  d << nid))"
+  using postdominates.simps strictly_postdominates.simps by presburger
+
+inductive wf_cfg :: "IRGraph  bool" where
+  " nid  ids g . (blockOf g nid  NoBlock)  (g  (blockOf g 0) ≥≥ (blockOf g nid))
+   wf_cfg g"
+code_pred [show_modes] wf_cfg .
+
+inductive immediately_dominates :: "IRGraph  Block  Block  bool" ("_  _ idom _" 20) where
+  "(g  d >> n); ( w  ids g . (g  (blockOf g w) >> n)  (g  (blockOf g w) ≥≥ d))  immediately_dominates g d n"
+code_pred [show_modes] immediately_dominates .
+
+definition simple_if :: IRGraph where
+  "simple_if = irgraph [
+    (0, StartNode None 2, VoidStamp),
+    (1, ParameterNode 0, default_stamp),
+    (2, IfNode 1 3 4, VoidStamp),
+    (3, BeginNode 5, VoidStamp),
+    (4, BeginNode 6, VoidStamp),
+    (5, EndNode, VoidStamp),
+    (6, EndNode, VoidStamp),
+    (7, ParameterNode 1, default_stamp),
+    (8, ParameterNode 2, default_stamp),
+    (9, AddNode 7 8, default_stamp),
+    (10, MergeNode [5,6] None 12, VoidStamp),
+    (11, ValuePhiNode 11 [9,7] 10, default_stamp),
+    (12, ReturnNode (Some 11) None, default_stamp)
+  ]"
+
+(*
+        Block 1:
+        0 StartNode
+        2 IfNode
+
+  Block 2:        Block 3:
+  3 BeginNode     4 BeginNode
+  5 EndNode       6 EndNode
+
+        Block 4:
+        10 MergeNode
+        12 ReturnNode
+*)
+
+value "wf_cfg simple_if"
+
+(**** Dominator ****)
+(* All true, Block 1 dominates everything *)
+value "simple_if  blockOf simple_if 0 ≥≥ blockOf simple_if 0"
+value "simple_if  blockOf simple_if 0 ≥≥ blockOf simple_if 3"
+value "simple_if  blockOf simple_if 0 ≥≥ blockOf simple_if 4"
+value "simple_if  blockOf simple_if 0 ≥≥ blockOf simple_if 12"
+
+(* Block 2 only dominates itself *)
+value "simple_if  blockOf simple_if 3 ≥≥ blockOf simple_if 0"
+value "simple_if  blockOf simple_if 3 ≥≥ blockOf simple_if 3"
+value "simple_if  blockOf simple_if 3 ≥≥ blockOf simple_if 4"
+value "simple_if  blockOf simple_if 3 ≥≥ blockOf simple_if 12"
+
+(* Block 3 only dominates itself *)
+value "simple_if  blockOf simple_if 4 ≥≥ blockOf simple_if 0"
+value "simple_if  blockOf simple_if 4 ≥≥ blockOf simple_if 3"
+value "simple_if  blockOf simple_if 4 ≥≥ blockOf simple_if 4"
+value "simple_if  blockOf simple_if 4 ≥≥ blockOf simple_if 12"
+
+(* Block 4 only dominates itself *)
+value "simple_if  blockOf simple_if 12 ≥≥ blockOf simple_if 0"
+value "simple_if  blockOf simple_if 12 ≥≥ blockOf simple_if 3"
+value "simple_if  blockOf simple_if 12 ≥≥ blockOf simple_if 4"
+value "simple_if  blockOf simple_if 12 ≥≥ blockOf simple_if 12"
+
+(**** Postdominates ****)
+(* Block 1 only postdominates itself *)
+value "simple_if  blockOf simple_if 0 ≤≤ blockOf simple_if 0"
+value "simple_if  blockOf simple_if 0 ≤≤ blockOf simple_if 3"
+value "simple_if  blockOf simple_if 0 ≤≤ blockOf simple_if 4"
+value "simple_if  blockOf simple_if 0 ≤≤ blockOf simple_if 12"
+
+(* Block 2 only postdominates itself *)
+value "simple_if  blockOf simple_if 3 ≤≤ blockOf simple_if 0"
+value "simple_if  blockOf simple_if 3 ≤≤ blockOf simple_if 3"
+value "simple_if  blockOf simple_if 3 ≤≤ blockOf simple_if 4"
+value "simple_if  blockOf simple_if 3 ≤≤ blockOf simple_if 12"
+
+(* Block 3 only postdominates itself *)
+value "simple_if  blockOf simple_if 4 ≤≤ blockOf simple_if 0"
+value "simple_if  blockOf simple_if 4 ≤≤ blockOf simple_if 3"
+value "simple_if  blockOf simple_if 4 ≤≤ blockOf simple_if 4"
+value "simple_if  blockOf simple_if 4 ≤≤ blockOf simple_if 12"
+
+(* Block 4 postdominates every other block *)
+value "simple_if  blockOf simple_if 12 ≤≤ blockOf simple_if 0"
+value "simple_if  blockOf simple_if 12 ≤≤ blockOf simple_if 3"
+value "simple_if  blockOf simple_if 12 ≤≤ blockOf simple_if 4"
+value "simple_if  blockOf simple_if 12 ≤≤ blockOf simple_if 12"
+
+value "blockOf simple_if 0" (* Block 1 *)
+value "blockOf simple_if 1" (* No Block *)
+value "blockOf simple_if 2" (* Block 1 *)
+value "blockOf simple_if 3" (* Block 2 *)
+value "blockOf simple_if 4" (* Block 3 *)
+value "blockOf simple_if 5" (* Block 2 *)
+value "blockOf simple_if 6" (* Block 3 *)
+value "blockOf simple_if 7" (* No Block *)
+value "blockOf simple_if 8" (* No Block *)
+value "blockOf simple_if 9" (* No Block *)
+value "blockOf simple_if 10" (* Block 4 *)
+value "blockOf simple_if 11" (* No Block *)
+value "blockOf simple_if 12" (* Block 4 *)
+
+(* Block 1 *)
+value "pred simple_if (blockOf simple_if 0)" (* {} *)
+value "succ simple_if (blockOf simple_if 0)" (* {Block 2, Block 3} *)
+(* Block 2 *)
+value "pred simple_if (blockOf simple_if 3)" (* {Block 1} *)
+value "succ simple_if (blockOf simple_if 3)" (* {Block 4} *)
+(* Block 3 *)
+value "pred simple_if (blockOf simple_if 4)" (* {Block 1} *)
+value "succ simple_if (blockOf simple_if 4)" (* {Block 4} *)
+(* Block 4 *)
+value "pred simple_if (blockOf simple_if 10)" (* {Block 2, Block 3} *)
+value "succ simple_if (blockOf simple_if 10)" (* {} *)
+
+(*
+definition loop :: IRGraph where
+  "loop =
+    (add_node 13 (ReturnNode (Some 7) None)
+    (add_node 12 (LoopEndNode 3)
+    (add_node 11 (BeginNode 12)
+    (add_node 10 (IfNode 9 11 13)
+    (add_node 9 (IntegerLessThanNode 7 6)
+    (add_node 8 (AddNode 7 5)
+    (add_node 7 (ValuePhiNode [4,8] 3)
+    (add_node 6 (ParameterNode 0)
+    (add_node 5 (ConstantNode 1)
+    (add_node 4 (ConstantNode 0)
+    (add_node 3 (LoopBeginNode [2,12] None None 10)
+    (add_node 2 (EndNode)
+    (add_node 1 (BeginNode 2)
+    (add_node 0 (StartNode None 1)
+    empty_graph))))))))))))))"
+
+(*
+            Block 1:
+            1 BeginNode
+            2 EndNode
+
+            Block 2:
+            3 LoopBeginNode
+            10 IfNode
+
+    Block 3:              Block 4:
+    11 BeginNode          13 ReturnNode
+    12 LoopEndNode
+*)
+
+value "blockOf loop 1" (* Block 1 *)
+value "blockOf loop 2" (* Block 1 *)
+value "blockOf loop 3" (* Block 2 *)
+value "blockOf loop 10" (* Block 2 *)
+value "blockOf loop 11" (* Block 3 *)
+value "blockOf loop 12" (* Block 3 *)
+value "blockOf loop 13" (* Block 4 *)
+
+(* Block 1 *)
+value "pred loop (blockOf loop 1)" (* {} *)
+value "succ loop (blockOf loop 1)" (* {Block 2} *)
+(* Block 2 *)
+value "pred loop (blockOf loop 3)" (* {Block 1, Block 3} *)
+value "succ loop (blockOf loop 3)" (* {Block 3, Block 4} *)
+(* Block 3 *)
+value "pred loop (blockOf loop 11)" (* {Block 2} *)
+value "succ loop (blockOf loop 11)" (* {Block 2} *)
+(* Block 4 *)
+value "pred loop (blockOf loop 13)" (* {Block 2} *)
+value "succ loop (blockOf loop 13)" (* {} *)
+*)
+
+definition ConditionalEliminationTest1_test1Snippet_initial :: IRGraph where
+  "ConditionalEliminationTest1_test1Snippet_initial = irgraph [
+  (0, (StartNode  (Some 2) 7), VoidStamp),
+  (1, (ParameterNode 0), IntegerStamp 32 (-2147483648) (2147483647)),
+  (2, (FrameState []  None None None), IllegalStamp),
+  (3, (ConstantNode (IntVal 32 (0))), IntegerStamp 32 (0) (0)),
+  (4, (IntegerEqualsNode 1 3), VoidStamp),
+  (5, (BeginNode 39), VoidStamp),
+  (6, (BeginNode 12), VoidStamp),
+  (7, (IfNode 4 6 5), VoidStamp),
+  (8, (ConstantNode (IntVal 32 (5))), IntegerStamp 32 (5) (5)),
+  (9, (IntegerEqualsNode 1 8), VoidStamp),
+  (10, (BeginNode 16), VoidStamp),
+  (11, (BeginNode 14), VoidStamp),
+  (12, (IfNode 9 11 10), VoidStamp),
+  (13, (ConstantNode (IntVal 32 (100))), IntegerStamp 32 (100) (100)),
+  (14, (StoreFieldNode 14 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink2'' 13  (Some 15)  None 18), VoidStamp),
+  (15, (FrameState []  None None None), IllegalStamp),
+  (16, (EndNode), VoidStamp),
+  (17, (MergeNode  [16, 18]  (Some 19) 24), VoidStamp),
+  (18, (EndNode), VoidStamp),
+  (19, (FrameState []  None None None), IllegalStamp),
+  (20, (ConstantNode (IntVal 32 (101))), IntegerStamp 32 (101) (101)),
+  (21, (IntegerLessThanNode 1 20), VoidStamp),
+  (22, (BeginNode 30), VoidStamp),
+  (23, (BeginNode 25), VoidStamp),
+  (24, (IfNode 21 23 22), VoidStamp),
+  (25, (EndNode), VoidStamp),
+  (26, (MergeNode  [25, 27, 34]  (Some 35) 43), VoidStamp),
+  (27, (EndNode), VoidStamp),
+  (28, (BeginNode 32), VoidStamp),
+  (29, (BeginNode 27), VoidStamp),
+  (30, (IfNode 4 28 29), VoidStamp),
+  (31, (ConstantNode (IntVal 32 (200))), IntegerStamp 32 (200) (200)),
+  (32, (StoreFieldNode 32 ''org.graalvm.compiler.core.test.ConditionalEliminationTest1::sink3'' 31  (Some 33)  None 34), VoidStamp),
+  (33, (FrameState []  None None None), IllegalStamp),
+  (34, (EndNode), VoidStamp),
+  (35, (FrameState []  None None None), IllegalStamp),
+  (36, (ConstantNode (IntVal 32 (2))), IntegerStamp 32 (2) (2)),
+  (37, (IntegerEqualsNode 1 36), VoidStamp),
+  (38, (BeginNode 45), VoidStamp),
+  (39, (EndNode), VoidStamp),
+  (40, (MergeNode  [39, 41, 47]  (Some 48) 49), VoidStamp),
+  (41, (EndNode), VoidStamp),
+  (42, (BeginNode 41), VoidStamp),
+  (43, (IfNode 37 42 38), VoidStamp),
+  (44, (ConstantNode (IntVal 32 (1))), IntegerStamp 32 (1) (1)),
+  (45, (StoreFieldNode 45 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink1'' 44  (Some 46)  None 47), VoidStamp),
+  (46, (FrameState []  None None None), IllegalStamp),
+  (47, (EndNode), VoidStamp),
+  (48, (FrameState []  None None None), IllegalStamp),
+  (49, (StoreFieldNode 49 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink0'' 3  (Some 50)  None 51), VoidStamp),
+  (50, (FrameState []  None None None), IllegalStamp),
+  (51, (ReturnNode  None  None), VoidStamp)
+  ]"
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 0" (* Block 0 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 7" (* Block 0 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 6" (* Block 1 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 12" (* Block 1 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 11" (* Block 2 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 14" (* Block 2 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 18" (* Block 2 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 10" (* Block 3 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 16" (* Block 3 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 17" (* Block 4 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 24" (* Block 4 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 23" (* Block 5 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 25" (* Block 5 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 22" (* Block 6*)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 30" (* Block 6 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 28" (* Block 7 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 32" (* Block 7 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 34" (* Block 7 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 29" (* Block 8 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 27" (* Block 8 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 26" (* Block 9 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 43" (* Block 9 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 42" (* Block 10 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 41" (* Block 10 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 38" (* Block 11 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 45" (* Block 11 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 47" (* Block 11 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 5" (* Block 12 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 39" (* Block 12 *)
+
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 40" (* Block 13 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 49" (* Block 13 *)
+value "blockOf ConditionalEliminationTest1_test1Snippet_initial 51" (* Block 13 *)
+
+(* Block 0 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 0)" (* {} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 0)" (* {Block 1, Block 12} *)
+
+(* Block 1 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 6)" (* {Block 1} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 6)" (* {Block 2, Block 3} *)
+
+(* Block 2 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 14)" (* {Block 1} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 14)" (* {Block 4} *)
+
+(* Block 3 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 10)" (* {Block 1} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 10)" (* {Block 4} *)
+
+(* Block 4 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 24)" (* {Block 2, Block 3} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 24)" (* {Block 5, Block 6} *)
+
+(* Block 5 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 23)" (* {Block 4} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 23)" (* {Block 9} *)
+
+(* Block 6 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 22)" (* {Block 4} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 22)" (* {Block 7, Block 8} *)
+
+(* Block 7 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 32)" (* {Block 6} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 32)" (* {Block 9} *)
+
+(* Block 8 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 29)" (* {Block 6} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 29)" (* {Block 9} *)
+
+(* Block 9 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 43)" (* {Block 5, Block 7, Block 8} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 43)" (* {Block 10, Block 11} *)
+
+(* Block 10 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 42)" (* {Block 9} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 42)" (* {Block 13} *)
+
+(* Block 11 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 45)" (* {Block 9} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 45)" (* {Block 13} *)
+
+(* Block 12 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 5)" (* {Block 0} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 5)" (* {Block 13} *)
+
+(* Block 13 *)
+value "pred ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 49)" (* {Block 10, Block 11, Block 12} *)
+value "succ ConditionalEliminationTest1_test1Snippet_initial
+  (blockOf ConditionalEliminationTest1_test1Snippet_initial 49)" (* {} *)
+
+end
+ + + \ No newline at end of file diff --git a/ConditionalElimination/ConditionalElimination.html b/ConditionalElimination/ConditionalElimination.html index 0e6c673c..f2f24828 100644 --- a/ConditionalElimination/ConditionalElimination.html +++ b/ConditionalElimination/ConditionalElimination.html @@ -12,46 +12,86 @@

Theory ConditionalElimination

-
section Conditional Elimination Phase
+
section ‹Conditional Elimination Phase›
+
+text ‹
+This theory presents the specification of the \texttt{ConditionalElimination} phase
+within the GraalVM compiler.
+The \texttt{ConditionalElimination} phase simplifies any condition of an \textsl{if}
+statement that can be implied by the conditions that dominate it.
+Such that if condition A implies that condition B \textsl{must} be true,
+the condition B is simplified to \texttt{true}.
+
+\begin{lstlisting}[language=java]
+if (A) {
+  if (B) {
+    ...
+  }
+}
+\end{lstlisting}
+
+We begin by defining the individual implication rules used by the phase
+in \ref{sec:rules}.
+These rules are then lifted to the rewriting of a condition within an \textsl{if}
+statement in \ref{sec:lift}.
+The traversal algorithm used by the compiler is specified in \ref{sec:traversal}.
+›
 
 theory ConditionalElimination
   imports
     Semantics.IRTreeEvalThms
     Proofs.Rewrites
     Proofs.Bisimulation
+    OptimizationDSL.Markup
 begin
 
-subsection Individual Elimination Rules
-
-text The set of rules used for determining whether a condition @{term q1} implies
-    another condition @{term q2} or its negation.
-    These rules are used for conditional elimination.
-
-inductive impliesx :: "IRExpr  IRExpr  bool" ("_  _") and 
-      impliesnot :: "IRExpr  IRExpr  bool" ("_ ⇛¬ _") where
-  q_imp_q: 
-  "q  q" |
-  eq_impliesnot_less:
-  "(BinaryExpr BinIntegerEquals x y) ⇛¬ (BinaryExpr BinIntegerLessThan x y)" |
-  eq_impliesnot_less_rev:
-  "(BinaryExpr BinIntegerEquals x y) ⇛¬ (BinaryExpr BinIntegerLessThan y x)" |
-  less_impliesnot_rev_less:
-  "(BinaryExpr BinIntegerLessThan x y) ⇛¬ (BinaryExpr BinIntegerLessThan y x)" |
-  less_impliesnot_eq:
-  "(BinaryExpr BinIntegerLessThan x y) ⇛¬ (BinaryExpr BinIntegerEquals x y)" |
-  less_impliesnot_eq_rev:
-  "(BinaryExpr BinIntegerLessThan x y) ⇛¬ (BinaryExpr BinIntegerEquals y x)" |
-  negate_true:
-  "x ⇛¬ y  x  (UnaryExpr UnaryLogicNegation y)" |
-  negate_false:
-  "x  y  x ⇛¬ (UnaryExpr UnaryLogicNegation y)"
-
-text The relation @{term "q1  q2"} indicates that the implication @{term "q1  q2"}
-    is known true (i.e. universally valid), 
-    and the relation @{term "q1 ⇛¬ q2"} indicates that the implication @{term "q1  q2"}
-    is known false (i.e. @{term "q1 ¬ q2"} is universally valid.
-    If neither @{term "q1  q2"} nor @{term "q1 ⇛¬ q2"} then the status is unknown.
-    Only the known true and known false cases can be used for conditional elimination.
+declare [[show_types=false]]
+
+subsection ‹Implication Rules \label{sec:rules}›
+
+text ‹
+The set of rules used for determining whether a condition, @{term q1},
+ implies another condition, @{term q2}, must be true or false.
+›
+
+subsubsection ‹Structural Implication›
+
+text ‹
+The first method for determining if a condition can be implied by another condition,
+is structural implication.
+That is, by looking at the structure of the conditions, we can determine the truth value.
+For instance, @{term "x == y"} implies that @{term "x < y"} cannot be true.
+›
+
+inductive 
+  impliesx :: "IRExpr  IRExpr  bool" ("_  _") and 
+  impliesnot :: "IRExpr  IRExpr  bool" ("_ ⇛¬ _") where
+  same:          "q  q" |
+  eq_not_less:   "exp[x eq y] ⇛¬ exp[x < y]" |
+  eq_not_less':  "exp[x eq y] ⇛¬ exp[y < x]" |
+  less_not_less: "exp[x < y] ⇛¬ exp[y < x]" |
+  less_not_eq:   "exp[x < y] ⇛¬ exp[x eq y]" |
+  less_not_eq':  "exp[x < y] ⇛¬ exp[y eq x]" |
+  negate_true:   "x ⇛¬ y  x  exp[!y]" |
+  negate_false:  "x  y  x ⇛¬ exp[!y]"
+
+inductive implies_complete :: "IRExpr  IRExpr  bool option  bool" where
+  implies:
+  "x  y  implies_complete x y (Some True)" |
+  impliesnot:
+  "x ⇛¬ y  implies_complete x y (Some False)" |
+  fail:
+  "¬((x  y)  (x ⇛¬ y))  implies_complete x y None"
+
+
+text ‹
+The relation @{term "q1  q2"} requires that the implication @{term "q1  q2"}
+is known true (i.e. universally valid).
+The relation @{term "q1 ⇛¬ q2"} requires that the implication @{term "q1  q2"}
+is known false (i.e. @{term "q1 ¬ q2"} is universally valid).
+If neither @{term "q1  q2"} nor @{term "q1 ⇛¬ q2"} then the status is unknown
+and the condition cannot be simplified.
+›
 
 fun implies_valid :: "IRExpr  IRExpr  bool" (infix "" 50) where
   "implies_valid q1 q2 = 
@@ -63,377 +103,163 @@ 

Theory ConditionalElimination

(m p v1 v2. ([m, p] q1 v1) ([m,p] q2 v2) (val_to_bool v1 ¬val_to_bool v2))"
-text The relation @{term "q1 q2"} means @{term "q1 q2"} is universally valid, - and the relation @{term "q1 q2"} means @{term "q1 ¬q2"} is universally valid. +text ‹ +The relation @{term "q1 q2"} means @{term "q1 q2"} is universally valid, +and the relation @{term "q1 q2"} means @{term "q1 ¬q2"} is universally valid. +› -lemma eq_impliesnot_less_helper: - "v1 = v2 ¬(int_signed_value b v1 < int_signed_value b v2)" - by force - -lemma eq_impliesnot_less_val: - "val_to_bool(intval_equals v1 v2) ¬val_to_bool(intval_less_than v1 v2)" -proof - - have unfoldEqualDefined: "(intval_equals v1 v2 UndefVal) +lemma eq_not_less_val: + "val_to_bool(val[v1 eq v2]) ¬val_to_bool(val[v1 < v2])" + proof - + have unfoldEqualDefined: "(intval_equals v1 v2 UndefVal) (val_to_bool(intval_equals v1 v2) (¬(val_to_bool(intval_less_than v1 v2))))" - subgoal premises p + subgoal premises p proof - - obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" - by (metis array_length.cases intval_equals.simps(2,3,4,5) p) - obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" - by (metis Value.exhaust_sel intval_equals.simps(6,7,8,9) p) - have sameWidth: "v1b=v2b" - by (metis bool_to_val_bin.simps intval_equals.simps(1) p v1v v2v) - have unfoldEqual: "intval_equals v1 v2 = (bool_to_val (v1v=v2v))" - by (simp add: sameWidth v1v v2v) - have unfoldLessThan: "intval_less_than v1 v2 = (bool_to_val (int_signed_value v1b v1v < int_signed_value v2b v2v))" - by (simp add: sameWidth v1v v2v) - have val: "((v1v=v2v)) (¬((int_signed_value v1b v1v < int_signed_value v2b v2v)))" - using sameWidth by auto - have doubleCast0: "val_to_bool (bool_to_val ((v1v = v2v))) = (v1v = v2v)" + obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" + by (metis array_length.cases intval_equals.simps(2,3,4,5) p) + obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" + by (metis Value.exhaust_sel intval_equals.simps(6,7,8,9) p) + have sameWidth: "v1b=v2b" + by (metis bool_to_val_bin.simps intval_equals.simps(1) p v1v v2v) + have unfoldEqual: "intval_equals v1 v2 = (bool_to_val (v1v=v2v))" + by (simp add: sameWidth v1v v2v) + have unfoldLessThan: "intval_less_than v1 v2 = (bool_to_val (int_signed_value v1b v1v < int_signed_value v2b v2v))" + by (simp add: sameWidth v1v v2v) + have val: "((v1v=v2v)) (¬((int_signed_value v1b v1v < int_signed_value v2b v2v)))" + using sameWidth by auto + have doubleCast0: "val_to_bool (bool_to_val ((v1v = v2v))) = (v1v = v2v)" using bool_to_val.elims val_to_bool.simps(1) by fastforce - have doubleCast1: "val_to_bool (bool_to_val ((int_signed_value v1b v1v < int_signed_value v2b v2v))) = + have doubleCast1: "val_to_bool (bool_to_val ((int_signed_value v1b v1v < int_signed_value v2b v2v))) = (int_signed_value v1b v1v < int_signed_value v2b v2v)" using bool_to_val.elims val_to_bool.simps(1) by fastforce then show ?thesis - using p val unfolding unfoldEqual unfoldLessThan doubleCast0 doubleCast1 by blast + using p val unfolding unfoldEqual unfoldLessThan doubleCast0 doubleCast1 by blast qed done show ?thesis - by (metis Value.distinct(1) val_to_bool.elims(2) unfoldEqualDefined) + by (metis Value.distinct(1) val_to_bool.elims(2) unfoldEqualDefined) qed -lemma eq_impliesnot_less_rev_val: - "val_to_bool(intval_equals v1 v2) ¬val_to_bool(intval_less_than v2 v1)" +lemma eq_not_less'_val: + "val_to_bool(val[v1 eq v2]) ¬val_to_bool(val[v2 < v1])" proof - - have a: "intval_equals v1 v2 = intval_equals v2 v1" + have a: "intval_equals v1 v2 = intval_equals v2 v1" apply (cases "intval_equals v1 v2 = UndefVal") apply (smt (z3) bool_to_val_bin.simps intval_equals.elims intval_equals.simps) - subgoal premises p + subgoal premises p proof - - obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" - by (metis Value.exhaust_sel intval_equals.simps(2,3,4,5) p) + obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" + by (metis Value.exhaust_sel intval_equals.simps(2,3,4,5) p) obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" - by (metis Value.exhaust_sel intval_equals.simps(6,7,8,9) p) + by (metis Value.exhaust_sel intval_equals.simps(6,7,8,9) p) then show ?thesis - by (smt (verit) bool_to_val_bin.simps intval_equals.simps(1) v1v) + by (smt (verit) bool_to_val_bin.simps intval_equals.simps(1) v1v) qed done show ?thesis - using a eq_impliesnot_less_val by presburger + using a eq_not_less_val by presburger qed -lemma less_impliesnot_rev_less_val: - "val_to_bool(intval_less_than v1 v2) ¬val_to_bool(intval_less_than v2 v1)" +lemma less_not_less_val: + "val_to_bool(val[v1 < v2]) ¬val_to_bool(val[v2 < v1])" apply (rule impI) - subgoal premises p + subgoal premises p proof - - obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" - by (metis Value.exhaust_sel intval_less_than.simps(2,3,4,5) p val_to_bool.simps(2)) - obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" - by (metis Value.exhaust_sel intval_less_than.simps(6,7,8,9) p val_to_bool.simps(2)) - then have unfoldLessThanRHS: "intval_less_than v2 v1 = + obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" + by (metis Value.exhaust_sel intval_less_than.simps(2,3,4,5) p val_to_bool.simps(2)) + obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" + by (metis Value.exhaust_sel intval_less_than.simps(6,7,8,9) p val_to_bool.simps(2)) + then have unfoldLessThanRHS: "intval_less_than v2 v1 = (bool_to_val (int_signed_value v2b v2v < int_signed_value v1b v1v))" - using p v1v by force - then have unfoldLessThanLHS: "intval_less_than v1 v2 = + using p v1v by force + then have unfoldLessThanLHS: "intval_less_than v1 v2 = (bool_to_val (int_signed_value v1b v1v < int_signed_value v2b v2v))" - using bool_to_val_bin.simps intval_less_than.simps(1) p v1v v2v val_to_bool.simps(2) by auto + using bool_to_val_bin.simps intval_less_than.simps(1) p v1v v2v val_to_bool.simps(2) by auto then have symmetry: "(int_signed_value v2b v2v < int_signed_value v1b v1v) (¬(int_signed_value v1b v1v < int_signed_value v2b v2v))" by simp then show ?thesis - using p unfoldLessThanLHS unfoldLessThanRHS by fastforce + using p unfoldLessThanLHS unfoldLessThanRHS by fastforce qed done -lemma less_impliesnot_eq_val: - "val_to_bool(intval_less_than v1 v2) ¬val_to_bool(intval_equals v1 v2)" - using eq_impliesnot_less_val by blast +lemma less_not_eq_val: + "val_to_bool(val[v1 < v2]) ¬val_to_bool(val[v1 eq v2])" + using eq_not_less_val by blast -lemma logic_negate_type: +lemma logic_negate_type: assumes "[m, p] UnaryExpr UnaryLogicNegation x v" shows "b v2. [m, p] x IntVal b v2" - by (metis assms UnaryExprE intval_logic_negation.elims unary_eval.simps(4)) + using assms + by (metis UnaryExprE intval_logic_negation.elims unary_eval.simps(4)) -lemma intval_logic_negation_inverse: +lemma intval_logic_negation_inverse: assumes "b > 0" assumes "x = IntVal b v" shows "val_to_bool (intval_logic_negation x) ¬(val_to_bool x)" - by (cases x; auto simp: logic_negate_def assms) + using assms by (cases x; auto simp: logic_negate_def) -lemma logic_negation_relation_tree: +lemma logic_negation_relation_tree: assumes "[m, p] y val" assumes "[m, p] UnaryExpr UnaryLogicNegation y invval" shows "val_to_bool val ¬(val_to_bool invval)" - by (metis UnaryExprE evalDet eval_bits_1_64 logic_negate_type unary_eval.simps(4) assms - intval_logic_negation_inverse) + using assms using intval_logic_negation_inverse + by (metis UnaryExprE evalDet eval_bits_1_64 logic_negate_type unary_eval.simps(4)) -text The following theorem shows that the known true/false rules are valid. +text ‹The following theorem show that the known true/false rules are valid.› theorem implies_impliesnot_valid: shows "((q1 q2) (q1 q2)) ((q1 ⇛¬ q2) (q1 q2))" (is "(?imp ?val) (?notimp ?notval)") proof (induct q1 q2 rule: impliesx_impliesnot.induct) - case (q_imp_q q) + case (same q) then show ?case using evalDet by fastforce next - case (eq_impliesnot_less x y) - then show ?case - apply auto using eq_impliesnot_less_val evalDet by blast + case (eq_not_less x y) + then show ?case apply auto[1] using eq_not_less_val evalDet by blast next - case (eq_impliesnot_less_rev x y) - then show ?case - apply auto using eq_impliesnot_less_rev_val evalDet by blast + case (eq_not_less' x y) + then show ?case apply auto[1] using eq_not_less'_val evalDet by blast next - case (less_impliesnot_rev_less x y) - then show ?case - apply auto using less_impliesnot_rev_less_val evalDet by blast + case (less_not_less x y) + then show ?case apply auto[1] using less_not_less_val evalDet by blast next - case (less_impliesnot_eq x y) - then show ?case - apply auto using less_impliesnot_eq_val evalDet by blast + case (less_not_eq x y) + then show ?case apply auto[1] using less_not_eq_val evalDet by blast next - case (less_impliesnot_eq_rev x y) - then show ?case - apply auto by (metis eq_impliesnot_less_rev_val evalDet) + case (less_not_eq' x y) + then show ?case apply auto[1] using eq_not_less'_val evalDet by metis next case (negate_true x y) - then show ?case - apply auto by (metis logic_negation_relation_tree unary_eval.simps(4) unfold_unary) + then show ?case apply auto[1] + by (metis logic_negation_relation_tree unary_eval.simps(4) unfold_unary) next case (negate_false x y) - then show ?case - apply auto by (metis UnaryExpr logic_negation_relation_tree unary_eval.simps(4)) + then show ?case apply auto[1] + by (metis UnaryExpr logic_negation_relation_tree unary_eval.simps(4)) qed -text -We introduce a type @{term "TriState"} (as in the GraalVM compiler) to represent when static -analysis can tell us information about the value of a Boolean expression. -If @{term "Unknown"} then no information can be inferred and if -@{term "KnownTrue"}/@{term "KnownFalse"} one can infer the expression is always true/false. - -datatype TriState = Unknown | KnownTrue | KnownFalse - -text -The implies relation corresponds to the LogicNode.implies -method from the compiler which attempts to infer when one -logic nodes value can be inferred from a known logic node. - -inductive implies :: "IRGraph IRNode IRNode TriState bool" - ("_ _ & _ _") for g where - eq_imp_less: - "g (IntegerEqualsNode x y) & (IntegerLessThanNode x y) KnownFalse" | - eq_imp_less_rev: - "g (IntegerEqualsNode x y) & (IntegerLessThanNode y x) KnownFalse" | - less_imp_rev_less: - "g (IntegerLessThanNode x y) & (IntegerLessThanNode y x) KnownFalse" | - less_imp_not_eq: - "g (IntegerLessThanNode x y) & (IntegerEqualsNode x y) KnownFalse" | - less_imp_not_eq_rev: - "g (IntegerLessThanNode x y) & (IntegerEqualsNode y x) KnownFalse" | - - x_imp_x: - "g x & x KnownTrue" | - - negate_false: - "g x & (kind g y) KnownTrue g x & (LogicNegationNode y) KnownFalse" | - negate_true: - "g x & (kind g y) KnownFalse g x & (LogicNegationNode y) KnownTrue" - -text Total relation over partial implies relation -inductive condition_implies :: "IRGraph IRNode IRNode TriState bool" - ("_ _ & _ _") for g where - "¬(g a & b imp) (g a & b Unknown)" | - "(g a & b imp) (g a & b imp)" - -inductive implies_tree :: "IRExpr IRExpr bool bool" - ("_ & _ _") where - eq_imp_less: - "(BinaryExpr BinIntegerEquals x y) & (BinaryExpr BinIntegerLessThan x y) False" | - eq_imp_less_rev: - "(BinaryExpr BinIntegerEquals x y) & (BinaryExpr BinIntegerLessThan y x) False" | - less_imp_rev_less: - "(BinaryExpr BinIntegerLessThan x y) & (BinaryExpr BinIntegerLessThan y x) False" | - less_imp_not_eq: - "(BinaryExpr BinIntegerLessThan x y) & (BinaryExpr BinIntegerEquals x y) False" | - less_imp_not_eq_rev: - "(BinaryExpr BinIntegerLessThan x y) & (BinaryExpr BinIntegerEquals y x) False" | - x_imp_x: - "x & x True" | - negate_false: - "x & y True x & (UnaryExpr UnaryLogicNegation y) False" | - negate_true: - "x & y False x & (UnaryExpr UnaryLogicNegation y) True" - -text -Proofs that the implies relation is correct with respect to the -existing evaluation semantics. - - -lemma logic_negation_relation: - assumes "[g, m, p] y val" - assumes "kind g neg = LogicNegationNode y" - assumes "[g, m, p] neg invval" - assumes "invval UndefVal" - shows "val_to_bool val ¬(val_to_bool invval)" - by (metis assms(1,2,3) LogicNegationNode encodeeval_def logic_negation_relation_tree repDet) - -lemma implies_valid: - assumes "x & y imp" - assumes "[m, p] x v1" - assumes "[m, p] y v2" - shows "(imp (val_to_bool v1 val_to_bool v2)) - (¬imp (val_to_bool v1 ¬(val_to_bool v2)))" - (is "(?TP ?TC) (?FP ?FC)") - apply (intro conjI; rule impI) -proof - - assume KnownTrue: ?TP - show ?TC - using assms(1) KnownTrue assms(2-) proof (induct x y imp rule: implies_tree.induct) - case (eq_imp_less x y) - then show ?case - by simp - next - case (eq_imp_less_rev x y) - then show ?case - by simp - next - case (less_imp_rev_less x y) - then show ?case - by simp - next - case (less_imp_not_eq x y) - then show ?case - by simp - next - case (less_imp_not_eq_rev x y) - then show ?case - by simp - next - case (x_imp_x) - then show ?case - by (metis evalDet) - next - case (negate_false x1) - then show ?case - using evalDet assms(2,3) by fast - next - case (negate_true x y) - then show ?case - using logic_negation_relation_tree sorry - qed -next - assume KnownFalse: ?FP - show ?FC using assms KnownFalse proof (induct x y imp rule: implies_tree.induct) - case (eq_imp_less x y) - obtain xval where xval: "[m, p] x xval" - using eq_imp_less(1) by blast - then obtain yval where yval: "[m, p] y yval" - using eq_imp_less.prems(2) by blast - have eqeval: "[m, p] (BinaryExpr BinIntegerEquals x y) intval_equals xval yval" - by (metis xval yval BinaryExprE bin_eval.simps(13) eq_imp_less.prems(1) evalDet) - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan x y) intval_less_than xval yval" - by (metis xval yval BinaryExprE bin_eval.simps(14) eq_imp_less.prems(2) evalDet) - have "val_to_bool (intval_equals xval yval) ¬(val_to_bool (intval_less_than xval yval))" - apply (cases xval; cases yval; auto) - by (smt (verit, best) bool_to_val.simps(2) val_to_bool.simps(1)) - then show ?case - by (metis eqeval lesseval eq_imp_less.prems(1,2) evalDet) - next - case (eq_imp_less_rev x y) - obtain xval where xval: "[m, p] x xval" - using eq_imp_less_rev.prems(2) by blast - obtain yval where yval: "[m, p] y yval" - using eq_imp_less_rev.prems(2) by blast - have eqeval: "[m, p] (BinaryExpr BinIntegerEquals x y) intval_equals xval yval" - by (metis xval yval BinaryExprE bin_eval.simps(13) eq_imp_less_rev.prems(1) evalDet) - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan y x) intval_less_than yval xval" - by (metis xval yval BinaryExprE bin_eval.simps(14) eq_imp_less_rev.prems(2) evalDet) - have "val_to_bool (intval_equals xval yval) ¬(val_to_bool (intval_less_than yval xval))" - apply (cases xval; cases yval; auto) - by (metis (full_types) bool_to_val.simps(2) less_irrefl val_to_bool.simps(1)) - then show ?case - by (metis eq_imp_less_rev.prems(1) eq_imp_less_rev.prems(2) evalDet eqeval lesseval) - next - case (less_imp_rev_less x y) - obtain xval where xval: "[m, p] x xval" - using less_imp_rev_less.prems(2) by blast - obtain yval where yval: "[m, p] y yval" - using less_imp_rev_less.prems(2) by blast - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan x y) intval_less_than xval yval" - by (metis BinaryExprE bin_eval.simps(14) evalDet less_imp_rev_less.prems(1) xval yval) - have revlesseval: "[m, p] (BinaryExpr BinIntegerLessThan y x) intval_less_than yval xval" - by (metis BinaryExprE bin_eval.simps(14) evalDet less_imp_rev_less.prems(2) xval yval) - have "val_to_bool (intval_less_than xval yval) ¬(val_to_bool (intval_less_than yval xval))" - apply (cases xval; cases yval; auto) - by (smt (verit) bool_to_val.simps(2) val_to_bool.simps(1)) - then show ?case - by (metis evalDet less_imp_rev_less.prems(1,2) lesseval revlesseval) - next - case (less_imp_not_eq x y) - obtain xval where xval: "[m, p] x xval" - using less_imp_not_eq.prems(1) by blast - obtain yval where yval: "[m, p] y yval" - using less_imp_not_eq.prems(1) by blast - have eqeval: "[m, p] (BinaryExpr BinIntegerEquals x y) intval_equals xval yval" - by (metis BinaryExprE bin_eval.simps(13) evalDet less_imp_not_eq.prems(2) xval yval) - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan x y) intval_less_than xval yval" - by (metis BinaryExprE bin_eval.simps(14) evalDet less_imp_not_eq.prems(1) xval yval) - have "val_to_bool (intval_less_than xval yval) ¬(val_to_bool (intval_equals xval yval))" - apply (cases xval; cases yval; auto) - by (smt (verit, best) bool_to_val.simps(2) val_to_bool.simps(1)) - then show ?case - by (metis eqeval evalDet less_imp_not_eq.prems(1,2) lesseval) - next - case (less_imp_not_eq_rev x y) - obtain xval where xval: "[m, p] x xval" - using less_imp_not_eq_rev.prems(1) by blast - obtain yval where yval: "[m, p] y yval" - using less_imp_not_eq_rev.prems(1) by blast - have eqeval: "[m, p] (BinaryExpr BinIntegerEquals y x) intval_equals yval xval" - by (metis xval yval BinaryExprE bin_eval.simps(13) evalDet less_imp_not_eq_rev.prems(2)) - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan x y) intval_less_than xval yval" - by (metis xval yval BinaryExprE bin_eval.simps(14) evalDet less_imp_not_eq_rev.prems(1)) - have "val_to_bool (intval_less_than xval yval) ¬(val_to_bool (intval_equals yval xval))" - apply (cases xval; cases yval; auto) - by (smt (verit, best) bool_to_val.simps(2) val_to_bool.simps(1)) - then show ?case - by (metis eqeval evalDet less_imp_not_eq_rev.prems(1,2) lesseval) - next - case (x_imp_x x1) - then show ?case - by simp - next - case (negate_false x y) - then show ?case sorry - next - case (negate_true x1) - then show ?case - by simp - qed -qed -lemma implies_true_valid: - assumes "x & y imp" - assumes "imp" - assumes "[m, p] x v1" - assumes "[m, p] y v2" - shows "val_to_bool v1 val_to_bool v2" - using assms implies_valid by blast - -lemma implies_false_valid: - assumes "x & y imp" - assumes "¬imp" - assumes "[m, p] x v1" - assumes "[m, p] y v2" - shows "val_to_bool v1 ¬(val_to_bool v2)" - using assms implies_valid by blast - -text -The following relation corresponds to the UnaryOpLogicNode.tryFold -and BinaryOpLogicNode.tryFold methods and their associated concrete implementations. - -The relation determines if a logic operation can be shown true or false -through the stamp typing information. - +subsubsection ‹Type Implication› + +text ‹ +The second mechanism to determine whether a condition implies another is +to use the type information of the relevant nodes. +For instance, @{term "x < 4"} implies @{term "x < 10"}. +We can show this by strengthening the type, stamp, +of the node @{term x} such that the upper bound is @{term 4}. +Then we the second condition is reached, +we know that the condition must be true by the upperbound. +› + +text ‹ +The following relation corresponds to the \texttt{UnaryOpLogicNode.tryFold} +and \texttt{BinaryOpLogicNode.tryFold} methods and their associated +concrete implementations. + +We track the refined stamps by mapping nodes to Stamps, +the second parameter to @{term tryFold}. +› + inductive tryFold :: "IRNode (ID Stamp) bool bool" where "alwaysDistinct (stamps x) (stamps y) @@ -449,129 +275,307 @@

Theory ConditionalElimination

stpi_lower (stamps x) stpi_upper (stamps y) tryFold (IntegerLessThanNode x y) stamps False"
-text -Proofs that show that when the stamp lookup function is well-formed, -the tryFold relation correctly predicts the output value with respect to -our evaluation semantics. - -lemma - assumes "kind g nid = IntegerEqualsNode x y" - assumes "[g, m, p] nid v" - assumes "([g, m, p] x xval) ([g, m, p] y yval)" - shows "val_to_bool (intval_equals xval yval) v = IntVal 32 1" +code_pred (modes: i i i bool) tryFold
. + +text ‹ +Prove that, when the stamp map is valid, +the @{term tryFold} relation correctly predicts the output value with respect to +our evaluation semantics. +› + +inductive_cases StepE: + "g, p (nid,m,h) (nid',m',h)" + + +lemma is_stamp_empty_valid: + assumes "is_stamp_empty s" + shows "¬( val. valid_value val s)" + using assms is_stamp_empty.simps apply (cases s; auto) + by (metis linorder_not_le not_less_iff_gr_or_eq order.strict_trans valid_value.elims(2) valid_value.simps(1) valid_value.simps(5)) + +lemma join_valid: + assumes "is_IntegerStamp s1 is_IntegerStamp s2" + assumes "valid_stamp s1 valid_stamp s2" + shows "(valid_value v s1 valid_value v s2) = valid_value v (join s1 s2)" (is "?lhs = ?rhs") +proof + assume ?lhs + then show ?rhs + using assms(1) apply (cases s1; cases s2; auto) + apply (metis Value.inject(1) valid_int) + by (smt (z3) valid_int valid_stamp.simps(1) valid_value.simps(1)) + next + assume ?rhs + then show ?lhs + using assms apply (cases s1; cases s2; simp) + by (smt (verit, best) assms(2) valid_int valid_value.simps(1) valid_value.simps(22)) +qed + +lemma alwaysDistinct_evaluate: + assumes "wf_stamp g stamps" + assumes "alwaysDistinct (stamps x) (stamps y)" + assumes "is_IntegerStamp (stamps x) is_IntegerStamp (stamps y) valid_stamp (stamps x) valid_stamp (stamps y)" + shows "¬( val . ([g, m, p] x val) ([g, m, p] y val))" proof - - have "v = intval_equals xval yval" - by (smt (verit) bin_eval.simps(13) encodeeval_def evalDet repDet IntegerEqualsNode BinaryExprE - assms) + obtain stampx stampy where stampdef: "stampx = stamps x stampy = stamps y" + by simp + then have xv: " xv . ([g, m, p] x xv) valid_value xv stampx" + by (meson assms(1) encodeeval.simps eval_in_ids wf_stamp.elims(2)) + from stampdef have yv: " yv . ([g, m, p] y yv) valid_value yv stampy" + by (meson assms(1) encodeeval.simps eval_in_ids wf_stamp.elims(2)) + have "v. valid_value v (join stampx stampy) = (valid_value v stampx valid_value v stampy)" + using assms(3) + by (simp add: join_valid stampdef) then show ?thesis - by (metis bool_to_val.simps(1,2) one_neq_zero val_to_bool.simps(1,2) intval_equals_result) + using assms unfolding alwaysDistinct.simps + using is_stamp_empty_valid stampdef xv yv by blast qed -lemma tryFoldIntegerEqualsAlwaysDistinct: +lemma alwaysDistinct_valid: assumes "wf_stamp g stamps" assumes "kind g nid = (IntegerEqualsNode x y)" assumes "[g, m, p] nid v" assumes "alwaysDistinct (stamps x) (stamps y)" - shows "v = IntVal 32 0" + shows "¬(val_to_bool v)" proof - - have " val. ¬(valid_value val (join (stamps x) (stamps y)))" - by (smt (verit, best) is_stamp_empty.elims(2) valid_int valid_value.simps(1) assms(1,4) + have no_valid: " val. ¬(valid_value val (join (stamps x) (stamps y)))" + by (smt (verit, best) is_stamp_empty.elims(2) valid_int valid_value.simps(1) assms(1,4) alwaysDistinct.simps) - obtain xv where "[g, m, p] x xv" - using assms unfolding encodeeval_def sorry - have "¬( val . ([g, m, p] x val) ([g, m, p] y val))" - using assms(1,4) unfolding alwaysDistinct.simps wf_stamp.simps encodeeval_def sorry + obtain xe ye where repr: "rep g nid (BinaryExpr BinIntegerEquals xe ye)" + by (metis assms(2) assms(3) encodeeval.simps rep_integer_equals) + moreover have evale: "[m, p] (BinaryExpr BinIntegerEquals xe ye) v" + by (metis assms(3) calculation encodeeval.simps repDet) + moreover have repsub: "rep g x xe rep g y ye" + by (metis IRNode.distinct(1955) IRNode.distinct(1997) IRNode.inject(17) IntegerEqualsNodeE assms(2) calculation) + ultimately obtain xv yv where evalsub: "[g, m, p] x xv [g, m, p] y yv" + by (meson BinaryExprE encodeeval.simps) + have xvalid: "valid_value xv (stamps x)" + using assms(1) encode_in_ids encodeeval.simps evalsub wf_stamp.simps by blast + then have xint: "is_IntegerStamp (stamps x)" + using assms(4) valid_value.elims(2) by fastforce + then have xstamp: "valid_stamp (stamps x)" + using xvalid apply (cases xv; auto) + apply (smt (z3) valid_stamp.simps(6) valid_value.elims(1)) + using is_IntegerStamp_def by fastforce + have yvalid: "valid_value yv (stamps y)" + using assms(1) encode_in_ids encodeeval.simps evalsub wf_stamp.simps by blast + then have yint: "is_IntegerStamp (stamps y)" + using assms(4) valid_value.elims(2) by fastforce + then have ystamp: "valid_stamp (stamps y)" + using yvalid apply (cases yv; auto) + apply (smt (z3) valid_stamp.simps(6) valid_value.elims(1)) + using is_IntegerStamp_def by fastforce + have disjoint: "¬( val . ([g, m, p] x val) ([g, m, p] y val))" + using alwaysDistinct_evaluate + using assms(1) assms(4) xint yint xvalid yvalid xstamp ystamp by simp + have "v = bin_eval BinIntegerEquals xv yv" + by (metis BinaryExprE encodeeval.simps evale evalsub graphDet repsub) + also have "v UndefVal" + using evale by auto + ultimately have "b1 b2. v = bool_to_val_bin b1 b2 (xv = yv)" + unfolding bin_eval.simps + by (smt (z3) Value.inject(1) bool_to_val_bin.simps intval_equals.elims) then show ?thesis - sorry + by (metis (mono_tags, lifting) (v::Value) UndefVal bool_to_val.elims bool_to_val_bin.simps disjoint evalsub val_to_bool.simps(1)) +qed +thm_oracles alwaysDistinct_valid + +lemma unwrap_valid: + assumes "0 < b b 64" + assumes "take_bit (b::nat) (vv::64 word) = vv" + shows "(vv::64 word) = take_bit b (word_of_int (int_signed_value (b::nat) (vv::64 word)))" + using assms apply auto[1] + by (simp add: take_bit_signed_take_bit) + +lemma asConstant_valid: + assumes "asConstant s = val" + assumes "val UndefVal" + assumes "valid_value v s" + shows "v = val" +proof - + obtain b l h where s: "s = IntegerStamp b l h" + using assms(1,2) by (cases s; auto) + obtain vv where vdef: "v = IntVal b vv" + using assms(3) s valid_int by blast + have "l int_signed_value b vv int_signed_value b vv h" + by (metis (v::Value) = IntVal (b::nat) (vv::64 word) assms(3) s valid_value.simps(1)) + then have veq: "int_signed_value b vv = l" + by (smt (verit) asConstant.simps(1) assms(1) assms(2) s) + have valdef: "val = new_int b (word_of_int l)" + by (metis asConstant.simps(1) assms(1) assms(2) s) + have "take_bit b vv = vv" + by (metis (v::Value) = IntVal (b::nat) (vv::64 word) assms(3) s valid_value.simps(1)) + then show ?thesis + using veq vdef valdef + using assms(3) s unwrap_valid by force qed -lemma tryFoldIntegerEqualsNeverDistinct: +lemma neverDistinct_valid: assumes "wf_stamp g stamps" assumes "kind g nid = (IntegerEqualsNode x y)" assumes "[g, m, p] nid v" assumes "neverDistinct (stamps x) (stamps y)" - shows "v = IntVal 32 1" - using assms IntegerEqualsNodeE sorry + shows "val_to_bool v" +proof - + obtain val where constx: "asConstant (stamps x) = val" + by simp + moreover have "val UndefVal" + using assms(4) calculation by auto + then have constx: "val = asConstant (stamps y)" + using calculation assms(4) by force + obtain xe ye where repr: "rep g nid (BinaryExpr BinIntegerEquals xe ye)" + by (metis assms(2) assms(3) encodeeval.simps rep_integer_equals) + moreover have evale: "[m, p] (BinaryExpr BinIntegerEquals xe ye) v" + by (metis assms(3) calculation encodeeval.simps repDet) + moreover have repsub: "rep g x xe rep g y ye" + by (metis IRNode.distinct(1955) IRNode.distinct(1997) IRNode.inject(17) IntegerEqualsNodeE assms(2) calculation) + ultimately obtain xv yv where evalsub: "[g, m, p] x xv [g, m, p] y yv" + by (meson BinaryExprE encodeeval.simps) + have xvalid: "valid_value xv (stamps x)" + using assms(1) encode_in_ids encodeeval.simps evalsub wf_stamp.simps by blast + then have xint: "is_IntegerStamp (stamps x)" + using assms(4) valid_value.elims(2) by fastforce + have yvalid: "valid_value yv (stamps y)" + using assms(1) encode_in_ids encodeeval.simps evalsub wf_stamp.simps by blast + then have yint: "is_IntegerStamp (stamps y)" + using assms(4) valid_value.elims(2) by fastforce + have eq: "v1 v2. (([g, m, p] x v1) ([g, m, p] y v2)) v1 = v2" + by (metis asConstant_valid assms(4) encodeEvalDet evalsub neverDistinct.elims(1) xvalid yvalid) + have "v = bin_eval BinIntegerEquals xv yv" + by (metis BinaryExprE encodeeval.simps evale evalsub graphDet repsub) + also have "v UndefVal" + using evale by auto + ultimately have "b1 b2. v = bool_to_val_bin b1 b2 (xv = yv)" + unfolding bin_eval.simps + by (smt (z3) Value.inject(1) bool_to_val_bin.simps intval_equals.elims) + then show ?thesis + using (v::Value) UndefVal eq evalsub by fastforce +qed -lemma tryFoldIntegerLessThanTrue: +lemma stampUnder_valid: assumes "wf_stamp g stamps" assumes "kind g nid = (IntegerLessThanNode x y)" assumes "[g, m, p] nid v" assumes "stpi_upper (stamps x) < stpi_lower (stamps y)" - shows "v = IntVal 32 1" + shows "val_to_bool v" proof - - have stamp_type: "is_IntegerStamp (stamps x)" - using assms - sorry - obtain xval where xval: "[g, m, p] x xval" - using assms(2,3) sorry - obtain yval where yval: "[g, m, p] y yval" - using assms(2,3) sorry - have "is_IntegerStamp (stamps x) is_IntegerStamp (stamps y)" - using assms(4) - sorry - then have "val_to_bool (intval_less_than xval yval)" - sorry + obtain xe ye where repr: "rep g nid (BinaryExpr BinIntegerLessThan xe ye)" + by (metis assms(2) assms(3) encodeeval.simps rep_integer_less_than) + moreover have evale: "[m, p] (BinaryExpr BinIntegerLessThan xe ye) v" + by (metis assms(3) calculation encodeeval.simps repDet) + moreover have repsub: "rep g x xe rep g y ye" + by (metis IRNode.distinct(2047) IRNode.distinct(2089) IRNode.inject(18) IntegerLessThanNodeE assms(2) repr) + ultimately obtain xv yv where evalsub: "[g, m, p] x xv [g, m, p] y yv" + by (meson BinaryExprE encodeeval.simps) + have vval: "v = intval_less_than xv yv" + by (metis BinaryExprE bin_eval.simps(14) encodeEvalDet encodeeval.simps evale evalsub repsub) + then obtain b xvv where "xv = IntVal b xvv" + by (metis bin_eval.simps(14) defined_eval_is_intval evale evaltree_not_undef is_IntVal_def) + also have xvalid: "valid_value xv (stamps x)" + by (meson assms(1) encodeeval.simps eval_in_ids evalsub wf_stamp.elims(2)) + then obtain xl xh where xstamp: "stamps x = IntegerStamp b xl xh" + using calculation valid_value.simps apply (cases "stamps x"; auto) + by presburger + from vval obtain yvv where yint: "yv = IntVal b yvv" + by (metis Value.collapse(1) bin_eval.simps(14) bool_to_val_bin.simps calculation defined_eval_is_intval evale evaltree_not_undef intval_less_than.simps(1)) + then have yvalid: "valid_value yv (stamps y)" + using assms(1) encodeeval.simps evalsub no_encoding wf_stamp.simps by blast + then obtain yl yh where ystamp: "stamps y = IntegerStamp b yl yh" + using calculation yint valid_value.simps apply (cases "stamps y"; auto) + by presburger + have "int_signed_value b xvv xh" + using calculation valid_value.simps(1) xstamp xvalid by presburger + moreover have "yl int_signed_value b yvv" + using valid_value.simps(1) yint ystamp yvalid by presburger + moreover have "xh < yl" + using assms(4) xstamp ystamp by auto + ultimately have "int_signed_value b xvv < int_signed_value b yvv" + by linarith + then have "val_to_bool (intval_less_than xv yv)" + by (simp add: (xv::Value) = IntVal (b::nat) (xvv::64 word) yint) then show ?thesis - sorry + by (simp add: vval) qed -lemma tryFoldIntegerLessThanFalse: +lemma stampOver_valid: assumes "wf_stamp g stamps" assumes "kind g nid = (IntegerLessThanNode x y)" assumes "[g, m, p] nid v" assumes "stpi_lower (stamps x) stpi_upper (stamps y)" - shows "v = IntVal 32 0" - proof - - have stamp_type: "is_IntegerStamp (stamps x)" - using assms sorry - obtain xval where xval: "[g, m, p] x xval" - using assms(2,3) sorry - obtain yval where yval: "[g, m, p] y yval" - using assms(2,3) sorry - have "is_IntegerStamp (stamps x) is_IntegerStamp (stamps y)" - using assms(4) sorry - then have "¬(val_to_bool (intval_less_than xval yval))" - sorry + shows "¬(val_to_bool v)" +proof - + obtain xe ye where repr: "rep g nid (BinaryExpr BinIntegerLessThan xe ye)" + by (metis assms(2) assms(3) encodeeval.simps rep_integer_less_than) + moreover have evale: "[m, p] (BinaryExpr BinIntegerLessThan xe ye) v" + by (metis assms(3) calculation encodeeval.simps repDet) + moreover have repsub: "rep g x xe rep g y ye" + by (metis IRNode.distinct(2047) IRNode.distinct(2089) IRNode.inject(18) IntegerLessThanNodeE assms(2) repr) + ultimately obtain xv yv where evalsub: "[g, m, p] x xv [g, m, p] y yv" + by (meson BinaryExprE encodeeval.simps) + have vval: "v = intval_less_than xv yv" + by (metis BinaryExprE bin_eval.simps(14) encodeEvalDet encodeeval.simps evale evalsub repsub) + then obtain b xvv where "xv = IntVal b xvv" + by (metis bin_eval.simps(14) defined_eval_is_intval evale evaltree_not_undef is_IntVal_def) + also have xvalid: "valid_value xv (stamps x)" + by (meson assms(1) encodeeval.simps eval_in_ids evalsub wf_stamp.elims(2)) + then obtain xl xh where xstamp: "stamps x = IntegerStamp b xl xh" + using calculation valid_value.simps apply (cases "stamps x"; auto) + by presburger + from vval obtain yvv where yint: "yv = IntVal b yvv" + by (metis Value.collapse(1) bin_eval.simps(14) bool_to_val_bin.simps calculation defined_eval_is_intval evale evaltree_not_undef intval_less_than.simps(1)) + then have yvalid: "valid_value yv (stamps y)" + using assms(1) encodeeval.simps evalsub no_encoding wf_stamp.simps by blast + then obtain yl yh where ystamp: "stamps y = IntegerStamp b yl yh" + using calculation yint valid_value.simps apply (cases "stamps y"; auto) + by presburger + have "xl int_signed_value b xvv" + using calculation valid_value.simps(1) xstamp xvalid by presburger + moreover have "int_signed_value b yvv yh" + using valid_value.simps(1) yint ystamp yvalid by presburger + moreover have "xl yh" + using assms(4) xstamp ystamp by auto + ultimately have "int_signed_value b xvv int_signed_value b yvv" + by linarith + then have "¬(val_to_bool (intval_less_than xv yv))" + by (simp add: (xv::Value) = IntVal (b::nat) (xvv::64 word) yint) then show ?thesis - sorry + by (simp add: vval) qed -theorem tryFoldProofTrue: +theorem tryFoldTrue_valid: assumes "wf_stamp g stamps" assumes "tryFold (kind g nid) stamps True" assumes "[g, m, p] nid v" shows "val_to_bool v" - using assms(2) proof (induction "kind g nid" stamps True rule: tryFold.induct) + using assms(2) proof (induction "kind g nid" stamps True rule: tryFold.induct) case (1 stamps x y) then show ?case - using tryFoldIntegerEqualsAlwaysDistinct assms by force + using alwaysDistinct_valid assms by force next case (2 stamps x y) then show ?case - by (smt (verit, best) one_neq_zero tryFold.cases tryFoldIntegerEqualsNeverDistinct assms - tryFoldIntegerLessThanTrue val_to_bool.simps(1)) + by (smt (verit, best) one_neq_zero tryFold.cases neverDistinct_valid assms + stampUnder_valid val_to_bool.simps(1)) next case (3 stamps x y) then show ?case - by (smt (verit, best) one_neq_zero tryFold.cases tryFoldIntegerEqualsNeverDistinct assms - val_to_bool.simps(1) tryFoldIntegerLessThanTrue) + by (smt (verit, best) one_neq_zero tryFold.cases neverDistinct_valid assms + val_to_bool.simps(1) stampUnder_valid) next case (4 stamps x y) then show ?case by force qed -theorem tryFoldProofFalse: +theorem tryFoldFalse_valid: assumes "wf_stamp g stamps" assumes "tryFold (kind g nid) stamps False" assumes "[g, m, p] nid v" shows "¬(val_to_bool v)" -using assms(2) proof (induction "kind g nid" stamps False rule: tryFold.induct) +using assms(2) proof (induction "kind g nid" stamps False rule: tryFold.induct) case (1 stamps x y) then show ?case - by (smt (verit) tryFoldIntegerLessThanFalse tryFoldIntegerEqualsAlwaysDistinct tryFold.cases - tryFoldIntegerEqualsNeverDistinct val_to_bool.simps(1) assms) + by (smt (verit) stampOver_valid alwaysDistinct_valid tryFold.cases + neverDistinct_valid val_to_bool.simps(1) assms) next case (2 stamps x y) then show ?case @@ -583,261 +587,462 @@

Theory ConditionalElimination

next case (4 stamps x y) then show ?case - by (smt (verit, del_insts) tryFold.cases tryFoldIntegerEqualsAlwaysDistinct val_to_bool.simps(1) - tryFoldIntegerLessThanFalse assms) + by (smt (verit, del_insts) tryFold.cases alwaysDistinct_valid val_to_bool.simps(1) + stampOver_valid assms) qed -inductive_cases StepE: - "g, p (nid,m,h) (nid',m',h)" -text -Perform conditional elimination rewrites on the graph for a particular node. - -In order to determine conditional eliminations appropriately the rule needs two -data structures produced by static analysis. -The first parameter is the set of IRNodes that we know result in a true value -when evaluated. -The second parameter is a mapping from node identifiers to the flow-sensitive stamp. - -The relation transforms the third parameter to the fifth parameter for a node identifier -which represents the fourth parameter. - +subsection ‹Lift rules› + +inductive condset_implies :: "IRExpr set IRExpr bool bool" where + impliesTrue: + "(ce conds . (ce cond)) condset_implies conds cond True" | + impliesFalse: + "(ce conds . (ce ⇛¬ cond)) condset_implies conds cond False" + +code_pred (modes: i i i bool) condset_implies
. + +text ‹ +The @{term cond_implies} function lifts the structural and type implication +rules to the one relation. +› + +fun conds_implies :: "IRExpr set (ID Stamp) IRNode IRExpr bool option" where + "conds_implies conds stamps condNode cond = + (if condset_implies conds cond True tryFold condNode stamps True + then Some True + else if condset_implies conds cond False tryFold condNode stamps False + then Some False + else None)" + +text ‹ +Perform conditional elimination rewrites on the graph for a particular node +by lifting the individual implication rules to a relation that rewrites the +condition of \textsl{if} statements to constant values. + +In order to determine conditional eliminations appropriately the rule needs two +data structures produced by static analysis. +The first parameter is the set of IRNodes that we know result in a true value +when evaluated. +The second parameter is a mapping from node identifiers to the flow-sensitive stamp. +› + inductive ConditionalEliminationStep :: - "IRExpr set (ID Stamp) IRGraph ID IRGraph bool" where + "IRExpr set (ID Stamp) ID IRGraph IRGraph bool" + where impliesTrue: "kind g ifcond = (IfNode cid t f); - g cid cond; - ce conds . (ce cond); + g cid cond; + condNode = kind g cid; + conds_implies conds stamps condNode cond = (Some True); g' = constantCondition True ifcond (kind g ifcond) g - ConditionalEliminationStep conds stamps g ifcond g'" | + ConditionalEliminationStep conds stamps ifcond g g'"
| impliesFalse: "kind g ifcond = (IfNode cid t f); g cid cond; - ce conds . (ce ⇛¬ cond); + condNode = kind g cid; + conds_implies conds stamps condNode cond = (Some False); g' = constantCondition False ifcond (kind g ifcond) g - ConditionalEliminationStep conds stamps g ifcond g'" | + ConditionalEliminationStep conds stamps ifcond g g'"
| - tryFoldTrue: + unknown: "kind g ifcond = (IfNode cid t f); - cond = kind g cid; - tryFold (kind g cid) stamps True; - g' = constantCondition True ifcond (kind g ifcond) g - ConditionalEliminationStep conds stamps g ifcond g'" | + g cid cond; + condNode = kind g cid; + conds_implies conds stamps condNode cond = None + ConditionalEliminationStep conds stamps ifcond g g"
| - tryFoldFalse: - "kind g ifcond = (IfNode cid t f); - cond = kind g cid; - tryFold (kind g cid) stamps False; - g' = constantCondition False ifcond (kind g ifcond) g - ConditionalEliminationStep conds stamps g ifcond g'" + notIfNode: + "¬(is_IfNode (kind g ifcond)) + ConditionalEliminationStep conds stamps ifcond g g" -code_pred (modes: i i i i o bool) ConditionalEliminationStep . +code_pred (modes: i i i i o bool) ConditionalEliminationStep . thm ConditionalEliminationStep.equation -subsection Control-flow Graph Traversal + + +subsection ‹Control-flow Graph Traversal› type_synonym Seen = "ID set" type_synonym Condition = "IRExpr" type_synonym Conditions = "Condition list" type_synonym StampFlow = "(ID Stamp) list" +type_synonym ToVisit = "ID list" -text -nextEdge helps determine which node to traverse next by returning the first successor -edge that isn't in the set of already visited nodes. -If there is not an appropriate successor, None is returned instead. - + +text ‹ +@{term "nextEdge"} helps determine which node to traverse next +by returning the first successor edge that isn't in the set of already visited nodes. +If there is not an appropriate successor, None is returned instead. +› fun nextEdge :: "Seen ID IRGraph ID option" where "nextEdge seen nid g = (let nids = (filter (λnid'. nid' seen) (successors_of (kind g nid))) in (if length nids > 0 then Some (hd nids) else None))" -text -pred determines which node, if any, acts as the predecessor of another. - -Merge nodes represent a special case where-in the predecessor exists as -an input edge of the merge node, to simplify the traversal we treat only -the first input end node as the predecessor, ignoring that multiple nodes -may act as a successor. - -For all other nodes, the predecessor is the first element of the predecessors set. -Note that in a well-formed graph there should only be one element in the predecessor set. -fun pred :: "IRGraph ID ID option" where - "pred g nid = (case kind g nid of - (MergeNode ends _ _) Some (hd ends) | +text ‹ +@{term "pred"} determines which node, if any, acts as the predecessor of another. + +Merge nodes represent a special case wherein the predecessor exists as +an input edge of the merge node, to simplify the traversal we treat only +the first input end node as the predecessor, ignoring that multiple nodes +may act as a successor. + +For all other nodes, the predecessor is the first element of the predecessors set. +Note that in a well-formed graph there should only be one element in the predecessor set. +› +fun preds :: "IRGraph ID ID list" where + "preds g nid = (case kind g nid of + (MergeNode ends _ _) ends | _ - (if IRGraph.predecessors g nid = {} - then None else - Some (hd (sorted_list_of_set (IRGraph.predecessors g nid))) - ) + sorted_list_of_set (IRGraph.predecessors g nid) )" +fun pred :: "IRGraph ID ID option" where + "pred g nid = (case preds g nid of [] None | x # xs Some x)" + -text -When the basic block of an if statement is entered, we know that the condition of the -preceding if statement must be true. -As in the GraalVM compiler, we introduce the registerNewCondition funciton which roughly -corresponds to the ConditionalEliminationPhase.registerNewCondition. -This method updates the flow-sensitive stamp information based on the condition which -we know must be true. - +text ‹ +When the basic block of an if statement is entered, we know that the condition of the +preceding if statement must be true. +As in the GraalVM compiler, we introduce the \texttt{registerNewCondition} function +which roughly corresponds to \texttt{ConditionalEliminationPhase.registerNewCondition}. +This method updates the flow-sensitive stamp information based on the condition which +we know must be true. +› fun clip_upper :: "Stamp int Stamp" where - "clip_upper (IntegerStamp b l h) c = (IntegerStamp b l c)" | + "clip_upper (IntegerStamp b l h) c = + (if c < h then (IntegerStamp b l c) else (IntegerStamp b l h))" | "clip_upper s c = s" fun clip_lower :: "Stamp int Stamp" where - "clip_lower (IntegerStamp b l h) c = (IntegerStamp b c h)" | + "clip_lower (IntegerStamp b l h) c = + (if l < c then (IntegerStamp b c h) else (IntegerStamp b l c))" | "clip_lower s c = s" +fun max_lower :: "Stamp Stamp Stamp" where + "max_lower (IntegerStamp b1 xl xh) (IntegerStamp b2 yl yh) = + (IntegerStamp b1 (max xl yl) xh)" | + "max_lower xs ys = xs" +fun min_higher :: "Stamp Stamp Stamp" where + "min_higher (IntegerStamp b1 xl xh) (IntegerStamp b2 yl yh) = + (IntegerStamp b1 yl (min xh yh))" | + "min_higher xs ys = ys" + fun registerNewCondition :: "IRGraph IRNode (ID Stamp) (ID Stamp)" where - (* constrain equality by joining the stamps *) + ― ‹constrain equality by joining the stamps› "registerNewCondition g (IntegerEqualsNode x y) stamps = (stamps (x := join (stamps x) (stamps y))) (y := join (stamps x) (stamps y))" | - (* constrain less than by removing overlapping stamps *) + ― ‹constrain less than by removing overlapping stamps› "registerNewCondition g (IntegerLessThanNode x y) stamps = (stamps - (x := clip_upper (stamps x) (stpi_lower (stamps y)))) - (y := clip_lower (stamps y) (stpi_upper (stamps x)))" | + (x := clip_upper (stamps x) ((stpi_lower (stamps y)) - 1))) + (y := clip_lower (stamps y) ((stpi_upper (stamps x)) + 1))" | + "registerNewCondition g (LogicNegationNode c) stamps = + (case (kind g c) of + (IntegerLessThanNode x y) + (stamps + (x := max_lower (stamps x) (stamps y))) + (y := min_higher (stamps x) (stamps y)) + | _ stamps)" | "registerNewCondition g _ stamps = stamps" fun hdOr :: "'a list 'a 'a" where "hdOr (x # xs) de = x" | "hdOr [] de = de" -text -The Step relation is a small-step traversal of the graph which handles transitions between -individual nodes of the graph. - -It relates a pairs of tuple of the current node, the set of seen nodes, -the always true stack of IfNode conditions, and the flow-sensitive stamp information. - -inductive Step - :: "IRGraph (ID × Seen × Conditions × StampFlow) (ID × Seen × Conditions × StampFlow) option bool" +(* +fun isCFGNode :: "IRNode ⇒ bool" where + "isCFGNode (BeginNode _) = True" | + "isCFGNode (EndNode) = True" | + "isCFGNode _ = False" + +inductive CFGSuccessor :: + "IRGraph ⇒ (ID × Seen × ToVisit) ⇒ (ID × Seen × ToVisit) ⇒ bool" + for g where + ― ‹ + Forward traversal transitively through successors until + a CFG node is reached.› + "⟦Some nid' = nextEdge seen nid g; + ¬(isCFGNode (kind g nid')); + CFGSuccessor g (nid', {nid} ∪ seen, nid # toVisit) (nid'', seen', toVisit')⟧ + ⟹ CFGSuccessor g (nid, seen, toVisit) (nid'', seen', toVisit')" | + "⟦Some nid' = nextEdge seen nid g; + isCFGNode (kind g nid')⟧ + ⟹ CFGSuccessor g (nid, seen, toVisit) (nid', {nid} ∪ seen, nid # toVisit)" | + + ― ‹ + Backwards traversal transitively through toVisit stack until + a CFG node is reached.› + "⟦toVisit = nid' # toVisit'; + CFGSuccessor g (nid', {nid} ∪ seen, nid # toVisit) (nid'', seen', toVisit')⟧ + ⟹ CFGSuccessor g (nid, seen, toVisit) (nid'', seen', toVisit')" + +code_pred (modes: i ⇒ i ⇒ o ⇒ bool) CFGSuccessor . +*) + +type_synonym DominatorCache = "(ID, ID set) map" + +inductive + dominators_all :: "IRGraph DominatorCache ID ID set set ID list DominatorCache ID set set ID list bool" and + dominators :: "IRGraph DominatorCache ID (ID set × DominatorCache) bool" where + + "pre = [] + dominators_all g c nid doms pre c doms pre" | + + "pre = pr # xs; + (dominators g c pr (doms', c')); + dominators_all g c' pr (doms {doms'}) xs c'' doms'' pre' + dominators_all g c nid doms pre c'' doms'' pre'" | + + "preds g nid = [] + dominators g c nid ({nid}, c)" | + + "c nid = None; + preds g nid = x # xs; + dominators_all g c nid {} (preds g nid) c' doms pre'; + c'' = c'(nid ({nid} (doms))) + dominators g c nid (({nid} (doms)), c'')" | + + "c nid = Some doms + dominators g c nid (doms, c)" + +― ‹ +Trying to simplify by removing the 3rd case won't work. +A base case for root nodes is required as @{term "{} = coset []"} +which swallows anything unioned with it. +› +value "({}::nat set set)" +value "- ({}::nat set set)" +value "({{}, {0}}::nat set set)" +value "{0::nat} ({})" + +code_pred (modes: i i i i i o o o bool) dominators_all . +code_pred (modes: i i i o bool) dominators . + +(* initial: ConditionalEliminationTest13_testSnippet2 *) +definition ConditionalEliminationTest13_testSnippet2_initial :: IRGraph where + "ConditionalEliminationTest13_testSnippet2_initial = irgraph [ + (0, (StartNode (Some 2) 8), VoidStamp), + (1, (ParameterNode 0), IntegerStamp 32 (-2147483648) (2147483647)), + (2, (FrameState [] None None None), IllegalStamp), + (3, (ConstantNode (new_int 32 (0))), IntegerStamp 32 (0) (0)), + (4, (ConstantNode (new_int 32 (1))), IntegerStamp 32 (1) (1)), + (5, (IntegerLessThanNode 1 4), VoidStamp), + (6, (BeginNode 13), VoidStamp), + (7, (BeginNode 23), VoidStamp), + (8, (IfNode 5 7 6), VoidStamp), + (9, (ConstantNode (new_int 32 (-1))), IntegerStamp 32 (-1) (-1)), + (10, (IntegerEqualsNode 1 9), VoidStamp), + (11, (BeginNode 17), VoidStamp), + (12, (BeginNode 15), VoidStamp), + (13, (IfNode 10 12 11), VoidStamp), + (14, (ConstantNode (new_int 32 (-2))), IntegerStamp 32 (-2) (-2)), + (15, (StoreFieldNode 15 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink2'' 14 (Some 16) None 19), VoidStamp), + (16, (FrameState [] None None None), IllegalStamp), + (17, (EndNode), VoidStamp), + (18, (MergeNode [17, 19] (Some 20) 21), VoidStamp), + (19, (EndNode), VoidStamp), + (20, (FrameState [] None None None), IllegalStamp), + (21, (StoreFieldNode 21 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink1'' 3 (Some 22) None 25), VoidStamp), + (22, (FrameState [] None None None), IllegalStamp), + (23, (EndNode), VoidStamp), + (24, (MergeNode [23, 25] (Some 26) 27), VoidStamp), + (25, (EndNode), VoidStamp), + (26, (FrameState [] None None None), IllegalStamp), + (27, (StoreFieldNode 27 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink0'' 9 (Some 28) None 29), VoidStamp), + (28, (FrameState [] None None None), IllegalStamp), + (29, (ReturnNode None None), VoidStamp) + ]" + +(* :( +fun dominators :: "IRGraph ⇒ ID ⇒ ID set" where + "dominators g nid = {nid} ∪ (⋂ y ∈ preds g nid. dominators g y)" +*) + +values "{(snd x) 13| x. dominators ConditionalEliminationTest13_testSnippet2_initial Map.empty 25 x}" + +(*fun condition_of :: "IRGraph ⇒ ID ⇒ ID option" where + "condition_of g nid = (case (kind g nid) of + (IfNode c t f) ⇒ Some c | + _ ⇒ None)"*) + +inductive + condition_of :: "IRGraph ID (IRExpr × IRNode) option bool" where + "Some ifcond = pred g nid; + kind g ifcond = IfNode cond t f; + + i = find_index nid (successors_of (kind g ifcond)); + c = (if i = 0 then kind g cond else LogicNegationNode cond); + rep g cond ce; + ce' = (if i = 0 then ce else UnaryExpr UnaryLogicNegation ce) + condition_of g nid (Some (ce', c))" | + + "pred g nid = None condition_of g nid None" | + "pred g nid = Some nid'; + ¬(is_IfNode (kind g nid')) condition_of g nid None" + +code_pred (modes: i i o bool) condition_of . + +(*inductive + conditions_of_dominators :: "IRGraph ⇒ ID list ⇒ Conditions ⇒ Conditions ⇒ bool" where + "⟦nids = []⟧ + ⟹ conditions_of_dominators g nids conditions conditions" | + + "⟦nids = nid # nids'; + condition_of g nid (Some (expr, _)); + conditions_of_dominators g nids' (expr # conditions) conditions'⟧ + ⟹ conditions_of_dominators g nids conditions conditions'" | + + "⟦nids = nid # nids'; + condition_of g nid None; + conditions_of_dominators g nids' conditions conditions'⟧ + ⟹ conditions_of_dominators g nids conditions conditions'"*) + +fun conditions_of_dominators :: "IRGraph ID list Conditions Conditions" where + "conditions_of_dominators g [] cds = cds" | + "conditions_of_dominators g (nid # nids) cds = + (case (Predicate.the (condition_of_i_i_o g nid)) of + None conditions_of_dominators g nids cds | + Some (expr, _) conditions_of_dominators g nids (expr # cds))" + +(*code_pred (modes: i ⇒ i ⇒ i ⇒ o ⇒ bool) conditions_of_dominators .*) + +(* +inductive + stamps_of_dominators :: "IRGraph ⇒ ID list ⇒ StampFlow ⇒ StampFlow ⇒ bool" where + "⟦nids = []⟧ + ⟹ stamps_of_dominators g nids stamps stamps" | + + "⟦nids = nid # nids'; + condition_of g nid (Some (_, node)); + he = registerNewCondition g node (hd stamps); + stamps_of_dominators g nids' (he # stamps) stamps'⟧ + ⟹ stamps_of_dominators g nids stamps stamps'" | + + "⟦nids = nid # nids'; + condition_of g nid None; + stamps_of_dominators g nids' stamps stamps'⟧ + ⟹ stamps_of_dominators g nids stamps stamps'" +*) + +fun stamps_of_dominators :: "IRGraph ID list StampFlow StampFlow" where + "stamps_of_dominators g [] stamps = stamps" | + "stamps_of_dominators g (nid # nids) stamps = + (case (Predicate.the (condition_of_i_i_o g nid)) of + None stamps_of_dominators g nids stamps | + Some (_, node) stamps_of_dominators g nids + ((registerNewCondition g node (hd stamps)) # stamps))" + +(*code_pred (modes: i ⇒ i ⇒ i ⇒ o ⇒ bool) stamps_of_dominators .*) + +inductive + analyse :: "IRGraph DominatorCache ID (Conditions × StampFlow × DominatorCache) bool" where + "dominators g c nid (doms, c'); + conditions_of_dominators g (sorted_list_of_set doms) [] = conds; + stamps_of_dominators g (sorted_list_of_set doms) [stamp g] = stamps + analyse g c nid (conds, stamps, c')" + +code_pred (modes: i i i o bool) analyse . + +values "{x. dominators ConditionalEliminationTest13_testSnippet2_initial Map.empty 13 x}" +values "{(conds, stamps, c). +analyse ConditionalEliminationTest13_testSnippet2_initial Map.empty 13 (conds, stamps, c)}" +values "{(hd stamps) 1| conds stamps c . +analyse ConditionalEliminationTest13_testSnippet2_initial Map.empty 13 (conds, stamps, c)}" +values "{(hd stamps) 1| conds stamps c . +analyse ConditionalEliminationTest13_testSnippet2_initial Map.empty 27 (conds, stamps, c)}" + +fun next_nid :: "IRGraph ID set ID ID option" where + "next_nid g seen nid = (case (kind g nid) of + (EndNode) Some (any_usage g nid) | + _ nextEdge seen nid g)" + +inductive Step + :: "IRGraph (ID × Seen) (ID × Seen) option bool" for g where - ― ‹ - Hit a BeginNode with an IfNode predecessor which represents - the start of a basic block for the IfNode. - 1. nid' will be the successor of the begin node. - 2. Find the first and only predecessor. - 3. Extract condition from the preceding IfNode. - 4. Negate condition if the begin node is second branch - (we've taken the else branch of the condition) - 5. Add the condition or the negated condition to stack - 6. Perform any stamp updates based on the condition using - the registerNewCondition function and place them on the - top of the stack of stamp information - › - "kind g nid = BeginNode nid'; - - nid seen; - seen' = {nid} seen; - - Some ifcond = pred g nid; - kind g ifcond = IfNode cond t f; - - i = find_index nid (successors_of (kind g ifcond)); - c = (if i = 0 then kind g cond else LogicNegationNode cond); - rep g cond ce; - ce' = (if i = 0 then ce else UnaryExpr UnaryLogicNegation ce); - conds' = ce' # conds; - - flow' = registerNewCondition g c (hdOr flow (stamp g)) - Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow' # flow))" | - - ― ‹ - Hit an EndNode - 1. nid' will be the usage of EndNode - 2. pop the conditions and stamp stack - › - "kind g nid = EndNode; - - nid seen; - seen' = {nid} seen; - - nid' = any_usage g nid; - - conds' = tl conds; - flow' = tl flow - Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow'))" | - - ― ‹We can find a successor edge that is not in seen, go there - "¬(is_EndNode (kind g nid)); - ¬(is_BeginNode (kind g nid)); - - nid seen; - seen' = {nid} seen; - - Some nid' = nextEdge seen' nid g - Step g (nid, seen, conds, flow) (Some (nid', seen', conds, flow))" | - - ― ‹We can cannot find a successor edge that is not in seen, give back None - "¬(is_EndNode (kind g nid)); - ¬(is_BeginNode (kind g nid)); - - nid seen; - seen' = {nid} seen; - - None = nextEdge seen' nid g - Step g (nid, seen, conds, flow) None" | - - ― ‹We've already seen this node, give back None - "nid seen Step g (nid, seen, conds, flow) None" + ― ‹We can find a successor edge that is not in seen, go there› + "seen' = {nid} seen; + + Some nid' = next_nid g seen' nid; + nid' seen' + Step g (nid, seen) (Some (nid', seen'))" | + + ― ‹We can cannot find a successor edge that is not in seen, give back None› + "seen' = {nid} seen; + + None = next_nid g seen' nid + Step g (nid, seen) None" | + + ― ‹We've already seen this node, give back None› + "seen' = {nid} seen; + + Some nid' = next_nid g seen' nid; + nid' seen' Step g (nid, seen) None" code_pred (modes: i i o bool) Step . -text -The ConditionalEliminationPhase relation is responsible for combining -the individual traversal steps from the Step relation and the optimizations -from the ConditionalEliminationStep relation to perform a transformation of the -whole graph. - +fun nextNode :: "IRGraph Seen (ID × Seen) option" where + "nextNode g seen = + (let toSee = sorted_list_of_set {n ids g. n seen} in + case toSee of [] None | (x # xs) Some (x, seen {x}))" -inductive ConditionalEliminationPhase - :: "IRGraph (ID × Seen × Conditions × StampFlow) IRGraph bool" where +values "{x. Step ConditionalEliminationTest13_testSnippet2_initial (17, {17,11,25,21,18,19,15,12,13,6,29,27,24,23,7,8,0}) x}" - ― ‹Can do a step and optimise for the current node - "Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow')); - ConditionalEliminationStep (set conds) (hdOr flow (stamp g)) g nid g'; - - ConditionalEliminationPhase g' (nid', seen', conds', flow') g'' - ConditionalEliminationPhase g (nid, seen, conds, flow) g''" | - ― ‹Can do a step, matches whether optimised or not causing non-determinism - We need to find a way to negate ConditionalEliminationStep - "Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow')); +text ‹ +The @{text "ConditionalEliminationPhase"} relation is responsible for combining +the individual traversal steps from the @{text "Step"} relation and the optimizations +from the @{text "ConditionalEliminationStep"} relation to perform a transformation of the +whole graph. +› + +inductive ConditionalEliminationPhase + :: "(Seen × DominatorCache) IRGraph IRGraph bool" + where + + ― ‹Can do a step and optimise for the current node› + "nextNode g seen = Some (nid, seen'); - ConditionalEliminationPhase g (nid', seen', conds', flow') g' - ConditionalEliminationPhase g (nid, seen, conds, flow) g'" | + analyse g c nid (conds, flow, c'); + ConditionalEliminationStep (set conds) (hd flow) nid g g'; - ― ‹Can't do a step but there is a predecessor we can backtrace to - "Step g (nid, seen, conds, flow) None; - Some nid' = pred g nid; - seen' = {nid} seen; - ConditionalEliminationPhase g (nid', seen', conds, flow) g' - ConditionalEliminationPhase g (nid, seen, conds, flow) g'" | + ConditionalEliminationPhase (seen', c') g' g'' + ConditionalEliminationPhase (seen, c) g g''" | - ― ‹Can't do a step and have no predecessors so terminate - "Step g (nid, seen, conds, flow) None; - None = pred g nid - ConditionalEliminationPhase g (nid, seen, conds, flow) g" + "nextNode g seen = None + ConditionalEliminationPhase (seen, c) g g" -code_pred (modes: i i o bool) ConditionalEliminationPhase . +code_pred (modes: i i o bool) ConditionalEliminationPhase . definition runConditionalElimination :: "IRGraph IRGraph" where "runConditionalElimination g = - (Predicate.the (ConditionalEliminationPhase_i_i_o g (0, {}, ([], []))))" - -(* - + (Predicate.the (ConditionalEliminationPhase_i_i_o ({}, Map.empty) g))" + + +values "{(doms, c')| doms c'. +dominators ConditionalEliminationTest13_testSnippet2_initial Map.empty 6 (doms, c')}" + +values "{(conds, stamps, c)| conds stamps c . +analyse ConditionalEliminationTest13_testSnippet2_initial Map.empty 6 (conds, stamps, c)}" +value " + (nextNode + ConditionalEliminationTest13_testSnippet2_initial {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29}) +" +(* +values "{g|g. (ConditionalEliminationPhase ({}, Map.empty) ConditionalEliminationTest13_testSnippet2_initial g)}" +*) +(* inductive ConditionalEliminationPhaseWithTrace✐‹tag invisible› :: "IRGraph ⇒ (ID × Seen × Conditions × StampFlow) ⇒ ID list ⇒ IRGraph ⇒ ID list ⇒ Conditions ⇒ bool" where✐‹tag invisible› (* Can do a step and optimise for the current nid *) "⟦Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow')); - ConditionalEliminationStep (set conds) (hdOr flow (stamp g)) g nid g'; + ConditionalEliminationStep (set conds) (hdOr flow (stamp g)) nid g g'; ConditionalEliminationPhaseWithTrace g' (nid', seen', conds', flow') (nid # t) g'' t' conds''⟧ ⟹ ConditionalEliminationPhaseWithTrace g (nid, seen, conds, flow) t g'' t' conds''" | @@ -862,207 +1067,346 @@

Theory ConditionalElimination

⟹ ConditionalEliminationPhaseWithTrace g (nid, seen, conds, flow) t g (nid # t) conds" code_pred (modes: i ⇒ i ⇒ i ⇒ o ⇒ o ⇒ o ⇒ bool) ConditionalEliminationPhaseWithTrace . +*)
+ +lemma IfNodeStepE: "g, p (nid, m, h) (nid', m', h) + (cond tb fb val. + kind g nid = IfNode cond tb fb + nid' = (if val_to_bool val then tb else fb) + [g, m, p] cond val m' = m)" + using StepE + by (smt (verit, best) IfNode Pair_inject stepDet) + +lemma ifNodeHasCondEvalStutter: + assumes "(g m p h nid nid')" + assumes "kind g nid = IfNode cond t f" + shows " v. ([g, m, p] cond v)" + using IfNodeStepE assms(1) assms(2) stutter.cases unfolding encodeeval.simps + by (smt (verit, ccfv_SIG) IfNodeCond) + +lemma ifNodeHasCondEval: + assumes "(g, p (nid, m, h) (nid', m', h'))" + assumes "kind g nid = IfNode cond t f" + shows " v. ([g, m, p] cond v)" + using IfNodeStepE assms(1) assms(2) apply auto[1] + by (smt (verit) IRNode.disc(1966) IRNode.distinct(1733) IRNode.distinct(1735) IRNode.distinct(1755) IRNode.distinct(1757) IRNode.distinct(1777) IRNode.distinct(1783) IRNode.distinct(1787) IRNode.distinct(1789) IRNode.distinct(401) IRNode.distinct(755) StutterStep fst_conv ifNodeHasCondEvalStutter is_AbstractEndNode.simps is_EndNode.simps(16) snd_conv step.cases) + +lemma replace_if_t: + assumes "kind g nid = IfNode cond tb fb" + assumes "[g, m, p] cond bool" + assumes "val_to_bool bool" + assumes g': "g' = replace_usages nid tb g" + shows "nid' .(g m p h nid nid') (g' m p h nid nid')" +proof - + have g1step: "g, p (nid, m, h) (tb, m, h)" + by (meson IfNode assms(1) assms(2) assms(3) encodeeval.simps) + have g2step: "g', p (nid, m, h) (tb, m, h)" + using g' unfolding replace_usages.simps + by (simp add: stepRefNode) + from g1step g2step show ?thesis + using StutterStep by blast +qed +lemma replace_if_t_imp: + assumes "kind g nid = IfNode cond tb fb" + assumes "[g, m, p] cond bool" + assumes "val_to_bool bool" + assumes g': "g' = replace_usages nid tb g" + shows "nid' .(g m p h nid nid') (g' m p h nid nid')" + using replace_if_t assms by blast + +lemma replace_if_f: + assumes "kind g nid = IfNode cond tb fb" + assumes "[g, m, p] cond bool" + assumes "¬(val_to_bool bool)" + assumes g': "g' = replace_usages nid fb g" + shows "nid' .(g m p h nid nid') (g' m p h nid nid')" +proof - + have g1step: "g, p (nid, m, h) (fb, m, h)" + by (meson IfNode assms(1) assms(2) assms(3) encodeeval.simps) + have g2step: "g', p (nid, m, h) (fb, m, h)" + using g' unfolding replace_usages.simps + by (simp add: stepRefNode) + from g1step g2step show ?thesis + using StutterStep by blast +qed -lemma IfNodeStepE: "g, p ⊢ (nid, m, h) → (nid', m', h) ⟹ - (⋀cond tb fb val. - kind g nid = IfNode cond tb fb ⟹ - nid' = (if val_to_bool val then tb else fb) ⟹ - [g, m, p] ⊢ kind g cond ↦ val ⟹ m' = m)" - using StepE - by (smt (verit, best) IfNode Pair_inject stepDet) - -lemma ifNodeHasCondEvalStutter: - assumes "(g m p h ⊢ nid ↝ nid')" - assumes "kind g nid = IfNode cond t f" - shows "∃ v. ([g, m, p] ⊢ kind g cond ↦ v)" - using IfNodeStepE assms(1) assms(2) stutter.cases - by (meson IfNodeCond) - -lemma ifNodeHasCondEval: - assumes "(g, p ⊢ (nid, m, h) → (nid', m', h'))" - assumes "kind g nid = IfNode cond t f" - shows "∃ v. ([g, m, p] ⊢ kind g cond ↦ v)" - using IfNodeStepE assms(1) assms(2) - by (smt (z3) IRNode.disc(932) IRNode.simps(938) IRNode.simps(958) IRNode.simps(972) IRNode.simps(974) IRNode.simps(978) Pair_inject StutterStep ifNodeHasCondEvalStutter is_AbstractEndNode.simps is_EndNode.simps(12) step.cases) - - -lemma replace_if_t: - assumes "kind g nid = IfNode cond tb fb" - assumes "[g, m, p] ⊢ kind g cond ↦ bool" - assumes "val_to_bool bool" - assumes g': "g' = replace_usages nid tb g" - shows "∃nid' .(g m p h ⊢ nid ↝ nid') ⟷ (g' m p h ⊢ nid ↝ nid')" -proof - - have g1step: "g, p ⊢ (nid, m, h) → (tb, m, h)" - by (meson IfNode assms(1) assms(2) assms(3)) - have g2step: "g', p ⊢ (nid, m, h) → (tb, m, h)" - using g' unfolding replace_usages.simps - by (simp add: stepRefNode) - from g1step g2step show ?thesis - using StutterStep by blast -qed - -lemma replace_if_t_imp: - assumes "kind g nid = IfNode cond tb fb" - assumes "[g, m, p] ⊢ kind g cond ↦ bool" - assumes "val_to_bool bool" - assumes g': "g' = replace_usages nid tb g" - shows "∃nid' .(g m p h ⊢ nid ↝ nid') ⟶ (g' m p h ⊢ nid ↝ nid')" - using replace_if_t assms by blast - -lemma replace_if_f: - assumes "kind g nid = IfNode cond tb fb" - assumes "[g, m, p] ⊢ kind g cond ↦ bool" - assumes "¬(val_to_bool bool)" - assumes g': "g' = replace_usages nid fb g" - shows "∃nid' .(g m p h ⊢ nid ↝ nid') ⟷ (g' m p h ⊢ nid ↝ nid')" -proof - - have g1step: "g, p ⊢ (nid, m, h) → (fb, m, h)" - by (meson IfNode assms(1) assms(2) assms(3)) - have g2step: "g', p ⊢ (nid, m, h) → (fb, m, h)" - using g' unfolding replace_usages.simps - by (simp add: stepRefNode) - from g1step g2step show ?thesis - using StutterStep by blast -qed - -text ‹ +text ‹ Prove that the individual conditional elimination rules are correct with respect to preservation of stuttering steps. -› -lemma ConditionalEliminationStepProof: - assumes wg: "wf_graph g" - assumes ws: "wf_stamps g" - assumes wv: "wf_values g" - assumes nid: "nid ∈ ids g" - assumes conds_valid: "∀ c ∈ conds . ∃ v. ([g, m, p] ⊢ c ↦ v) ∧ val_to_bool v" - assumes ce: "ConditionalEliminationStep conds stamps g nid g'" - - shows "∃nid' .(g m p h ⊢ nid ↝ nid') ⟶ (g' m p h ⊢ nid ↝ nid')" - using ce using assms -proof (induct g nid g' rule: ConditionalEliminationStep.induct) - case (impliesTrue g ifcond cid t f cond conds g') - show ?case proof (cases "(g m p h ⊢ ifcond ↝ nid')") - case True - obtain condv where condv: "[g, m, p] ⊢ kind g cid ↦ condv" - using implies.simps impliesTrue.hyps(3) impliesTrue.prems(4) - using impliesTrue.hyps(2) True - by (metis ifNodeHasCondEvalStutter impliesTrue.hyps(1)) - have condvTrue: "val_to_bool condv" - by (metis condition_implies.intros(2) condv impliesTrue.hyps(2) impliesTrue.hyps(3) impliesTrue.prems(1) impliesTrue.prems(3) impliesTrue.prems(5) implies_true_valid) - then show ?thesis - using constantConditionValid - using impliesTrue.hyps(1) condv impliesTrue.hyps(4) - by blast - next - case False - then show ?thesis by auto - qed -next - case (impliesFalse g ifcond cid t f cond conds g') - then show ?case - proof (cases "(g m p h ⊢ ifcond ↝ nid')") - case True - obtain condv where condv: "[g, m, p] ⊢ kind g cid ↦ condv" - using ifNodeHasCondEvalStutter impliesFalse.hyps(1) - using True by blast - have condvFalse: "False = val_to_bool condv" - by (metis condition_implies.intros(2) condv impliesFalse.hyps(2) impliesFalse.hyps(3) impliesFalse.prems(1) impliesFalse.prems(3) impliesFalse.prems(5) implies_false_valid) - then show ?thesis - using constantConditionValid - using impliesFalse.hyps(1) condv impliesFalse.hyps(4) - by blast - next - case False - then show ?thesis - by auto - qed -next - case (tryFoldTrue g ifcond cid t f cond g' conds) - then show ?case using constantConditionValid tryFoldProofTrue - using StutterStep constantConditionTrue by metis -next - case (tryFoldFalse g ifcond cid t f cond g' conds) - then show ?case using constantConditionValid tryFoldProofFalse - using StutterStep constantConditionFalse by metis -qed +› +lemma ConditionalEliminationStepProof: + assumes wg: "wf_graph g" + assumes ws: "wf_stamps g" + assumes wv: "wf_values g" + assumes nid: "nid ids g" + assumes conds_valid: " c conds . v. ([m, p] c v) val_to_bool v" + assumes ce: "ConditionalEliminationStep conds stamps nid g g'" + + shows "nid' .(g m p h nid nid') (g' m p h nid nid')" + using ce using assms +proof (induct nid g g' rule: ConditionalEliminationStep.induct) + case (impliesTrue g ifcond cid t f cond conds g') + show ?case proof (cases "nid'. (g m p h ifcond nid')") + case True + show ?thesis + by (metis StutterStep constantConditionNoIf constantConditionTrue impliesTrue.hyps(5)) + next + case False + then show ?thesis by auto + qed +next + case (impliesFalse g ifcond cid t f cond conds g') + then show ?case + proof (cases "nid'. (g m p h ifcond nid')") + case True + then show ?thesis + by (metis StutterStep constantConditionFalse constantConditionNoIf impliesFalse.hyps(5)) + next + case False + then show ?thesis + by auto + qed +next + case (unknown g ifcond cid t f cond condNode conds stamps) + then show ?case + by blast +next + case (notIfNode g ifcond conds stamps) + then show ?case + by blast +qed -text ‹ +text ‹ Prove that the individual conditional elimination rules are correct with respect to finding a bisimulation between the unoptimized and optimized graphs. -› -lemma ConditionalEliminationStepProofBisimulation: - assumes wf: "wf_graph g ∧ wf_stamp g stamps ∧ wf_values g" - assumes nid: "nid ∈ ids g" - assumes conds_valid: "∀ c ∈ conds . ∃ v. ([g, m, p] ⊢ c ↦ v) ∧ val_to_bool v" - assumes ce: "ConditionalEliminationStep conds stamps g nid g'" - assumes gstep: "∃ h nid'. (g, p ⊢ (nid, m, h) → (nid', m, h))" (* we don't yet consider optimizations which produce a step that didn't already exist *) - - shows "nid | g ∼ g'" - using ce gstep using assms -proof (induct g nid g' rule: ConditionalEliminationStep.induct) - case (impliesTrue g ifcond cid t f cond conds g' stamps) - from impliesTrue(5) obtain h where gstep: "g, p ⊢ (ifcond, m, h) → (t, m, h)" - by (metis IfNode StutterStep condition_implies.intros(2) ifNodeHasCondEvalStutter impliesTrue.hyps(1) impliesTrue.hyps(2) impliesTrue.hyps(3) impliesTrue.prems(2) impliesTrue.prems(4) implies_true_valid) - have "g', p ⊢ (ifcond, m, h) → (t, m, h)" - using constantConditionTrue impliesTrue.hyps(1) impliesTrue.hyps(4) by blast - then show ?case using gstep - by (metis stepDet strong_noop_bisimilar.intros) -next - case (impliesFalse g ifcond cid t f cond conds g' stamps) - from impliesFalse(5) obtain h where gstep: "g, p ⊢ (ifcond, m, h) → (f, m, h)" - by (metis IfNode condition_implies.intros(2) ifNodeHasCondEval impliesFalse.hyps(1) impliesFalse.hyps(2) impliesFalse.hyps(3) impliesFalse.prems(2) impliesFalse.prems(4) implies_false_valid) - have "g', p ⊢ (ifcond, m, h) → (f, m, h)" - using constantConditionFalse impliesFalse.hyps(1) impliesFalse.hyps(4) by blast - then show ?case using gstep - by (metis stepDet strong_noop_bisimilar.intros) -next - case (tryFoldTrue g ifcond cid t f cond stamps g' conds) - from tryFoldTrue(5) obtain val where "[g, m, p] ⊢ kind g cid ↦ val" - using ifNodeHasCondEval tryFoldTrue.hyps(1) by blast - then have "val_to_bool val" - using tryFoldProofTrue tryFoldTrue.prems(2) tryFoldTrue(3) - by blast - then obtain h where gstep: "g, p ⊢ (ifcond, m, h) → (t, m, h)" - using tryFoldTrue(5) - by (meson IfNode ‹[g, m, p] ⊢ kind g cid ↦ val› tryFoldTrue.hyps(1)) - have "g', p ⊢ (ifcond, m, h) → (t, m, h)" - using constantConditionTrue tryFoldTrue.hyps(1) tryFoldTrue.hyps(4) by presburger - then show ?case using gstep - by (metis stepDet strong_noop_bisimilar.intros) -next - case (tryFoldFalse g ifcond cid t f cond stamps g' conds) - from tryFoldFalse(5) obtain h where gstep: "g, p ⊢ (ifcond, m, h) → (f, m, h)" - by (meson IfNode ifNodeHasCondEval tryFoldFalse.hyps(1) tryFoldFalse.hyps(3) tryFoldFalse.prems(2) tryFoldProofFalse) - have "g', p ⊢ (ifcond, m, h) → (f, m, h)" - using constantConditionFalse tryFoldFalse.hyps(1) tryFoldFalse.hyps(4) by blast - then show ?case using gstep - by (metis stepDet strong_noop_bisimilar.intros) -qed - +› +lemma ConditionalEliminationStepProofBisimulation: + assumes wf: "wf_graph g wf_stamp g stamps wf_values g" + assumes nid: "nid ids g" + assumes conds_valid: " c conds . v. ([m, p] c v) val_to_bool v" + assumes ce: "ConditionalEliminationStep conds stamps nid g g'" + assumes gstep: " h nid'. (g, p (nid, m, h) (nid', m, h))" (* we don't yet consider optimizations which produce a step that didn't already exist *) + + shows "nid | g g'" + using ce gstep using assms +proof (induct nid g g' rule: ConditionalEliminationStep.induct) + case (impliesTrue g ifcond cid t f cond condNode conds stamps g') + from impliesTrue(5) obtain h where gstep: "g, p (ifcond, m, h) (t, m, h)" + using IfNode encodeeval.simps ifNodeHasCondEval impliesTrue.hyps(1) impliesTrue.hyps(2) impliesTrue.hyps(3) impliesTrue.prems(4) implies_impliesnot_valid implies_valid.simps repDet + by (smt (verit) conds_implies.elims condset_implies.simps impliesTrue.hyps(4) impliesTrue.prems(1) impliesTrue.prems(2) option.distinct(1) option.inject tryFoldTrue_valid) + have "g', p (ifcond, m, h) (t, m, h)" + using constantConditionTrue impliesTrue.hyps(1) impliesTrue.hyps(5) by blast + then show ?case using gstep + by (metis stepDet strong_noop_bisimilar.intros) +next + case (impliesFalse g ifcond cid t f cond condNode conds stamps g') + from impliesFalse(5) obtain h where gstep: "g, p (ifcond, m, h) (f, m, h)" + using IfNode encodeeval.simps ifNodeHasCondEval impliesFalse.hyps(1) impliesFalse.hyps(2) impliesFalse.hyps(3) impliesFalse.prems(4) implies_impliesnot_valid impliesnot_valid.simps repDet + by (smt (verit) conds_implies.elims condset_implies.simps impliesFalse.hyps(4) impliesFalse.prems(1) impliesFalse.prems(2) option.distinct(1) option.inject tryFoldFalse_valid) + have "g', p (ifcond, m, h) (f, m, h)" + using constantConditionFalse impliesFalse.hyps(1) impliesFalse.hyps(5) by blast + then show ?case using gstep + by (metis stepDet strong_noop_bisimilar.intros) +next + case (unknown g ifcond cid t f cond condNode conds stamps) + then show ?case + using strong_noop_bisimilar.simps by presburger +next + case (notIfNode g ifcond conds stamps) + then show ?case + using strong_noop_bisimilar.simps by presburger +qed -text ‹Mostly experimental proofs from here on out.› -experiment begin -lemma if_step: +experiment begin +(*lemma if_step: assumes "nid ∈ ids g" assumes "(kind g nid) ∈ control_nodes" shows "(g m p h ⊢ nid ↝ nid')" using assms apply (cases "kind g nid") sorry +*) +(* +definition blockNodes :: "IRGraph ⇒ Block ⇒ ID set" where + "blockNodes g b = {n ∈ ids g. blockOf g n = b}" + +lemma phiInCFG: + "∀n ∈ blockNodes g nid. (g, p ⊢ (n, m, h) → (n', m', h'))" +*) + +lemma inverse_succ: + "n' (succ g n). n ids g n (predecessors g n')" + by simp + +lemma sequential_successors: + assumes "is_sequential_node n" + shows "successors_of n []" + using assms by (cases n; auto) + +lemma nid'_succ: + assumes "nid ids g" + assumes "¬(is_AbstractEndNode (kind g nid0))" + assumes "g, p (nid0, m0, h0) (nid, m, h)" + shows "nid succ g nid0" + using assms(3) proof (induction "(nid0, m0, h0)" "(nid, m, h)" rule: step.induct) + case SequentialNode + then show ?case + by (metis length_greater_0_conv nth_mem sequential_successors succ.simps) +next + case (FixedGuardNode cond before val) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_FixedGuardNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + using FixedGuardNode.hyps(5) by blast +next + case (BytecodeExceptionNode args st exceptionType ref) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_BytecodeExceptionNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (IfNode cond tb fb val) + then have "{tb, fb} = succ g nid0" + using IRNodes.successors_of_IfNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by (metis IfNode.hyps(3) insert_iff) +next + case (EndNodes i phis inps vs) + then show ?case using assms(2) by blast +next + case (NewArrayNode len st length' arrayType h' ref refNo) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_NewArrayNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (ArrayLengthNode x ref arrayVal length') + then have "{nid} = succ g nid0" + using IRNodes.successors_of_ArrayLengthNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (LoadIndexedNode index guard array indexVal ref arrayVal loaded) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_LoadIndexedNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (StoreIndexedNode check val st index guard array indexVal ref "value" arrayVal updated) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_StoreIndexedNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (NewInstanceNode cname obj ref) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_NewInstanceNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (LoadFieldNode f obj ref) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_LoadFieldNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (SignedDivNode x y zero sb v1 v2) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_SignedDivNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (SignedRemNode x y zero sb v1 v2) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_SignedRemNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (StaticLoadFieldNode f) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_LoadFieldNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (StoreFieldNode _ _ _ _ _ _) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_StoreFieldNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (StaticStoreFieldNode _ _ _ _) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_StoreFieldNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +qed +lemma nid'_pred: + assumes "nid ids g" + assumes "¬(is_AbstractEndNode (kind g nid0))" + assumes "g, p (nid0, m0, h0) (nid, m, h)" + shows "nid0 predecessors g nid" + using assms + by (meson inverse_succ nid'_succ step_in_ids) + +definition wf_pred: + "wf_pred g = (n ids g. card (predecessors g n) = 1)" + +lemma + assumes "¬(is_AbstractMergeNode (kind g n'))" + assumes "wf_pred g" + shows "v. predecessors g n = {v} pred g n' = Some v" + using assms unfolding pred.simps sorry + +lemma inverse_succ1: + assumes "¬(is_AbstractEndNode (kind g n'))" + assumes "wf_pred g" + shows "n' (succ g n). n ids g Some n = (pred g n')" + using assms sorry + +lemma BeginNodeFlow: + assumes "g, p (nid0, m0, h0) (nid, m, h)" + assumes "Some ifcond = pred g nid" + assumes "kind g ifcond = IfNode cond t f" + assumes "i = find_index nid (successors_of (kind g ifcond))" + shows "i = 0 ([g, m, p] cond v) val_to_bool v" +proof - + obtain tb fb where "[tb, fb] = successors_of (kind g ifcond)" + by (simp add: assms(3)) + have "nid0 = ifcond" + using assms step.IfNode sorry + show ?thesis sorry +qed + +(* lemma StepConditionsValid: - assumes "∀ cond ∈ set conds. ([g, m, p] ⊢ cond ↦ v) ∧ val_to_bool v" + assumes "∀ cond ∈ set conds. ([m, p] ⊢ cond ↦ v) ⟶ val_to_bool v" + assumes "g, p ⊢ (nid0, m0, h0) → (nid, m, h)" assumes "Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow'))" - shows "∀ cond ∈ set conds'. ([g, m, p] ⊢ cond ↦ v) ∧ val_to_bool v" - using assms(2) + shows "∀ cond ∈ set conds'. ([m, p] ⊢ cond ↦ v) ⟶ val_to_bool v" + using assms(3) proof (induction "(nid, seen, conds, flow)" "Some (nid', seen', conds', flow')" rule: Step.induct) - case (1 ifcond cond t f i c) - obtain cv where cv: "[g, m, p] ⊢ c ↦ cv" - sorry + case (1 ifcond cond t f i c ce ce' flow') + assume "∃cv. [m, p] ⊢ ce ↦ cv" + then obtain cv where "[m, p] ⊢ ce ↦ cv" + by blast have cvt: "val_to_bool cv" - sorry + using assms(2) sorry have "set conds' = {c} ∪ set conds" using "1.hyps"(8) by auto then show ?case using cv cvt assms(1) sorry @@ -1103,10 +1447,12 @@

Theory ConditionalElimination

then show ?case sorry qed qed -end -
*)
+*) + +end -end
+
end +
\ No newline at end of file diff --git a/ConditionalElimination/document.pdf b/ConditionalElimination/document.pdf index e7a3f475..177f6d87 100644 Binary files a/ConditionalElimination/document.pdf and b/ConditionalElimination/document.pdf differ diff --git a/ConditionalElimination/index.html b/ConditionalElimination/index.html index 418f94c1..bb62130e 100644 --- a/ConditionalElimination/index.html +++ b/ConditionalElimination/index.html @@ -3,7 +3,7 @@ -Session ConditionalElimination (Isabelle2022) +Session ConditionalElimination (Isabelle2023) @@ -12,7 +12,8 @@

Session ConditionalElimination

View theory dependencies
-View document

+View document
+View outline

@@ -20,6 +21,8 @@

Theories

diff --git a/ConditionalElimination/outline.pdf b/ConditionalElimination/outline.pdf new file mode 100644 index 00000000..c910cc07 Binary files /dev/null and b/ConditionalElimination/outline.pdf differ diff --git a/ConditionalElimination/session_graph.pdf b/ConditionalElimination/session_graph.pdf index ba4644cf..1050bf4a 100644 Binary files a/ConditionalElimination/session_graph.pdf and b/ConditionalElimination/session_graph.pdf differ diff --git a/Document/.browser_info/build_uuid b/Document/.browser_info/build_uuid index b00ace5f..c84274f9 100644 --- a/Document/.browser_info/build_uuid +++ b/Document/.browser_info/build_uuid @@ -1 +1 @@ -702f3a78-eaae-4de6-bfea-98f6e5fc1747 \ No newline at end of file +9410185a-1397-4e37-823e-e573c61b1bda \ No newline at end of file diff --git a/Document/ConditionalElimination.ConditionalElimination.html b/Document/ConditionalElimination.ConditionalElimination.html index bcd5bb31..d29867c6 100644 --- a/Document/ConditionalElimination.ConditionalElimination.html +++ b/Document/ConditionalElimination.ConditionalElimination.html @@ -12,46 +12,86 @@

Theory ConditionalElimination.ConditionalElimination

-
section Conditional Elimination Phase
+
section ‹Conditional Elimination Phase›
+
+text ‹
+This theory presents the specification of the \texttt{ConditionalElimination} phase
+within the GraalVM compiler.
+The \texttt{ConditionalElimination} phase simplifies any condition of an \textsl{if}
+statement that can be implied by the conditions that dominate it.
+Such that if condition A implies that condition B \textsl{must} be true,
+the condition B is simplified to \texttt{true}.
+
+\begin{lstlisting}[language=java]
+if (A) {
+  if (B) {
+    ...
+  }
+}
+\end{lstlisting}
+
+We begin by defining the individual implication rules used by the phase
+in \ref{sec:rules}.
+These rules are then lifted to the rewriting of a condition within an \textsl{if}
+statement in \ref{sec:lift}.
+The traversal algorithm used by the compiler is specified in \ref{sec:traversal}.
+›
 
 theory ConditionalElimination
   imports
     Semantics.IRTreeEvalThms
     Proofs.Rewrites
     Proofs.Bisimulation
+    OptimizationDSL.Markup
 begin
 
-subsection Individual Elimination Rules
-
-text The set of rules used for determining whether a condition @{term q1} implies
-    another condition @{term q2} or its negation.
-    These rules are used for conditional elimination.
-
-inductive impliesx :: "IRExpr  IRExpr  bool" ("_  _") and 
-      impliesnot :: "IRExpr  IRExpr  bool" ("_ ⇛¬ _") where
-  q_imp_q: 
-  "q  q" |
-  eq_impliesnot_less:
-  "(BinaryExpr BinIntegerEquals x y) ⇛¬ (BinaryExpr BinIntegerLessThan x y)" |
-  eq_impliesnot_less_rev:
-  "(BinaryExpr BinIntegerEquals x y) ⇛¬ (BinaryExpr BinIntegerLessThan y x)" |
-  less_impliesnot_rev_less:
-  "(BinaryExpr BinIntegerLessThan x y) ⇛¬ (BinaryExpr BinIntegerLessThan y x)" |
-  less_impliesnot_eq:
-  "(BinaryExpr BinIntegerLessThan x y) ⇛¬ (BinaryExpr BinIntegerEquals x y)" |
-  less_impliesnot_eq_rev:
-  "(BinaryExpr BinIntegerLessThan x y) ⇛¬ (BinaryExpr BinIntegerEquals y x)" |
-  negate_true:
-  "x ⇛¬ y  x  (UnaryExpr UnaryLogicNegation y)" |
-  negate_false:
-  "x  y  x ⇛¬ (UnaryExpr UnaryLogicNegation y)"
-
-text The relation @{term "q1  q2"} indicates that the implication @{term "q1  q2"}
-    is known true (i.e. universally valid), 
-    and the relation @{term "q1 ⇛¬ q2"} indicates that the implication @{term "q1  q2"}
-    is known false (i.e. @{term "q1 ¬ q2"} is universally valid.
-    If neither @{term "q1  q2"} nor @{term "q1 ⇛¬ q2"} then the status is unknown.
-    Only the known true and known false cases can be used for conditional elimination.
+declare [[show_types=false]]
+
+subsection ‹Implication Rules \label{sec:rules}›
+
+text ‹
+The set of rules used for determining whether a condition, @{term q1},
+ implies another condition, @{term q2}, must be true or false.
+›
+
+subsubsection ‹Structural Implication›
+
+text ‹
+The first method for determining if a condition can be implied by another condition,
+is structural implication.
+That is, by looking at the structure of the conditions, we can determine the truth value.
+For instance, @{term "x == y"} implies that @{term "x < y"} cannot be true.
+›
+
+inductive 
+  impliesx :: "IRExpr  IRExpr  bool" ("_  _") and 
+  impliesnot :: "IRExpr  IRExpr  bool" ("_ ⇛¬ _") where
+  same:          "q  q" |
+  eq_not_less:   "exp[x eq y] ⇛¬ exp[x < y]" |
+  eq_not_less':  "exp[x eq y] ⇛¬ exp[y < x]" |
+  less_not_less: "exp[x < y] ⇛¬ exp[y < x]" |
+  less_not_eq:   "exp[x < y] ⇛¬ exp[x eq y]" |
+  less_not_eq':  "exp[x < y] ⇛¬ exp[y eq x]" |
+  negate_true:   "x ⇛¬ y  x  exp[!y]" |
+  negate_false:  "x  y  x ⇛¬ exp[!y]"
+
+inductive implies_complete :: "IRExpr  IRExpr  bool option  bool" where
+  implies:
+  "x  y  implies_complete x y (Some True)" |
+  impliesnot:
+  "x ⇛¬ y  implies_complete x y (Some False)" |
+  fail:
+  "¬((x  y)  (x ⇛¬ y))  implies_complete x y None"
+
+
+text ‹
+The relation @{term "q1  q2"} requires that the implication @{term "q1  q2"}
+is known true (i.e. universally valid).
+The relation @{term "q1 ⇛¬ q2"} requires that the implication @{term "q1  q2"}
+is known false (i.e. @{term "q1 ¬ q2"} is universally valid).
+If neither @{term "q1  q2"} nor @{term "q1 ⇛¬ q2"} then the status is unknown
+and the condition cannot be simplified.
+›
 
 fun implies_valid :: "IRExpr  IRExpr  bool" (infix "" 50) where
   "implies_valid q1 q2 = 
@@ -63,377 +103,163 @@ 

Theory ConditionalElimination.ConditionalElimination

(m p v1 v2. ([m, p] q1 v1) ([m,p] q2 v2) (val_to_bool v1 ¬val_to_bool v2))"
-text The relation @{term "q1 q2"} means @{term "q1 q2"} is universally valid, - and the relation @{term "q1 q2"} means @{term "q1 ¬q2"} is universally valid. +text ‹ +The relation @{term "q1 q2"} means @{term "q1 q2"} is universally valid, +and the relation @{term "q1 q2"} means @{term "q1 ¬q2"} is universally valid. +› -lemma eq_impliesnot_less_helper: - "v1 = v2 ¬(int_signed_value b v1 < int_signed_value b v2)" - by force - -lemma eq_impliesnot_less_val: - "val_to_bool(intval_equals v1 v2) ¬val_to_bool(intval_less_than v1 v2)" -proof - - have unfoldEqualDefined: "(intval_equals v1 v2 UndefVal) +lemma eq_not_less_val: + "val_to_bool(val[v1 eq v2]) ¬val_to_bool(val[v1 < v2])" + proof - + have unfoldEqualDefined: "(intval_equals v1 v2 UndefVal) (val_to_bool(intval_equals v1 v2) (¬(val_to_bool(intval_less_than v1 v2))))" - subgoal premises p + subgoal premises p proof - - obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" - by (metis array_length.cases intval_equals.simps(2,3,4,5) p) - obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" - by (metis Value.exhaust_sel intval_equals.simps(6,7,8,9) p) - have sameWidth: "v1b=v2b" - by (metis bool_to_val_bin.simps intval_equals.simps(1) p v1v v2v) - have unfoldEqual: "intval_equals v1 v2 = (bool_to_val (v1v=v2v))" - by (simp add: sameWidth v1v v2v) - have unfoldLessThan: "intval_less_than v1 v2 = (bool_to_val (int_signed_value v1b v1v < int_signed_value v2b v2v))" - by (simp add: sameWidth v1v v2v) - have val: "((v1v=v2v)) (¬((int_signed_value v1b v1v < int_signed_value v2b v2v)))" - using sameWidth by auto - have doubleCast0: "val_to_bool (bool_to_val ((v1v = v2v))) = (v1v = v2v)" + obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" + by (metis array_length.cases intval_equals.simps(2,3,4,5) p) + obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" + by (metis Value.exhaust_sel intval_equals.simps(6,7,8,9) p) + have sameWidth: "v1b=v2b" + by (metis bool_to_val_bin.simps intval_equals.simps(1) p v1v v2v) + have unfoldEqual: "intval_equals v1 v2 = (bool_to_val (v1v=v2v))" + by (simp add: sameWidth v1v v2v) + have unfoldLessThan: "intval_less_than v1 v2 = (bool_to_val (int_signed_value v1b v1v < int_signed_value v2b v2v))" + by (simp add: sameWidth v1v v2v) + have val: "((v1v=v2v)) (¬((int_signed_value v1b v1v < int_signed_value v2b v2v)))" + using sameWidth by auto + have doubleCast0: "val_to_bool (bool_to_val ((v1v = v2v))) = (v1v = v2v)" using bool_to_val.elims val_to_bool.simps(1) by fastforce - have doubleCast1: "val_to_bool (bool_to_val ((int_signed_value v1b v1v < int_signed_value v2b v2v))) = + have doubleCast1: "val_to_bool (bool_to_val ((int_signed_value v1b v1v < int_signed_value v2b v2v))) = (int_signed_value v1b v1v < int_signed_value v2b v2v)" using bool_to_val.elims val_to_bool.simps(1) by fastforce then show ?thesis - using p val unfolding unfoldEqual unfoldLessThan doubleCast0 doubleCast1 by blast + using p val unfolding unfoldEqual unfoldLessThan doubleCast0 doubleCast1 by blast qed done show ?thesis - by (metis Value.distinct(1) val_to_bool.elims(2) unfoldEqualDefined) + by (metis Value.distinct(1) val_to_bool.elims(2) unfoldEqualDefined) qed -lemma eq_impliesnot_less_rev_val: - "val_to_bool(intval_equals v1 v2) ¬val_to_bool(intval_less_than v2 v1)" +lemma eq_not_less'_val: + "val_to_bool(val[v1 eq v2]) ¬val_to_bool(val[v2 < v1])" proof - - have a: "intval_equals v1 v2 = intval_equals v2 v1" + have a: "intval_equals v1 v2 = intval_equals v2 v1" apply (cases "intval_equals v1 v2 = UndefVal") apply (smt (z3) bool_to_val_bin.simps intval_equals.elims intval_equals.simps) - subgoal premises p + subgoal premises p proof - - obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" - by (metis Value.exhaust_sel intval_equals.simps(2,3,4,5) p) + obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" + by (metis Value.exhaust_sel intval_equals.simps(2,3,4,5) p) obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" - by (metis Value.exhaust_sel intval_equals.simps(6,7,8,9) p) + by (metis Value.exhaust_sel intval_equals.simps(6,7,8,9) p) then show ?thesis - by (smt (verit) bool_to_val_bin.simps intval_equals.simps(1) v1v) + by (smt (verit) bool_to_val_bin.simps intval_equals.simps(1) v1v) qed done show ?thesis - using a eq_impliesnot_less_val by presburger + using a eq_not_less_val by presburger qed -lemma less_impliesnot_rev_less_val: - "val_to_bool(intval_less_than v1 v2) ¬val_to_bool(intval_less_than v2 v1)" +lemma less_not_less_val: + "val_to_bool(val[v1 < v2]) ¬val_to_bool(val[v2 < v1])" apply (rule impI) - subgoal premises p + subgoal premises p proof - - obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" - by (metis Value.exhaust_sel intval_less_than.simps(2,3,4,5) p val_to_bool.simps(2)) - obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" - by (metis Value.exhaust_sel intval_less_than.simps(6,7,8,9) p val_to_bool.simps(2)) - then have unfoldLessThanRHS: "intval_less_than v2 v1 = + obtain v1b v1v where v1v: "v1 = IntVal v1b v1v" + by (metis Value.exhaust_sel intval_less_than.simps(2,3,4,5) p val_to_bool.simps(2)) + obtain v2b v2v where v2v: "v2 = IntVal v2b v2v" + by (metis Value.exhaust_sel intval_less_than.simps(6,7,8,9) p val_to_bool.simps(2)) + then have unfoldLessThanRHS: "intval_less_than v2 v1 = (bool_to_val (int_signed_value v2b v2v < int_signed_value v1b v1v))" - using p v1v by force - then have unfoldLessThanLHS: "intval_less_than v1 v2 = + using p v1v by force + then have unfoldLessThanLHS: "intval_less_than v1 v2 = (bool_to_val (int_signed_value v1b v1v < int_signed_value v2b v2v))" - using bool_to_val_bin.simps intval_less_than.simps(1) p v1v v2v val_to_bool.simps(2) by auto + using bool_to_val_bin.simps intval_less_than.simps(1) p v1v v2v val_to_bool.simps(2) by auto then have symmetry: "(int_signed_value v2b v2v < int_signed_value v1b v1v) (¬(int_signed_value v1b v1v < int_signed_value v2b v2v))" by simp then show ?thesis - using p unfoldLessThanLHS unfoldLessThanRHS by fastforce + using p unfoldLessThanLHS unfoldLessThanRHS by fastforce qed done -lemma less_impliesnot_eq_val: - "val_to_bool(intval_less_than v1 v2) ¬val_to_bool(intval_equals v1 v2)" - using eq_impliesnot_less_val by blast +lemma less_not_eq_val: + "val_to_bool(val[v1 < v2]) ¬val_to_bool(val[v1 eq v2])" + using eq_not_less_val by blast -lemma logic_negate_type: +lemma logic_negate_type: assumes "[m, p] UnaryExpr UnaryLogicNegation x v" shows "b v2. [m, p] x IntVal b v2" - by (metis assms UnaryExprE intval_logic_negation.elims unary_eval.simps(4)) + using assms + by (metis UnaryExprE intval_logic_negation.elims unary_eval.simps(4)) -lemma intval_logic_negation_inverse: +lemma intval_logic_negation_inverse: assumes "b > 0" assumes "x = IntVal b v" shows "val_to_bool (intval_logic_negation x) ¬(val_to_bool x)" - by (cases x; auto simp: logic_negate_def assms) + using assms by (cases x; auto simp: logic_negate_def) -lemma logic_negation_relation_tree: +lemma logic_negation_relation_tree: assumes "[m, p] y val" assumes "[m, p] UnaryExpr UnaryLogicNegation y invval" shows "val_to_bool val ¬(val_to_bool invval)" - by (metis UnaryExprE evalDet eval_bits_1_64 logic_negate_type unary_eval.simps(4) assms - intval_logic_negation_inverse) + using assms using intval_logic_negation_inverse + by (metis UnaryExprE evalDet eval_bits_1_64 logic_negate_type unary_eval.simps(4)) -text The following theorem shows that the known true/false rules are valid. +text ‹The following theorem show that the known true/false rules are valid.› theorem implies_impliesnot_valid: shows "((q1 q2) (q1 q2)) ((q1 ⇛¬ q2) (q1 q2))" (is "(?imp ?val) (?notimp ?notval)") proof (induct q1 q2 rule: impliesx_impliesnot.induct) - case (q_imp_q q) + case (same q) then show ?case using evalDet by fastforce next - case (eq_impliesnot_less x y) - then show ?case - apply auto using eq_impliesnot_less_val evalDet by blast + case (eq_not_less x y) + then show ?case apply auto[1] using eq_not_less_val evalDet by blast next - case (eq_impliesnot_less_rev x y) - then show ?case - apply auto using eq_impliesnot_less_rev_val evalDet by blast + case (eq_not_less' x y) + then show ?case apply auto[1] using eq_not_less'_val evalDet by blast next - case (less_impliesnot_rev_less x y) - then show ?case - apply auto using less_impliesnot_rev_less_val evalDet by blast + case (less_not_less x y) + then show ?case apply auto[1] using less_not_less_val evalDet by blast next - case (less_impliesnot_eq x y) - then show ?case - apply auto using less_impliesnot_eq_val evalDet by blast + case (less_not_eq x y) + then show ?case apply auto[1] using less_not_eq_val evalDet by blast next - case (less_impliesnot_eq_rev x y) - then show ?case - apply auto by (metis eq_impliesnot_less_rev_val evalDet) + case (less_not_eq' x y) + then show ?case apply auto[1] using eq_not_less'_val evalDet by metis next case (negate_true x y) - then show ?case - apply auto by (metis logic_negation_relation_tree unary_eval.simps(4) unfold_unary) + then show ?case apply auto[1] + by (metis logic_negation_relation_tree unary_eval.simps(4) unfold_unary) next case (negate_false x y) - then show ?case - apply auto by (metis UnaryExpr logic_negation_relation_tree unary_eval.simps(4)) + then show ?case apply auto[1] + by (metis UnaryExpr logic_negation_relation_tree unary_eval.simps(4)) qed -text -We introduce a type @{term "TriState"} (as in the GraalVM compiler) to represent when static -analysis can tell us information about the value of a Boolean expression. -If @{term "Unknown"} then no information can be inferred and if -@{term "KnownTrue"}/@{term "KnownFalse"} one can infer the expression is always true/false. - -datatype TriState = Unknown | KnownTrue | KnownFalse - -text -The implies relation corresponds to the LogicNode.implies -method from the compiler which attempts to infer when one -logic nodes value can be inferred from a known logic node. - -inductive implies :: "IRGraph IRNode IRNode TriState bool" - ("_ _ & _ _") for g where - eq_imp_less: - "g (IntegerEqualsNode x y) & (IntegerLessThanNode x y) KnownFalse" | - eq_imp_less_rev: - "g (IntegerEqualsNode x y) & (IntegerLessThanNode y x) KnownFalse" | - less_imp_rev_less: - "g (IntegerLessThanNode x y) & (IntegerLessThanNode y x) KnownFalse" | - less_imp_not_eq: - "g (IntegerLessThanNode x y) & (IntegerEqualsNode x y) KnownFalse" | - less_imp_not_eq_rev: - "g (IntegerLessThanNode x y) & (IntegerEqualsNode y x) KnownFalse" | - - x_imp_x: - "g x & x KnownTrue" | - - negate_false: - "g x & (kind g y) KnownTrue g x & (LogicNegationNode y) KnownFalse" | - negate_true: - "g x & (kind g y) KnownFalse g x & (LogicNegationNode y) KnownTrue" - -text Total relation over partial implies relation -inductive condition_implies :: "IRGraph IRNode IRNode TriState bool" - ("_ _ & _ _") for g where - "¬(g a & b imp) (g a & b Unknown)" | - "(g a & b imp) (g a & b imp)" - -inductive implies_tree :: "IRExpr IRExpr bool bool" - ("_ & _ _") where - eq_imp_less: - "(BinaryExpr BinIntegerEquals x y) & (BinaryExpr BinIntegerLessThan x y) False" | - eq_imp_less_rev: - "(BinaryExpr BinIntegerEquals x y) & (BinaryExpr BinIntegerLessThan y x) False" | - less_imp_rev_less: - "(BinaryExpr BinIntegerLessThan x y) & (BinaryExpr BinIntegerLessThan y x) False" | - less_imp_not_eq: - "(BinaryExpr BinIntegerLessThan x y) & (BinaryExpr BinIntegerEquals x y) False" | - less_imp_not_eq_rev: - "(BinaryExpr BinIntegerLessThan x y) & (BinaryExpr BinIntegerEquals y x) False" | - x_imp_x: - "x & x True" | - negate_false: - "x & y True x & (UnaryExpr UnaryLogicNegation y) False" | - negate_true: - "x & y False x & (UnaryExpr UnaryLogicNegation y) True" - -text -Proofs that the implies relation is correct with respect to the -existing evaluation semantics. - - -lemma logic_negation_relation: - assumes "[g, m, p] y val" - assumes "kind g neg = LogicNegationNode y" - assumes "[g, m, p] neg invval" - assumes "invval UndefVal" - shows "val_to_bool val ¬(val_to_bool invval)" - by (metis assms(1,2,3) LogicNegationNode encodeeval_def logic_negation_relation_tree repDet) - -lemma implies_valid: - assumes "x & y imp" - assumes "[m, p] x v1" - assumes "[m, p] y v2" - shows "(imp (val_to_bool v1 val_to_bool v2)) - (¬imp (val_to_bool v1 ¬(val_to_bool v2)))" - (is "(?TP ?TC) (?FP ?FC)") - apply (intro conjI; rule impI) -proof - - assume KnownTrue: ?TP - show ?TC - using assms(1) KnownTrue assms(2-) proof (induct x y imp rule: implies_tree.induct) - case (eq_imp_less x y) - then show ?case - by simp - next - case (eq_imp_less_rev x y) - then show ?case - by simp - next - case (less_imp_rev_less x y) - then show ?case - by simp - next - case (less_imp_not_eq x y) - then show ?case - by simp - next - case (less_imp_not_eq_rev x y) - then show ?case - by simp - next - case (x_imp_x) - then show ?case - by (metis evalDet) - next - case (negate_false x1) - then show ?case - using evalDet assms(2,3) by fast - next - case (negate_true x y) - then show ?case - using logic_negation_relation_tree sorry - qed -next - assume KnownFalse: ?FP - show ?FC using assms KnownFalse proof (induct x y imp rule: implies_tree.induct) - case (eq_imp_less x y) - obtain xval where xval: "[m, p] x xval" - using eq_imp_less(1) by blast - then obtain yval where yval: "[m, p] y yval" - using eq_imp_less.prems(2) by blast - have eqeval: "[m, p] (BinaryExpr BinIntegerEquals x y) intval_equals xval yval" - by (metis xval yval BinaryExprE bin_eval.simps(13) eq_imp_less.prems(1) evalDet) - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan x y) intval_less_than xval yval" - by (metis xval yval BinaryExprE bin_eval.simps(14) eq_imp_less.prems(2) evalDet) - have "val_to_bool (intval_equals xval yval) ¬(val_to_bool (intval_less_than xval yval))" - apply (cases xval; cases yval; auto) - by (smt (verit, best) bool_to_val.simps(2) val_to_bool.simps(1)) - then show ?case - by (metis eqeval lesseval eq_imp_less.prems(1,2) evalDet) - next - case (eq_imp_less_rev x y) - obtain xval where xval: "[m, p] x xval" - using eq_imp_less_rev.prems(2) by blast - obtain yval where yval: "[m, p] y yval" - using eq_imp_less_rev.prems(2) by blast - have eqeval: "[m, p] (BinaryExpr BinIntegerEquals x y) intval_equals xval yval" - by (metis xval yval BinaryExprE bin_eval.simps(13) eq_imp_less_rev.prems(1) evalDet) - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan y x) intval_less_than yval xval" - by (metis xval yval BinaryExprE bin_eval.simps(14) eq_imp_less_rev.prems(2) evalDet) - have "val_to_bool (intval_equals xval yval) ¬(val_to_bool (intval_less_than yval xval))" - apply (cases xval; cases yval; auto) - by (metis (full_types) bool_to_val.simps(2) less_irrefl val_to_bool.simps(1)) - then show ?case - by (metis eq_imp_less_rev.prems(1) eq_imp_less_rev.prems(2) evalDet eqeval lesseval) - next - case (less_imp_rev_less x y) - obtain xval where xval: "[m, p] x xval" - using less_imp_rev_less.prems(2) by blast - obtain yval where yval: "[m, p] y yval" - using less_imp_rev_less.prems(2) by blast - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan x y) intval_less_than xval yval" - by (metis BinaryExprE bin_eval.simps(14) evalDet less_imp_rev_less.prems(1) xval yval) - have revlesseval: "[m, p] (BinaryExpr BinIntegerLessThan y x) intval_less_than yval xval" - by (metis BinaryExprE bin_eval.simps(14) evalDet less_imp_rev_less.prems(2) xval yval) - have "val_to_bool (intval_less_than xval yval) ¬(val_to_bool (intval_less_than yval xval))" - apply (cases xval; cases yval; auto) - by (smt (verit) bool_to_val.simps(2) val_to_bool.simps(1)) - then show ?case - by (metis evalDet less_imp_rev_less.prems(1,2) lesseval revlesseval) - next - case (less_imp_not_eq x y) - obtain xval where xval: "[m, p] x xval" - using less_imp_not_eq.prems(1) by blast - obtain yval where yval: "[m, p] y yval" - using less_imp_not_eq.prems(1) by blast - have eqeval: "[m, p] (BinaryExpr BinIntegerEquals x y) intval_equals xval yval" - by (metis BinaryExprE bin_eval.simps(13) evalDet less_imp_not_eq.prems(2) xval yval) - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan x y) intval_less_than xval yval" - by (metis BinaryExprE bin_eval.simps(14) evalDet less_imp_not_eq.prems(1) xval yval) - have "val_to_bool (intval_less_than xval yval) ¬(val_to_bool (intval_equals xval yval))" - apply (cases xval; cases yval; auto) - by (smt (verit, best) bool_to_val.simps(2) val_to_bool.simps(1)) - then show ?case - by (metis eqeval evalDet less_imp_not_eq.prems(1,2) lesseval) - next - case (less_imp_not_eq_rev x y) - obtain xval where xval: "[m, p] x xval" - using less_imp_not_eq_rev.prems(1) by blast - obtain yval where yval: "[m, p] y yval" - using less_imp_not_eq_rev.prems(1) by blast - have eqeval: "[m, p] (BinaryExpr BinIntegerEquals y x) intval_equals yval xval" - by (metis xval yval BinaryExprE bin_eval.simps(13) evalDet less_imp_not_eq_rev.prems(2)) - have lesseval: "[m, p] (BinaryExpr BinIntegerLessThan x y) intval_less_than xval yval" - by (metis xval yval BinaryExprE bin_eval.simps(14) evalDet less_imp_not_eq_rev.prems(1)) - have "val_to_bool (intval_less_than xval yval) ¬(val_to_bool (intval_equals yval xval))" - apply (cases xval; cases yval; auto) - by (smt (verit, best) bool_to_val.simps(2) val_to_bool.simps(1)) - then show ?case - by (metis eqeval evalDet less_imp_not_eq_rev.prems(1,2) lesseval) - next - case (x_imp_x x1) - then show ?case - by simp - next - case (negate_false x y) - then show ?case sorry - next - case (negate_true x1) - then show ?case - by simp - qed -qed -lemma implies_true_valid: - assumes "x & y imp" - assumes "imp" - assumes "[m, p] x v1" - assumes "[m, p] y v2" - shows "val_to_bool v1 val_to_bool v2" - using assms implies_valid by blast - -lemma implies_false_valid: - assumes "x & y imp" - assumes "¬imp" - assumes "[m, p] x v1" - assumes "[m, p] y v2" - shows "val_to_bool v1 ¬(val_to_bool v2)" - using assms implies_valid by blast - -text -The following relation corresponds to the UnaryOpLogicNode.tryFold -and BinaryOpLogicNode.tryFold methods and their associated concrete implementations. - -The relation determines if a logic operation can be shown true or false -through the stamp typing information. - +subsubsection ‹Type Implication› + +text ‹ +The second mechanism to determine whether a condition implies another is +to use the type information of the relevant nodes. +For instance, @{term "x < 4"} implies @{term "x < 10"}. +We can show this by strengthening the type, stamp, +of the node @{term x} such that the upper bound is @{term 4}. +Then we the second condition is reached, +we know that the condition must be true by the upperbound. +› + +text ‹ +The following relation corresponds to the \texttt{UnaryOpLogicNode.tryFold} +and \texttt{BinaryOpLogicNode.tryFold} methods and their associated +concrete implementations. + +We track the refined stamps by mapping nodes to Stamps, +the second parameter to @{term tryFold}. +› + inductive tryFold :: "IRNode (ID Stamp) bool bool" where "alwaysDistinct (stamps x) (stamps y) @@ -449,129 +275,307 @@

Theory ConditionalElimination.ConditionalElimination

stpi_lower (stamps x) stpi_upper (stamps y) tryFold (IntegerLessThanNode x y) stamps False"
-text -Proofs that show that when the stamp lookup function is well-formed, -the tryFold relation correctly predicts the output value with respect to -our evaluation semantics. - -lemma - assumes "kind g nid = IntegerEqualsNode x y" - assumes "[g, m, p] nid v" - assumes "([g, m, p] x xval) ([g, m, p] y yval)" - shows "val_to_bool (intval_equals xval yval) v = IntVal 32 1" +code_pred (modes: i i i bool) tryFold
. + +text ‹ +Prove that, when the stamp map is valid, +the @{term tryFold} relation correctly predicts the output value with respect to +our evaluation semantics. +› + +inductive_cases StepE: + "g, p (nid,m,h) (nid',m',h)" + + +lemma is_stamp_empty_valid: + assumes "is_stamp_empty s" + shows "¬( val. valid_value val s)" + using assms is_stamp_empty.simps apply (cases s; auto) + by (metis linorder_not_le not_less_iff_gr_or_eq order.strict_trans valid_value.elims(2) valid_value.simps(1) valid_value.simps(5)) + +lemma join_valid: + assumes "is_IntegerStamp s1 is_IntegerStamp s2" + assumes "valid_stamp s1 valid_stamp s2" + shows "(valid_value v s1 valid_value v s2) = valid_value v (join s1 s2)" (is "?lhs = ?rhs") +proof + assume ?lhs + then show ?rhs + using assms(1) apply (cases s1; cases s2; auto) + apply (metis Value.inject(1) valid_int) + by (smt (z3) valid_int valid_stamp.simps(1) valid_value.simps(1)) + next + assume ?rhs + then show ?lhs + using assms apply (cases s1; cases s2; simp) + by (smt (verit, best) assms(2) valid_int valid_value.simps(1) valid_value.simps(22)) +qed + +lemma alwaysDistinct_evaluate: + assumes "wf_stamp g stamps" + assumes "alwaysDistinct (stamps x) (stamps y)" + assumes "is_IntegerStamp (stamps x) is_IntegerStamp (stamps y) valid_stamp (stamps x) valid_stamp (stamps y)" + shows "¬( val . ([g, m, p] x val) ([g, m, p] y val))" proof - - have "v = intval_equals xval yval" - by (smt (verit) bin_eval.simps(13) encodeeval_def evalDet repDet IntegerEqualsNode BinaryExprE - assms) + obtain stampx stampy where stampdef: "stampx = stamps x stampy = stamps y" + by simp + then have xv: " xv . ([g, m, p] x xv) valid_value xv stampx" + by (meson assms(1) encodeeval.simps eval_in_ids wf_stamp.elims(2)) + from stampdef have yv: " yv . ([g, m, p] y yv) valid_value yv stampy" + by (meson assms(1) encodeeval.simps eval_in_ids wf_stamp.elims(2)) + have "v. valid_value v (join stampx stampy) = (valid_value v stampx valid_value v stampy)" + using assms(3) + by (simp add: join_valid stampdef) then show ?thesis - by (metis bool_to_val.simps(1,2) one_neq_zero val_to_bool.simps(1,2) intval_equals_result) + using assms unfolding alwaysDistinct.simps + using is_stamp_empty_valid stampdef xv yv by blast qed -lemma tryFoldIntegerEqualsAlwaysDistinct: +lemma alwaysDistinct_valid: assumes "wf_stamp g stamps" assumes "kind g nid = (IntegerEqualsNode x y)" assumes "[g, m, p] nid v" assumes "alwaysDistinct (stamps x) (stamps y)" - shows "v = IntVal 32 0" + shows "¬(val_to_bool v)" proof - - have " val. ¬(valid_value val (join (stamps x) (stamps y)))" - by (smt (verit, best) is_stamp_empty.elims(2) valid_int valid_value.simps(1) assms(1,4) + have no_valid: " val. ¬(valid_value val (join (stamps x) (stamps y)))" + by (smt (verit, best) is_stamp_empty.elims(2) valid_int valid_value.simps(1) assms(1,4) alwaysDistinct.simps) - obtain xv where "[g, m, p] x xv" - using assms unfolding encodeeval_def sorry - have "¬( val . ([g, m, p] x val) ([g, m, p] y val))" - using assms(1,4) unfolding alwaysDistinct.simps wf_stamp.simps encodeeval_def sorry + obtain xe ye where repr: "rep g nid (BinaryExpr BinIntegerEquals xe ye)" + by (metis assms(2) assms(3) encodeeval.simps rep_integer_equals) + moreover have evale: "[m, p] (BinaryExpr BinIntegerEquals xe ye) v" + by (metis assms(3) calculation encodeeval.simps repDet) + moreover have repsub: "rep g x xe rep g y ye" + by (metis IRNode.distinct(1955) IRNode.distinct(1997) IRNode.inject(17) IntegerEqualsNodeE assms(2) calculation) + ultimately obtain xv yv where evalsub: "[g, m, p] x xv [g, m, p] y yv" + by (meson BinaryExprE encodeeval.simps) + have xvalid: "valid_value xv (stamps x)" + using assms(1) encode_in_ids encodeeval.simps evalsub wf_stamp.simps by blast + then have xint: "is_IntegerStamp (stamps x)" + using assms(4) valid_value.elims(2) by fastforce + then have xstamp: "valid_stamp (stamps x)" + using xvalid apply (cases xv; auto) + apply (smt (z3) valid_stamp.simps(6) valid_value.elims(1)) + using is_IntegerStamp_def by fastforce + have yvalid: "valid_value yv (stamps y)" + using assms(1) encode_in_ids encodeeval.simps evalsub wf_stamp.simps by blast + then have yint: "is_IntegerStamp (stamps y)" + using assms(4) valid_value.elims(2) by fastforce + then have ystamp: "valid_stamp (stamps y)" + using yvalid apply (cases yv; auto) + apply (smt (z3) valid_stamp.simps(6) valid_value.elims(1)) + using is_IntegerStamp_def by fastforce + have disjoint: "¬( val . ([g, m, p] x val) ([g, m, p] y val))" + using alwaysDistinct_evaluate + using assms(1) assms(4) xint yint xvalid yvalid xstamp ystamp by simp + have "v = bin_eval BinIntegerEquals xv yv" + by (metis BinaryExprE encodeeval.simps evale evalsub graphDet repsub) + also have "v UndefVal" + using evale by auto + ultimately have "b1 b2. v = bool_to_val_bin b1 b2 (xv = yv)" + unfolding bin_eval.simps + by (smt (z3) Value.inject(1) bool_to_val_bin.simps intval_equals.elims) then show ?thesis - sorry + by (metis (mono_tags, lifting) (v::Value) UndefVal bool_to_val.elims bool_to_val_bin.simps disjoint evalsub val_to_bool.simps(1)) +qed +thm_oracles alwaysDistinct_valid + +lemma unwrap_valid: + assumes "0 < b b 64" + assumes "take_bit (b::nat) (vv::64 word) = vv" + shows "(vv::64 word) = take_bit b (word_of_int (int_signed_value (b::nat) (vv::64 word)))" + using assms apply auto[1] + by (simp add: take_bit_signed_take_bit) + +lemma asConstant_valid: + assumes "asConstant s = val" + assumes "val UndefVal" + assumes "valid_value v s" + shows "v = val" +proof - + obtain b l h where s: "s = IntegerStamp b l h" + using assms(1,2) by (cases s; auto) + obtain vv where vdef: "v = IntVal b vv" + using assms(3) s valid_int by blast + have "l int_signed_value b vv int_signed_value b vv h" + by (metis (v::Value) = IntVal (b::nat) (vv::64 word) assms(3) s valid_value.simps(1)) + then have veq: "int_signed_value b vv = l" + by (smt (verit) asConstant.simps(1) assms(1) assms(2) s) + have valdef: "val = new_int b (word_of_int l)" + by (metis asConstant.simps(1) assms(1) assms(2) s) + have "take_bit b vv = vv" + by (metis (v::Value) = IntVal (b::nat) (vv::64 word) assms(3) s valid_value.simps(1)) + then show ?thesis + using veq vdef valdef + using assms(3) s unwrap_valid by force qed -lemma tryFoldIntegerEqualsNeverDistinct: +lemma neverDistinct_valid: assumes "wf_stamp g stamps" assumes "kind g nid = (IntegerEqualsNode x y)" assumes "[g, m, p] nid v" assumes "neverDistinct (stamps x) (stamps y)" - shows "v = IntVal 32 1" - using assms IntegerEqualsNodeE sorry + shows "val_to_bool v" +proof - + obtain val where constx: "asConstant (stamps x) = val" + by simp + moreover have "val UndefVal" + using assms(4) calculation by auto + then have constx: "val = asConstant (stamps y)" + using calculation assms(4) by force + obtain xe ye where repr: "rep g nid (BinaryExpr BinIntegerEquals xe ye)" + by (metis assms(2) assms(3) encodeeval.simps rep_integer_equals) + moreover have evale: "[m, p] (BinaryExpr BinIntegerEquals xe ye) v" + by (metis assms(3) calculation encodeeval.simps repDet) + moreover have repsub: "rep g x xe rep g y ye" + by (metis IRNode.distinct(1955) IRNode.distinct(1997) IRNode.inject(17) IntegerEqualsNodeE assms(2) calculation) + ultimately obtain xv yv where evalsub: "[g, m, p] x xv [g, m, p] y yv" + by (meson BinaryExprE encodeeval.simps) + have xvalid: "valid_value xv (stamps x)" + using assms(1) encode_in_ids encodeeval.simps evalsub wf_stamp.simps by blast + then have xint: "is_IntegerStamp (stamps x)" + using assms(4) valid_value.elims(2) by fastforce + have yvalid: "valid_value yv (stamps y)" + using assms(1) encode_in_ids encodeeval.simps evalsub wf_stamp.simps by blast + then have yint: "is_IntegerStamp (stamps y)" + using assms(4) valid_value.elims(2) by fastforce + have eq: "v1 v2. (([g, m, p] x v1) ([g, m, p] y v2)) v1 = v2" + by (metis asConstant_valid assms(4) encodeEvalDet evalsub neverDistinct.elims(1) xvalid yvalid) + have "v = bin_eval BinIntegerEquals xv yv" + by (metis BinaryExprE encodeeval.simps evale evalsub graphDet repsub) + also have "v UndefVal" + using evale by auto + ultimately have "b1 b2. v = bool_to_val_bin b1 b2 (xv = yv)" + unfolding bin_eval.simps + by (smt (z3) Value.inject(1) bool_to_val_bin.simps intval_equals.elims) + then show ?thesis + using (v::Value) UndefVal eq evalsub by fastforce +qed -lemma tryFoldIntegerLessThanTrue: +lemma stampUnder_valid: assumes "wf_stamp g stamps" assumes "kind g nid = (IntegerLessThanNode x y)" assumes "[g, m, p] nid v" assumes "stpi_upper (stamps x) < stpi_lower (stamps y)" - shows "v = IntVal 32 1" + shows "val_to_bool v" proof - - have stamp_type: "is_IntegerStamp (stamps x)" - using assms - sorry - obtain xval where xval: "[g, m, p] x xval" - using assms(2,3) sorry - obtain yval where yval: "[g, m, p] y yval" - using assms(2,3) sorry - have "is_IntegerStamp (stamps x) is_IntegerStamp (stamps y)" - using assms(4) - sorry - then have "val_to_bool (intval_less_than xval yval)" - sorry + obtain xe ye where repr: "rep g nid (BinaryExpr BinIntegerLessThan xe ye)" + by (metis assms(2) assms(3) encodeeval.simps rep_integer_less_than) + moreover have evale: "[m, p] (BinaryExpr BinIntegerLessThan xe ye) v" + by (metis assms(3) calculation encodeeval.simps repDet) + moreover have repsub: "rep g x xe rep g y ye" + by (metis IRNode.distinct(2047) IRNode.distinct(2089) IRNode.inject(18) IntegerLessThanNodeE assms(2) repr) + ultimately obtain xv yv where evalsub: "[g, m, p] x xv [g, m, p] y yv" + by (meson BinaryExprE encodeeval.simps) + have vval: "v = intval_less_than xv yv" + by (metis BinaryExprE bin_eval.simps(14) encodeEvalDet encodeeval.simps evale evalsub repsub) + then obtain b xvv where "xv = IntVal b xvv" + by (metis bin_eval.simps(14) defined_eval_is_intval evale evaltree_not_undef is_IntVal_def) + also have xvalid: "valid_value xv (stamps x)" + by (meson assms(1) encodeeval.simps eval_in_ids evalsub wf_stamp.elims(2)) + then obtain xl xh where xstamp: "stamps x = IntegerStamp b xl xh" + using calculation valid_value.simps apply (cases "stamps x"; auto) + by presburger + from vval obtain yvv where yint: "yv = IntVal b yvv" + by (metis Value.collapse(1) bin_eval.simps(14) bool_to_val_bin.simps calculation defined_eval_is_intval evale evaltree_not_undef intval_less_than.simps(1)) + then have yvalid: "valid_value yv (stamps y)" + using assms(1) encodeeval.simps evalsub no_encoding wf_stamp.simps by blast + then obtain yl yh where ystamp: "stamps y = IntegerStamp b yl yh" + using calculation yint valid_value.simps apply (cases "stamps y"; auto) + by presburger + have "int_signed_value b xvv xh" + using calculation valid_value.simps(1) xstamp xvalid by presburger + moreover have "yl int_signed_value b yvv" + using valid_value.simps(1) yint ystamp yvalid by presburger + moreover have "xh < yl" + using assms(4) xstamp ystamp by auto + ultimately have "int_signed_value b xvv < int_signed_value b yvv" + by linarith + then have "val_to_bool (intval_less_than xv yv)" + by (simp add: (xv::Value) = IntVal (b::nat) (xvv::64 word) yint) then show ?thesis - sorry + by (simp add: vval) qed -lemma tryFoldIntegerLessThanFalse: +lemma stampOver_valid: assumes "wf_stamp g stamps" assumes "kind g nid = (IntegerLessThanNode x y)" assumes "[g, m, p] nid v" assumes "stpi_lower (stamps x) stpi_upper (stamps y)" - shows "v = IntVal 32 0" - proof - - have stamp_type: "is_IntegerStamp (stamps x)" - using assms sorry - obtain xval where xval: "[g, m, p] x xval" - using assms(2,3) sorry - obtain yval where yval: "[g, m, p] y yval" - using assms(2,3) sorry - have "is_IntegerStamp (stamps x) is_IntegerStamp (stamps y)" - using assms(4) sorry - then have "¬(val_to_bool (intval_less_than xval yval))" - sorry + shows "¬(val_to_bool v)" +proof - + obtain xe ye where repr: "rep g nid (BinaryExpr BinIntegerLessThan xe ye)" + by (metis assms(2) assms(3) encodeeval.simps rep_integer_less_than) + moreover have evale: "[m, p] (BinaryExpr BinIntegerLessThan xe ye) v" + by (metis assms(3) calculation encodeeval.simps repDet) + moreover have repsub: "rep g x xe rep g y ye" + by (metis IRNode.distinct(2047) IRNode.distinct(2089) IRNode.inject(18) IntegerLessThanNodeE assms(2) repr) + ultimately obtain xv yv where evalsub: "[g, m, p] x xv [g, m, p] y yv" + by (meson BinaryExprE encodeeval.simps) + have vval: "v = intval_less_than xv yv" + by (metis BinaryExprE bin_eval.simps(14) encodeEvalDet encodeeval.simps evale evalsub repsub) + then obtain b xvv where "xv = IntVal b xvv" + by (metis bin_eval.simps(14) defined_eval_is_intval evale evaltree_not_undef is_IntVal_def) + also have xvalid: "valid_value xv (stamps x)" + by (meson assms(1) encodeeval.simps eval_in_ids evalsub wf_stamp.elims(2)) + then obtain xl xh where xstamp: "stamps x = IntegerStamp b xl xh" + using calculation valid_value.simps apply (cases "stamps x"; auto) + by presburger + from vval obtain yvv where yint: "yv = IntVal b yvv" + by (metis Value.collapse(1) bin_eval.simps(14) bool_to_val_bin.simps calculation defined_eval_is_intval evale evaltree_not_undef intval_less_than.simps(1)) + then have yvalid: "valid_value yv (stamps y)" + using assms(1) encodeeval.simps evalsub no_encoding wf_stamp.simps by blast + then obtain yl yh where ystamp: "stamps y = IntegerStamp b yl yh" + using calculation yint valid_value.simps apply (cases "stamps y"; auto) + by presburger + have "xl int_signed_value b xvv" + using calculation valid_value.simps(1) xstamp xvalid by presburger + moreover have "int_signed_value b yvv yh" + using valid_value.simps(1) yint ystamp yvalid by presburger + moreover have "xl yh" + using assms(4) xstamp ystamp by auto + ultimately have "int_signed_value b xvv int_signed_value b yvv" + by linarith + then have "¬(val_to_bool (intval_less_than xv yv))" + by (simp add: (xv::Value) = IntVal (b::nat) (xvv::64 word) yint) then show ?thesis - sorry + by (simp add: vval) qed -theorem tryFoldProofTrue: +theorem tryFoldTrue_valid: assumes "wf_stamp g stamps" assumes "tryFold (kind g nid) stamps True" assumes "[g, m, p] nid v" shows "val_to_bool v" - using assms(2) proof (induction "kind g nid" stamps True rule: tryFold.induct) + using assms(2) proof (induction "kind g nid" stamps True rule: tryFold.induct) case (1 stamps x y) then show ?case - using tryFoldIntegerEqualsAlwaysDistinct assms by force + using alwaysDistinct_valid assms by force next case (2 stamps x y) then show ?case - by (smt (verit, best) one_neq_zero tryFold.cases tryFoldIntegerEqualsNeverDistinct assms - tryFoldIntegerLessThanTrue val_to_bool.simps(1)) + by (smt (verit, best) one_neq_zero tryFold.cases neverDistinct_valid assms + stampUnder_valid val_to_bool.simps(1)) next case (3 stamps x y) then show ?case - by (smt (verit, best) one_neq_zero tryFold.cases tryFoldIntegerEqualsNeverDistinct assms - val_to_bool.simps(1) tryFoldIntegerLessThanTrue) + by (smt (verit, best) one_neq_zero tryFold.cases neverDistinct_valid assms + val_to_bool.simps(1) stampUnder_valid) next case (4 stamps x y) then show ?case by force qed -theorem tryFoldProofFalse: +theorem tryFoldFalse_valid: assumes "wf_stamp g stamps" assumes "tryFold (kind g nid) stamps False" assumes "[g, m, p] nid v" shows "¬(val_to_bool v)" -using assms(2) proof (induction "kind g nid" stamps False rule: tryFold.induct) +using assms(2) proof (induction "kind g nid" stamps False rule: tryFold.induct) case (1 stamps x y) then show ?case - by (smt (verit) tryFoldIntegerLessThanFalse tryFoldIntegerEqualsAlwaysDistinct tryFold.cases - tryFoldIntegerEqualsNeverDistinct val_to_bool.simps(1) assms) + by (smt (verit) stampOver_valid alwaysDistinct_valid tryFold.cases + neverDistinct_valid val_to_bool.simps(1) assms) next case (2 stamps x y) then show ?case @@ -583,261 +587,462 @@

Theory ConditionalElimination.ConditionalElimination

next case (4 stamps x y) then show ?case - by (smt (verit, del_insts) tryFold.cases tryFoldIntegerEqualsAlwaysDistinct val_to_bool.simps(1) - tryFoldIntegerLessThanFalse assms) + by (smt (verit, del_insts) tryFold.cases alwaysDistinct_valid val_to_bool.simps(1) + stampOver_valid assms) qed -inductive_cases StepE: - "g, p (nid,m,h) (nid',m',h)" -text -Perform conditional elimination rewrites on the graph for a particular node. - -In order to determine conditional eliminations appropriately the rule needs two -data structures produced by static analysis. -The first parameter is the set of IRNodes that we know result in a true value -when evaluated. -The second parameter is a mapping from node identifiers to the flow-sensitive stamp. - -The relation transforms the third parameter to the fifth parameter for a node identifier -which represents the fourth parameter. - +subsection ‹Lift rules› + +inductive condset_implies :: "IRExpr set IRExpr bool bool" where + impliesTrue: + "(ce conds . (ce cond)) condset_implies conds cond True" | + impliesFalse: + "(ce conds . (ce ⇛¬ cond)) condset_implies conds cond False" + +code_pred (modes: i i i bool) condset_implies
. + +text ‹ +The @{term cond_implies} function lifts the structural and type implication +rules to the one relation. +› + +fun conds_implies :: "IRExpr set (ID Stamp) IRNode IRExpr bool option" where + "conds_implies conds stamps condNode cond = + (if condset_implies conds cond True tryFold condNode stamps True + then Some True + else if condset_implies conds cond False tryFold condNode stamps False + then Some False + else None)" + +text ‹ +Perform conditional elimination rewrites on the graph for a particular node +by lifting the individual implication rules to a relation that rewrites the +condition of \textsl{if} statements to constant values. + +In order to determine conditional eliminations appropriately the rule needs two +data structures produced by static analysis. +The first parameter is the set of IRNodes that we know result in a true value +when evaluated. +The second parameter is a mapping from node identifiers to the flow-sensitive stamp. +› + inductive ConditionalEliminationStep :: - "IRExpr set (ID Stamp) IRGraph ID IRGraph bool" where + "IRExpr set (ID Stamp) ID IRGraph IRGraph bool" + where impliesTrue: "kind g ifcond = (IfNode cid t f); - g cid cond; - ce conds . (ce cond); + g cid cond; + condNode = kind g cid; + conds_implies conds stamps condNode cond = (Some True); g' = constantCondition True ifcond (kind g ifcond) g - ConditionalEliminationStep conds stamps g ifcond g'" | + ConditionalEliminationStep conds stamps ifcond g g'"
| impliesFalse: "kind g ifcond = (IfNode cid t f); g cid cond; - ce conds . (ce ⇛¬ cond); + condNode = kind g cid; + conds_implies conds stamps condNode cond = (Some False); g' = constantCondition False ifcond (kind g ifcond) g - ConditionalEliminationStep conds stamps g ifcond g'" | + ConditionalEliminationStep conds stamps ifcond g g'"
| - tryFoldTrue: + unknown: "kind g ifcond = (IfNode cid t f); - cond = kind g cid; - tryFold (kind g cid) stamps True; - g' = constantCondition True ifcond (kind g ifcond) g - ConditionalEliminationStep conds stamps g ifcond g'" | + g cid cond; + condNode = kind g cid; + conds_implies conds stamps condNode cond = None + ConditionalEliminationStep conds stamps ifcond g g"
| - tryFoldFalse: - "kind g ifcond = (IfNode cid t f); - cond = kind g cid; - tryFold (kind g cid) stamps False; - g' = constantCondition False ifcond (kind g ifcond) g - ConditionalEliminationStep conds stamps g ifcond g'" + notIfNode: + "¬(is_IfNode (kind g ifcond)) + ConditionalEliminationStep conds stamps ifcond g g" -code_pred (modes: i i i i o bool) ConditionalEliminationStep . +code_pred (modes: i i i i o bool) ConditionalEliminationStep . thm ConditionalEliminationStep.equation -subsection Control-flow Graph Traversal + + +subsection ‹Control-flow Graph Traversal› type_synonym Seen = "ID set" type_synonym Condition = "IRExpr" type_synonym Conditions = "Condition list" type_synonym StampFlow = "(ID Stamp) list" +type_synonym ToVisit = "ID list" -text -nextEdge helps determine which node to traverse next by returning the first successor -edge that isn't in the set of already visited nodes. -If there is not an appropriate successor, None is returned instead. - + +text ‹ +@{term "nextEdge"} helps determine which node to traverse next +by returning the first successor edge that isn't in the set of already visited nodes. +If there is not an appropriate successor, None is returned instead. +› fun nextEdge :: "Seen ID IRGraph ID option" where "nextEdge seen nid g = (let nids = (filter (λnid'. nid' seen) (successors_of (kind g nid))) in (if length nids > 0 then Some (hd nids) else None))" -text -pred determines which node, if any, acts as the predecessor of another. - -Merge nodes represent a special case where-in the predecessor exists as -an input edge of the merge node, to simplify the traversal we treat only -the first input end node as the predecessor, ignoring that multiple nodes -may act as a successor. - -For all other nodes, the predecessor is the first element of the predecessors set. -Note that in a well-formed graph there should only be one element in the predecessor set. -fun pred :: "IRGraph ID ID option" where - "pred g nid = (case kind g nid of - (MergeNode ends _ _) Some (hd ends) | +text ‹ +@{term "pred"} determines which node, if any, acts as the predecessor of another. + +Merge nodes represent a special case wherein the predecessor exists as +an input edge of the merge node, to simplify the traversal we treat only +the first input end node as the predecessor, ignoring that multiple nodes +may act as a successor. + +For all other nodes, the predecessor is the first element of the predecessors set. +Note that in a well-formed graph there should only be one element in the predecessor set. +› +fun preds :: "IRGraph ID ID list" where + "preds g nid = (case kind g nid of + (MergeNode ends _ _) ends | _ - (if IRGraph.predecessors g nid = {} - then None else - Some (hd (sorted_list_of_set (IRGraph.predecessors g nid))) - ) + sorted_list_of_set (IRGraph.predecessors g nid) )" +fun pred :: "IRGraph ID ID option" where + "pred g nid = (case preds g nid of [] None | x # xs Some x)" + -text -When the basic block of an if statement is entered, we know that the condition of the -preceding if statement must be true. -As in the GraalVM compiler, we introduce the registerNewCondition funciton which roughly -corresponds to the ConditionalEliminationPhase.registerNewCondition. -This method updates the flow-sensitive stamp information based on the condition which -we know must be true. - +text ‹ +When the basic block of an if statement is entered, we know that the condition of the +preceding if statement must be true. +As in the GraalVM compiler, we introduce the \texttt{registerNewCondition} function +which roughly corresponds to \texttt{ConditionalEliminationPhase.registerNewCondition}. +This method updates the flow-sensitive stamp information based on the condition which +we know must be true. +› fun clip_upper :: "Stamp int Stamp" where - "clip_upper (IntegerStamp b l h) c = (IntegerStamp b l c)" | + "clip_upper (IntegerStamp b l h) c = + (if c < h then (IntegerStamp b l c) else (IntegerStamp b l h))" | "clip_upper s c = s" fun clip_lower :: "Stamp int Stamp" where - "clip_lower (IntegerStamp b l h) c = (IntegerStamp b c h)" | + "clip_lower (IntegerStamp b l h) c = + (if l < c then (IntegerStamp b c h) else (IntegerStamp b l c))" | "clip_lower s c = s" +fun max_lower :: "Stamp Stamp Stamp" where + "max_lower (IntegerStamp b1 xl xh) (IntegerStamp b2 yl yh) = + (IntegerStamp b1 (max xl yl) xh)" | + "max_lower xs ys = xs" +fun min_higher :: "Stamp Stamp Stamp" where + "min_higher (IntegerStamp b1 xl xh) (IntegerStamp b2 yl yh) = + (IntegerStamp b1 yl (min xh yh))" | + "min_higher xs ys = ys" + fun registerNewCondition :: "IRGraph IRNode (ID Stamp) (ID Stamp)" where - (* constrain equality by joining the stamps *) + ― ‹constrain equality by joining the stamps› "registerNewCondition g (IntegerEqualsNode x y) stamps = (stamps (x := join (stamps x) (stamps y))) (y := join (stamps x) (stamps y))" | - (* constrain less than by removing overlapping stamps *) + ― ‹constrain less than by removing overlapping stamps› "registerNewCondition g (IntegerLessThanNode x y) stamps = (stamps - (x := clip_upper (stamps x) (stpi_lower (stamps y)))) - (y := clip_lower (stamps y) (stpi_upper (stamps x)))" | + (x := clip_upper (stamps x) ((stpi_lower (stamps y)) - 1))) + (y := clip_lower (stamps y) ((stpi_upper (stamps x)) + 1))" | + "registerNewCondition g (LogicNegationNode c) stamps = + (case (kind g c) of + (IntegerLessThanNode x y) + (stamps + (x := max_lower (stamps x) (stamps y))) + (y := min_higher (stamps x) (stamps y)) + | _ stamps)" | "registerNewCondition g _ stamps = stamps" fun hdOr :: "'a list 'a 'a" where "hdOr (x # xs) de = x" | "hdOr [] de = de" -text -The Step relation is a small-step traversal of the graph which handles transitions between -individual nodes of the graph. - -It relates a pairs of tuple of the current node, the set of seen nodes, -the always true stack of IfNode conditions, and the flow-sensitive stamp information. - -inductive Step - :: "IRGraph (ID × Seen × Conditions × StampFlow) (ID × Seen × Conditions × StampFlow) option bool" +(* +fun isCFGNode :: "IRNode ⇒ bool" where + "isCFGNode (BeginNode _) = True" | + "isCFGNode (EndNode) = True" | + "isCFGNode _ = False" + +inductive CFGSuccessor :: + "IRGraph ⇒ (ID × Seen × ToVisit) ⇒ (ID × Seen × ToVisit) ⇒ bool" + for g where + ― ‹ + Forward traversal transitively through successors until + a CFG node is reached.› + "⟦Some nid' = nextEdge seen nid g; + ¬(isCFGNode (kind g nid')); + CFGSuccessor g (nid', {nid} ∪ seen, nid # toVisit) (nid'', seen', toVisit')⟧ + ⟹ CFGSuccessor g (nid, seen, toVisit) (nid'', seen', toVisit')" | + "⟦Some nid' = nextEdge seen nid g; + isCFGNode (kind g nid')⟧ + ⟹ CFGSuccessor g (nid, seen, toVisit) (nid', {nid} ∪ seen, nid # toVisit)" | + + ― ‹ + Backwards traversal transitively through toVisit stack until + a CFG node is reached.› + "⟦toVisit = nid' # toVisit'; + CFGSuccessor g (nid', {nid} ∪ seen, nid # toVisit) (nid'', seen', toVisit')⟧ + ⟹ CFGSuccessor g (nid, seen, toVisit) (nid'', seen', toVisit')" + +code_pred (modes: i ⇒ i ⇒ o ⇒ bool) CFGSuccessor . +*) + +type_synonym DominatorCache = "(ID, ID set) map" + +inductive + dominators_all :: "IRGraph DominatorCache ID ID set set ID list DominatorCache ID set set ID list bool" and + dominators :: "IRGraph DominatorCache ID (ID set × DominatorCache) bool" where + + "pre = [] + dominators_all g c nid doms pre c doms pre" | + + "pre = pr # xs; + (dominators g c pr (doms', c')); + dominators_all g c' pr (doms {doms'}) xs c'' doms'' pre' + dominators_all g c nid doms pre c'' doms'' pre'" | + + "preds g nid = [] + dominators g c nid ({nid}, c)" | + + "c nid = None; + preds g nid = x # xs; + dominators_all g c nid {} (preds g nid) c' doms pre'; + c'' = c'(nid ({nid} (doms))) + dominators g c nid (({nid} (doms)), c'')" | + + "c nid = Some doms + dominators g c nid (doms, c)" + +― ‹ +Trying to simplify by removing the 3rd case won't work. +A base case for root nodes is required as @{term "{} = coset []"} +which swallows anything unioned with it. +› +value "({}::nat set set)" +value "- ({}::nat set set)" +value "({{}, {0}}::nat set set)" +value "{0::nat} ({})" + +code_pred (modes: i i i i i o o o bool) dominators_all . +code_pred (modes: i i i o bool) dominators . + +(* initial: ConditionalEliminationTest13_testSnippet2 *) +definition ConditionalEliminationTest13_testSnippet2_initial :: IRGraph where + "ConditionalEliminationTest13_testSnippet2_initial = irgraph [ + (0, (StartNode (Some 2) 8), VoidStamp), + (1, (ParameterNode 0), IntegerStamp 32 (-2147483648) (2147483647)), + (2, (FrameState [] None None None), IllegalStamp), + (3, (ConstantNode (new_int 32 (0))), IntegerStamp 32 (0) (0)), + (4, (ConstantNode (new_int 32 (1))), IntegerStamp 32 (1) (1)), + (5, (IntegerLessThanNode 1 4), VoidStamp), + (6, (BeginNode 13), VoidStamp), + (7, (BeginNode 23), VoidStamp), + (8, (IfNode 5 7 6), VoidStamp), + (9, (ConstantNode (new_int 32 (-1))), IntegerStamp 32 (-1) (-1)), + (10, (IntegerEqualsNode 1 9), VoidStamp), + (11, (BeginNode 17), VoidStamp), + (12, (BeginNode 15), VoidStamp), + (13, (IfNode 10 12 11), VoidStamp), + (14, (ConstantNode (new_int 32 (-2))), IntegerStamp 32 (-2) (-2)), + (15, (StoreFieldNode 15 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink2'' 14 (Some 16) None 19), VoidStamp), + (16, (FrameState [] None None None), IllegalStamp), + (17, (EndNode), VoidStamp), + (18, (MergeNode [17, 19] (Some 20) 21), VoidStamp), + (19, (EndNode), VoidStamp), + (20, (FrameState [] None None None), IllegalStamp), + (21, (StoreFieldNode 21 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink1'' 3 (Some 22) None 25), VoidStamp), + (22, (FrameState [] None None None), IllegalStamp), + (23, (EndNode), VoidStamp), + (24, (MergeNode [23, 25] (Some 26) 27), VoidStamp), + (25, (EndNode), VoidStamp), + (26, (FrameState [] None None None), IllegalStamp), + (27, (StoreFieldNode 27 ''org.graalvm.compiler.core.test.ConditionalEliminationTestBase::sink0'' 9 (Some 28) None 29), VoidStamp), + (28, (FrameState [] None None None), IllegalStamp), + (29, (ReturnNode None None), VoidStamp) + ]" + +(* :( +fun dominators :: "IRGraph ⇒ ID ⇒ ID set" where + "dominators g nid = {nid} ∪ (⋂ y ∈ preds g nid. dominators g y)" +*) + +values "{(snd x) 13| x. dominators ConditionalEliminationTest13_testSnippet2_initial Map.empty 25 x}" + +(*fun condition_of :: "IRGraph ⇒ ID ⇒ ID option" where + "condition_of g nid = (case (kind g nid) of + (IfNode c t f) ⇒ Some c | + _ ⇒ None)"*) + +inductive + condition_of :: "IRGraph ID (IRExpr × IRNode) option bool" where + "Some ifcond = pred g nid; + kind g ifcond = IfNode cond t f; + + i = find_index nid (successors_of (kind g ifcond)); + c = (if i = 0 then kind g cond else LogicNegationNode cond); + rep g cond ce; + ce' = (if i = 0 then ce else UnaryExpr UnaryLogicNegation ce) + condition_of g nid (Some (ce', c))" | + + "pred g nid = None condition_of g nid None" | + "pred g nid = Some nid'; + ¬(is_IfNode (kind g nid')) condition_of g nid None" + +code_pred (modes: i i o bool) condition_of . + +(*inductive + conditions_of_dominators :: "IRGraph ⇒ ID list ⇒ Conditions ⇒ Conditions ⇒ bool" where + "⟦nids = []⟧ + ⟹ conditions_of_dominators g nids conditions conditions" | + + "⟦nids = nid # nids'; + condition_of g nid (Some (expr, _)); + conditions_of_dominators g nids' (expr # conditions) conditions'⟧ + ⟹ conditions_of_dominators g nids conditions conditions'" | + + "⟦nids = nid # nids'; + condition_of g nid None; + conditions_of_dominators g nids' conditions conditions'⟧ + ⟹ conditions_of_dominators g nids conditions conditions'"*) + +fun conditions_of_dominators :: "IRGraph ID list Conditions Conditions" where + "conditions_of_dominators g [] cds = cds" | + "conditions_of_dominators g (nid # nids) cds = + (case (Predicate.the (condition_of_i_i_o g nid)) of + None conditions_of_dominators g nids cds | + Some (expr, _) conditions_of_dominators g nids (expr # cds))" + +(*code_pred (modes: i ⇒ i ⇒ i ⇒ o ⇒ bool) conditions_of_dominators .*) + +(* +inductive + stamps_of_dominators :: "IRGraph ⇒ ID list ⇒ StampFlow ⇒ StampFlow ⇒ bool" where + "⟦nids = []⟧ + ⟹ stamps_of_dominators g nids stamps stamps" | + + "⟦nids = nid # nids'; + condition_of g nid (Some (_, node)); + he = registerNewCondition g node (hd stamps); + stamps_of_dominators g nids' (he # stamps) stamps'⟧ + ⟹ stamps_of_dominators g nids stamps stamps'" | + + "⟦nids = nid # nids'; + condition_of g nid None; + stamps_of_dominators g nids' stamps stamps'⟧ + ⟹ stamps_of_dominators g nids stamps stamps'" +*) + +fun stamps_of_dominators :: "IRGraph ID list StampFlow StampFlow" where + "stamps_of_dominators g [] stamps = stamps" | + "stamps_of_dominators g (nid # nids) stamps = + (case (Predicate.the (condition_of_i_i_o g nid)) of + None stamps_of_dominators g nids stamps | + Some (_, node) stamps_of_dominators g nids + ((registerNewCondition g node (hd stamps)) # stamps))" + +(*code_pred (modes: i ⇒ i ⇒ i ⇒ o ⇒ bool) stamps_of_dominators .*) + +inductive + analyse :: "IRGraph DominatorCache ID (Conditions × StampFlow × DominatorCache) bool" where + "dominators g c nid (doms, c'); + conditions_of_dominators g (sorted_list_of_set doms) [] = conds; + stamps_of_dominators g (sorted_list_of_set doms) [stamp g] = stamps + analyse g c nid (conds, stamps, c')" + +code_pred (modes: i i i o bool) analyse . + +values "{x. dominators ConditionalEliminationTest13_testSnippet2_initial Map.empty 13 x}" +values "{(conds, stamps, c). +analyse ConditionalEliminationTest13_testSnippet2_initial Map.empty 13 (conds, stamps, c)}" +values "{(hd stamps) 1| conds stamps c . +analyse ConditionalEliminationTest13_testSnippet2_initial Map.empty 13 (conds, stamps, c)}" +values "{(hd stamps) 1| conds stamps c . +analyse ConditionalEliminationTest13_testSnippet2_initial Map.empty 27 (conds, stamps, c)}" + +fun next_nid :: "IRGraph ID set ID ID option" where + "next_nid g seen nid = (case (kind g nid) of + (EndNode) Some (any_usage g nid) | + _ nextEdge seen nid g)" + +inductive Step + :: "IRGraph (ID × Seen) (ID × Seen) option bool" for g where - ― ‹ - Hit a BeginNode with an IfNode predecessor which represents - the start of a basic block for the IfNode. - 1. nid' will be the successor of the begin node. - 2. Find the first and only predecessor. - 3. Extract condition from the preceding IfNode. - 4. Negate condition if the begin node is second branch - (we've taken the else branch of the condition) - 5. Add the condition or the negated condition to stack - 6. Perform any stamp updates based on the condition using - the registerNewCondition function and place them on the - top of the stack of stamp information - › - "kind g nid = BeginNode nid'; - - nid seen; - seen' = {nid} seen; - - Some ifcond = pred g nid; - kind g ifcond = IfNode cond t f; - - i = find_index nid (successors_of (kind g ifcond)); - c = (if i = 0 then kind g cond else LogicNegationNode cond); - rep g cond ce; - ce' = (if i = 0 then ce else UnaryExpr UnaryLogicNegation ce); - conds' = ce' # conds; - - flow' = registerNewCondition g c (hdOr flow (stamp g)) - Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow' # flow))" | - - ― ‹ - Hit an EndNode - 1. nid' will be the usage of EndNode - 2. pop the conditions and stamp stack - › - "kind g nid = EndNode; - - nid seen; - seen' = {nid} seen; - - nid' = any_usage g nid; - - conds' = tl conds; - flow' = tl flow - Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow'))" | - - ― ‹We can find a successor edge that is not in seen, go there - "¬(is_EndNode (kind g nid)); - ¬(is_BeginNode (kind g nid)); - - nid seen; - seen' = {nid} seen; - - Some nid' = nextEdge seen' nid g - Step g (nid, seen, conds, flow) (Some (nid', seen', conds, flow))" | - - ― ‹We can cannot find a successor edge that is not in seen, give back None - "¬(is_EndNode (kind g nid)); - ¬(is_BeginNode (kind g nid)); - - nid seen; - seen' = {nid} seen; - - None = nextEdge seen' nid g - Step g (nid, seen, conds, flow) None" | - - ― ‹We've already seen this node, give back None - "nid seen Step g (nid, seen, conds, flow) None" + ― ‹We can find a successor edge that is not in seen, go there› + "seen' = {nid} seen; + + Some nid' = next_nid g seen' nid; + nid' seen' + Step g (nid, seen) (Some (nid', seen'))" | + + ― ‹We can cannot find a successor edge that is not in seen, give back None› + "seen' = {nid} seen; + + None = next_nid g seen' nid + Step g (nid, seen) None" | + + ― ‹We've already seen this node, give back None› + "seen' = {nid} seen; + + Some nid' = next_nid g seen' nid; + nid' seen' Step g (nid, seen) None" code_pred (modes: i i o bool) Step . -text -The ConditionalEliminationPhase relation is responsible for combining -the individual traversal steps from the Step relation and the optimizations -from the ConditionalEliminationStep relation to perform a transformation of the -whole graph. - +fun nextNode :: "IRGraph Seen (ID × Seen) option" where + "nextNode g seen = + (let toSee = sorted_list_of_set {n ids g. n seen} in + case toSee of [] None | (x # xs) Some (x, seen {x}))" -inductive ConditionalEliminationPhase - :: "IRGraph (ID × Seen × Conditions × StampFlow) IRGraph bool" where +values "{x. Step ConditionalEliminationTest13_testSnippet2_initial (17, {17,11,25,21,18,19,15,12,13,6,29,27,24,23,7,8,0}) x}" - ― ‹Can do a step and optimise for the current node - "Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow')); - ConditionalEliminationStep (set conds) (hdOr flow (stamp g)) g nid g'; - - ConditionalEliminationPhase g' (nid', seen', conds', flow') g'' - ConditionalEliminationPhase g (nid, seen, conds, flow) g''" | - ― ‹Can do a step, matches whether optimised or not causing non-determinism - We need to find a way to negate ConditionalEliminationStep - "Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow')); +text ‹ +The @{text "ConditionalEliminationPhase"} relation is responsible for combining +the individual traversal steps from the @{text "Step"} relation and the optimizations +from the @{text "ConditionalEliminationStep"} relation to perform a transformation of the +whole graph. +› + +inductive ConditionalEliminationPhase + :: "(Seen × DominatorCache) IRGraph IRGraph bool" + where + + ― ‹Can do a step and optimise for the current node› + "nextNode g seen = Some (nid, seen'); - ConditionalEliminationPhase g (nid', seen', conds', flow') g' - ConditionalEliminationPhase g (nid, seen, conds, flow) g'" | + analyse g c nid (conds, flow, c'); + ConditionalEliminationStep (set conds) (hd flow) nid g g'; - ― ‹Can't do a step but there is a predecessor we can backtrace to - "Step g (nid, seen, conds, flow) None; - Some nid' = pred g nid; - seen' = {nid} seen; - ConditionalEliminationPhase g (nid', seen', conds, flow) g' - ConditionalEliminationPhase g (nid, seen, conds, flow) g'" | + ConditionalEliminationPhase (seen', c') g' g'' + ConditionalEliminationPhase (seen, c) g g''" | - ― ‹Can't do a step and have no predecessors so terminate - "Step g (nid, seen, conds, flow) None; - None = pred g nid - ConditionalEliminationPhase g (nid, seen, conds, flow) g" + "nextNode g seen = None + ConditionalEliminationPhase (seen, c) g g" -code_pred (modes: i i o bool) ConditionalEliminationPhase . +code_pred (modes: i i o bool) ConditionalEliminationPhase . definition runConditionalElimination :: "IRGraph IRGraph" where "runConditionalElimination g = - (Predicate.the (ConditionalEliminationPhase_i_i_o g (0, {}, ([], []))))" - -(* - + (Predicate.the (ConditionalEliminationPhase_i_i_o ({}, Map.empty) g))" + + +values "{(doms, c')| doms c'. +dominators ConditionalEliminationTest13_testSnippet2_initial Map.empty 6 (doms, c')}" + +values "{(conds, stamps, c)| conds stamps c . +analyse ConditionalEliminationTest13_testSnippet2_initial Map.empty 6 (conds, stamps, c)}" +value " + (nextNode + ConditionalEliminationTest13_testSnippet2_initial {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29}) +" +(* +values "{g|g. (ConditionalEliminationPhase ({}, Map.empty) ConditionalEliminationTest13_testSnippet2_initial g)}" +*) +(* inductive ConditionalEliminationPhaseWithTrace✐‹tag invisible› :: "IRGraph ⇒ (ID × Seen × Conditions × StampFlow) ⇒ ID list ⇒ IRGraph ⇒ ID list ⇒ Conditions ⇒ bool" where✐‹tag invisible› (* Can do a step and optimise for the current nid *) "⟦Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow')); - ConditionalEliminationStep (set conds) (hdOr flow (stamp g)) g nid g'; + ConditionalEliminationStep (set conds) (hdOr flow (stamp g)) nid g g'; ConditionalEliminationPhaseWithTrace g' (nid', seen', conds', flow') (nid # t) g'' t' conds''⟧ ⟹ ConditionalEliminationPhaseWithTrace g (nid, seen, conds, flow) t g'' t' conds''" | @@ -862,207 +1067,346 @@

Theory ConditionalElimination.ConditionalElimination

⟹ ConditionalEliminationPhaseWithTrace g (nid, seen, conds, flow) t g (nid # t) conds" code_pred (modes: i ⇒ i ⇒ i ⇒ o ⇒ o ⇒ o ⇒ bool) ConditionalEliminationPhaseWithTrace . +*)
+ +lemma IfNodeStepE: "g, p (nid, m, h) (nid', m', h) + (cond tb fb val. + kind g nid = IfNode cond tb fb + nid' = (if val_to_bool val then tb else fb) + [g, m, p] cond val m' = m)" + using StepE + by (smt (verit, best) IfNode Pair_inject stepDet) + +lemma ifNodeHasCondEvalStutter: + assumes "(g m p h nid nid')" + assumes "kind g nid = IfNode cond t f" + shows " v. ([g, m, p] cond v)" + using IfNodeStepE assms(1) assms(2) stutter.cases unfolding encodeeval.simps + by (smt (verit, ccfv_SIG) IfNodeCond) + +lemma ifNodeHasCondEval: + assumes "(g, p (nid, m, h) (nid', m', h'))" + assumes "kind g nid = IfNode cond t f" + shows " v. ([g, m, p] cond v)" + using IfNodeStepE assms(1) assms(2) apply auto[1] + by (smt (verit) IRNode.disc(1966) IRNode.distinct(1733) IRNode.distinct(1735) IRNode.distinct(1755) IRNode.distinct(1757) IRNode.distinct(1777) IRNode.distinct(1783) IRNode.distinct(1787) IRNode.distinct(1789) IRNode.distinct(401) IRNode.distinct(755) StutterStep fst_conv ifNodeHasCondEvalStutter is_AbstractEndNode.simps is_EndNode.simps(16) snd_conv step.cases) + +lemma replace_if_t: + assumes "kind g nid = IfNode cond tb fb" + assumes "[g, m, p] cond bool" + assumes "val_to_bool bool" + assumes g': "g' = replace_usages nid tb g" + shows "nid' .(g m p h nid nid') (g' m p h nid nid')" +proof - + have g1step: "g, p (nid, m, h) (tb, m, h)" + by (meson IfNode assms(1) assms(2) assms(3) encodeeval.simps) + have g2step: "g', p (nid, m, h) (tb, m, h)" + using g' unfolding replace_usages.simps + by (simp add: stepRefNode) + from g1step g2step show ?thesis + using StutterStep by blast +qed +lemma replace_if_t_imp: + assumes "kind g nid = IfNode cond tb fb" + assumes "[g, m, p] cond bool" + assumes "val_to_bool bool" + assumes g': "g' = replace_usages nid tb g" + shows "nid' .(g m p h nid nid') (g' m p h nid nid')" + using replace_if_t assms by blast + +lemma replace_if_f: + assumes "kind g nid = IfNode cond tb fb" + assumes "[g, m, p] cond bool" + assumes "¬(val_to_bool bool)" + assumes g': "g' = replace_usages nid fb g" + shows "nid' .(g m p h nid nid') (g' m p h nid nid')" +proof - + have g1step: "g, p (nid, m, h) (fb, m, h)" + by (meson IfNode assms(1) assms(2) assms(3) encodeeval.simps) + have g2step: "g', p (nid, m, h) (fb, m, h)" + using g' unfolding replace_usages.simps + by (simp add: stepRefNode) + from g1step g2step show ?thesis + using StutterStep by blast +qed -lemma IfNodeStepE: "g, p ⊢ (nid, m, h) → (nid', m', h) ⟹ - (⋀cond tb fb val. - kind g nid = IfNode cond tb fb ⟹ - nid' = (if val_to_bool val then tb else fb) ⟹ - [g, m, p] ⊢ kind g cond ↦ val ⟹ m' = m)" - using StepE - by (smt (verit, best) IfNode Pair_inject stepDet) - -lemma ifNodeHasCondEvalStutter: - assumes "(g m p h ⊢ nid ↝ nid')" - assumes "kind g nid = IfNode cond t f" - shows "∃ v. ([g, m, p] ⊢ kind g cond ↦ v)" - using IfNodeStepE assms(1) assms(2) stutter.cases - by (meson IfNodeCond) - -lemma ifNodeHasCondEval: - assumes "(g, p ⊢ (nid, m, h) → (nid', m', h'))" - assumes "kind g nid = IfNode cond t f" - shows "∃ v. ([g, m, p] ⊢ kind g cond ↦ v)" - using IfNodeStepE assms(1) assms(2) - by (smt (z3) IRNode.disc(932) IRNode.simps(938) IRNode.simps(958) IRNode.simps(972) IRNode.simps(974) IRNode.simps(978) Pair_inject StutterStep ifNodeHasCondEvalStutter is_AbstractEndNode.simps is_EndNode.simps(12) step.cases) - - -lemma replace_if_t: - assumes "kind g nid = IfNode cond tb fb" - assumes "[g, m, p] ⊢ kind g cond ↦ bool" - assumes "val_to_bool bool" - assumes g': "g' = replace_usages nid tb g" - shows "∃nid' .(g m p h ⊢ nid ↝ nid') ⟷ (g' m p h ⊢ nid ↝ nid')" -proof - - have g1step: "g, p ⊢ (nid, m, h) → (tb, m, h)" - by (meson IfNode assms(1) assms(2) assms(3)) - have g2step: "g', p ⊢ (nid, m, h) → (tb, m, h)" - using g' unfolding replace_usages.simps - by (simp add: stepRefNode) - from g1step g2step show ?thesis - using StutterStep by blast -qed - -lemma replace_if_t_imp: - assumes "kind g nid = IfNode cond tb fb" - assumes "[g, m, p] ⊢ kind g cond ↦ bool" - assumes "val_to_bool bool" - assumes g': "g' = replace_usages nid tb g" - shows "∃nid' .(g m p h ⊢ nid ↝ nid') ⟶ (g' m p h ⊢ nid ↝ nid')" - using replace_if_t assms by blast - -lemma replace_if_f: - assumes "kind g nid = IfNode cond tb fb" - assumes "[g, m, p] ⊢ kind g cond ↦ bool" - assumes "¬(val_to_bool bool)" - assumes g': "g' = replace_usages nid fb g" - shows "∃nid' .(g m p h ⊢ nid ↝ nid') ⟷ (g' m p h ⊢ nid ↝ nid')" -proof - - have g1step: "g, p ⊢ (nid, m, h) → (fb, m, h)" - by (meson IfNode assms(1) assms(2) assms(3)) - have g2step: "g', p ⊢ (nid, m, h) → (fb, m, h)" - using g' unfolding replace_usages.simps - by (simp add: stepRefNode) - from g1step g2step show ?thesis - using StutterStep by blast -qed - -text ‹ +text ‹ Prove that the individual conditional elimination rules are correct with respect to preservation of stuttering steps. -› -lemma ConditionalEliminationStepProof: - assumes wg: "wf_graph g" - assumes ws: "wf_stamps g" - assumes wv: "wf_values g" - assumes nid: "nid ∈ ids g" - assumes conds_valid: "∀ c ∈ conds . ∃ v. ([g, m, p] ⊢ c ↦ v) ∧ val_to_bool v" - assumes ce: "ConditionalEliminationStep conds stamps g nid g'" - - shows "∃nid' .(g m p h ⊢ nid ↝ nid') ⟶ (g' m p h ⊢ nid ↝ nid')" - using ce using assms -proof (induct g nid g' rule: ConditionalEliminationStep.induct) - case (impliesTrue g ifcond cid t f cond conds g') - show ?case proof (cases "(g m p h ⊢ ifcond ↝ nid')") - case True - obtain condv where condv: "[g, m, p] ⊢ kind g cid ↦ condv" - using implies.simps impliesTrue.hyps(3) impliesTrue.prems(4) - using impliesTrue.hyps(2) True - by (metis ifNodeHasCondEvalStutter impliesTrue.hyps(1)) - have condvTrue: "val_to_bool condv" - by (metis condition_implies.intros(2) condv impliesTrue.hyps(2) impliesTrue.hyps(3) impliesTrue.prems(1) impliesTrue.prems(3) impliesTrue.prems(5) implies_true_valid) - then show ?thesis - using constantConditionValid - using impliesTrue.hyps(1) condv impliesTrue.hyps(4) - by blast - next - case False - then show ?thesis by auto - qed -next - case (impliesFalse g ifcond cid t f cond conds g') - then show ?case - proof (cases "(g m p h ⊢ ifcond ↝ nid')") - case True - obtain condv where condv: "[g, m, p] ⊢ kind g cid ↦ condv" - using ifNodeHasCondEvalStutter impliesFalse.hyps(1) - using True by blast - have condvFalse: "False = val_to_bool condv" - by (metis condition_implies.intros(2) condv impliesFalse.hyps(2) impliesFalse.hyps(3) impliesFalse.prems(1) impliesFalse.prems(3) impliesFalse.prems(5) implies_false_valid) - then show ?thesis - using constantConditionValid - using impliesFalse.hyps(1) condv impliesFalse.hyps(4) - by blast - next - case False - then show ?thesis - by auto - qed -next - case (tryFoldTrue g ifcond cid t f cond g' conds) - then show ?case using constantConditionValid tryFoldProofTrue - using StutterStep constantConditionTrue by metis -next - case (tryFoldFalse g ifcond cid t f cond g' conds) - then show ?case using constantConditionValid tryFoldProofFalse - using StutterStep constantConditionFalse by metis -qed +› +lemma ConditionalEliminationStepProof: + assumes wg: "wf_graph g" + assumes ws: "wf_stamps g" + assumes wv: "wf_values g" + assumes nid: "nid ids g" + assumes conds_valid: " c conds . v. ([m, p] c v) val_to_bool v" + assumes ce: "ConditionalEliminationStep conds stamps nid g g'" + + shows "nid' .(g m p h nid nid') (g' m p h nid nid')" + using ce using assms +proof (induct nid g g' rule: ConditionalEliminationStep.induct) + case (impliesTrue g ifcond cid t f cond conds g') + show ?case proof (cases "nid'. (g m p h ifcond nid')") + case True + show ?thesis + by (metis StutterStep constantConditionNoIf constantConditionTrue impliesTrue.hyps(5)) + next + case False + then show ?thesis by auto + qed +next + case (impliesFalse g ifcond cid t f cond conds g') + then show ?case + proof (cases "nid'. (g m p h ifcond nid')") + case True + then show ?thesis + by (metis StutterStep constantConditionFalse constantConditionNoIf impliesFalse.hyps(5)) + next + case False + then show ?thesis + by auto + qed +next + case (unknown g ifcond cid t f cond condNode conds stamps) + then show ?case + by blast +next + case (notIfNode g ifcond conds stamps) + then show ?case + by blast +qed -text ‹ +text ‹ Prove that the individual conditional elimination rules are correct with respect to finding a bisimulation between the unoptimized and optimized graphs. -› -lemma ConditionalEliminationStepProofBisimulation: - assumes wf: "wf_graph g ∧ wf_stamp g stamps ∧ wf_values g" - assumes nid: "nid ∈ ids g" - assumes conds_valid: "∀ c ∈ conds . ∃ v. ([g, m, p] ⊢ c ↦ v) ∧ val_to_bool v" - assumes ce: "ConditionalEliminationStep conds stamps g nid g'" - assumes gstep: "∃ h nid'. (g, p ⊢ (nid, m, h) → (nid', m, h))" (* we don't yet consider optimizations which produce a step that didn't already exist *) - - shows "nid | g ∼ g'" - using ce gstep using assms -proof (induct g nid g' rule: ConditionalEliminationStep.induct) - case (impliesTrue g ifcond cid t f cond conds g' stamps) - from impliesTrue(5) obtain h where gstep: "g, p ⊢ (ifcond, m, h) → (t, m, h)" - by (metis IfNode StutterStep condition_implies.intros(2) ifNodeHasCondEvalStutter impliesTrue.hyps(1) impliesTrue.hyps(2) impliesTrue.hyps(3) impliesTrue.prems(2) impliesTrue.prems(4) implies_true_valid) - have "g', p ⊢ (ifcond, m, h) → (t, m, h)" - using constantConditionTrue impliesTrue.hyps(1) impliesTrue.hyps(4) by blast - then show ?case using gstep - by (metis stepDet strong_noop_bisimilar.intros) -next - case (impliesFalse g ifcond cid t f cond conds g' stamps) - from impliesFalse(5) obtain h where gstep: "g, p ⊢ (ifcond, m, h) → (f, m, h)" - by (metis IfNode condition_implies.intros(2) ifNodeHasCondEval impliesFalse.hyps(1) impliesFalse.hyps(2) impliesFalse.hyps(3) impliesFalse.prems(2) impliesFalse.prems(4) implies_false_valid) - have "g', p ⊢ (ifcond, m, h) → (f, m, h)" - using constantConditionFalse impliesFalse.hyps(1) impliesFalse.hyps(4) by blast - then show ?case using gstep - by (metis stepDet strong_noop_bisimilar.intros) -next - case (tryFoldTrue g ifcond cid t f cond stamps g' conds) - from tryFoldTrue(5) obtain val where "[g, m, p] ⊢ kind g cid ↦ val" - using ifNodeHasCondEval tryFoldTrue.hyps(1) by blast - then have "val_to_bool val" - using tryFoldProofTrue tryFoldTrue.prems(2) tryFoldTrue(3) - by blast - then obtain h where gstep: "g, p ⊢ (ifcond, m, h) → (t, m, h)" - using tryFoldTrue(5) - by (meson IfNode ‹[g, m, p] ⊢ kind g cid ↦ val› tryFoldTrue.hyps(1)) - have "g', p ⊢ (ifcond, m, h) → (t, m, h)" - using constantConditionTrue tryFoldTrue.hyps(1) tryFoldTrue.hyps(4) by presburger - then show ?case using gstep - by (metis stepDet strong_noop_bisimilar.intros) -next - case (tryFoldFalse g ifcond cid t f cond stamps g' conds) - from tryFoldFalse(5) obtain h where gstep: "g, p ⊢ (ifcond, m, h) → (f, m, h)" - by (meson IfNode ifNodeHasCondEval tryFoldFalse.hyps(1) tryFoldFalse.hyps(3) tryFoldFalse.prems(2) tryFoldProofFalse) - have "g', p ⊢ (ifcond, m, h) → (f, m, h)" - using constantConditionFalse tryFoldFalse.hyps(1) tryFoldFalse.hyps(4) by blast - then show ?case using gstep - by (metis stepDet strong_noop_bisimilar.intros) -qed - +› +lemma ConditionalEliminationStepProofBisimulation: + assumes wf: "wf_graph g wf_stamp g stamps wf_values g" + assumes nid: "nid ids g" + assumes conds_valid: " c conds . v. ([m, p] c v) val_to_bool v" + assumes ce: "ConditionalEliminationStep conds stamps nid g g'" + assumes gstep: " h nid'. (g, p (nid, m, h) (nid', m, h))" (* we don't yet consider optimizations which produce a step that didn't already exist *) + + shows "nid | g g'" + using ce gstep using assms +proof (induct nid g g' rule: ConditionalEliminationStep.induct) + case (impliesTrue g ifcond cid t f cond condNode conds stamps g') + from impliesTrue(5) obtain h where gstep: "g, p (ifcond, m, h) (t, m, h)" + using IfNode encodeeval.simps ifNodeHasCondEval impliesTrue.hyps(1) impliesTrue.hyps(2) impliesTrue.hyps(3) impliesTrue.prems(4) implies_impliesnot_valid implies_valid.simps repDet + by (smt (verit) conds_implies.elims condset_implies.simps impliesTrue.hyps(4) impliesTrue.prems(1) impliesTrue.prems(2) option.distinct(1) option.inject tryFoldTrue_valid) + have "g', p (ifcond, m, h) (t, m, h)" + using constantConditionTrue impliesTrue.hyps(1) impliesTrue.hyps(5) by blast + then show ?case using gstep + by (metis stepDet strong_noop_bisimilar.intros) +next + case (impliesFalse g ifcond cid t f cond condNode conds stamps g') + from impliesFalse(5) obtain h where gstep: "g, p (ifcond, m, h) (f, m, h)" + using IfNode encodeeval.simps ifNodeHasCondEval impliesFalse.hyps(1) impliesFalse.hyps(2) impliesFalse.hyps(3) impliesFalse.prems(4) implies_impliesnot_valid impliesnot_valid.simps repDet + by (smt (verit) conds_implies.elims condset_implies.simps impliesFalse.hyps(4) impliesFalse.prems(1) impliesFalse.prems(2) option.distinct(1) option.inject tryFoldFalse_valid) + have "g', p (ifcond, m, h) (f, m, h)" + using constantConditionFalse impliesFalse.hyps(1) impliesFalse.hyps(5) by blast + then show ?case using gstep + by (metis stepDet strong_noop_bisimilar.intros) +next + case (unknown g ifcond cid t f cond condNode conds stamps) + then show ?case + using strong_noop_bisimilar.simps by presburger +next + case (notIfNode g ifcond conds stamps) + then show ?case + using strong_noop_bisimilar.simps by presburger +qed -text ‹Mostly experimental proofs from here on out.› -experiment begin -lemma if_step: +experiment begin +(*lemma if_step: assumes "nid ∈ ids g" assumes "(kind g nid) ∈ control_nodes" shows "(g m p h ⊢ nid ↝ nid')" using assms apply (cases "kind g nid") sorry +*) +(* +definition blockNodes :: "IRGraph ⇒ Block ⇒ ID set" where + "blockNodes g b = {n ∈ ids g. blockOf g n = b}" + +lemma phiInCFG: + "∀n ∈ blockNodes g nid. (g, p ⊢ (n, m, h) → (n', m', h'))" +*) + +lemma inverse_succ: + "n' (succ g n). n ids g n (predecessors g n')" + by simp + +lemma sequential_successors: + assumes "is_sequential_node n" + shows "successors_of n []" + using assms by (cases n; auto) + +lemma nid'_succ: + assumes "nid ids g" + assumes "¬(is_AbstractEndNode (kind g nid0))" + assumes "g, p (nid0, m0, h0) (nid, m, h)" + shows "nid succ g nid0" + using assms(3) proof (induction "(nid0, m0, h0)" "(nid, m, h)" rule: step.induct) + case SequentialNode + then show ?case + by (metis length_greater_0_conv nth_mem sequential_successors succ.simps) +next + case (FixedGuardNode cond before val) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_FixedGuardNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + using FixedGuardNode.hyps(5) by blast +next + case (BytecodeExceptionNode args st exceptionType ref) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_BytecodeExceptionNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (IfNode cond tb fb val) + then have "{tb, fb} = succ g nid0" + using IRNodes.successors_of_IfNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by (metis IfNode.hyps(3) insert_iff) +next + case (EndNodes i phis inps vs) + then show ?case using assms(2) by blast +next + case (NewArrayNode len st length' arrayType h' ref refNo) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_NewArrayNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (ArrayLengthNode x ref arrayVal length') + then have "{nid} = succ g nid0" + using IRNodes.successors_of_ArrayLengthNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (LoadIndexedNode index guard array indexVal ref arrayVal loaded) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_LoadIndexedNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (StoreIndexedNode check val st index guard array indexVal ref "value" arrayVal updated) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_StoreIndexedNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (NewInstanceNode cname obj ref) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_NewInstanceNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (LoadFieldNode f obj ref) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_LoadFieldNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (SignedDivNode x y zero sb v1 v2) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_SignedDivNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (SignedRemNode x y zero sb v1 v2) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_SignedRemNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (StaticLoadFieldNode f) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_LoadFieldNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (StoreFieldNode _ _ _ _ _ _) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_StoreFieldNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +next + case (StaticStoreFieldNode _ _ _ _) + then have "{nid} = succ g nid0" + using IRNodes.successors_of_StoreFieldNode unfolding succ.simps + by (metis empty_set list.simps(15)) + then show ?case + by blast +qed +lemma nid'_pred: + assumes "nid ids g" + assumes "¬(is_AbstractEndNode (kind g nid0))" + assumes "g, p (nid0, m0, h0) (nid, m, h)" + shows "nid0 predecessors g nid" + using assms + by (meson inverse_succ nid'_succ step_in_ids) + +definition wf_pred: + "wf_pred g = (n ids g. card (predecessors g n) = 1)" + +lemma + assumes "¬(is_AbstractMergeNode (kind g n'))" + assumes "wf_pred g" + shows "v. predecessors g n = {v} pred g n' = Some v" + using assms unfolding pred.simps sorry + +lemma inverse_succ1: + assumes "¬(is_AbstractEndNode (kind g n'))" + assumes "wf_pred g" + shows "n' (succ g n). n ids g Some n = (pred g n')" + using assms sorry + +lemma BeginNodeFlow: + assumes "g, p (nid0, m0, h0) (nid, m, h)" + assumes "Some ifcond = pred g nid" + assumes "kind g ifcond = IfNode cond t f" + assumes "i = find_index nid (successors_of (kind g ifcond))" + shows "i = 0 ([g, m, p] cond v) val_to_bool v" +proof - + obtain tb fb where "[tb, fb] = successors_of (kind g ifcond)" + by (simp add: assms(3)) + have "nid0 = ifcond" + using assms step.IfNode sorry + show ?thesis sorry +qed + +(* lemma StepConditionsValid: - assumes "∀ cond ∈ set conds. ([g, m, p] ⊢ cond ↦ v) ∧ val_to_bool v" + assumes "∀ cond ∈ set conds. ([m, p] ⊢ cond ↦ v) ⟶ val_to_bool v" + assumes "g, p ⊢ (nid0, m0, h0) → (nid, m, h)" assumes "Step g (nid, seen, conds, flow) (Some (nid', seen', conds', flow'))" - shows "∀ cond ∈ set conds'. ([g, m, p] ⊢ cond ↦ v) ∧ val_to_bool v" - using assms(2) + shows "∀ cond ∈ set conds'. ([m, p] ⊢ cond ↦ v) ⟶ val_to_bool v" + using assms(3) proof (induction "(nid, seen, conds, flow)" "Some (nid', seen', conds', flow')" rule: Step.induct) - case (1 ifcond cond t f i c) - obtain cv where cv: "[g, m, p] ⊢ c ↦ cv" - sorry + case (1 ifcond cond t f i c ce ce' flow') + assume "∃cv. [m, p] ⊢ ce ↦ cv" + then obtain cv where "[m, p] ⊢ ce ↦ cv" + by blast have cvt: "val_to_bool cv" - sorry + using assms(2) sorry have "set conds' = {c} ∪ set conds" using "1.hyps"(8) by auto then show ?case using cv cvt assms(1) sorry @@ -1103,10 +1447,12 @@

Theory ConditionalElimination.ConditionalElimination

then show ?case sorry qed qed -end -
*)
+*) + +end -end
+
end +
\ No newline at end of file diff --git a/Document/document.pdf b/Document/document.pdf index 0be5a593..f661fd43 100644 Binary files a/Document/document.pdf and b/Document/document.pdf differ diff --git a/Document/index.html b/Document/index.html index 868f1f0b..3760e325 100644 --- a/Document/index.html +++ b/Document/index.html @@ -3,7 +3,7 @@ -Session Document (Isabelle2022) +Session Document (Isabelle2023) diff --git a/Document/outline.pdf b/Document/outline.pdf index 88271128..a97f4e12 100644 Binary files a/Document/outline.pdf and b/Document/outline.pdf differ diff --git a/Document/session_graph.pdf b/Document/session_graph.pdf index 30519e8d..50987936 100644 Binary files a/Document/session_graph.pdf and b/Document/session_graph.pdf differ diff --git a/Graph/.browser_info/build_uuid b/Graph/.browser_info/build_uuid index 53a1ceed..c84274f9 100644 --- a/Graph/.browser_info/build_uuid +++ b/Graph/.browser_info/build_uuid @@ -1 +1 @@ -d2d47bf6-a64f-4b4e-96e5-548dbe51d592 \ No newline at end of file +9410185a-1397-4e37-823e-e573c61b1bda \ No newline at end of file diff --git a/Graph/Class.html b/Graph/Class.html index 330a290d..ec3c4475 100644 --- a/Graph/Class.html +++ b/Graph/Class.html @@ -16,9 +16,9 @@

Theory Class

imports Main begin -text Representation of a standard class containing fields, methods and constructors +text ‹ Representation of a standard class containing fields, methods and constructors › -text ----- Representation of Fields and Parameters ----- +text ‹ ----- Representation of Fields and Parameters ----- › type_synonym FieldName = "string" type_synonym FieldType = "string" @@ -29,28 +29,28 @@

Theory Class

(field_type: FieldType) | NewParameter (parameter_type: ParameterType) -text ----- Representation of a Method ----- +text ‹ ----- Representation of a Method ----- › type_synonym MethodName = "string" type_synonym ReturnType = "string" type_synonym MethodParameters = "JVMField list" type_synonym MethodUniqueName = "string" -(* TODO could extend this to include exceptions throwable? *) +(* TODO could extend this to include exceptions throwable? *) datatype JVMMethod = NewMethod (method_name: MethodName) (method_returnType: ReturnType) (method_parameters: MethodParameters) (method_unique_name: MethodUniqueName) -text ----- Representation of a Constructor ----- +text ‹ ----- Representation of a Constructor ----- › type_synonym ConstructorParameters = "JVMField list" datatype JVMConstructor = NewConstructor (constructor_params: ConstructorParameters) -text ----- Representation of a standard class ----- +text ‹ ----- Representation of a standard class ----- › type_synonym Fields = "JVMField list" type_synonym Methods = "JVMMethod list" @@ -67,11 +67,11 @@

Theory Class

(class_parents: "ParentClass list") (class_parent: ParentClass) -(* Empty placeholder class *) +(* Empty placeholder class *) definition emptyClass :: "JVMClass" where "emptyClass = NewClass ''name_empty'' [] [] [] [] ''parent_empty''" -(* java.lang.Object *) +(* java.lang.Object *) definition jlObject :: "JVMClass" where "jlObject = NewClass ''java.lang.Object'' @@ -91,35 +91,35 @@

Theory Class

[''None''] ''None''"
-text ----- General Functions ----- +text ‹ ----- General Functions ----- › -(* Yoinked from https://www.isa-afp.org/browser_info/Isabelle2012/HOL/List-Index/List_Index.html*) +(* Yoinked from https://www.isa-afp.org/browser_info/Isabelle2012/HOL/List-Index/List_Index.html*) fun find_index :: "'a 'a list nat" where "find_index _ [] = 0" | "find_index v (x # xs) = (if (x=v) then 0 else find_index v xs + 1)" -text ----- Functions to interact with JVMClass lists ----- +text ‹ ----- Functions to interact with JVMClass lists ----- › -(* Returns the index of a class in the JVMClass list *) +(* Returns the index of a class in the JVMClass list *) fun find_class_index :: "string JVMClass list nat" where "find_class_index name cl = find_index name (map class_name cl)" -(* Returns a JVMClass given its name and the JVMClass mapping *) +(* Returns a JVMClass given its name and the JVMClass mapping *) fun get_JVMClass :: "string JVMClass list JVMClass" where "get_JVMClass cName cList = (if ((find_class_index cName cList) = (length cList)) then (emptyClass) else (nth cList (find_class_index cName cList)))" -(* Returns the methods belonging to a particular class, given its name and the JVMClass mapping *) +(* Returns the methods belonging to a particular class, given its name and the JVMClass mapping *) fun get_Methods :: "string JVMClass list JVMMethod list" where "get_Methods cname clist = class_methods (get_JVMClass cname clist)" -(* Returns the simple signature of a method (e.g., "plus(I)I") given its fully-qualified name *) +(* Returns the simple signature of a method (e.g., "plus(I)I") given its fully-qualified name *) fun get_simple_signature :: "string string" where "get_simple_signature fqn = rev (take (find_index (CHR ''.'') (rev fqn)) (rev fqn))" -(* Returns the simple signatures of all the methods belonging to a given class *) +(* Returns the simple signatures of all the methods belonging to a given class *) fun simple_signatures :: "string JVMClass list string list" where "simple_signatures cname clist = (map get_simple_signature (map method_unique_name (get_Methods cname clist)))" @@ -167,9 +167,9 @@

Theory Class

"trans (superclassOf cl)" by simp -(** ----- Testing ----- **) +(** ----- Testing ----- **) -(* +(* public class bestClassEver extends Object { @@ -193,7 +193,7 @@

Theory Class

} } -
*)
+*)
definition bestClassEver :: "JVMClass" where "bestClassEver = @@ -205,21 +205,21 @@

Theory Class

[''Object''] ''Object''"
-(* Testing class-based functions *) +(* Testing class-based functions *) value "class_name bestClassEver" value "class_parent bestClassEver" value "class_fields bestClassEver" value "class_methods bestClassEver" value "class_constructors bestClassEver" -(* Testing field-based functions *) +(* Testing field-based functions *) value "field_name (hd (class_fields bestClassEver))" value "field_type (hd (class_fields bestClassEver))" value "field_name (hd (tl (class_fields bestClassEver)))" value "field_type (hd (tl (class_fields bestClassEver)))" -(* Testing method-based functions *) +(* Testing method-based functions *) value "method_name (hd (class_methods bestClassEver))" value "method_returnType (hd (class_methods bestClassEver))" value "method_parameters (hd (class_methods bestClassEver))" @@ -230,12 +230,12 @@

Theory Class

value "method_parameters (hd (tl (class_methods bestClassEver)))" value "method_unique_name (hd (tl (class_methods bestClassEver)))" -(* Testing constructor-based functions *) +(* Testing constructor-based functions *) value "constructor_params (hd (class_constructors bestClassEver))" value "constructor_params (hd (tl (class_constructors bestClassEver)))" -(* Testing parameter-based functions *) +(* Testing parameter-based functions *) value "parameter_type (hd (method_parameters (hd (class_methods bestClassEver))))" value "parameter_type (hd (method_parameters (hd (tl (class_methods bestClassEver)))))" @@ -243,7 +243,7 @@

Theory Class

value "parameter_type (hd (constructor_params (hd (tl (class_constructors bestClassEver)))))" -(* Samples from Java translator *) +(* Samples from Java translator *) definition unit_InstanceOfTest_instanceOfSnippet4_mapping :: "JVMClass list" where "unit_InstanceOfTest_instanceOfSnippet4_mapping = [ NewClass ''org.graalvm.compiler.core.test.InstanceOfTest$B'' @@ -297,7 +297,7 @@

Theory Class

[''java.lang.Object'', ''None''] ''java.lang.Object'']"
-(* Testing out functions *) +(* Testing out functions *) value "parentRel unit_InvokeVirtual_01_test_mapping" value "superclassOf unit_InvokeVirtual_01_test_mapping" value "classNames unit_InvokeVirtual_01_test_mapping" @@ -308,7 +308,7 @@

Theory Class

value "get_JVMClass ''org.graalvm.compiler.jtt.micro.InvokeVirtual_01$B'' unit_InvokeVirtual_01_test_mapping" value "get_simple_signature ''org.graalvm.compiler.jtt.micro.InvokeVirtual_01$A.plus(I)I''" -(* Lemmas to help with Classes invariants *) +(* Lemmas to help with Classes invariants *) definition inheritsFromObject :: "JVMClass list bool" where "inheritsFromObject cl = ((remdups (map List.last (map class_parents cl))) = [''None''])" @@ -367,7 +367,7 @@

Theory Class

using cl b c d by blast qed -(* Equality *) +(* Equality *) lemma classes_eq_iff: "cl1 = cl2 classToJVMList cl1 = classToJVMList cl2" by (simp add: classToJVMList_inject) @@ -376,7 +376,7 @@

Theory Class

"classToJVMList cl1 = classToJVMList cl2 cl1 = cl2" by (simp add: classToJVMList_inject) -(* Constructor *) +(* Constructor *) setup_lifting type_definition_Classes lift_definition JVMClasses :: "JVMClass list Classes" is @@ -387,7 +387,7 @@

Theory Class

remdupsInherit by fastforce -(* Maintaining invariant *) +(* Maintaining invariant *) lemma nonempty_cl [simp, intro]: "(classToJVMList cl) []" using classToJVMList [of cl] by simp @@ -415,16 +415,16 @@

Theory Class

else [jlObject])" using JVMClasses.rep_eq by auto -(* Abstraction transformation *) +(* Abstraction transformation *) lemma classesToClasses [simp, code abstype]: "JVMClasses (classToJVMList cl) = cl" using acyclic_cl classes_eqI by auto -(* Operations *) +(* Operations *) context begin -(* empty = contains java.lang.Object only *) +(* empty = contains java.lang.Object only *) qualified definition empty :: "Classes" where "empty = JVMClasses []" @@ -442,7 +442,7 @@

Theory Class

end -(* Code gen version with invariant maintained *) +(* Code gen version with invariant maintained *) lemma classToJVM_empty [simp, code abstract]: "classToJVMList Class.empty = [jlObject]" by (metis JVMClasses.rep_eq containsObjImpliesNonEmpty Class.empty_def) @@ -451,7 +451,7 @@

Theory Class

"(Class.mapJVMFunc f cl) = List.map f (classToJVMList cl)" by (simp add: Class.mapJVMFunc_def) -(* Code gen setup *) +(* Code gen setup *) code_datatype JVMClasses lemma [code]: @@ -461,7 +461,7 @@

Theory Class

else [jlObject])" by (simp add: JVMClasses.rep_eq) -(* Testing code gen *) +(* Testing code gen *) definition newclass :: "Classes" where "newclass = JVMClasses [NewClass ''name'' [] [] [] [''parent'', ''None''] ''parent'', jlObject, jlObject]" @@ -473,31 +473,31 @@

Theory Class

value "Class.mapJVMFunc class_name newclass" value "Class.mapJVMFunc class_parent newclass" -(* invalid; java.lang.Object*) +(* invalid; java.lang.Object*) value "classToJVMList (JVMClasses [])" value "classToJVMList (JVMClasses cyclicClass)" -value "acyclic (parentRel cyclicClass)" (* False *) -value "acyclic (parentRel (classToJVMList (JVMClasses cyclicClass)))" (* True *) +value "acyclic (parentRel cyclicClass)" (* False *) +value "acyclic (parentRel (classToJVMList (JVMClasses cyclicClass)))" (* True *) -(* Redefining some functions in terms of Classes, not JVMClass list *) -(* TODO update original functions to these *) +(* Redefining some functions in terms of Classes, not JVMClass list *) +(* TODO update original functions to these *) -(* Returns the index of a class in the Classes list *) +(* Returns the index of a class in the Classes list *) fun CLfind_class_index :: "string Classes nat" where "CLfind_class_index name cl = find_index name (Class.mapJVMFunc class_name cl)" -(* Returns a JVMClass given its name and the Classes list *) +(* Returns a JVMClass given its name and the Classes list *) fun CLget_JVMClass :: "string Classes JVMClass" where "CLget_JVMClass cName cList = (if ((CLfind_class_index cName cList) = (Class.length cList)) then (emptyClass) else (Class.nth cList (CLfind_class_index cName cList)))" -(* Returns the methods belonging to a particular class, given its name and the Classes list *) +(* Returns the methods belonging to a particular class, given its name and the Classes list *) fun CLget_Methods :: "string Classes JVMMethod list" where "CLget_Methods cname clist = class_methods (CLget_JVMClass cname clist)" -(* Returns the simple signatures of all the methods belonging to a given class *) +(* Returns the simple signatures of all the methods belonging to a given class *) fun CLsimple_signatures :: "string Classes string list" where "CLsimple_signatures cname clist = (map get_simple_signature (map method_unique_name (CLget_Methods cname clist)))" diff --git a/Graph/Comparison.html b/Graph/Comparison.html index 03d37a89..1fed31ce 100644 --- a/Graph/Comparison.html +++ b/Graph/Comparison.html @@ -12,7 +12,7 @@

Theory Comparison

-
subsection Structural Graph Comparison
+
subsection ‹Structural Graph Comparison›
 
 theory
   Comparison
@@ -20,10 +20,10 @@ 

Theory Comparison

IRGraph begin -text -We introduce a form of structural graph comparison that is able to assert structural -equivalence of graphs which differ in zero or more reference node chains for any given nodes. - +text ‹ +We introduce a form of structural graph comparison that is able to assert structural +equivalence of graphs which differ in zero or more reference node chains for any given nodes. +› fun find_ref_nodes :: "IRGraph (ID ID)" where "find_ref_nodes g = map_of @@ -42,7 +42,7 @@

Theory Comparison

"Some n = find_next to_see seen; node = kind g n; new = (inputs_of node) @ (successors_of node); - reachables g (to_see @ new) ({n} seen) seen' reachables g to_see seen seen' " + reachables g (to_see @ new) ({n} seen) seen' reachables g to_see seen seen' "
code_pred (modes: i ⇒ i ⇒ i ⇒ o ⇒ bool) [show_steps,show_mode_inference,show_intermediate_results] reachables . diff --git a/Graph/IRGraph.html b/Graph/IRGraph.html index 309dcb75..32360c26 100644 --- a/Graph/IRGraph.html +++ b/Graph/IRGraph.html @@ -12,7 +12,7 @@

Theory IRGraph

-
subsection IR Graph Type
+
subsection ‹IR Graph Type›
 
 theory IRGraph
   imports 
@@ -22,12 +22,12 @@ 

Theory IRGraph

"HOL.Relation" begin -text This theory defines the main Graal data structure - an entire IR Graph. +text ‹This theory defines the main Graal data structure - an entire IR Graph.› -text -IRGraph is defined as a partial map with a finite domain. -The finite domain is required to be able to generate code and produce an interpreter. - +text ‹ +IRGraph is defined as a partial map with a finite domain. +The finite domain is required to be able to generate code and produce an interpreter. +› typedef IRGraph = "{g :: ID (IRNode × Stamp) . finite (dom g)}" proof - have "finite(dom(Map.empty)) ran Map.empty = {}" by auto @@ -80,9 +80,9 @@

Theory IRGraph

"domain_subtraction s r = {(x, y) . (x, y) r x s}" notation (latex) - domain_subtraction ("_ latex‹$\\ndres$› _") + domain_subtraction ("_ latex‹$\\ndres$› _") -(* Theories are required for code generation to work *) +(* Theories are required for code generation to work *) code_datatype irgraph fun filter_none where @@ -108,16 +108,16 @@

Theory IRGraph

lemma [code]: "Rep_IRGraph (irgraph m) = map_of (no_node m)" by (simp add: irgraph.rep_eq) -― ‹Get the inputs set of a given node ID +― ‹Get the inputs set of a given node ID› fun inputs :: "IRGraph ID ID set" where "inputs g nid = set (inputs_of (kind g nid))" -― ‹Get the successor set of a given node ID +― ‹Get the successor set of a given node ID› fun succ :: "IRGraph ID ID set" where "succ g nid = set (successors_of (kind g nid))" -― ‹Gives a relation between node IDs - between a node and its input nodes +― ‹Gives a relation between node IDs - between a node and its input nodes› fun input_edges :: "IRGraph ID rel" where "input_edges g = ( i ids g. {(i,j)|j. j (inputs g i)})" -― ‹Find all the nodes in the graph that have nid as an input - the usages of nid +― ‹Find all the nodes in the graph that have nid as an input - the usages of nid› fun usages :: "IRGraph ID ID set" where "usages g nid = {i. i ids g nid inputs g i}" fun successor_edges :: "IRGraph ID rel" where @@ -188,7 +188,7 @@

Theory IRGraph

lemma map_of_upd: "(map_of g)(k v) = (map_of ((k, v) # g))" by simp -(* this proof should be simplier *) +(* this proof should be simplier *) lemma [code]: "replace_node nid k (irgraph g) = (irgraph ( ((nid, k) # g)))" proof (cases "fst k = NoNode") case True @@ -232,21 +232,21 @@

Theory IRGraph

"gup = replace_node nid (k, s) g ( n (ids g - {nid}) . n ids g n ids gup kind g n = kind gup n)" by (simp add: kind.rep_eq replace_node.rep_eq) -subsubsection "Example Graphs" -text "Example 1: empty graph (just a start and end node)" +subsubsection "Example Graphs" +text "Example 1: empty graph (just a start and end node)" definition start_end_graph:: IRGraph where "start_end_graph = irgraph [(0, StartNode None 1, VoidStamp), (1, ReturnNode None None, VoidStamp)]" -text Example 2: - public static int sq(int x) { return x * x; } - - [1 P(0)] - \ / - [0 Start] [4 *] - | / - V / - [5 Return] - +text ‹Example 2: + public static int sq(int x) { return x * x; } + + [1 P(0)] + \ / + [0 Start] [4 *] + | / + V / + [5 Return] +› definition eg2_sq :: "IRGraph" where "eg2_sq = irgraph [ (0, StartNode None 5, VoidStamp), @@ -255,13 +255,13 @@

Theory IRGraph

(5, ReturnNode (Some 4) None, default_stamp) ]"
-(* TODO: to include the float type (used by stamps) we need +(* TODO: to include the float type (used by stamps) we need a code equation for float_of but it is not clear how to implement this correctly lemma[code]: "float_of n = 0" -*) +*) -(* Test the code generation. *) +(* Test the code generation. *) value "input_edges eg2_sq" value "usages eg2_sq 1" diff --git a/Graph/IRNodeHierarchy.html b/Graph/IRNodeHierarchy.html index 4a8ef071..4822b79b 100644 --- a/Graph/IRNodeHierarchy.html +++ b/Graph/IRNodeHierarchy.html @@ -12,31 +12,31 @@

Theory IRNodeHierarchy

-
subsection IR Graph Node Hierarchy
+
subsection ‹IR Graph Node Hierarchy›
 
 theory IRNodeHierarchy
 imports IRNodes
 begin
 
-text 
-It is helpful to introduce a node hierarchy into our formalization.
-Often the GraalVM compiler relies on explicit type checks to determine
-which operations to perform on a given node, we try to mimic the same
-functionality by using a suite of predicate functions over the IRNode
-class to determine inheritance.
-
-As one would expect, the function is<ClassName>Type will be true if
-the node parameter is a subclass of the ClassName within the GraalVM compiler.
-
-These functions have been automatically generated from the compiler.
-
-
-(* Datatype with no parameters don't generate selectors *)
+text ‹
+It is helpful to introduce a node hierarchy into our formalization.
+Often the GraalVM compiler relies on explicit type checks to determine
+which operations to perform on a given node, we try to mimic the same
+functionality by using a suite of predicate functions over the IRNode
+class to determine inheritance.
+
+As one would expect, the function is<ClassName>Type will be true if
+the node parameter is a subclass of the ClassName within the GraalVM compiler.
+
+These functions have been automatically generated from the compiler.
+›
+
+(* Datatype with no parameters don't generate selectors *)
 fun is_EndNode :: "IRNode  bool" where
   "is_EndNode EndNode = True" |
   "is_EndNode _ = False"
 
-(* nodeout: isabelle-subclass *)
+(* nodeout: isabelle-subclass *)
 fun is_VirtualState :: "IRNode  bool" where
   "is_VirtualState n = ((is_FrameState n))"
 
@@ -249,7 +249,7 @@ 

Theory IRNodeHierarchy

fun is_ConvertNode :: "IRNode bool" where "is_ConvertNode n = ((is_IntegerConvertNode n))" -(* nodeout *) +(* nodeout *) fun is_sequential_node :: "IRNode bool" where "is_sequential_node (StartNode _ _) = True" | @@ -262,13 +262,13 @@

Theory IRNodeHierarchy

"is_sequential_node (ControlFlowAnchorNode _) = True" | "is_sequential_node _ = False" -text -The following convenience function is useful in determining if -two IRNodes are of the same type irregardless of their edges. -It will return true if both the node parameters are the same node class. - +text ‹ +The following convenience function is useful in determining if +two IRNodes are of the same type irregardless of their edges. +It will return true if both the node parameters are the same node class. +› -(* nodeout: isabelle-compare-type *) +(* nodeout: isabelle-compare-type *) fun is_same_ir_node_type :: "IRNode IRNode bool" where "is_same_ir_node_type n1 n2 = ( ((is_AbsNode n1) (is_AbsNode n2)) diff --git a/Graph/IRNodes.html b/Graph/IRNodes.html index 5a794c57..adbc57a4 100644 --- a/Graph/IRNodes.html +++ b/Graph/IRNodes.html @@ -12,60 +12,60 @@

Theory IRNodes

-
section Graph Representation
-subsection IR Graph Nodes
+
section ‹Graph Representation›
+subsection ‹IR Graph Nodes›
 
 theory IRNodes
   imports
     Values
 begin
 
-text 
-The GraalVM IR is represented using a graph data structure.
-Here we define the nodes that are contained within the graph.
-Each node represents a Node subclass in the GraalVM compiler,
-the node classes have annotated fields to indicate input and successor edges.
-
-We represent these classes with each IRNode constructor explicitly labelling
-a reference to the node IDs that it stores as inputs and successors.
-
-The inputs\_of and successors\_of functions partition those labelled references
-into input edges and successor edges of a node.
-
-To identify each Node, we use a simple natural number index.
-Zero is always the start node in a graph.
-For human readability, within nodes we write 
-INPUT (or special case thereof) instead of ID for input edges, and
-SUCC instead of ID for control-flow successor edges.
-Optional edges are handled as "INPUT option" etc.
-
+text ‹
+The GraalVM IR is represented using a graph data structure.
+Here we define the nodes that are contained within the graph.
+Each node represents a Node subclass in the GraalVM compiler,
+the node classes have annotated fields to indicate input and successor edges.
 
-(* Represents the InvokeKind of a CallTargetNode *)
+We represent these classes with each IRNode constructor explicitly labelling
+a reference to the node IDs that it stores as inputs and successors.
+
+The inputs\_of and successors\_of functions partition those labelled references
+into input edges and successor edges of a node.
+
+To identify each Node, we use a simple natural number index.
+Zero is always the start node in a graph.
+For human readability, within nodes we write 
+INPUT (or special case thereof) instead of ID for input edges, and
+SUCC instead of ID for control-flow successor edges.
+Optional edges are handled as "INPUT option" etc.
+›
+
+(* Represents the InvokeKind of a CallTargetNode *)
 datatype IRInvokeKind = 
   Interface | Special | Static | Virtual
 
-(* Mimics isDirect in the compiler *)
+(* Mimics isDirect in the compiler *)
 fun isDirect :: "IRInvokeKind  bool" where
   "isDirect Interface = False" |
   "isDirect Special = True" |
   "isDirect Static = True" |
   "isDirect Virtual = False"
 
-(* Mimics hasReceiver in the compiler *)
+(* Mimics hasReceiver in the compiler *)
 fun hasReceiver :: "IRInvokeKind  bool" where
   "hasReceiver Static = False" |
   "hasReceiver _ = True"
 
 type_synonym ID = "nat"
-type_synonym INPUT = "ID"   (* InputType.Value is the default *)
-type_synonym INPUT_ASSOC = "ID" (* InputType.Association *)
-type_synonym INPUT_STATE = "ID" (* InputType.State *)
-type_synonym INPUT_GUARD = "ID" (* InputType.Guard *)
-type_synonym INPUT_COND = "ID"  (* InputType.Condition *)
-type_synonym INPUT_EXT = "ID"  (* InputType.Extension *)
+type_synonym INPUT = "ID"   (* InputType.Value is the default *)
+type_synonym INPUT_ASSOC = "ID" (* InputType.Association *)
+type_synonym INPUT_STATE = "ID" (* InputType.State *)
+type_synonym INPUT_GUARD = "ID" (* InputType.Guard *)
+type_synonym INPUT_COND = "ID"  (* InputType.Condition *)
+type_synonym INPUT_EXT = "ID"  (* InputType.Extension *)
 type_synonym SUCC = "ID"
 
-(* nodeout: isabelle-datatypes *)
+(* nodeout: isabelle-datatypes *)
 datatype (discs_sels) IRNode =
   AbsNode (ir_value: "INPUT") 
   | AddNode (ir_x: "INPUT") (ir_y: "INPUT") 
@@ -131,13 +131,13 @@ 

Theory IRNodes

| XorNode (ir_x: "INPUT") (ir_y: "INPUT") | ZeroExtendNode (ir_inputBits: nat) (ir_resultBits: nat) (ir_value: "INPUT") | NoNode -(* nodeout *) +(* nodeout *) - (* Manually added *) + (* Manually added *) | RefNode (ir_ref:ID) -(* Surely this must exist already? I cannot find it in option or list theory. *) +(* Surely this must exist already? I cannot find it in option or list theory. *) fun opt_to_list :: "'a option 'a list" where "opt_to_list None = []" | "opt_to_list (Some v) = [v]" @@ -146,12 +146,12 @@

Theory IRNodes

"opt_list_to_list None = []" | "opt_list_to_list (Some x) = x" -text -The following functions, inputs\_of and successors\_of, are automatically generated -from the GraalVM compiler. -Their purpose is to partition the node edges into input or successor edges. - -(* nodeout: isabelle-inputs *) +text ‹ +The following functions, inputs\_of and successors\_of, are automatically generated +from the GraalVM compiler. +Their purpose is to partition the node edges into input or successor edges. +› +(* nodeout: isabelle-inputs *) fun inputs_of :: "IRNode ID list" where inputs_of_AbsNode: "inputs_of (AbsNode value) = [value]" | @@ -280,11 +280,11 @@

Theory IRNodes

inputs_of_ZeroExtendNode: "inputs_of (ZeroExtendNode inputBits resultBits value) = [value]" | inputs_of_NoNode: "inputs_of (NoNode) = []" | -(* nodeout *) +(* nodeout *) inputs_of_RefNode: "inputs_of (RefNode ref) = [ref]" -(* nodeout: isabelle-succs *) +(* nodeout: isabelle-succs *) fun successors_of :: "IRNode ID list" where successors_of_AbsNode: "successors_of (AbsNode value) = []" | @@ -413,7 +413,7 @@

Theory IRNodes

successors_of_ZeroExtendNode: "successors_of (ZeroExtendNode inputBits resultBits value) = []" | successors_of_NoNode: "successors_of (NoNode) = []" | -(* nodeout *) +(* nodeout *) successors_of_RefNode: "successors_of (RefNode ref) = [ref]" diff --git a/Graph/JavaLong.html b/Graph/JavaLong.html index 21321b3e..11619bf6 100644 --- a/Graph/JavaLong.html +++ b/Graph/JavaLong.html @@ -12,11 +12,11 @@

Theory JavaLong

-
section java.lang.Long
+
section ‹java.lang.Long›
 
-text 
-Utility functions from the Java Long class that Graal occasionally makes use of.
-
+text ‹
+Utility functions from the Java Long class that Graal occasionally makes use of.
+›
 
 theory JavaLong
   imports JavaWords
@@ -27,7 +27,7 @@ 

Theory JavaLong

"n < 32 bit (-1::int32) n" apply transfer by auto -(* TODO: better handle empty *) +(* TODO: better handle empty *) definition MaxOrNeg :: "nat set int" where "MaxOrNeg s = (if s = {} then -1 else Max s)" @@ -41,7 +41,7 @@

Theory JavaLong

subsection Long.highestOneBit -(* This is a different definition to Long.highestOneBit *) +(* This is a different definition to Long.highestOneBit *) definition highestOneBit :: "('a::len) word int" where "highestOneBit v = MaxOrNeg {n. bit v n}" @@ -102,7 +102,7 @@

Theory JavaLong

by (metis Max_in finite_bit_word le0 le_minus_one_simps(3) mem_Collect_eq of_nat_0_le_iff of_nat_eq_iff) -text A recursive implementation of highestOneBit that is suitable for code generation. +text ‹A recursive implementation of highestOneBit that is suitable for code generation.› fun highestOneBitRec :: "nat ('a::len) word int" where "highestOneBitRec n v = @@ -146,8 +146,8 @@

Theory JavaLong

using assms by force -text Some lemmas that use masks to restrict highestOneBit - and relate it to highestOneBitRec. +text ‹Some lemmas that use masks to restrict highestOneBit + and relate it to highestOneBitRec.› lemma highestOneBitMask: assumes "size v = n" @@ -200,7 +200,7 @@

Theory JavaLong

qed -text Finally - we can use the mask lemmas to relate highestOneBitRec to its spec. +text ‹Finally - we can use the mask lemmas to relate highestOneBitRec to its spec.› lemma highestOneBitImpl[code]: "highestOneBit v = highestOneBitRec (size v) v" @@ -208,7 +208,7 @@

Theory JavaLong

lemma "highestOneBit (0x5 :: int8) = 2" by code_simp -subsection Long.lowestOneBit +subsection ‹Long.lowestOneBit› definition lowestOneBit :: "('a::len) word nat" where "lowestOneBit v = MinOrHighest {n . bit v n} (size v)" @@ -220,7 +220,7 @@

Theory JavaLong

using max_bit unfolding MaxOrNeg_def by force -subsection Long.numberOfLeadingZeros +subsection ‹Long.numberOfLeadingZeros› definition numberOfLeadingZeros :: "('a::len) word nat" where "numberOfLeadingZeros v = nat (Nat.size v - highestOneBit v - 1)" @@ -261,7 +261,7 @@

Theory JavaLong

unfolding numberOfLeadingZeros_def highestOneBit_def using MaxOrNeg_def int_nat_eq int_ops(6) max_bit order_less_irrefl by fastforce -subsection Long.numberOfTrailingZeros +subsection ‹Long.numberOfTrailingZeros› definition numberOfTrailingZeros :: "('a::len) word nat" where "numberOfTrailingZeros v = lowestOneBit v" @@ -280,19 +280,19 @@

Theory JavaLong

unfolding numberOfTrailingZeros_def using lowestOneBit_bot by simp -subsection Long.reverseBytes +subsection ‹Long.reverseBytes› -(* Recursive version of reverseBytes for code generation *) +(* Recursive version of reverseBytes for code generation *) fun reverseBytes_fun :: "('a::len) word nat ('a::len) word ('a::len) word" where "reverseBytes_fun v b flip = (if (b = 0) then (flip) else (reverseBytes_fun (v >> 8) (b - 8) (or (flip << 8) (take_bit 8 v))))" -subsection Long.bitCount +subsection ‹Long.bitCount› definition bitCount :: "('a::len) word nat" where "bitCount v = card {n . bit v n}" -(* Recursive version of bitCount for code generation *) +(* Recursive version of bitCount for code generation *) fun bitCount_fun :: "('a::len) word nat nat" where "bitCount_fun v n = (if (n = 0) then (if (bit v n) then 1 else 0) else @@ -303,7 +303,7 @@

Theory JavaLong

unfolding bitCount_def by (metis card.empty zero_no_bits) -subsection Long.zeroCount +subsection ‹Long.zeroCount› definition zeroCount :: "('a::len) word nat" where "zeroCount v = card {n. n < Nat.size v ¬(bit v n)}" diff --git a/Graph/JavaWords.html b/Graph/JavaWords.html index 1c9adb01..212c4275 100644 --- a/Graph/JavaWords.html +++ b/Graph/JavaWords.html @@ -12,7 +12,7 @@

Theory JavaWords

-
section Additional Theorems about Computer Words
+
section ‹Additional Theorems about Computer Words›
 
 theory JavaWords
   imports
@@ -22,24 +22,24 @@ 

Theory JavaWords

"HOL-Library.LaTeXsugar" begin -text Java supports 64, 32, 16, 8 signed ints, plus 1 bit (boolean) -ints, and char is 16-bit unsigned. -E.g. an 8-bit stamp has a default range of -128..+127. -And a 1-bit stamp has a default range of -1..0, surprisingly. - -During calculations the smaller sizes are sign-extended to 32 bits. - +text ‹Java supports 64, 32, 16, 8 signed ints, plus 1 bit (boolean) +ints, and char is 16-bit unsigned. +E.g. an 8-bit stamp has a default range of -128..+127. +And a 1-bit stamp has a default range of -1..0, surprisingly. -type_synonym int64 = "64 word" ― ‹long -type_synonym int32 = "32 word" ― ‹int -type_synonym int16 = "16 word" ― ‹short -type_synonym int8 = "8 word" ― ‹char -type_synonym int1 = "1 word" ― ‹boolean +During calculations the smaller sizes are sign-extended to 32 bits. +› + +type_synonym int64 = "64 word" ― ‹long› +type_synonym int32 = "32 word" ― ‹int› +type_synonym int16 = "16 word" ― ‹short› +type_synonym int8 = "8 word" ― ‹char› +type_synonym int1 = "1 word" ― ‹boolean› abbreviation valid_int_widths :: "nat set" where "valid_int_widths {1, 8, 16, 32, 64}" -type_synonym iwidth = "nat" (* TODO: 1..64 *) +type_synonym iwidth = "nat" (* TODO: 1..64 *) fun bit_bounds :: "nat (int × int)" where @@ -54,12 +54,12 @@

Theory JavaWords

fun int_unsigned_value :: "iwidth int64 int" where "int_unsigned_value b v = uint v" -text A convenience function for directly constructing -1 values of a given bit size. +text ‹A convenience function for directly constructing -1 values of a given bit size.› fun neg_one :: "iwidth int64" where "neg_one b = mask b" -subsection Bit-Shifting Operators +subsection ‹Bit-Shifting Operators› definition shiftl (infix "<<" 75) where "shiftl w n = (push_bit n) w" @@ -82,27 +82,27 @@

Theory JavaWords

by (simp add: right_diff_distrib) -text Unsigned shift right. +text ‹Unsigned shift right.› definition shiftr (infix ">>>" 75) where "shiftr w n = drop_bit n w" corollary "(255 :: 8 word) >>> (2 :: nat) = 63" by code_simp -(* TODO: define this using Word.signed_drop_bit ? *) -text Signed shift right. +(* TODO: define this using Word.signed_drop_bit ? *) +text ‹Signed shift right.› definition sshiftr :: "'a :: len word nat 'a :: len word" (infix ">>" 75) where "sshiftr w n = word_of_int ((sint w) div (2 ^ n))" corollary "(128 :: 8 word) >> 2 = 0xE0" by code_simp -subsection Fixed-width Word Theories +subsection ‹Fixed-width Word Theories› -(* declare [[show_types=true]] *) +(* declare [[show_types=true]] *) -subsubsection Support Lemmas for Upper/Lower Bounds +subsubsection ‹Support Lemmas for Upper/Lower Bounds› -(* these two were weirdly hard to prove given it should be by definition *) +(* these two were weirdly hard to prove given it should be by definition *) lemma size32: "size v = 32" for v :: "32 word" by (smt (verit, del_insts) mult.commute One_nat_def add.right_neutral add_Suc_right numeral_2_eq_2 len_of_numeral_defs(2,3) mult.right_neutral mult_Suc_right numeral_Bit0 size_word.rep_eq) @@ -111,7 +111,7 @@

Theory JavaWords

by (metis numeral_times_numeral semiring_norm(12) semiring_norm(13) size32 len_of_numeral_defs(3) size_word.rep_eq) -(* Nb. Word.sint_ge and sint_lt subsume these lemmas. +(* Nb. Word.sint_ge and sint_lt subsume these lemmas. lemma signed_int_bottom32: "-(((2::int) ^ 31)) ≤ sint (v::int32)" using sint_range_size size32 by (smt (verit, ccfv_SIG) One_nat_def Suc_pred add_Suc add_Suc_right eval_nat_numeral(3) nat.inject numeral_2_eq_2 numeral_Bit0 numeral_Bit1 zero_less_numeral) @@ -119,19 +119,19 @@

Theory JavaWords

lemma signed_int_top32: "(2 ^ 31) - 1 ≥ sint (v::int32)" using sint_range_size size32 by (smt (verit, ccfv_SIG) One_nat_def Suc_pred add_Suc add_Suc_right eval_nat_numeral(3) nat.inject numeral_2_eq_2 numeral_Bit0 numeral_Bit1 zero_less_numeral) -
*)
+*)
lemma lower_bounds_equiv: assumes "0 < N" shows "-(((2::int) ^ (N-1))) = (2::int) ^ N div 2 * - 1" - by (simp add: assms int_power_div_base) + by (simp add: assms int_power_div_base) lemma upper_bounds_equiv: assumes "0 < N" shows "(2::int) ^ (N-1) = (2::int) ^ N div 2" - by (simp add: assms int_power_div_base) + by (simp add: assms int_power_div_base) -text Some min/max bounds for 64-bit words +text ‹Some min/max bounds for 64-bit words› lemma bit_bounds_min64: "((fst (bit_bounds 64))) (sint (v::int64))" unfolding bit_bounds.simps fst_def @@ -142,10 +142,10 @@

Theory JavaWords

using sint_lt[of v] by simp -text Extend these min/max bounds to extracting smaller signed words using $signed\_take\_bit$. +text ‹Extend these min/max bounds to extracting smaller signed words using $signed\_take\_bit$.› -text Note: we could use signed to convert between bit-widths, instead of - $signed\_take\_bit$. But that would have to be done separately for each bit-width type. +text ‹Note: we could use signed to convert between bit-widths, instead of + $signed\_take\_bit$. But that would have to be done separately for each bit-width type.› corollary "sint(signed_take_bit 7 (128 :: int8)) = -128" by code_simp @@ -177,7 +177,7 @@

Theory JavaWords

using signed_take_bit_int_greater_eq_minus_exp_word signed_take_bit_int_less_exp_word using assms by blast -text A $bit\_bounds$ version of the above lemma. +text ‹A $bit\_bounds$ version of the above lemma.› lemma signed_take_bit_bounds: fixes ival :: "'a :: len word" @@ -188,8 +188,8 @@

Theory JavaWords

using assms signed_take_bit_range lower_bounds_equiv upper_bounds_equiv by (metis bit_bounds.simps fst_conv less_imp_diff_less nat_less_le sint_ge sint_lt snd_conv zle_diff1_eq) -(* It is helpful to have the 64-bit instance of the above, to avoid uninstantiated types - when applying it backwards. *) +(* It is helpful to have the 64-bit instance of the above, to avoid uninstantiated types + when applying it backwards. *) lemma signed_take_bit_bounds64: fixes ival :: "int64" assumes "n 64" @@ -217,7 +217,7 @@

Theory JavaWords

word_exp_length_eq_0 diff_less diff_zero len_gt_0 sint_less power_strict_increasing signed_take_bit_range power_less_imp_less_exp) -text Some lemmas to relate (int) bit bounds to bit-shifting values. +text ‹Some lemmas to relate (int) bit bounds to bit-shifting values.› lemma bit_bounds_lower: assumes "0 < bits" @@ -228,18 +228,18 @@

Theory JavaWords

lemma two_exp_div: assumes "0 < bits" shows "((2::int) ^ bits div (2::int)) = (2::int) ^ (bits - Suc 0)" - using assms by (auto simp: int_power_div_base) + using assms by (auto simp: int_power_div_base) declare [[show_types]] -(* +(* lemma mask_drop_bit_test: "∀ n bits :: nat. 0 < bits ∧ bits < 4 ∧ n < bits ∧ bits < LENGTH('a) ⟶ drop_bit n (mask bits :: 'a :: len word) = mask (bits - n)" nitpick -*) -(* +*) +(* lemma mask_drop_bit: fixes n bits :: nat assumes "0 < bits" @@ -274,9 +274,9 @@

Theory JavaWords

apply (simp add: int_power_div_base) apply (simp add: mask_eq_decr_exp) -
*)
+*)
-text Some lemmas about unsigned words smaller than 64-bit, for zero-extend operators. +text ‹Some lemmas about unsigned words smaller than 64-bit, for zero-extend operators.› lemma take_bit_smaller_range: fixes ival :: "'a :: len word" @@ -291,7 +291,7 @@

Theory JavaWords

shows "ival = take_bit n ival" by (simp add: assms) -text A simplification lemma for $new\_int$, showing that upper bits can be ignored. +text ‹A simplification lemma for $new\_int$, showing that upper bits can be ignored.› lemma take_bit_redundant[simp]: fixes ival :: "'a :: len word" @@ -322,8 +322,8 @@

Theory JavaWords

using assms take_bit_same_size_range by force -text Next we show that casting a word to a wider word preserves any upper/lower bounds. - (These lemmas may not be needed any more, since we are not using scast now?) +text ‹Next we show that casting a word to a wider word preserves any upper/lower bounds. + (These lemmas may not be needed any more, since we are not using scast now?)› lemma scast_max_bound: assumes "sint (v :: 'a :: len word) < M" @@ -356,9 +356,9 @@

Theory JavaWords

using assms scast_bigger_min_bound scast_bigger_max_bound by auto -subsubsection Support lemmas for take bit and signed take bit. +subsubsection ‹Support lemmas for take bit and signed take bit.› -text Lemmas for removing redundant take\_bit wrappers. +text ‹Lemmas for removing redundant take\_bit wrappers.› lemma take_bit_dist_addL[simp]: fixes x :: "'a :: len word" @@ -408,10 +408,10 @@

Theory JavaWords

fixes m n :: nat assumes "n < m" shows "(a mod 2 ^ m) mod 2 ^ n = a mod 2 ^ n" - by (meson assms le_imp_power_dvd less_or_eq_imp_le mod_mod_cancel) + by (meson assms le_imp_power_dvd less_or_eq_imp_le mod_mod_cancel) lemma mod_dist_over_add: - fixes a b c :: int64 (* "'a :: len word" *) + fixes a b c :: int64 (* "'a :: len word" *) fixes n :: nat assumes 1: "0 < n" assumes 2: "n < 64" @@ -425,10 +425,10 @@

Theory JavaWords

by (metis (no_types, opaque_lifting) and.right_idem take_bit_add take_bit_eq_mask) qed -subsection Java min and max operators on 64-bit values +subsection ‹Java min and max operators on 64-bit values› -text Java uses signed comparison, so we define a convenient abbreviation for this to avoid - accidental mistakes, because by default the Isabelle min/max will assume unsigned words. +text ‹Java uses signed comparison, so we define a convenient abbreviation for this to avoid + accidental mistakes, because by default the Isabelle min/max will assume unsigned words.› abbreviation javaMin64 :: "int64 int64 int64" where "javaMin64 a b (if a ≤s b then a else b)" diff --git a/Graph/Stamp.html b/Graph/Stamp.html index 83a21ba5..bef1b52e 100644 --- a/Graph/Stamp.html +++ b/Graph/Stamp.html @@ -12,26 +12,26 @@

Theory Stamp

-
section Stamp Typing
+
section ‹Stamp Typing›
 
 theory Stamp
   imports Values
 begin
 
-text 
-The GraalVM compiler uses the Stamp class to store range and type information
-for a given node in the IR graph.
-We model the Stamp class as a datatype, Stamp, and provide a number of functions
-on the datatype which correspond to the class methods within the compiler.
-
-Stamp information is used in a variety of ways in optimizations, and so, we
-additionally provide a number of lemmas which help to prove future optimizations.
-
+text ‹
+The GraalVM compiler uses the Stamp class to store range and type information
+for a given node in the IR graph.
+We model the Stamp class as a datatype, Stamp, and provide a number of functions
+on the datatype which correspond to the class methods within the compiler.
+
+Stamp information is used in a variety of ways in optimizations, and so, we
+additionally provide a number of lemmas which help to prove future optimizations.
+›
 
 datatype Stamp = 
   VoidStamp
   | IntegerStamp (stp_bits: nat) (stpi_lower: int) (stpi_upper: int)
-  (* | FloatStamp (stp_bits: nat) (stpf_lower: float) (stpf_upper: float) *)
+  (* | FloatStamp (stp_bits: nat) (stpf_lower: float) (stpf_upper: float) *)
   | KlassPointerStamp (stp_nonNull: bool) (stp_alwaysNull: bool)
   | MethodCountersPointerStamp (stp_nonNull: bool) (stp_alwaysNull: bool)
   | MethodPointersStamp (stp_nonNull: bool) (stp_alwaysNull: bool)
@@ -40,32 +40,32 @@ 

Theory Stamp

| IllegalStamp -text To help with supporting masks in future, this constructor allows masks but ignores them. +text ‹To help with supporting masks in future, this constructor allows masks but ignores them.› abbreviation IntegerStampM :: "nat int int int64 int64 Stamp" where "IntegerStampM b lo hi down up IntegerStamp b lo hi" fun is_stamp_empty :: "Stamp bool" where "is_stamp_empty (IntegerStamp b lower upper) = (upper < lower)" | - (* "is_stamp_empty (FloatStamp b lower upper) = (upper < lower)" | *) + (* "is_stamp_empty (FloatStamp b lower upper) = (upper < lower)" | *) "is_stamp_empty x = False" -text Just like the IntegerStamp class, we need to know that our lo/hi bounds - fit into the given number of bits (either signed or unsigned). - Our integer stamps have infinite lo/hi bounds, so if the lower - bound is non-negative, we can assume that all values are positive, - and the integer bits of a related value can be interpreted as unsigned. - This is similar (but slightly more general) to what IntegerStamp.java - does with its test: if (sameSignBounds()) in the unsignedUpperBound() method. - - Note that this is a bit different and more accurate than what - StampFactory.forUnsignedInteger does (it widens large unsigned ranges to the - max signed range to allow all bit patterns) because its lo/hi values are only 64-bit. - -(* TODO: should we have tight bounds for empty stamp, or just hi<lo? +text ‹Just like the IntegerStamp class, we need to know that our lo/hi bounds + fit into the given number of bits (either signed or unsigned). + Our integer stamps have infinite lo/hi bounds, so if the lower + bound is non-negative, we can assume that all values are positive, + and the integer bits of a related value can be interpreted as unsigned. + This is similar (but slightly more general) to what IntegerStamp.java + does with its test: if (sameSignBounds()) in the unsignedUpperBound() method. + + Note that this is a bit different and more accurate than what + StampFactory.forUnsignedInteger does (it widens large unsigned ranges to the + max signed range to allow all bit patterns) because its lo/hi values are only 64-bit. +› +(* TODO: should we have tight bounds for empty stamp, or just hi<lo? We could have: (lo = snd (bit_bounds bits) ∧ hi = fst (bit_bounds bits) - *) + *) fun valid_stamp :: "Stamp bool" where "valid_stamp (IntegerStamp bits lo hi) = (0 < bits bits 64 @@ -73,30 +73,30 @@

Theory Stamp

fst (bit_bounds bits) hi hi snd (bit_bounds bits))"
| "valid_stamp s = True" -(* Note: we could support 32/64-bit unsigned values by relaxing this definition to: +(* Note: we could support 32/64-bit unsigned values by relaxing this definition to: (is_stamp_empty (IntegerStamp bits lo hi) ∨ lo < 0 ∧ fst (bit_bounds bits) ≤ lo ∧ lo ≤ hi ∧ hi ≤ snd (bit_bounds bits) ∨ 0 ≤ lo ∧ lo ≤ hi ∧ hi < 2 ^ bits))" -*) +*) experiment begin -corollary "bit_bounds 1 = (-1, 0)" by simp (* this matches the compiler stamps. *) +corollary "bit_bounds 1 = (-1, 0)" by simp (* this matches the compiler stamps. *) end -(* NOTE: the FloatStamp has been commented out to allow use of code generation facilities *) -(* +(* NOTE: the FloatStamp has been commented out to allow use of code generation facilities *) +(* definition pos_infinity :: "float" where "pos_infinity = float_of (0 * 2 powr 255)" definition neg_infinity :: "float" where "neg_infinity = -pos_infinity" -*) +*) -― ‹A stamp which includes the full range of the type +― ‹A stamp which includes the full range of the type› fun unrestricted_stamp :: "Stamp Stamp" where "unrestricted_stamp VoidStamp = VoidStamp" | "unrestricted_stamp (IntegerStamp bits lower upper) = (IntegerStamp bits (fst (bit_bounds bits)) (snd (bit_bounds bits)))" | - (* "unrestricted_stamp (FloatStamp bits lower upper) = (FloatStamp bits neg_infinity pos_infinity)" | *) + (* "unrestricted_stamp (FloatStamp bits lower upper) = (FloatStamp bits neg_infinity pos_infinity)" | *) "unrestricted_stamp (KlassPointerStamp nonNull alwaysNull) = (KlassPointerStamp False False)" | "unrestricted_stamp (MethodCountersPointerStamp nonNull alwaysNull) = (MethodCountersPointerStamp False False)" | "unrestricted_stamp (MethodPointersStamp nonNull alwaysNull) = (MethodPointersStamp False False)" | @@ -106,11 +106,11 @@

Theory Stamp

fun is_stamp_unrestricted :: "Stamp bool" where "is_stamp_unrestricted s = (s = unrestricted_stamp s)" -― ‹A stamp which provides type information but has an empty range of values +― ‹A stamp which provides type information but has an empty range of values› fun empty_stamp :: "Stamp Stamp" where "empty_stamp VoidStamp = VoidStamp" | "empty_stamp (IntegerStamp bits lower upper) = (IntegerStamp bits (snd (bit_bounds bits)) (fst (bit_bounds bits)))" | - (* "empty_stamp (FloatStamp bits lower upper) = (FloatStamp bits pos_infinity neg_infinity)" | *) + (* "empty_stamp (FloatStamp bits lower upper) = (FloatStamp bits pos_infinity neg_infinity)" | *) "empty_stamp (KlassPointerStamp nonNull alwaysNull) = (KlassPointerStamp nonNull alwaysNull)" | "empty_stamp (MethodCountersPointerStamp nonNull alwaysNull) = (MethodCountersPointerStamp nonNull alwaysNull)" | "empty_stamp (MethodPointersStamp nonNull alwaysNull) = (MethodPointersStamp nonNull alwaysNull)" | @@ -118,17 +118,17 @@

Theory Stamp

"empty_stamp stamp = IllegalStamp" -― ‹Calculate the meet stamp of two stamps +― ‹Calculate the meet stamp of two stamps› fun meet :: "Stamp Stamp Stamp" where "meet VoidStamp VoidStamp = VoidStamp" | "meet (IntegerStamp b1 l1 u1) (IntegerStamp b2 l2 u2) = ( if b1 b2 then IllegalStamp else (IntegerStamp b1 (min l1 l2) (max u1 u2)) )" | - (* "meet (FloatStamp b1 l1 u1) (FloatStamp b2 l2 u2) = ( + (* "meet (FloatStamp b1 l1 u1) (FloatStamp b2 l2 u2) = ( if b1 ≠ b2 then IllegalStamp else (FloatStamp b1 (min l1 l2) (max u1 u2)) - )" | *) + )" | *) "meet (KlassPointerStamp nn1 an1) (KlassPointerStamp nn2 an2) = ( KlassPointerStamp (nn1 nn2) (an1 an2) )" | @@ -140,17 +140,17 @@

Theory Stamp

)" | "meet s1 s2 = IllegalStamp" -― ‹Calculate the join stamp of two stamps +― ‹Calculate the join stamp of two stamps› fun join :: "Stamp Stamp Stamp" where "join VoidStamp VoidStamp = VoidStamp" | "join (IntegerStamp b1 l1 u1) (IntegerStamp b2 l2 u2) = ( if b1 b2 then IllegalStamp else (IntegerStamp b1 (max l1 l2) (min u1 u2)) )" | - (* "join (FloatStamp b1 l1 u1) (FloatStamp b2 l2 u2) = ( + (* "join (FloatStamp b1 l1 u1) (FloatStamp b2 l2 u2) = ( if b1 ≠ b2 then IllegalStamp else (FloatStamp b1 (max l1 l2) (min u1 u2)) - )" | *) + )" | *) "join (KlassPointerStamp nn1 an1) (KlassPointerStamp nn2 an2) = ( if ((nn1 nn2) (an1 an2)) then (empty_stamp (KlassPointerStamp nn1 an1)) @@ -169,19 +169,19 @@

Theory Stamp

"join s1 s2 = IllegalStamp" ― ‹ -In certain circumstances a stamp provides enough information to evaluate a value as a stamp, -the asConstant function converts the stamp to a value where one can be inferred. +In certain circumstances a stamp provides enough information to evaluate a value as a stamp, +the asConstant function converts the stamp to a value where one can be inferred. › -(* NOTE: we could also add a 32-bit version of this if needed. *) +(* NOTE: we could also add a 32-bit version of this if needed. *) fun asConstant :: "Stamp Value" where - "asConstant (IntegerStamp b l h) = (if l = h then IntVal b (word_of_int l) else UndefVal)" | + "asConstant (IntegerStamp b l h) = (if l = h then new_int b (word_of_int l) else UndefVal)" | "asConstant _ = UndefVal" -― ‹Determine if two stamps never have value overlaps i.e. their join is empty +― ‹Determine if two stamps never have value overlaps i.e. their join is empty› fun alwaysDistinct :: "Stamp Stamp bool" where "alwaysDistinct stamp1 stamp2 = is_stamp_empty (join stamp1 stamp2)" -― ‹Determine if two stamps must always be the same value i.e. two equal constants +― ‹Determine if two stamps must always be the same value i.e. two equal constants› fun neverDistinct :: "Stamp Stamp bool" where "neverDistinct stamp1 stamp2 = (asConstant stamp1 = asConstant stamp2 asConstant stamp1 UndefVal)" @@ -189,11 +189,11 @@

Theory Stamp

"constantAsStamp (IntVal b v) = (IntegerStamp b (int_signed_value b v) (int_signed_value b v))" | "constantAsStamp (ObjRef (None)) = ObjectStamp '''' False False True" | "constantAsStamp (ObjRef (Some n)) = ObjectStamp '''' False True False" | - (* TODO: float *) + (* TODO: float *) "constantAsStamp _ = IllegalStamp" -― ‹Define when a runtime value is valid for a stamp. - The stamp bounds must be valid, and val must be zero-extended. +― ‹Define when a runtime value is valid for a stamp. + The stamp bounds must be valid, and val must be zero-extended.› fun valid_value :: "Value Stamp bool" where "valid_value (IntVal b1 val) (IntegerStamp b l h) = (if b1 = b then @@ -201,32 +201,32 @@

Theory Stamp

take_bit b val = val l int_signed_value b val int_signed_value b val h else False)"
| - (* "valid_value (FloatStamp b1 l h) (FloatVal b2 v) = ((b1 = b2) ∧ (v ≥ l) ∧ (v ≤ h))" | *) + (* "valid_value (FloatStamp b1 l h) (FloatVal b2 v) = ((b1 = b2) ∧ (v ≥ l) ∧ (v ≤ h))" | *) "valid_value (ObjRef ref) (ObjectStamp klass exact nonNull alwaysNull) = ((alwaysNull ref = None) (ref=None ¬ nonNull))" | "valid_value stamp val = False" -(* NOTE: we could allow for unsigned interpretations too, like this: +(* NOTE: we could allow for unsigned interpretations too, like this: (if l < 0 then (l ≤ int_signed_value b val ∧ int_signed_value b val ≤ h) else (l ≤ int_unsigned_value b val ∧ int_unsigned_value b val ≤ h)) but that is only necessary for handling unsigned long, so we take the simpler always-signed approach here. In Java, the only unsigned stamps we see are for char, but they are 32-bit: IntegerStamp 32 0 65535. -*) -(* TODO: add the other stamps: +*) +(* TODO: add the other stamps: | KlassPointerStamp (stp_nonNull: bool) (stp_alwaysNull: bool) | MethodCountersPointerStamp (stp_nonNull: bool) (stp_alwaysNull: bool) | MethodPointersStamp (stp_nonNull: bool) (stp_alwaysNull: bool) | RawPointerStamp (stp_nonNull: bool) (stp_alwaysNull: bool) -*) +*) -(* A preferable wf_value definition +(* A preferable wf_value definition fun wf_value :: "Value ⇒ bool" where "wf_value (IntVal b v) = (0 < b ∧ b ≤ 64 ∧ take_bit b v = v ∧ sint v ≤ snd (bit_bounds b) ∧ fst (bit_bounds b) ≤ sint v)" | "wf_value _ = False" -*) +*) definition wf_value :: "Value bool" where "wf_value v = valid_value v (constantAsStamp v)" @@ -246,8 +246,8 @@

Theory Stamp

"stamp_under _ _ = False" ― ‹ -The most common type of stamp within the compiler (apart from the VoidStamp) is a 32 bit -integer stamp with an unrestricted range. We use @{text default_stamp} as it is a frequently used stamp. +The most common type of stamp within the compiler (apart from the VoidStamp) is a 32 bit +integer stamp with an unrestricted range. We use @{text default_stamp} as it is a frequently used stamp. › definition default_stamp :: "Stamp" where "default_stamp = (unrestricted_stamp (IntegerStamp 32 0 0))" diff --git a/Graph/Traversal.html b/Graph/Traversal.html index 1f2a334b..ae7e0858 100644 --- a/Graph/Traversal.html +++ b/Graph/Traversal.html @@ -12,7 +12,7 @@

Theory Traversal

-
subsection Control-flow Graph Traversal
+
subsection ‹Control-flow Graph Traversal›
 
 theory
   Traversal
@@ -23,26 +23,26 @@ 

Theory Traversal

type_synonym Seen = "ID set" -text -nextEdge helps determine which node to traverse next by returning the first successor -edge that isn't in the set of already visited nodes. -If there is not an appropriate successor, None is returned instead. - +text ‹ +nextEdge helps determine which node to traverse next by returning the first successor +edge that isn't in the set of already visited nodes. +If there is not an appropriate successor, None is returned instead. +› fun nextEdge :: "Seen ID IRGraph ID option" where "nextEdge seen nid g = (let nids = (filter (λnid'. nid' seen) (successors_of (kind g nid))) in (if length nids > 0 then Some (hd nids) else None))" -text -pred determines which node, if any, acts as the predecessor of another. - -Merge nodes represent a special case where-in the predecessor exists as -an input edge of the merge node, to simplify the traversal we treat only -the first input end node as the predecessor, ignoring that multiple nodes -may act as a successor. - -For all other nodes, the predecessor is the first element of the predecessors set. -Note that in a well-formed graph there should only be one element in the predecessor set. +text ‹ +pred determines which node, if any, acts as the predecessor of another. + +Merge nodes represent a special case where-in the predecessor exists as +an input edge of the merge node, to simplify the traversal we treat only +the first input end node as the predecessor, ignoring that multiple nodes +may act as a successor. + +For all other nodes, the predecessor is the first element of the predecessors set. +Note that in a well-formed graph there should only be one element in the predecessor set.› fun pred :: "IRGraph ID ID option" where "pred g nid = (case kind g nid of (MergeNode ends _ _) Some (hd ends) | @@ -54,27 +54,27 @@

Theory Traversal

)"
-text -Here we try to implement a generic fork of the control-flow traversal algorithm -that was initially implemented for the ConditionalElimination phase - +text ‹ +Here we try to implement a generic fork of the control-flow traversal algorithm +that was initially implemented for the ConditionalElimination phase +› type_synonym 'a TraversalState = "(ID × Seen × 'a)" inductive Step :: "('a TraversalState 'a) IRGraph 'a TraversalState 'a TraversalState option bool" for sa g where ― ‹ - Hit a BeginNode with an IfNode predecessor which represents - the start of a basic block for the IfNode. - 1. nid' will be the successor of the begin node. - 2. Find the first and only predecessor. - 3. Extract condition from the preceding IfNode. - 4. Negate condition if the begin node is second branch - (we've taken the else branch of the condition) - 5. Add the condition or the negated condition to stack - 6. Perform any stamp updates based on the condition using - the registerNewCondition function and place them on the - top of the stack of stamp information + Hit a BeginNode with an IfNode predecessor which represents + the start of a basic block for the IfNode. + 1. nid' will be the successor of the begin node. + 2. Find the first and only predecessor. + 3. Extract condition from the preceding IfNode. + 4. Negate condition if the begin node is second branch + (we've taken the else branch of the condition) + 5. Add the condition or the negated condition to stack + 6. Perform any stamp updates based on the condition using + the registerNewCondition function and place them on the + top of the stack of stamp information › "kind g nid = BeginNode nid'; @@ -88,9 +88,9 @@

Theory Traversal

Step sa g (nid, seen, analysis) (Some (nid', seen', analysis'))"
| ― ‹ - Hit an EndNode - 1. nid' will be the usage of EndNode - 2. pop the conditions and stamp stack + Hit an EndNode + 1. nid' will be the usage of EndNode + 2. pop the conditions and stamp stack › "kind g nid = EndNode; @@ -102,7 +102,7 @@

Theory Traversal

analysis' = sa (nid, seen, analysis) Step sa g (nid, seen, analysis) (Some (nid', seen', analysis'))"
| - ― ‹We can find a successor edge that is not in seen, go there + ― ‹We can find a successor edge that is not in seen, go there› "¬(is_EndNode (kind g nid)); ¬(is_BeginNode (kind g nid)); @@ -114,7 +114,7 @@

Theory Traversal

analysis' = sa (nid, seen, analysis) Step sa g (nid, seen, analysis) (Some (nid', seen', analysis'))"
| - ― ‹We can cannot find a successor edge that is not in seen, give back None + ― ‹We can cannot find a successor edge that is not in seen, give back None› "¬(is_EndNode (kind g nid)); ¬(is_BeginNode (kind g nid)); @@ -124,7 +124,7 @@

Theory Traversal

None = nextEdge seen' nid g Step sa g (nid, seen, analysis) None"
| - ― ‹We've already seen this node, give back None + ― ‹We've already seen this node, give back None› "nid seen Step sa g (nid, seen, analysis) None" code_pred (modes: i ⇒ i ⇒ i ⇒ o ⇒ bool) Step . diff --git a/Graph/ValueThms.html b/Graph/ValueThms.html index 95fb23ac..3bce4cd3 100644 --- a/Graph/ValueThms.html +++ b/Graph/ValueThms.html @@ -12,17 +12,17 @@

Theory ValueThms

-
subsection Fixed-width Word Theories
+
subsection ‹Fixed-width Word Theories›
 
 theory ValueThms
   imports Values
 begin
 
-(* declare [[show_types=true]] *)
+(* declare [[show_types=true]] *)
 
-subsubsection Support Lemmas for Upper/Lower Bounds
+subsubsection ‹Support Lemmas for Upper/Lower Bounds›
 
-(* these two were weirdly hard to prove given it should be by definition *)
+(* these two were weirdly hard to prove given it should be by definition *)
 lemma size32: "size v = 32" for v :: "32 word"
   by (smt (verit, del_insts) size_word.rep_eq numeral_Bit0 numeral_2_eq_2 mult_Suc_right One_nat_def
       mult.commute len_of_numeral_defs(2,3) mult.right_neutral)
@@ -30,7 +30,7 @@ 

Theory ValueThms

lemma size64: "size v = 64" for v :: "64 word" by (simp add: size64) -(* Nb. Word.sint_ge and sint_lt subsume these lemmas. +(* Nb. Word.sint_ge and sint_lt subsume these lemmas. lemma signed_int_bottom32: "-(((2::int) ^ 31)) ≤ sint (v::int32)" using sint_range_size size32 by (smt (verit, ccfv_SIG) One_nat_def Suc_pred add_Suc add_Suc_right eval_nat_numeral(3) nat.inject numeral_2_eq_2 numeral_Bit0 numeral_Bit1 zero_less_numeral) @@ -38,19 +38,19 @@

Theory ValueThms

lemma signed_int_top32: "(2 ^ 31) - 1 ≥ sint (v::int32)" using sint_range_size size32 by (smt (verit, ccfv_SIG) One_nat_def Suc_pred add_Suc add_Suc_right eval_nat_numeral(3) nat.inject numeral_2_eq_2 numeral_Bit0 numeral_Bit1 zero_less_numeral) -
*)
+*)
lemma lower_bounds_equiv: assumes "0 < N" shows "-(((2::int) ^ (N-1))) = (2::int) ^ N div 2 * - 1" - by (simp add: assms int_power_div_base) + by (simp add: assms int_power_div_base) lemma upper_bounds_equiv: assumes "0 < N" shows "(2::int) ^ (N-1) = (2::int) ^ N div 2" - by (simp add: assms int_power_div_base) + by (simp add: assms int_power_div_base) -text Some min/max bounds for 64-bit words +text ‹Some min/max bounds for 64-bit words› lemma bit_bounds_min64: "((fst (bit_bounds 64))) (sint (v::int64))" using sint_ge[of v] by simp @@ -58,10 +58,10 @@

Theory ValueThms

lemma bit_bounds_max64: "((snd (bit_bounds 64))) (sint (v::int64))" using sint_lt[of v] by simp -text Extend these min/max bounds to extracting smaller signed words using $signed\_take\_bit$. +text ‹Extend these min/max bounds to extracting smaller signed words using $signed\_take\_bit$.› -text Note: we could use signed to convert between bit-widths, instead of - signed\_take\_bit. But that would have to be done separately for each bit-width type. +text ‹Note: we could use signed to convert between bit-widths, instead of + signed\_take\_bit. But that would have to be done separately for each bit-width type.› value "sint(signed_take_bit 7 (128 :: int8))" @@ -91,7 +91,7 @@

Theory ValueThms

by (auto simp add: assms signed_take_bit_int_greater_eq_minus_exp_word signed_take_bit_int_less_exp_word) -text A $bit\_bounds$ version of the above lemma. +text ‹A $bit\_bounds$ version of the above lemma.› lemma signed_take_bit_bounds: fixes ival :: "'a :: len word" @@ -102,8 +102,8 @@

Theory ValueThms

by (metis bit_bounds.simps fst_conv less_imp_diff_less nat_less_le sint_ge sint_lt snd_conv zle_diff1_eq upper_bounds_equiv lower_bounds_equiv signed_take_bit_range assms) -(* It is helpful to have the 64-bit instance of the above, to avoid uninstantiated types - when apply it backwards. *) +(* It is helpful to have the 64-bit instance of the above, to avoid uninstantiated types + when apply it backwards. *) lemma signed_take_bit_bounds64: fixes ival :: "int64" assumes "n 64" @@ -125,7 +125,7 @@

Theory ValueThms

shows "- (2 ^ (n - 1)) val val < 2 ^ (n - 1)" using assms int_signed_value_range by blast -text Some lemmas about unsigned words smaller than 64-bit, for zero-extend operators. +text ‹Some lemmas about unsigned words smaller than 64-bit, for zero-extend operators.› lemma take_bit_smaller_range: fixes ival :: "'a :: len word" @@ -140,7 +140,7 @@

Theory ValueThms

shows "ival = take_bit n ival" by (simp add: assms) -text A simplification lemma for $new\_int$, showing that upper bits can be ignored. +text ‹A simplification lemma for $new\_int$, showing that upper bits can be ignored.› lemma take_bit_redundant[simp]: fixes ival :: "'a :: len word" @@ -170,15 +170,15 @@

Theory ValueThms

shows "fst (bit_bounds n) sint ival2 sint ival2 snd (bit_bounds n)" using assms take_bit_same_size_range by force -text Next we show that casting a word to a wider word preserves any upper/lower bounds. - (These lemmas may not be needed any more, since we are not using scast now?) +text ‹Next we show that casting a word to a wider word preserves any upper/lower bounds. + (These lemmas may not be needed any more, since we are not using scast now?)› lemma scast_max_bound: assumes "sint (v :: 'a :: len word) < M" assumes "LENGTH('a) < LENGTH('b)" shows "sint ((scast v) :: 'b :: len word) < M" using scast_max_bound assms by fast -(* helpful thms? +(* helpful thms? Word.scast_eq: scast (?w::?'b word) = word_of_int (sint ?w) Word.sint_lt: sint (?x::?'a word) < (2::int) ^ (LENGTH(?'a) - (1::nat) Word.sint_uint: sint (w::'a word) = signed_take_bit (LENGTH('a) - Suc (0::nat)) (uint w) @@ -188,7 +188,7 @@

Theory ValueThms

(signed_take_bit (?n::nat) (?k::int) = ?k) = (- ((2::int) ^ ?n) ⊑ ?k ∧ ?k < (2::int) ^ ?n) Bit_Operations.signed_take_bit_int_eq_self: - ((2::int) ^ (?n::nat)) ⊑ (?k::int) ⟹ ?k < (2::int) ^ ?n ⟹ signed_take_bit ?n ?k = ?k -
*)
+*)
lemma scast_min_bound: assumes "M sint (v :: 'a :: len word)" @@ -211,17 +211,17 @@

Theory ValueThms

shows "fst (bit_bounds (LENGTH('a))) sint result sint result snd (bit_bounds (LENGTH('a)))" by (auto simp add: scast_bigger_max_bound scast_bigger_min_bound assms) -text Results about $new\_int$. +text ‹Results about $new\_int$.› -(* may be too trivial? *) +(* may be too trivial? *) lemma new_int_take_bits: assumes "IntVal b val = new_int b ival" shows "take_bit b val = val" using assms by simp -subsubsection Support lemmas for take bit and signed take bit. +subsubsection ‹Support lemmas for take bit and signed take bit.› -text Lemmas for removing redundant take\_bit wrappers. +text ‹Lemmas for removing redundant take\_bit wrappers.› lemma take_bit_dist_addL[simp]: fixes x :: "'a :: len word" @@ -270,7 +270,7 @@

Theory ValueThms

using mod_larger_ignore assms by blast lemma mod_dist_over_add: - fixes a b c :: int64 (* "'a :: len word" *) + fixes a b c :: int64 (* "'a :: len word" *) fixes n :: nat assumes 1: "0 < n" assumes 2: "n < 64" diff --git a/Graph/Values.html b/Graph/Values.html index 81af28af..ecf73bad 100644 --- a/Graph/Values.html +++ b/Graph/Values.html @@ -12,50 +12,50 @@

Theory Values

-
section Operator Semantics
+
section ‹Operator Semantics›
 
 theory Values
   imports
     JavaLong
 begin
 
-text 
-In order to properly implement the IR semantics we first introduce
-a type that represents runtime values.
-These runtime values represent the full range of primitive types
-currently allowed by our semantics, ranging from basic integer types
-to object references and arrays.
-
-Note that Java supports 64, 32, 16, 8 signed ints, plus 1 bit (boolean)
-ints, and char is 16-bit unsigned.
-E.g. an 8-bit stamp has a default range of -128..+127.
-And a 1-bit stamp has a default range of -1..0, surprisingly.
-
-During calculations the smaller sizes are sign-extended to 32 bits, but explicit 
-widening nodes will do that, so most binary calculations should see equal input sizes.
-
-An object reference is an option type where the @{term None} object reference
-points to the static fields. This is examined more closely in our
-definition of the heap.
-
+text ‹
+In order to properly implement the IR semantics we first introduce
+a type that represents runtime values.
+These runtime values represent the full range of primitive types
+currently allowed by our semantics, ranging from basic integer types
+to object references and arrays.
+
+Note that Java supports 64, 32, 16, 8 signed ints, plus 1 bit (boolean)
+ints, and char is 16-bit unsigned.
+E.g. an 8-bit stamp has a default range of -128..+127.
+And a 1-bit stamp has a default range of -1..0, surprisingly.
+
+During calculations the smaller sizes are sign-extended to 32 bits, but explicit 
+widening nodes will do that, so most binary calculations should see equal input sizes.
+
+An object reference is an option type where the @{term None} object reference
+points to the static fields. This is examined more closely in our
+definition of the heap.
+›
 
 type_synonym objref = "nat option"
 type_synonym length = "nat"
 
 datatype (discs_sels) Value  =
   UndefVal |
-  (* IntVal32 "32 word" | *)  (* also used for 16, 8, and 1-bit (boolean) values *)
-  (* IntVal64 "64 word" | *)
-  (* IntVal IntType int64 |  -- all types smaller than 64 bits are zero-extended *)
-  (* or widths: IntVal (ibits:IntWidth) (ival:int64) | *)
-  (* or just:   IntVal (ibits:nat) (ival:int64) ? *)
-  (* or         IntVal IntWord where IntWord = (nat,int64)? *)
-  (* IntValv2 nat bool int64 |   bits, signed, word *)
-  IntVal iwidth int64 | (* bits and word because we cannot know sign until do compare! *)
-  (* FloatVal float | not supported *)
+  (* IntVal32 "32 word" | *)  (* also used for 16, 8, and 1-bit (boolean) values *)
+  (* IntVal64 "64 word" | *)
+  (* IntVal IntType int64 |  -- all types smaller than 64 bits are zero-extended *)
+  (* or widths: IntVal (ibits:IntWidth) (ival:int64) | *)
+  (* or just:   IntVal (ibits:nat) (ival:int64) ? *)
+  (* or         IntVal IntWord where IntWord = (nat,int64)? *)
+  (* IntValv2 nat bool int64 |   bits, signed, word *)
+  IntVal iwidth int64 | (* bits and word because we cannot know sign until do compare! *)
+  (* FloatVal float | not supported *)
   ObjRef objref |
   ObjStr string |
-  ArrayVal length "Value list"  (* Length characteristic not currently enforced in Value list *)
+  ArrayVal length "Value list"  (* Length characteristic not currently enforced in Value list *)
 
 fun intval_bits :: "Value  nat" where
   "intval_bits (IntVal b v) = b"
@@ -63,11 +63,11 @@ 

Theory Values

fun intval_word :: "Value int64" where "intval_word (IntVal b v) = v" -text Converts an integer word into a Java value. +text ‹Converts an integer word into a Java value.› fun new_int :: "iwidth int64 Value" where "new_int b w = IntVal b (take_bit b w)" -text Converts an integer word into a Java value, iff the two types are equal. +text ‹Converts an integer word into a Java value, iff the two types are equal.› fun new_int_bin :: "iwidth iwidth int64 Value" where "new_int_bin b1 b2 w = (if b1=b2 then new_int b1 w else UndefVal)" @@ -86,11 +86,11 @@

Theory Values

"bool_to_val True = (IntVal 32 1)" | "bool_to_val False = (IntVal 32 0)" -text Converts an Isabelle bool into a Java value, iff the two types are equal. +text ‹Converts an Isabelle bool into a Java value, iff the two types are equal.› fun bool_to_val_bin :: "iwidth iwidth bool Value" where "bool_to_val_bin t1 t2 b = (if t1 = t2 then bool_to_val b else UndefVal)" -(* Deprecated - just for backwards compatibility. *) +(* Deprecated - just for backwards compatibility. *) fun is_int_val :: "Value bool" where "is_int_val v = is_IntVal v" @@ -108,41 +108,41 @@

Theory Values

shows " b1 v1. (IntVal b1 (word_of_int (int_unsigned_value b1 v1))) = IntVal b1 v1" by simp -subsection Arithmetic Operators - -text -We need to introduce arithmetic operations which agree with the JVM. - -Within the JVM, bytecode arithmetic operations are performed on 32 -or 64 bit integers, unboxing where appropriate. - -The following collection of intval functions correspond to the JVM -arithmetic operations. We merge the 32 and 64 bit operations into -a single function, even though the stamp of each IRNode tells us -exactly what the bit widths will be. These merged functions -make it easier to do the instantiation of Value as 'plus', etc. -It might be worse for reasoning, because it could cause more case analysis, -but this does not seem to be a problem in practice. - - -(* Corresponds to JVM iadd and ladd instructions. *) +subsection ‹Arithmetic Operators› + +text ‹ +We need to introduce arithmetic operations which agree with the JVM. + +Within the JVM, bytecode arithmetic operations are performed on 32 +or 64 bit integers, unboxing where appropriate. + +The following collection of intval functions correspond to the JVM +arithmetic operations. We merge the 32 and 64 bit operations into +a single function, even though the stamp of each IRNode tells us +exactly what the bit widths will be. These merged functions +make it easier to do the instantiation of Value as 'plus', etc. +It might be worse for reasoning, because it could cause more case analysis, +but this does not seem to be a problem in practice. +› + +(* Corresponds to JVM iadd and ladd instructions. *) fun intval_add :: "Value Value Value" where "intval_add (IntVal b1 v1) (IntVal b2 v2) = (if b1 = b2 then IntVal b1 (take_bit b1 (v1+v2)) else UndefVal)" | "intval_add _ _ = UndefVal" -(* Corresponds to JVM isub and lsub instructions. *) +(* Corresponds to JVM isub and lsub instructions. *) fun intval_sub :: "Value Value Value" where "intval_sub (IntVal b1 v1) (IntVal b2 v2) = new_int_bin b1 b2 (v1-v2)" | "intval_sub _ _ = UndefVal" -(* Corresponds to JVM imul and lmul instructions. *) +(* Corresponds to JVM imul and lmul instructions. *) fun intval_mul :: "Value Value Value" where "intval_mul (IntVal b1 v1) (IntVal b2 v2) = new_int_bin b1 b2 (v1*v2)" | "intval_mul _ _ = UndefVal" -(* Java division rounds towards 0, so we use sdiv, not div. *) -(* TODO: find a signed division operator in the Word library? *) +(* Java division rounds towards 0, so we use sdiv, not div. *) +(* TODO: find a signed division operator in the Word library? *) fun intval_div :: "Value Value Value" where "intval_div (IntVal b1 v1) (IntVal b2 v2) = (if v2 = 0 then UndefVal else @@ -152,7 +152,7 @@

Theory Values

value "intval_div (IntVal 32 5) (IntVal 32 0)" -(* Java % is a modulo operator that can give negative results, since div rounds towards 0. *) +(* Java % is a modulo operator that can give negative results, since div rounds towards 0. *) fun intval_mod :: "Value Value Value" where "intval_mod (IntVal b1 v1) (IntVal b2 v2) = (if v2 = 0 then UndefVal else @@ -160,7 +160,7 @@

Theory Values

((int_signed_value b1 v1) smod (int_signed_value b2 v2))))"
| "intval_mod _ _ = UndefVal" -(* Corresponds to Math.multiplyHigh(L,L) and ExactMath.multiplyHigh(I,I) *) +(* Corresponds to Math.multiplyHigh(L,L) and ExactMath.multiplyHigh(I,I) *) fun intval_mul_high :: "Value Value Value" where "intval_mul_high (IntVal b1 v1) (IntVal b2 v2) = ( if (b1 = b2 b1 = 64) then ( @@ -213,7 +213,7 @@

Theory Values

"intval_reverse_bytes (IntVal b1 v1) = (new_int b1 (reverseBytes_fun v1 b1 0))" | "intval_reverse_bytes _ = UndefVal" -(* Corresponds to Integer.bitCount(I) and Long.bitCount(L) *) +(* Corresponds to Integer.bitCount(I) and Long.bitCount(L) *) fun intval_bit_count :: "Value Value" where "intval_bit_count (IntVal b1 v1) = (new_int 32 (word_of_nat (bitCount_fun v1 64)))" | "intval_bit_count _ = UndefVal" @@ -226,12 +226,12 @@

Theory Values

"intval_abs (IntVal t v) = new_int t (if int_signed_value t v < 0 then - v else v)" | "intval_abs _ = UndefVal" -text TODO: clarify which widths this should work on: just 1-bit or all? +text ‹TODO: clarify which widths this should work on: just 1-bit or all?› fun intval_logic_negation :: "Value Value" where "intval_logic_negation (IntVal b v) = new_int b (logic_negate v)" | "intval_logic_negation _ = UndefVal" -subsection Bitwise Operators +subsection ‹Bitwise Operators› fun intval_and :: "Value Value Value" where "intval_and (IntVal b1 v1) (IntVal b2 v2) = new_int_bin b1 b2 (and v1 v2)" | @@ -249,7 +249,7 @@

Theory Values

"intval_not (IntVal t v) = new_int t (not v)" | "intval_not _ = UndefVal" -subsection Comparison Operators +subsection ‹Comparison Operators› fun intval_short_circuit_or :: "Value Value Value" where "intval_short_circuit_or (IntVal b1 v1) (IntVal b2 v2) = bool_to_val_bin b1 b2 (((v1 0) (v2 0)))" | @@ -279,16 +279,16 @@

Theory Values

"intval_test (IntVal b1 v1) (IntVal b2 v2) = bool_to_val_bin b1 b2 ((and v1 v2) = 0)" | "intval_test _ _ = UndefVal" -(* Corresponds to Integer.compareUnsigned and Long.compareUnsigned *) +(* Corresponds to Integer.compareUnsigned and Long.compareUnsigned *) fun intval_normalize_compare :: "Value Value Value" where "intval_normalize_compare (IntVal b1 v1) (IntVal b2 v2) = (if (b1 = b2) then new_int 32 (if (v1 < v2) then -1 else (if (v1 = v2) then 0 else 1)) else UndefVal)" | "intval_normalize_compare _ _ = UndefVal" -(* Array-related operators and helper functions *) +(* Array-related operators and helper functions *) -(* Yoinked from https://www.isa-afp.org/browser_info/Isabelle2012/HOL/List-Index/List_Index.html*) +(* Yoinked from https://www.isa-afp.org/browser_info/Isabelle2012/HOL/List-Index/List_Index.html*) fun find_index :: "'a 'a list nat" where "find_index _ [] = 0" | "find_index v (x # xs) = (if (x=v) then 0 else find_index v xs + 1)" @@ -344,12 +344,12 @@

Theory Values

using assms(1) bool_to_val.elims i1 i2 by auto qed -subsection Narrowing and Widening Operators +subsection ‹Narrowing and Widening Operators› -text Note: we allow these operators to have inBits=outBits, because the Graal compiler - also seems to allow that case, even though it should rarely / never arise in practice. +text ‹Note: we allow these operators to have inBits=outBits, because the Graal compiler + also seems to allow that case, even though it should rarely / never arise in practice.› -text Some sanity checks that $take\_bit N$ and $signed\_take\_bit (N-1)$ match up as expected. +text ‹Some sanity checks that $take\_bit N$ and $signed\_take\_bit (N-1)$ match up as expected.› corollary "sint (signed_take_bit 0 (1 :: int32)) = -1" by code_simp corollary "sint (signed_take_bit 7 ((256 + 128) :: int64)) = -128" by code_simp corollary "sint (take_bit 7 ((256 + 128 + 64) :: int64)) = 64" by code_simp @@ -376,7 +376,7 @@

Theory Values

else UndefVal)"
| "intval_zero_extend _ _ _ = UndefVal" -text Some well-formedness results to help reasoning about narrowing and widening operators +text ‹Some well-formedness results to help reasoning about narrowing and widening operators› lemma intval_narrow_ok: assumes "intval_narrow inBits outBits val UndefVal" @@ -401,12 +401,12 @@

Theory Values

intval_bits val = inBits"
by (metis intval_bits.simps intval_zero_extend.elims is_IntVal_def assms) -subsection Bit-Shifting Operators +subsection ‹Bit-Shifting Operators› -text Note that Java shift operators use unary numeric promotion, unlike other binary - operators, which use binary numeric promotion (see the Java language reference manual). - This means that the left-hand input determines the output size, while the - right-hand input can be any size. +text ‹Note that Java shift operators use unary numeric promotion, unlike other binary + operators, which use binary numeric promotion (see the Java language reference manual). + This means that the left-hand input determines the output size, while the + right-hand input can be any size.› fun shift_amount :: "iwidth int64 nat" where "shift_amount b val = unat (and val (if b = 64 then 0x3F else 0x1f))" @@ -415,8 +415,8 @@

Theory Values

"intval_left_shift (IntVal b1 v1) (IntVal b2 v2) = new_int b1 (v1 << shift_amount b1 v2)" | "intval_left_shift _ _ = UndefVal" -text Signed shift is more complex, because we sometimes have to insert 1 bits - at the correct point, which is at b1 bits. +text ‹Signed shift is more complex, because we sometimes have to insert 1 bits + at the correct point, which is at b1 bits.› fun intval_right_shift :: "Value Value Value" where "intval_right_shift (IntVal b1 v1) (IntVal b2 v2) = (let shift = shift_amount b1 v2 in @@ -430,7 +430,7 @@

Theory Values

"intval_uright_shift (IntVal b1 v1) (IntVal b2 v2) = new_int b1 (v1 >>> shift_amount b1 v2)" | "intval_uright_shift _ _ = UndefVal" -subsubsection Examples of Narrowing / Widening Functions +subsubsection ‹Examples of Narrowing / Widening Functions› experiment begin corollary "intval_narrow 32 8 (IntVal 32 (256 + 128)) = IntVal 8 128" by simp @@ -438,7 +438,7 @@

Theory Values

corollary "intval_narrow 32 1 (IntVal 32 (-2)) = IntVal 1 0" by simp corollary "intval_narrow 32 1 (IntVal 32 (-3)) = IntVal 1 1" by simp -(* now test some 64 bit inputs and outputs *) +(* now test some 64 bit inputs and outputs *) corollary "intval_narrow 32 8 (IntVal 64 (-2)) = UndefVal" by simp corollary "intval_narrow 64 8 (IntVal 32 (-2)) = UndefVal" by simp corollary "intval_narrow 64 8 (IntVal 64 254) = IntVal 8 254" by simp @@ -452,7 +452,7 @@

Theory Values

corollary "intval_sign_extend 1 32 (IntVal 1 (-2)) = IntVal 32 0" by simp corollary "intval_sign_extend 1 32 (IntVal 1 (-3)) = IntVal 32 (mask 32)" by simp -(* now test some 64 bit inputs and outputs *) +(* now test some 64 bit inputs and outputs *) corollary "intval_sign_extend 8 32 (IntVal 64 254) = UndefVal" by simp corollary "intval_sign_extend 8 64 (IntVal 32 254) = UndefVal" by simp corollary "intval_sign_extend 8 64 (IntVal 8 254) = IntVal 64 (-2)" by simp @@ -466,7 +466,7 @@

Theory Values

corollary "intval_zero_extend 1 32 (IntVal 1 (-1)) = IntVal 32 1" by simp corollary "intval_zero_extend 1 32 (IntVal 1 (-2)) = IntVal 32 0" by simp -(* now test some 64 bit inputs and outputs *) +(* now test some 64 bit inputs and outputs *) corollary "intval_zero_extend 8 32 (IntVal 64 (-2)) = UndefVal" by simp corollary "intval_zero_extend 8 64 (IntVal 64 (-2)) = UndefVal" by simp corollary "intval_zero_extend 8 64 (IntVal 8 254) = IntVal 64 254" by simp @@ -482,23 +482,23 @@

Theory Values

corollary "intval_right_shift (IntVal 8 128) (IntVal 8 31) = IntVal 8 255" by eval end -(* ======================================================================== +(* ======================================================================== Commutative and Associative results. (Not used yet). - ======================================================================== *) + ======================================================================== *) -(* commutative rules to be used when needed. *) +(* commutative rules to be used when needed. *) lemma intval_add_sym: shows "intval_add a b = intval_add b a" by (induction a; induction b; auto simp: add.commute) -(* view dependency graph of code definitions: +(* view dependency graph of code definitions: code_deps intval_add -*) -(* print all code definitions used by intval_add: +*) +(* print all code definitions used by intval_add: code_thms intval_add -*) +*) -(* Some example tests. *) +(* Some example tests. *) lemma "intval_add (IntVal 32 (2^31-1)) (IntVal 32 (2^31-1)) = IntVal 32 (2^32 - 2)" by eval lemma "intval_add (IntVal 64 (2^31-1)) (IntVal 64 (2^31-1)) = IntVal 64 4294967294" diff --git a/Graph/document.pdf b/Graph/document.pdf index aa8ccbba..5d39f60f 100644 Binary files a/Graph/document.pdf and b/Graph/document.pdf differ diff --git a/Graph/index.html b/Graph/index.html index d98a7c54..e55fe144 100644 --- a/Graph/index.html +++ b/Graph/index.html @@ -3,7 +3,7 @@ -Session Graph (Isabelle2022) +Session Graph (Isabelle2023) diff --git a/Graph/session_graph.pdf b/Graph/session_graph.pdf index 6a34972b..1dc63d38 100644 Binary files a/Graph/session_graph.pdf and b/Graph/session_graph.pdf differ diff --git a/OptimizationDSL/.browser_info/build_uuid b/OptimizationDSL/.browser_info/build_uuid index e9cd6be6..c84274f9 100644 --- a/OptimizationDSL/.browser_info/build_uuid +++ b/OptimizationDSL/.browser_info/build_uuid @@ -1 +1 @@ -4d8e1ad5-dabf-4bf2-b5b0-daa958ba7b43 \ No newline at end of file +9410185a-1397-4e37-823e-e573c61b1bda \ No newline at end of file diff --git a/OptimizationDSL/Canonicalization.html b/OptimizationDSL/Canonicalization.html index c6d0601f..4022a8a3 100644 --- a/OptimizationDSL/Canonicalization.html +++ b/OptimizationDSL/Canonicalization.html @@ -12,7 +12,7 @@

Theory Canonicalization

-
subsection Canonicalization DSL
+
subsection ‹Canonicalization DSL›
 
 theory Canonicalization
   imports
@@ -20,28 +20,28 @@ 

Theory Canonicalization

Phase "HOL-Eisbach.Eisbach" keywords - "phase" :: thy_decl and - "terminating" :: quasi_command and - "print_phases" :: diag and - "export_phases" :: thy_decl and - "optimization" :: thy_goal_defn + "phase" :: thy_decl and + "terminating" :: quasi_command and + "print_phases" :: diag and + "export_phases" :: thy_decl and + "optimization" :: thy_goal_defn begin print_methods -ML -datatype 'a Rewrite = - Transform of 'a * 'a | - Conditional of 'a * 'a * term | - Sequential of 'a Rewrite * 'a Rewrite | - Transitive of 'a Rewrite +ML ‹ +datatype 'a Rewrite = + Transform of 'a * 'a | + Conditional of 'a * 'a * term | + Sequential of 'a Rewrite * 'a Rewrite | + Transitive of 'a Rewrite type rewrite = { - name: binding, - rewrite: term Rewrite, - proofs: thm list, - code: thm list, - source: term + name: binding, + rewrite: term Rewrite, + proofs: thm list, + code: thm list, + source: term } structure RewriteRule : Rule = @@ -70,7 +70,7 @@

Theory Canonicalization

fun pretty ctxt obligations t = let - val is_skipped = Thm_Deps.has_skip_proof (#proofs t); + val is_skipped = Thm_Deps.has_skip_proof (#proofs t); val warning = (if is_skipped then [Pretty.str "(proof skipped)", Pretty.brk 0] @@ -79,7 +79,7 @@

Theory Canonicalization

val obligations = (if obligations then [Pretty.big_list "obligations:" - (map (pretty_thm ctxt) (#proofs t)), + (map (pretty_thm ctxt) (#proofs t)), Pretty.brk 0] else []); @@ -90,8 +90,8 @@

Theory Canonicalization

in Pretty.block ([ - pretty_bind (#name t), Pretty.str ": ", - Syntax.pretty_term ctxt (#source t), Pretty.fbrk + pretty_bind (#name t), Pretty.str ": ", + Syntax.pretty_term ctxt (#source t), Pretty.fbrk ] @ obligations @ warning) end end @@ -122,7 +122,7 @@

Theory Canonicalization

fun export_phases thy name = let - val state = Toplevel.theory_toplevel thy; + val state = Toplevel.make_state (SOME thy); val ctxt = Toplevel.context_of state; val content = Pretty.string_of (Pretty.chunks (print_phases false ctxt)); val cleaned = YXML.content_of content; @@ -147,11 +147,11 @@

Theory Canonicalization

"export information about encoded optimizations" (Parse.path >> (fn name => Toplevel.theory (fn state => export_phases state name))) -
+›
-ML_file "rewrites.ML" +ML_file "rewrites.ML" -subsubsection Semantic Preservation Obligation +subsubsection ‹Semantic Preservation Obligation› fun rewrite_preservation :: "IRExpr Rewrite bool" where "rewrite_preservation (Transform x y) = (y x)" | @@ -159,7 +159,7 @@

Theory Canonicalization

"rewrite_preservation (Sequential x y) = (rewrite_preservation x rewrite_preservation y)" | "rewrite_preservation (Transitive x) = rewrite_preservation x" -subsubsection Termination Obligation +subsubsection ‹Termination Obligation› fun rewrite_termination :: "IRExpr Rewrite (IRExpr nat) bool" where "rewrite_termination (Transform x y) trm = (trm x > trm y)" | @@ -173,13 +173,13 @@

Theory Canonicalization

"intval (Sequential x y) = (intval x intval y)" | "intval (Transitive x) = intval x" -subsubsection Standard Termination Measure +subsubsection ‹Standard Termination Measure› fun size :: "IRExpr nat" where unary_size: "size (UnaryExpr op x) = (size x) + 2" | - (*"size (BinaryExpr BinSub x y) = (size x) + (size y) + 3" | - "size (BinaryExpr BinMul x y) = (size x) + (size y) + 3" |*) + (*"size (BinaryExpr BinSub x y) = (size x) + (size y) + 3" | + "size (BinaryExpr BinMul x y) = (size x) + (size y) + 3" |*) bin_const_size: "size (BinaryExpr op x (ConstantExpr cy)) = (size x) + 2" | bin_size: @@ -195,9 +195,9 @@

Theory Canonicalization

"size (ConstantVar c) = 2" | "size (VariableExpr x s) = 2" -subsubsection Automated Tactics +subsubsection ‹Automated Tactics› -named_theorems size_simps "size simplication rules" +named_theorems size_simps "size simplication rules" method unfold_optimization = (unfold rewrite_preservation.simps, unfold rewrite_termination.simps, @@ -215,7 +215,7 @@

Theory Canonicalization

print_methods -ML +ML structure System : RewriteSystem = struct val preservation = @{const rewrite_preservation}; @@ -230,7 +230,55 @@

Theory Canonicalization

"define an optimization and open proof obligation" (Parse_Spec.thm_name ":" -- Parse.term >> DSL.rewrite_cmd); -
+›
+ +ML_file "~~/src/Doc/antiquote_setup.ML" + + +snipbegin ‹PhaseRail› +text ‹ +rail‹ +@{syntax_def phase}: @'phase' @{syntax name} +@'terminating' @{syntax measure} +@'begin' (body*) +@'end' +; + +@{syntax_def optimization}: @'optimization' @{syntax name} options? ':' +rule proof +; + +options: '[' (intval | subgoals) ']' +; + +rule: term '↦' term +('when' condition ((condition '&&')*))? +; + +@{syntax_def print_phases}: @'print_phases' '!'? +; + +@{syntax_def export_phases}: @'export_phases' filename +; + +@{syntax_def gencode}: @'gencode' filename term +; +› + + @{command phase}~name›~terminating›~measure› +opens a new optimization phase environment. +A termination measure is provided as the measure argument. +All optimizations within the phase must satisfy termination for the given measure. + + @{command optimization}~name› +defines a new optimization rule with a proof of correctness. +An obligation for semantic preservation and termination are opened. +An optimization can only be defined within a ‹phase›. + +› +snipend - + +print_syntax end
diff --git a/OptimizationDSL/ISABELLE_HOME/src/Doc/antiquote_setup.ML.html b/OptimizationDSL/ISABELLE_HOME/src/Doc/antiquote_setup.ML.html new file mode 100644 index 00000000..bd8d8599 --- /dev/null +++ b/OptimizationDSL/ISABELLE_HOME/src/Doc/antiquote_setup.ML.html @@ -0,0 +1,176 @@ + + + + + +File ‹~~/src/Doc/antiquote_setup.ML› + + + + +
+

File ‹~~/src/Doc/antiquote_setup.ML›

+
+ +
(*  Title:      Doc/antiquote_setup.ML
+    Author:     Makarius
+
+Auxiliary antiquotations for the Isabelle manuals.
+*)
+
+structure Antiquote_Setup: sig end =
+struct
+
+(* misc utils *)
+
+fun translate f = Symbol.explode #> map f #> implode;
+
+val clean_string = translate
+  (fn "_" => "\\_"
+    | "#" => "\\#"
+    | "$" => "\\$"
+    | "%" => "\\%"
+    | "<" => "$<$"
+    | ">" => "$>$"
+    | "{" => "\\{"
+    | "|" => "$\\mid$"
+    | "}" => "\\}"
+    | "‐" => "-"
+    | c => c);
+
+fun clean_name "…" = "dots"
+  | clean_name ".." = "ddot"
+  | clean_name "." = "dot"
+  | clean_name "_" = "underscore"
+  | clean_name "{" = "braceleft"
+  | clean_name "}" = "braceright"
+  | clean_name s = s |> translate (fn "_" => "-" | "‐" => "-" | c => c);
+
+
+(* named theorems *)
+
+val _ =
+  Theory.setup (Document_Output.antiquotation_raw bindingnamed_thms
+    (Scan.repeat (Attrib.thm -- Scan.lift (Args.parens Args.name)))
+    (fn ctxt =>
+      map (fn (thm, name) =>
+        Output.output
+          (Document_Antiquotation.format ctxt
+            (Document_Antiquotation.delimit ctxt (Document_Output.pretty_thm ctxt thm))) ^
+        enclose "\\rulename{" "}" (Output.output name))
+      #> space_implode "\\par\\smallskip%\n"
+      #> Latex.string
+      #> Document_Output.isabelle ctxt));
+
+
+(* Isabelle/Isar entities (with index) *)
+
+local
+
+fun no_check (_: Proof.context) (name, _: Position.T) = name;
+
+fun check_keyword ctxt (name, pos) =
+  if Keyword.is_keyword (Thy_Header.get_keywords' ctxt) name then name
+  else error ("Bad outer syntax keyword " ^ quote name ^ Position.here pos);
+
+fun check_system_option ctxt arg =
+  (Completion.check_option (Options.default ()) ctxt arg; true)
+    handle ERROR _ => false;
+
+val arg = enclose "{" "}" o clean_string;
+
+fun entity check markup binding index =
+  Document_Output.antiquotation_raw
+    (binding |> Binding.map_name (fn name => name ^
+      (case index of NONE => "" | SOME true => "_def" | SOME false => "_ref")))
+    (Scan.lift (Scan.optional (Args.parens Args.name) "" -- Args.name_position))
+    (fn ctxt => fn (logic, (name, pos)) =>
+      let
+        val kind = translate (fn "_" => " " | c => c) (Binding.name_of binding);
+        val hyper_name =
+          "{" ^ Long_Name.append kind (Long_Name.append logic (clean_name name)) ^ "}";
+        val hyper =
+          enclose ("\\hyperlink" ^ hyper_name ^ "{") "}" #>
+          index = SOME true ? enclose ("\\hypertarget" ^ hyper_name ^ "{") "}";
+        val idx =
+          (case index of
+            NONE => ""
+          | SOME is_def =>
+              "\\index" ^ (if is_def then "def" else "ref") ^ arg logic ^ arg kind ^ arg name);
+        val _ =
+          if Context_Position.is_reported ctxt pos then ignore (check ctxt (name, pos)) else ();
+        val latex =
+          idx ^
+          (Output.output name
+            |> (if markup = "" then I else enclose ("\\" ^ markup ^ "{") "}")
+            |> hyper o enclose "\\mbox{\\isa{" "}}");
+      in Latex.string latex end);
+
+fun entity_antiqs check markup kind =
+  entity check markup kind NONE #>
+  entity check markup kind (SOME true) #>
+  entity check markup kind (SOME false);
+
+in
+
+val _ =
+  Theory.setup
+   (entity_antiqs no_check "" bindingsyntax #>
+    entity_antiqs Outer_Syntax.check_command "isacommand" bindingcommand #>
+    entity_antiqs check_keyword "isakeyword" bindingkeyword #>
+    entity_antiqs check_keyword "isakeyword" bindingelement #>
+    entity_antiqs Method.check_name "" bindingmethod #>
+    entity_antiqs Attrib.check_name "" bindingattribute #>
+    entity_antiqs no_check "" bindingfact #>
+    entity_antiqs no_check "" bindingvariable #>
+    entity_antiqs no_check "" bindingcase #>
+    entity_antiqs Document_Antiquotation.check "" bindingantiquotation #>
+    entity_antiqs Document_Antiquotation.check_option "" bindingantiquotation_option #>
+    entity_antiqs Document_Marker.check "" bindingdocument_marker #>
+    entity_antiqs no_check "isasystem" bindingsetting #>
+    entity_antiqs check_system_option "isasystem" bindingsystem_option #>
+    entity_antiqs no_check "" bindinginference #>
+    entity_antiqs no_check "isasystem" bindingexecutable #>
+    entity_antiqs Isabelle_Tool.check "isatool" bindingtool #>
+    entity_antiqs ML_Context.check_antiquotation "" bindingML_antiquotation #>
+    entity_antiqs (K JEdit.check_action) "isasystem" bindingaction);
+
+end;
+
+
+(* show symbols *)
+
+val _ =
+  Theory.setup (Document_Output.antiquotation_raw bindingshow_symbols (Scan.succeed ())
+    (fn _ => fn _ =>
+      let
+        val symbol_name =
+          unprefix "\\newcommand{\\isasym"
+          #> raw_explode
+          #> take_prefix Symbol.is_ascii_letter
+          #> implode;
+
+        val symbols =
+          File.read 🗏‹~~/lib/texinputs/isabellesym.sty›
+          |> split_lines
+          |> map_filter (fn line =>
+            (case try symbol_name line of
+              NONE => NONE
+            | SOME "" => NONE
+            | SOME name => SOME ("\\verb,\\" ^ "<" ^ name ^ ">, & {\\isasym" ^ name ^ "}")));
+
+        val eol = "\\\\\n";
+        fun table (a :: b :: rest) = a ^ " & " ^ b ^ eol :: table rest
+          | table [a] = [a ^ eol]
+          | table [] = [];
+      in
+        Latex.string
+          ("\\begin{supertabular}{ll@{\\qquad}ll}\n" ^ implode (table symbols) ^
+           "\\end{supertabular}\n")
+      end))
+
+end;
+
+ + + \ No newline at end of file diff --git a/OptimizationDSL/ISABELLE_HOME/src/Doc/isabelle.css b/OptimizationDSL/ISABELLE_HOME/src/Doc/isabelle.css new file mode 100644 index 00000000..4bd9e699 --- /dev/null +++ b/OptimizationDSL/ISABELLE_HOME/src/Doc/isabelle.css @@ -0,0 +1,231 @@ +/* Isabelle fonts */ + +@font-face { + font-family: 'Isabelle DejaVu Sans'; + src: url('../../../../../fonts/IsabelleDejaVuSans.ttf') format('truetype'); +} + +@font-face { + font-family: 'Isabelle DejaVu Sans'; + src: url('../../../../../fonts/IsabelleDejaVuSans-Bold.ttf') format('truetype'); + font-weight: bold; +} + +@font-face { + font-family: 'Isabelle DejaVu Sans'; + src: url('../../../../../fonts/IsabelleDejaVuSans-Oblique.ttf') format('truetype'); + font-style: italic; +} + +@font-face { + font-family: 'Isabelle DejaVu Sans'; + src: url('../../../../../fonts/IsabelleDejaVuSans-BoldOblique.ttf') format('truetype'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'Isabelle DejaVu Sans Mono'; + src: url('../../../../../fonts/IsabelleDejaVuSansMono.ttf') format('truetype'); +} + +@font-face { + font-family: 'Isabelle DejaVu Sans Mono'; + src: url('../../../../../fonts/IsabelleDejaVuSansMono-Bold.ttf') format('truetype'); + font-weight: bold; +} + +@font-face { + font-family: 'Isabelle DejaVu Sans Mono'; + src: url('../../../../../fonts/IsabelleDejaVuSansMono-Oblique.ttf') format('truetype'); + font-style: italic; +} + +@font-face { + font-family: 'Isabelle DejaVu Sans Mono'; + src: url('../../../../../fonts/IsabelleDejaVuSansMono-BoldOblique.ttf') format('truetype'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'Isabelle DejaVu Serif'; + src: url('../../../../../fonts/IsabelleDejaVuSerif.ttf') format('truetype'); +} + +@font-face { + font-family: 'Isabelle DejaVu Serif'; + src: url('../../../../../fonts/IsabelleDejaVuSerif-Bold.ttf') format('truetype'); + font-weight: bold; +} + +@font-face { + font-family: 'Isabelle DejaVu Serif'; + src: url('../../../../../fonts/IsabelleDejaVuSerif-Italic.ttf') format('truetype'); + font-style: italic; +} + +@font-face { + font-family: 'Isabelle DejaVu Serif'; + src: url('../../../../../fonts/IsabelleDejaVuSerif-BoldItalic.ttf') format('truetype'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'Vacuous'; + src: url('../../../../../fonts/Vacuous.ttf') format('truetype'); +} + + +/* standard document markup */ + +dt { + float: left; + clear: left; + padding-right: 0.5em; + font-weight: bold; +} + +body { + color: #000000; + background-color: #FFFFFF; +} + +.head { background-color: #FFFFFF; } +.source { + direction: ltr; unicode-bidi: bidi-override; + background-color: #FFFFFF; + padding: 10px; + font-family: "Isabelle DejaVu Sans Mono", monospace; +} + +.contents { background-color: #FFFFFF; padding: 10px; } +.sessions { background-color: #FFFFFF; padding: 10px; } +.document { white-space: normal; font-family: "Isabelle DejaVu Serif", serif; } + +.name { font-style: italic; } +.filename { font-family: "Isabelle DejaVu Sans Mono", monospace; } + + +/* basic syntax markup */ + +.hidden { font-family: Vacuous; font-size: 1%; color: rgba(255,255,255,0); } +.control { font-weight: bold; font-style: italic; } + +.binding { color: #336655; } +.tfree { color: #A020F0; } +.tvar { color: #A020F0; } +.free { color: #0000FF; } +.skolem { color: #D2691E; } +.bound { color: #008000; } +.var { color: #00009B; } +.numeral { } +.literal { font-weight: bold; } +.delimiter { } +.inner_numeral { color: #FF0000; } +.inner_quoted { color: #FF00CC; } +.inner_cartouche { color: #CC6600; } +.comment1 { color: #CC0000; } +.comment2 { color: #FF8400; } +.comment3 { color: #6600CC; } +.dynamic { color: #7BA428; } +.class_parameter_color { color: #D2691E; } + +.bold { font-weight: bold; } + +.main { color: #000000; } +.command { font-weight: bold; } +.keyword { font-weight: bold; } +.keyword1 { color: #006699; } +.keyword2 { color: #009966; } +.keyword3 { color: #0099FF; } +.quasi_keyword { color: #9966FF; } +.operator { color: #323232; } +.string { color: #FF00CC; } +.alt_string { color: #CC00CC; } +.verbatim { color: #6600CC; } +.cartouche { color: #CC6600; } +.comment { color: #CC0000; } +.improper { color: #FF5050; } +.antiquote { color: #6600CC; } +.raw_text { color: #6600CC; } +.plain_text { color: #CC6600; } +.bad { background-color: #FF6A6A; } +.quoted { background-color: rgba(139,139,139,0.05); } +.antiquoted { background-color: rgba(255,200,50,0.1); } + + +/* message background */ + +.writeln_message { background-color: #F0F0F0; } +.information_message { background-color: #DCEAF3; } +.tracing_message { background-color: #F0F8FF; } +.warning_message { background-color: #EEE8AA; } +.legacy_message { background-color: #EEE8AA; } +.error_message { background-color: #FFC1C1; } + + +/* message underline */ + +.writeln { border-bottom: 1px dotted #C0C0C0; } +.information { border-bottom: 1px dotted #C1DFEE; } +.warning { border-bottom: 1px dotted #FF8C00; } +.legacy { border-bottom: 1px dotted #FF8C00; } +.error { border-bottom: 1px dotted #B22222; } + + +/* tooltips */ + +.writeln { position: relative; display: inline-block; } +.information { position: relative; display: inline-block; } +.warning { position: relative; display: inline-block; } +.legacy { position: relative; display: inline-block; } +.error { position: relative; display: inline-block; } + +.writeln:hover .tooltip { visibility: visible; } +.information:hover .tooltip { visibility: visible; } +.warning:hover .tooltip { visibility: visible; } +.legacy:hover .tooltip { visibility: visible; } +.error:hover .tooltip { visibility: visible; } + +.tooltip { + top: -0.5ex; + left: 5em; + visibility: hidden; + width: 50em; + border: 1px solid #808080; + padding: 1px 1px; + background-color: #FFFFE9; + position: absolute; + z-index: 1; +} + +.tooltip pre { margin: 1px; white-space: pre-wrap; } + + +/* formal entities */ + +.entity_def { + color: inherit; + text-decoration: inherit; +} + +.entity_def:hover { + color: inherit; + text-decoration: inherit; + background-color: rgba(50,50,50,20%); +} + +.entity_ref { + color: inherit; + text-decoration: inherit; + border: 0.5px solid rgba(0,0,0,0); +} + +.entity_ref:hover { + color: inherit; + text-decoration: inherit; + background-color: rgba(50,50,50,20%); + border: 0.5px solid black; +} diff --git a/OptimizationDSL/Markup.html b/OptimizationDSL/Markup.html index 24504345..a4e7d8de 100644 --- a/OptimizationDSL/Markup.html +++ b/OptimizationDSL/Markup.html @@ -12,39 +12,39 @@

Theory Markup

-
section Optization DSL (* first theory in list, not related to file contents *)
+
section ‹Optization DSL› (* first theory in list, not related to file contents *)
 
-subsection Markup
+subsection ‹Markup›
 
 theory Markup
-  imports Semantics.IRTreeEval Snippets.Snipping
+  imports Semantics.IRTreeEval Snippets.Snipping
 begin
 
 datatype 'a Rewrite =
-  Transform 'a 'a ("_  _" 10) |
-  Conditional 'a 'a "bool" ("_  _ when _" 11) |
+  Transform 'a 'a ("_  _" 10) |
+  Conditional 'a 'a "bool" ("_  _ when _" 11) |
   Sequential "'a Rewrite" "'a Rewrite" |
   Transitive "'a Rewrite"
 
 datatype 'a ExtraNotation =
-  ConditionalNotation 'a 'a 'a ("_ ? _ : _" 50) |
-  EqualsNotation 'a 'a ("_ eq _") |
-  ConstantNotation 'a ("const _" 120) |
+  ConditionalNotation 'a 'a 'a ("_ ? _ : _" 50) |
+  EqualsNotation 'a 'a ("_ eq _") |
+  ConstantNotation 'a ("const _" 120) |
   TrueNotation ("true") |
   FalseNotation ("false") |
-  ExclusiveOr 'a 'a ("_  _") |
-  LogicNegationNotation 'a ("!_") |
-  ShortCircuitOr 'a 'a ("_ || _") |
-  Remainder 'a 'a ("_ % _")
+  ExclusiveOr 'a 'a ("_  _") |
+  LogicNegationNotation 'a ("!_") |
+  ShortCircuitOr 'a 'a ("_ || _") |
+  Remainder 'a 'a ("_ % _")
 
 definition word :: "('a::len) word  'a word" where
   "word x = x"
 
 ML_val "@{term x % x}"
-ML_file markup.ML
+ML_file ‹markup.ML›
 
-subsubsection Expression Markup
-ML 
+subsubsection ‹Expression Markup›
+ML structure IRExprTranslator : DSL_TRANSLATION =
 struct
 fun markup DSL_Tokens.Add = @{term BinaryExpr} $ @{term BinAdd}
@@ -71,20 +71,20 @@ 

Theory Markup

| markup DSL_Tokens.FalseConstant = @{term "ConstantExpr (IntVal 32 0)"} end structure IRExprMarkup = DSL_Markup(IRExprTranslator); -
+›
-snipbegin ir expression translation -syntax "_expandExpr" :: "term term" ("exp[_]") -parse_translation [( @{syntax_const "_expandExpr"} , IRExprMarkup.markup_expr [])] +snipbegin ‹ir expression translation› +syntax "_expandExpr" :: "term term" ("exp[_]") +parse_translation [( @{syntax_const "_expandExpr"} , IRExprMarkup.markup_expr [])] snipend - -snipbegin ir expression example +snipbegin ‹ir expression example› value "exp[(e1 < e2) ? e1 : e2]" text @{term exp[(e1 < e2) ? e1 : e2]} snipend - -subsubsection Value Markup -ML +subsubsection ‹Value Markup› +ML structure IntValTranslator : DSL_TRANSLATION = struct fun markup DSL_Tokens.Add = @{term intval_add} @@ -111,20 +111,20 @@

Theory Markup

| markup DSL_Tokens.FalseConstant = @{term "IntVal 32 0"} end structure IntValMarkup = DSL_Markup(IntValTranslator); -
+›
-snipbegin value expression translation -syntax "_expandIntVal" :: "term term" ("val[_]") -parse_translation [( @{syntax_const "_expandIntVal"} , IntValMarkup.markup_expr [])] +snipbegin ‹value expression translation› +syntax "_expandIntVal" :: "term term" ("val[_]") +parse_translation [( @{syntax_const "_expandIntVal"} , IntValMarkup.markup_expr [])] snipend - -snipbegin value expression example +snipbegin ‹value expression example› value "val[(e1 < e2) ? e1 : e2]" text @{term val[(e1 < e2) ? e1 : e2]} snipend - -subsubsection Word Markup -ML +subsubsection ‹Word Markup› +ML structure WordTranslator : DSL_TRANSLATION = struct fun markup DSL_Tokens.Add = @{term plus} @@ -149,14 +149,14 @@

Theory Markup

| markup DSL_Tokens.FalseConstant = @{term 0} end structure WordMarkup = DSL_Markup(WordTranslator); -
+›
-snipbegin word expression translation -syntax "_expandWord" :: "term term" ("bin[_]") -parse_translation [( @{syntax_const "_expandWord"} , WordMarkup.markup_expr [])] +snipbegin ‹word expression translation› +syntax "_expandWord" :: "term term" ("bin[_]") +parse_translation [( @{syntax_const "_expandWord"} , WordMarkup.markup_expr [])] snipend - -snipbegin word expression example +snipbegin ‹word expression example› value "bin[x & y | z]" text @{term val[(e1 < e2) ? e1 : e2]} snipend - diff --git a/OptimizationDSL/Phase.html b/OptimizationDSL/Phase.html index 09e57e0b..b9b02a71 100644 --- a/OptimizationDSL/Phase.html +++ b/OptimizationDSL/Phase.html @@ -12,14 +12,14 @@

Theory Phase

-
subsection Optimization Phases
+
subsection ‹Optimization Phases›
 
 theory Phase
   imports Main
 begin
 
-ML_file "map.ML"
-ML_file "phase.ML"
+ML_file "map.ML"
+ML_file "phase.ML"
 
 end
diff --git a/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/map.ML.html b/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/map.ML.html index 51935a63..c58cf306 100644 --- a/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/map.ML.html +++ b/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/map.ML.html @@ -20,19 +20,19 @@

File ‹map.ML›

signature MAP = sig -type (''k, 'v) map = (''k list * (''k -> 'v option)) +type (''k, 'v) map = (''k list * (''k -> 'v option)) -val insert: (''k, 'v) map -> (''k * 'v) -> (''k, 'v) map -val lookup: (''k, 'v) map -> ''k -> 'v option -val values: (''k, 'v) map -> 'v list -val empty: (''k, 'v) map -val merge: (''k, 'v) map -> (''k, 'v) map -> (''k, 'v) map +val insert: (''k, 'v) map -> (''k * 'v) -> (''k, 'v) map +val lookup: (''k, 'v) map -> ''k -> 'v option +val values: (''k, 'v) map -> 'v list +val empty: (''k, 'v) map +val merge: (''k, 'v) map -> (''k, 'v) map -> (''k, 'v) map end structure Map : MAP = struct -type ('k, 'v) map = ('k list * ('k -> 'v option)) +type ('k, 'v) map = ('k list * ('k -> 'v option)) fun add_if_not xs x = if member (op =) xs x then xs else cons x xs diff --git a/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/phase.ML.html b/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/phase.ML.html index 72f9b81f..c11b9cb9 100644 --- a/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/phase.ML.html +++ b/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/phase.ML.html @@ -30,8 +30,8 @@

File ‹phase.ML›

type phase = {name: binding, - trm: term, - rules: (binding, T) Map.map} + trm: term, + rules: (binding, T) Map.map} type config = (binding * string) @@ -53,8 +53,8 @@

File ‹phase.ML›

type phase = {name: binding, - trm: term, - rules: (binding, T) Map.map} + trm: term, + rules: (binding, T) Map.map} type store = (binding, phase) Map.map @@ -64,12 +64,12 @@

File ‹phase.ML›

type state = {store: store, - status: status} + status: status} type config = (binding * string) -val empty = {store=Map.empty, status=NoPhase}; +val empty = {store=Map.empty, status=NoPhase}; fun merge_statuses (NoPhase, NoPhase) = NoPhase | merge_statuses (NoPhase, InPhase name) = InPhase name @@ -81,20 +81,20 @@

File ‹phase.ML›

type T = state; val empty = empty; fun merge (lhs, rhs) = - {status=merge_statuses (#status lhs, #status rhs), - store= Map.merge (#store lhs) (#store rhs)} + {status=merge_statuses (#status lhs, #status rhs), + store= Map.merge (#store lhs) (#store rhs)} ); val state = PhaseData.get; fun phase_name thy = - (case #status (state thy) of + (case #status (state thy) of NoPhase => NONE | InPhase name => SOME name) fun phase_by_name data name : phase option = let - val lookup = snd (#store data); + val lookup = snd (#store data); in case name of NONE => NONE @@ -108,23 +108,23 @@

File ‹phase.ML›

phase_by_name (state thy) phase end -fun phases thy = Map.values (#store (state thy)) +fun phases thy = Map.values (#store (state thy)) fun expand_phase rule (phase: phase): phase = - {name = (#name phase), trm = (#trm phase), - rules = Map.insert (#rules phase) rule} + {name = (#name phase), trm = (#trm phase), + rules = Map.insert (#rules phase) rule} fun insert_rule' t phase data = let val phase' = expand_phase t phase; - val data' = Map.insert (#store data) (#name phase, phase') + val data' = Map.insert (#store data) (#name phase, phase') in - {status= #status data, store= data'} + {status= #status data, store= data'} end fun insert_rule t data = let - val phase = (case (#status data) of + val phase = (case (#status data) of NoPhase => raise TERM ("Optimization phase missing", []) | InPhase name => phase_by_name data (SOME name) ); @@ -138,11 +138,11 @@

File ‹phase.ML›

fun register t thy = PhaseData.map (insert_rule t) thy -fun new_phase name trm = {name = name, trm = trm, rules = Map.empty}; +fun new_phase name trm = {name = name, trm = trm, rules = Map.empty}; fun enter' name trm thy = PhaseData.map (fn state => - case (#status state) of - NoPhase => {status=InPhase name, store=Map.insert (#store state) (name, new_phase name trm)} | + case (#status state) of + NoPhase => {status=InPhase name, store=Map.insert (#store state) (name, new_phase name trm)} | InPhase _ => raise TERM ("optimization phase already established", []) ) thy @@ -150,9 +150,9 @@

File ‹phase.ML›

Proof_Context.init_global (enter' name (Syntax.read_term_global thy trm) thy) fun exit' thy = PhaseData.map (fn state => - case (#status state) of + case (#status state) of NoPhase => raise TERM ("no phase to exit", []) | - InPhase _ => {status=NoPhase, store=(#store state)} + InPhase _ => {status=NoPhase, store=(#store state)} ) thy val exit = Local_Theory.background_theory exit' @@ -164,18 +164,18 @@

File ‹phase.ML›

fun pretty_phase obligation (phase:phase) ctxt = Pretty.block - [Pretty.str "phase: ", pretty_bind (#name phase), Pretty.fbrk, - Pretty.str "trm: ", Syntax.pretty_term ctxt (#trm phase), Pretty.fbrk, - Pretty.big_list "rules:" (map (Rule.pretty ctxt obligation) (Map.values (#rules phase)))] + [Pretty.str "phase: ", pretty_bind (#name phase), Pretty.fbrk, + Pretty.str "trm: ", Syntax.pretty_term ctxt (#trm phase), Pretty.fbrk, + Pretty.big_list "rules:" (map (Rule.pretty ctxt obligation) (Map.values (#rules phase)))] fun pretty obligation phase ctxt = pretty_phase obligation phase ctxt fun pretty' state ctxt = - case (#status state) of + case (#status state) of NoPhase => Pretty.str "No phase" | InPhase name => - (case Map.lookup (#store state) name of + (case Map.lookup (#store state) name of NONE => raise ERROR "Bug" | SOME phase => pretty_phase false phase ctxt ) @@ -185,16 +185,16 @@

File ‹phase.ML›

fun setup config thy = Local_Theory.init - {background_naming = Sign.naming_of thy, - setup = enter config, - conclude = exit} - {define = Generic_Target.define Generic_Target.theory_target_foundation, - notes = Generic_Target.notes Generic_Target.theory_target_notes, - abbrev = Generic_Target.abbrev Generic_Target.theory_target_abbrev, - declaration = K Generic_Target.theory_declaration, - theory_registration = Generic_Target.theory_registration, - locale_dependency = fn _ => error "Not possible in instantiation target", - pretty = pretty''} + {background_naming = Sign.naming_of thy, + setup = enter config, + conclude = exit} + {define = Generic_Target.define Generic_Target.theory_target_foundation, + notes = Generic_Target.notes Generic_Target.theory_target_notes, + abbrev = Generic_Target.abbrev Generic_Target.theory_target_abbrev, + declaration = K Generic_Target.theory_declaration, + theory_registration = Generic_Target.theory_registration, + locale_dependency = fn _ => error "Not possible in instantiation target", + pretty = pretty''} thy end
diff --git a/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/rewrites.ML.html b/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/rewrites.ML.html index 434b142e..5eaab9b5 100644 --- a/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/rewrites.ML.html +++ b/OptimizationDSL/ROOT/github/workspace/Optimizations/DSL/rewrites.ML.html @@ -42,13 +42,13 @@

File ‹rewrites.ML›

fun of_term name term source = case term of (((Const ("Markup.Rewrite.Transform", _)) $ lhs) $ rhs) => - {name=name, rewrite=Transform (lhs, rhs), proofs=[], code=[], source=source} + {name=name, rewrite=Transform (lhs, rhs), proofs=[], code=[], source=source} | ((((Const ("Markup.Rewrite.Conditional", _)) $ lhs) $ rhs) $ cond) => - {name=name, rewrite=Conditional (lhs, rhs, cond), proofs=[], code=[], source=source} + {name=name, rewrite=Conditional (lhs, rhs, cond), proofs=[], code=[], source=source} | _ => raise TERM ("optimization is not a rewrite", [term]) fun to_term rewrite = - case (#rewrite rewrite) of + case (#rewrite rewrite) of Transform (lhs, rhs) => (Const ("Markup.Rewrite.Transform", @{typ "IRExpr => IRExpr => IRExpr Rewrite"})) $ lhs $ rhs | Conditional (lhs, rhs, cond) => @@ -118,7 +118,7 @@

File ‹rewrites.ML›

val state = RewritePhase.current (Proof_Context.theory_of ctxt); val trm = (case state of NONE => raise TERM ("Optimization phase missing", []) | - SOME phase => (#trm phase) + SOME phase => (#trm phase) ); in termination_of' ctxt trm rewrite @@ -127,17 +127,17 @@

File ‹rewrites.ML›

fun code_of _ rewrite = @{const Trueprop} $ ((Const ("HOL.eq", @{typ "(IRExpr IRExpr option) (IRExpr IRExpr option) bool"}) - $ (Free ((Binding.name_of (#name rewrite)) ^ "_code", @{typ "IRExpr IRExpr option"})) + $ (Free ((Binding.name_of (#name rewrite)) ^ "_code", @{typ "IRExpr IRExpr option"})) $ @{term λ (x::IRExpr) (None::IRExpr option)})) fun add_proofs (rewrite: rewrite) proofs = { - name= #name rewrite, - rewrite= #rewrite rewrite, - proofs= proofs, - code= #code rewrite, - source= #source rewrite + name= #name rewrite, + rewrite= #rewrite rewrite, + proofs= proofs, + code= #code rewrite, + source= #source rewrite } fun rewrite_cmd ((bind, options), opt) ctxt = @@ -153,7 +153,7 @@

File ‹rewrites.ML›

val ctxt = (if subgoals then (Specification.abbreviation (Syntax.mode_default) NONE [] - (val_def_const ctxt (#name rewrite) raw_term) + (val_def_const ctxt (#name rewrite) raw_term) false ctxt) (*((Binding.prefix_name "val_" bind, []), value_def ctxt (#name rewrite) raw_term) ctxt)*) else ctxt); diff --git a/OptimizationDSL/document.pdf b/OptimizationDSL/document.pdf index 1770ab49..1c6ed487 100644 Binary files a/OptimizationDSL/document.pdf and b/OptimizationDSL/document.pdf differ diff --git a/OptimizationDSL/index.html b/OptimizationDSL/index.html index 3ab465d2..5df81370 100644 --- a/OptimizationDSL/index.html +++ b/OptimizationDSL/index.html @@ -3,7 +3,7 @@ -Session OptimizationDSL (Isabelle2022) +Session OptimizationDSL (Isabelle2023) @@ -19,8 +19,6 @@

Session OptimizationDSL

Theories