Theory NewAnd
subsection ‹Experimental AndNode Phase›
theory NewAnd
imports
Common
Graph.JavaLong
begin
lemma intval_distribute_and_over_or:
"val[z & (x | y)] = val[(z & x) | (z & y)]"
by (cases x; cases y; cases z; auto simp add: bit.conj_disj_distrib)
lemma exp_distribute_and_over_or:
"exp[z & (x | y)] ≥ exp[(z & x) | (z & y)]"
apply auto
by (metis bin_eval.simps(6,7) intval_or.simps(2,6) intval_distribute_and_over_or BinaryExpr)
lemma intval_and_commute:
"val[x & y] = val[y & x]"
by (cases x; cases y; auto simp: and.commute)
lemma intval_or_commute:
"val[x | y] = val[y | x]"
by (cases x; cases y; auto simp: or.commute)
lemma intval_xor_commute:
"val[x ⊕ y] = val[y ⊕ x]"
by (cases x; cases y; auto simp: xor.commute)
lemma exp_and_commute:
"exp[x & z] ≥ exp[z & x]"
by (auto simp: intval_and_commute)
lemma exp_or_commute:
"exp[x | y] ≥ exp[y | x]"
by (auto simp: intval_or_commute)
lemma exp_xor_commute:
"exp[x ⊕ y] ≥ exp[y ⊕ x]"
by (auto simp: intval_xor_commute)
lemma intval_eliminate_y:
assumes "val[y & z] = IntVal b 0"
shows "val[(x | y) & z] = val[x & z]"
using assms by (cases x; cases y; cases z; auto simp add: bit.conj_disj_distrib2)
lemma intval_and_associative:
"val[(x & y) & z] = val[x & (y & z)]"
by (cases x; cases y; cases z; auto simp: and.assoc)
lemma intval_or_associative:
"val[(x | y) | z] = val[x | (y | z)]"
by (cases x; cases y; cases z; auto simp: or.assoc)
lemma intval_xor_associative:
"val[(x ⊕ y) ⊕ z] = val[x ⊕ (y ⊕ z)]"
by (cases x; cases y; cases z; auto simp: xor.assoc)
lemma exp_and_associative:
"exp[(x & y) & z] ≥ exp[x & (y & z)]"
using intval_and_associative by fastforce
lemma exp_or_associative:
"exp[(x | y) | z] ≥ exp[x | (y | z)]"
using intval_or_associative by fastforce
lemma exp_xor_associative:
"exp[(x ⊕ y) ⊕ z] ≥ exp[x ⊕ (y ⊕ z)]"
using intval_xor_associative by fastforce
lemma intval_and_absorb_or:
assumes "∃b v . x = new_int b v"
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"
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_or.simps(6))
lemma exp_and_absorb_or:
"exp[x & (x | y)] ≥ exp[x]"
apply auto
subgoal premises p for m p xa xaa ya
proof-
obtain xv where xv: "[m,p] ⊢ x ↦ xv"
using p(1) by auto
obtain yv where yv: "[m,p] ⊢ y ↦ yv"
using p(4) by auto
then have lhsDefined: "val[xv & (xv | yv)] ≠ UndefVal"
by (metis evalDet p(1,2,3,4) xv)
obtain xb xvv where xvv: "xv = IntVal xb xvv"
by (metis Value.exhaust_sel intval_and.simps(2,3,4,5) lhsDefined)
obtain yb yvv where yvv: "yv = IntVal yb yvv"
by (metis Value.exhaust_sel intval_and.simps(6) intval_or.simps(6,7,8,9) lhsDefined)
then have valEval: "val[xv & (xv | yv)] = val[xv]"
by (metis eval_unused_bits_zero intval_and_absorb_or lhsDefined new_int.elims xv xvv)
then show ?thesis
by (metis evalDet p(1,3,4) xv yv)
qed
done
lemma exp_or_absorb_and:
"exp[x | (x & y)] ≥ exp[x]"
apply auto
subgoal premises p for m p xa xaa ya
proof-
obtain xv where xv: "[m,p] ⊢ x ↦ xv"
using p(1) by auto
obtain yv where yv: "[m,p] ⊢ y ↦ yv"
using p(4) by auto
then have lhsDefined: "val[xv | (xv & yv)] ≠ UndefVal"
by (metis evalDet p(1,2,3,4) xv)
obtain xb xvv where xvv: "xv = IntVal xb xvv"
by (metis Value.exhaust_sel intval_and.simps(3,4,5) intval_or.simps(2,6) lhsDefined)
obtain yb yvv where yvv: "yv = IntVal yb yvv"
by (metis Value.exhaust_sel intval_and.simps(6,7,8,9) intval_or.simps(6) lhsDefined)
then have valEval: "val[xv | (xv & yv)] = val[xv]"
by (metis eval_unused_bits_zero intval_or_absorb_and lhsDefined new_int.elims xv xvv)
then show ?thesis
by (metis evalDet p(1,3,4) xv yv)
qed
done
lemma
assumes "y = 0"
shows "x + y = or x y"
by (simp add: assms)
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)
context stamp_mask
begin
lemma intval_up_and_zero_implies_zero:
assumes "and (↑x) (↑y) = 0"
assumes "[m, p] ⊢ x ↦ xv"
assumes "[m, p] ⊢ y ↦ yv"
assumes "val[xv & yv] ≠ UndefVal"
shows "∃ b . val[xv & yv] = new_int b 0"
using assms apply (cases xv; cases yv; auto)
apply (metis eval_unused_bits_zero stamp_mask.up_mask_and_zero_implies_zero stamp_mask_axioms)
by presburger
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
proof -
obtain xv where xv: "[m,p] ⊢ x ↦ xv"
using e by auto
obtain yv where yv: "[m,p] ⊢ y ↦ yv"
using e by auto
obtain zv where zv: "[m,p] ⊢ z ↦ zv"
using e by auto
have lhs: "v = val[(xv | yv) & zv]"
by (smt (verit, best) BinaryExprE bin_eval.simps(6,7) e evalDet xv yv zv)
then have "v = val[(xv & zv) | (yv & zv)]"
by (simp add: intval_and_commute intval_distribute_and_over_or)
also have "∃b. val[yv & zv] = new_int b 0"
by (metis calculation e intval_or.simps(6) p unfold_binary intval_up_and_zero_implies_zero yv
zv)
ultimately have rhs: "v = val[xv & zv]"
by (auto simp: intval_eliminate_y lhs)
from lhs rhs show ?thesis
by (metis BinaryExpr BinaryExprE bin_eval.simps(6) e xv zv)
qed
done
done
lemma leadingZeroBounds:
fixes x :: "'a::len word"
assumes "n = numberOfLeadingZeros x"
shows "0 ≤ n ∧ n ≤ Nat.size x"
by (simp add: MaxOrNeg_def highestOneBit_def nat_le_iff numberOfLeadingZeros_def assms)
lemma above_nth_not_set:
fixes x :: int64
assumes "n = 64 - numberOfLeadingZeros x"
shows "j > n ⟶ ¬(bit x j)"
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 ("!_")
lemma zero_horner:
"horner_sum of_bool 2 (map (λx. False) xs) = 0"
by (induction xs; auto)
lemma zero_map:
assumes "j ≤ n"
assumes "∀i. j ≤ i ⟶ ¬(f i)"
shows "map f [0..<n] = map f [0..<j] @ map (λx. False) [j..<n]"
by (smt (verit, del_insts) add_diff_inverse_nat atLeastLessThan_iff bot_nat_0.extremum leD assms
map_append map_eq_conv set_upt upt_add_eq_append)
lemma map_join_horner:
assumes "map f [0..<n] = map f [0..<j] @ map (λx. False) [j..<n]"
shows "horner_sum of_bool (2::'a::len word) (map f [0..<n]) = horner_sum of_bool 2 (map f [0..<j])"
proof -
have "horner_sum of_bool (2::'a::len word) (map f [0..<n]) = horner_sum of_bool 2 (map f [0..<j]) + 2 ^ length [0..<j] * horner_sum of_bool 2 (map f [j..<n])"
using assms apply auto
by (smt (verit) assms diff_le_self diff_zero le_add_same_cancel2 length_append length_map
length_upt map_append upt_add_eq_append horner_sum_append)
also have "... = horner_sum of_bool 2 (map f [0..<j]) + 2 ^ length [0..<j] * horner_sum of_bool 2 (map (λx. False) [j..<n])"
by (metis calculation horner_sum_append length_map assms)
also have "... = horner_sum of_bool 2 (map f [0..<j])"
using zero_horner mult_not_zero by auto
finally show ?thesis
by simp
qed
lemma split_horner:
assumes "j ≤ n"
assumes "∀i. j ≤ i ⟶ ¬(f i)"
shows "horner_sum of_bool (2::'a::len word) (map f [0..<n]) = horner_sum of_bool 2 (map f [0..<j])"
by (auto simp: assms zero_map map_join_horner)
lemma transfer_map:
assumes "∀i. i < n ⟶ f i = f' i"
shows "(map f [0..<n]) = (map f' [0..<n])"
by (simp add: assms)
lemma transfer_horner:
assumes "∀i. i < n ⟶ f i = f' i"
shows "horner_sum of_bool (2::'a::len word) (map f [0..<n]) = horner_sum of_bool 2 (map f' [0..<n])"
by (smt (verit, best) assms transfer_map)
lemma L1:
assumes "n = 64 - numberOfLeadingZeros (↑z)"
assumes "[m, p] ⊢ z ↦ IntVal b zv"
shows "and v zv = and (v mod 2^n) zv"
proof -
have nle: "n ≤ 64"
using assms diff_le_self by blast
also have "and v zv = horner_sum of_bool 2 (map (bit (and v zv)) [0..<64])"
by (metis size_word.rep_eq take_bit_length_eq horner_sum_bit_eq_take_bit size64)
also have "... = horner_sum of_bool 2 (map (λi. bit (and v zv) i) [0..<64])"
by blast
also have "... = horner_sum of_bool 2 (map (λi. ((bit v i) ∧ (bit zv i))) [0..<64])"
by (metis bit_and_iff)
also have "... = horner_sum of_bool 2 (map (λi. ((bit v i) ∧ (bit zv i))) [0..<n])"
proof -
have "∀i. i ≥ n ⟶ ¬(bit zv i)"
by (smt (verit, ccfv_SIG) One_nat_def diff_less int_ops(6) leadingZerosAddHighestOne assms
linorder_not_le nat_int_comparison(2) not_numeral_le_zero size64 zero_less_Suc
zerosAboveHighestOne not_may_implies_false)
then have "∀i. i ≥ n ⟶ ¬((bit v i) ∧ (bit zv i))"
by auto
then show ?thesis using nle split_horner
by (metis (no_types, lifting))
qed
also have "... = horner_sum of_bool 2 (map (λi. ((bit (v mod 2^n) i) ∧ (bit zv i))) [0..<n])"
proof -
have "∀i. i < n ⟶ bit (v mod 2^n) i = bit v i"
by (metis bit_take_bit_iff take_bit_eq_mod)
then have "∀i. i < n ⟶ ((bit v i) ∧ (bit zv i)) = ((bit (v mod 2^n) i) ∧ (bit zv i))"
by force
then show ?thesis
by (rule transfer_horner)
qed
also have "... = horner_sum of_bool 2 (map (λi. ((bit (v mod 2^n) i) ∧ (bit zv i))) [0..<64])"
proof -
have "∀i. i ≥ n ⟶ ¬(bit zv i)"
by (smt (verit, ccfv_SIG) One_nat_def diff_less int_ops(6) leadingZerosAddHighestOne assms
linorder_not_le nat_int_comparison(2) not_numeral_le_zero size64 zero_less_Suc
zerosAboveHighestOne not_may_implies_false)
then show ?thesis
by (metis (no_types, lifting) assms(1) diff_le_self split_horner)
qed
also have "... = horner_sum of_bool 2 (map (bit (and (v mod 2^n) zv)) [0..<64])"
by (meson bit_and_iff)
also have "... = and (v mod 2^n) zv"
by (metis size_word.rep_eq take_bit_length_eq horner_sum_bit_eq_take_bit size64)
finally show ?thesis
using ‹and (v::64 word) (zv::64 word) = horner_sum of_bool (2::64 word) (map (bit (and v zv)) [0::nat..<64::nat])› ‹horner_sum of_bool (2::64 word) (map (λi::nat. bit ((v::64 word) mod (2::64 word) ^ (n::nat)) i ∧ bit (zv::64 word) i) [0::nat..<64::nat]) = horner_sum of_bool (2::64 word) (map (bit (and (v mod (2::64 word) ^ n) zv)) [0::nat..<64::nat])› ‹horner_sum of_bool (2::64 word) (map (λi::nat. bit ((v::64 word) mod (2::64 word) ^ (n::nat)) i ∧ bit (zv::64 word) i) [0::nat..<n]) = horner_sum of_bool (2::64 word) (map (λi::nat. bit (v mod (2::64 word) ^ n) i ∧ bit zv i) [0::nat..<64::nat])› ‹horner_sum of_bool (2::64 word) (map (λi::nat. bit (v::64 word) i ∧ bit (zv::64 word) i) [0::nat..<64::nat]) = horner_sum of_bool (2::64 word) (map (λi::nat. bit v i ∧ bit zv i) [0::nat..<n::nat])› ‹horner_sum of_bool (2::64 word) (map (λi::nat. bit (v::64 word) i ∧ bit (zv::64 word) i) [0::nat..<n::nat]) = horner_sum of_bool (2::64 word) (map (λi::nat. bit (v mod (2::64 word) ^ n) i ∧ bit zv i) [0::nat..<n])› ‹horner_sum of_bool (2::64 word) (map (bit (and ((v::64 word) mod (2::64 word) ^ (n::nat)) (zv::64 word))) [0::nat..<64::nat]) = and (v mod (2::64 word) ^ n) zv› ‹horner_sum of_bool (2::64 word) (map (bit (and (v::64 word) (zv::64 word))) [0::nat..<64::nat]) = horner_sum of_bool (2::64 word) (map (λi::nat. bit v i ∧ bit zv i) [0::nat..<64::nat])› by presburger
qed
lemma up_mask_upper_bound:
assumes "[m, p] ⊢ x ↦ IntVal b xv"
shows "xv ≤ (↑x)"
by (metis (no_types, lifting) and.right_neutral bit.conj_cancel_left bit.conj_disj_distribs(1)
bit.double_compl ucast_id up_spec word_and_le1 word_not_dist(2) assms)
lemma L2:
assumes "numberOfLeadingZeros (↑z) + numberOfTrailingZeros (↑y) ≥ 64"
assumes "n = 64 - numberOfLeadingZeros (↑z)"
assumes "[m, p] ⊢ z ↦ IntVal b zv"
assumes "[m, p] ⊢ y ↦ IntVal b yv"
shows "yv mod 2^n = 0"
proof -
have "yv mod 2^n = horner_sum of_bool 2 (map (bit yv) [0..<n])"
by (simp add: horner_sum_bit_eq_take_bit take_bit_eq_mod)
also have "... ≤ horner_sum of_bool 2 (map (bit (↑y)) [0..<n])"
by (metis (no_types, opaque_lifting) and.right_neutral bit.conj_cancel_right word_not_dist(2)
bit.conj_disj_distribs(1) bit.double_compl horner_sum_bit_eq_take_bit take_bit_and ucast_id
up_spec word_and_le1 assms(4))
also have "horner_sum of_bool 2 (map (bit (↑y)) [0..<n]) = horner_sum of_bool 2 (map (λx. False) [0..<n])"
proof -
have "∀i < n. ¬(bit (↑y) i)"
by (metis add.commute add_diff_inverse_nat add_lessD1 leD le_diff_conv zerosBelowLowestOne
numberOfTrailingZeros_def assms(1,2))
then show ?thesis
by (metis (full_types) transfer_map)
qed
also have "horner_sum of_bool 2 (map (λx. False) [0..<n]) = 0"
by (auto simp: zero_horner)
finally show ?thesis
by auto
qed
thm_oracles L1 L2
lemma unfold_binary_width_add:
shows "([m,p] ⊢ BinaryExpr BinAdd xe ye ↦ IntVal b val) = (∃ x y.
(([m,p] ⊢ xe ↦ IntVal b x) ∧
([m,p] ⊢ ye ↦ IntVal b y) ∧
(IntVal b val = bin_eval BinAdd (IntVal b x) (IntVal b y)) ∧
(IntVal b val ≠ UndefVal)
))" (is "?L = ?R")
using unfold_binary_width by simp
lemma unfold_binary_width_and:
shows "([m,p] ⊢ BinaryExpr BinAnd xe ye ↦ IntVal b val) = (∃ x y.
(([m,p] ⊢ xe ↦ IntVal b x) ∧
([m,p] ⊢ ye ↦ IntVal b y) ∧
(IntVal b val = bin_eval BinAnd (IntVal b x) (IntVal b y)) ∧
(IntVal b val ≠ UndefVal)
))" (is "?L = ?R")
using unfold_binary_width by simp
lemma mod_dist_over_add_right:
fixes a b c :: int64
fixes n :: nat
assumes "0 < n"
assumes "n < 64"
shows "(a + b mod 2^n) mod 2^n = (a + b) mod 2^n"
using mod_dist_over_add by (simp add: assms add.commute)
lemma numberOfLeadingZeros_range:
"0 ≤ numberOfLeadingZeros n ∧ numberOfLeadingZeros n ≤ Nat.size n"
by (simp add: leadingZeroBounds)
lemma improved_opt:
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
proof -
obtain n where n: "n = 64 - numberOfLeadingZeros (↑z)"
by simp
obtain b val where val: "[m, p] ⊢ exp[(x + y) & z] ↦ IntVal b val"
by (metis BinaryExprE bin_eval_new_int eval new_int.simps)
then obtain xv yv where addv: "[m, p] ⊢ exp[x + y] ↦ IntVal b (xv + yv)"
apply (subst (asm) unfold_binary_width_and) by (metis add.right_neutral)
then obtain yv where yv: "[m, p] ⊢ y ↦ IntVal b yv"
apply (subst (asm) unfold_binary_width_add) by blast
from addv obtain xv where xv: "[m, p] ⊢ x ↦ IntVal b xv"
apply (subst (asm) unfold_binary_width_add) by blast
from val obtain zv where zv: "[m, p] ⊢ z ↦ IntVal b zv"
apply (subst (asm) unfold_binary_width_and) by blast
have addv: "[m, p] ⊢ exp[x + y] ↦ new_int b (xv + yv)"
using xv yv evaltree.BinaryExpr by auto
have lhs: "[m, p] ⊢ exp[(x + y) & z] ↦ new_int b (and (xv + yv) zv)"
using addv zv apply (rule evaltree.BinaryExpr) by simp+
have rhs: "[m, p] ⊢ exp[x & z] ↦ new_int b (and xv zv)"
using xv zv evaltree.BinaryExpr by auto
then show ?thesis
proof (cases "numberOfLeadingZeros (↑z) > 0")
case True
have n_bounds: "0 ≤ n ∧ n < 64"
by (simp add: True n)
have "and (xv + yv) zv = and ((xv + yv) mod 2^n) zv"
using L1 n zv by blast
also have "... = and ((xv + (yv mod 2^n)) mod 2^n) zv"
by (metis take_bit_0 take_bit_eq_mod zero_less_iff_neq_zero mod_dist_over_add_right n_bounds)
also have "... = and (((xv mod 2^n) + (yv mod 2^n)) mod 2^n) zv"
by (metis bits_mod_by_1 mod_dist_over_add n_bounds order_le_imp_less_or_eq power_0)
also have "... = and ((xv mod 2^n) mod 2^n) zv"
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)
also have "... = and xv zv"
by (metis L1 n zv)
finally show ?thesis
by (metis evalDet eval lhs rhs)
next
case False
then have "numberOfLeadingZeros (↑z) = 0"
by simp
then have "numberOfTrailingZeros (↑y) ≥ 64"
using assms by fastforce
then have "yv = 0"
by (metis (no_types, lifting) L1 L2 add_diff_cancel_left' and.comm_neutral linorder_not_le
bit.conj_cancel_right bit.conj_disj_distribs(1) bit.double_compl less_imp_diff_less yv
word_not_dist(2))
then show ?thesis
by (metis add.right_neutral eval evalDet lhs rhs)
qed
qed
done
thm_oracles improved_opt
end
phase NewAnd
terminating size
begin
optimization redundant_lhs_y_or: "((x | y) & z) ⟼ x & z
when (((and (IRExpr_up y) (IRExpr_up z)) = 0))"
by (simp add: IRExpr_up_def)+
optimization redundant_lhs_x_or: "((x | y) & z) ⟼ y & z
when (((and (IRExpr_up x) (IRExpr_up z)) = 0))"
by (simp add: IRExpr_up_def)+
optimization redundant_rhs_y_or: "(z & (x | y)) ⟼ z & x
when (((and (IRExpr_up y) (IRExpr_up z)) = 0))"
by (simp add: IRExpr_up_def)+
optimization redundant_rhs_x_or: "(z & (x | y)) ⟼ z & y
when (((and (IRExpr_up x) (IRExpr_up z)) = 0))"
by (simp add: IRExpr_up_def)+
end
end