aboutsummaryrefslogtreecommitdiff
path: root/src/RewriterRulesInterpGood.v
diff options
context:
space:
mode:
Diffstat (limited to 'src/RewriterRulesInterpGood.v')
-rw-r--r--src/RewriterRulesInterpGood.v779
1 files changed, 779 insertions, 0 deletions
diff --git a/src/RewriterRulesInterpGood.v b/src/RewriterRulesInterpGood.v
new file mode 100644
index 000000000..40177e3a0
--- /dev/null
+++ b/src/RewriterRulesInterpGood.v
@@ -0,0 +1,779 @@
+Require Import Coq.ZArith.ZArith.
+Require Import Coq.micromega.Lia.
+Require Import Coq.Lists.List.
+Require Import Coq.Classes.Morphisms.
+Require Import Coq.MSets.MSetPositive.
+Require Import Coq.FSets.FMapPositive.
+Require Import Crypto.Language.
+Require Import Crypto.LanguageInversion.
+Require Import Crypto.LanguageWf.
+Require Import Crypto.UnderLetsProofs.
+Require Import Crypto.GENERATEDIdentifiersWithoutTypesProofs.
+Require Import Crypto.Rewriter.
+Require Import Crypto.RewriterWf1.
+Require Import Crypto.Util.ZUtil.Tactics.LtbToLt.
+Require Import Crypto.Util.ZUtil.Tactics.DivModToQuotRem.
+Require Import Crypto.Util.ZUtil.Tactics.PullPush.Modulo.
+Require Import Crypto.Util.ZUtil.Hints.
+Require Import Crypto.Util.ZUtil.Hints.Core.
+Require Import Crypto.Util.ZUtil.ZSimplify.Core.
+Require Import Crypto.Util.ZUtil.ZSimplify.
+Require Import Crypto.Util.ZUtil.ZSimplify.Simple.
+Require Import Crypto.Util.ZUtil.Definitions.
+Require Import Crypto.Util.ZUtil.AddGetCarry.
+Require Import Crypto.Util.ZUtil.MulSplit.
+Require Import Crypto.Util.ZUtil.Zselect.
+Require Import Crypto.Util.ZUtil.Div.
+Require Import Crypto.Util.ZUtil.Modulo.
+Require Import Crypto.Util.ZRange.
+Require Import Crypto.Util.ZRange.Operations.
+Require Import Crypto.Util.ZRange.BasicLemmas.
+Require Import Crypto.Util.ZRange.OperationsBounds.
+Require Import Crypto.Util.Tactics.NormalizeCommutativeIdentifier.
+Require Import Crypto.Util.Tactics.BreakMatch.
+Require Import Crypto.Util.Tactics.SplitInContext.
+Require Import Crypto.Util.Tactics.SpecializeAllWays.
+Require Import Crypto.Util.Tactics.SpecializeBy.
+Require Import Crypto.Util.Tactics.RewriteHyp.
+Require Import Crypto.Util.Tactics.Head.
+Require Import Crypto.Util.Tactics.SetEvars.
+Require Import Crypto.Util.Tactics.SubstEvars.
+Require Import Crypto.Util.Prod.
+Require Import Crypto.Util.Bool.
+Require Import Crypto.Util.ListUtil.
+Require Import Crypto.Util.ListUtil.Forall.
+Require Import Crypto.Util.ListUtil.ForallIn.
+Require Import Crypto.Util.NatUtil.
+Require Import Crypto.Util.Option.
+Require Import Crypto.Util.CPSNotations.
+Require Import Crypto.Util.HProp.
+Require Import Crypto.Util.Decidable.
+Import ListNotations. Local Open Scope list_scope.
+Local Open Scope Z_scope.
+
+Import EqNotations.
+Module Compilers.
+ Import Language.Compilers.
+ Import LanguageInversion.Compilers.
+ Import LanguageWf.Compilers.
+ Import UnderLetsProofs.Compilers.
+ Import GENERATEDIdentifiersWithoutTypesProofs.Compilers.
+ Import Rewriter.Compilers.
+ Import RewriterWf1.Compilers.
+ Import expr.Notations.
+ Import RewriterWf1.Compilers.RewriteRules.
+ Import defaults.
+
+ Module Import RewriteRules.
+ Import Rewriter.Compilers.RewriteRules.
+ Section with_cast.
+ Context {cast_outside_of_range : zrange -> Z -> Z}.
+
+ Local Notation ident_interp := (@ident.gen_interp cast_outside_of_range).
+
+ Local Lemma rlist_rect_eq {var A P ivar} Pnil Pcons ls
+ : @rlist_rect var A P ivar Pnil Pcons ls
+ = match invert_expr.reflect_list ls with
+ | Some ls
+ => Some (list_rect
+ (fun _ => _)
+ Pnil
+ (fun x xs rec => rec' <-- rec; Pcons x xs rec')
+ ls)%under_lets
+ | None => None
+ end.
+ Proof. cbv [rlist_rect Compile.option_bind' Option.bind]; reflexivity. Qed.
+
+ Local Lemma UnderLets_interp_list_rect {A P} Pnil Pcons ls
+ : UnderLets.interp
+ (@ident_interp)
+ (list_rect
+ (fun _ : list A => UnderLets.UnderLets base.type ident _ P)
+ Pnil
+ (fun x xs rec => rec' <-- rec; Pcons x xs rec')
+ ls)%under_lets
+ = list_rect
+ (fun _ => P)
+ (UnderLets.interp (@ident_interp) Pnil)
+ (fun x xs rec => UnderLets.interp (@ident_interp) (Pcons x xs rec))
+ ls.
+ Proof.
+ induction ls as [|x xs IHxs]; cbn [list_rect]; [ reflexivity | ].
+ rewrite UnderLets.interp_splice, IHxs; reflexivity.
+ Qed.
+
+ Local Lemma unfold_is_bounded_by_bool v r
+ : is_bounded_by_bool v r = true -> lower r <= v <= upper r.
+ Proof using Type.
+ cbv [is_bounded_by_bool]; intro; split_andb; Z.ltb_to_lt; split; assumption.
+ Qed.
+
+ Local Lemma unfold_is_tighter_than_bool r1 r2
+ : is_tighter_than_bool r1 r2 = true -> lower r2 <= lower r1 /\ upper r1 <= upper r2.
+ Proof using Type.
+ cbv [is_tighter_than_bool]; intro; split_andb; Z.ltb_to_lt; split; assumption.
+ Qed.
+
+ Local Notation rewrite_rules_interp_goodT := (@Compile.rewrite_rules_interp_goodT ident pattern.ident (@pattern.ident.arg_types) (@pattern.ident.to_typed) (@ident_interp)).
+
+ Local Ltac do_cbv0 :=
+ cbv [id
+ Compile.rewrite_rules_interp_goodT_curried
+ Compile.rewrite_rule_data_interp_goodT_curried Compile.under_with_unification_resultT_relation_hetero Compile.under_with_unification_resultT'_relation_hetero Compile.wf_with_unification_resultT Compile.under_type_of_list_relation_cps Compile.under_type_of_list_relation1_cps pattern.pattern_of_anypattern pattern.type_of_anypattern Compile.rew_replacement Compile.rew_should_do_again Compile.rew_with_opt Compile.rew_under_lets Compile.wf_with_unification_resultT Compile.pattern_default_interp pattern.type.under_forall_vars_relation pattern.type.under_forall_vars_relation1 Compile.deep_rewrite_ruleTP_gen Compile.with_unification_resultT' pattern.ident.arg_types pattern.type.lam_forall_vars Compilers.pattern.type.lam_forall_vars_gen Compile.pattern_default_interp' pattern.collect_vars PositiveMap.empty pattern.type.collect_vars PositiveSet.elements PositiveSet.union pattern.base.collect_vars PositiveSet.empty PositiveSet.xelements Compile.lam_type_of_list id pattern.ident.to_typed Compile.under_type_of_list_relation_cps Compile.deep_rewrite_ruleTP_gen_good_relation Compile.normalize_deep_rewrite_rule pattern.type.subst_default PositiveSet.add PositiveSet.rev PositiveSet.rev_append PositiveMap.add Compile.option_bind' Compile.wf_value Compile.value pattern.base.subst_default PositiveMap.find Compile.rewrite_ruleTP ident.smart_Literal Compile.value_interp_related].
+ Local Ltac do_cbv :=
+ do_cbv0;
+ cbv [List.map List.fold_right List.rev list_rect orb List.app].
+
+ Local Ltac start_interp_good :=
+ apply Compile.rewrite_rules_interp_goodT_by_curried;
+ do_cbv;
+ lazymatch goal with
+ | [ |- forall x p, In (@existT ?A ?P x p) ?ls -> @?Q x p ]
+ => let Q' := fresh in
+ pose Q as Q';
+ change (forall x p, In (@existT A P x p) ls -> Q' x p);
+ apply (@forall_In_existT A P Q' ls); subst Q'; cbv [projT1 projT2 id]
+ end;
+ do_cbv0;
+ repeat first [ progress intros
+ | match goal with
+ | [ |- { pf : ?x = ?x | _ } ] => (exists eq_refl)
+ | [ |- True /\ _ ] => split; [ exact I | ]
+ | [ |- _ /\ _ ] => split; [ intros; exact I | ]
+ end
+ | progress cbn [eq_rect] in * ];
+ cbn [fst snd base.interp base.base_interp type.interp projT1 projT2 UnderLets.interp expr.interp type.related ident.gen_interp UnderLets.interp_related] in *.
+
+ Ltac recurse_interp_related_step :=
+ let do_replace v :=
+ ((tryif is_evar v then fail else idtac);
+ let v' := open_constr:(_) in
+ let v'' := fresh in
+ cut (v = v'); [ generalize v; intros v'' ?; subst v'' | symmetry ]) in
+ match goal with
+ | _ => progress cbv [expr.interp_related] in *
+ | _ => progress cbn [Compile.reify_expr]
+ | [ |- context[(fst ?x, snd ?x)] ] => progress eta_expand
+ | [ |- context[match ?x with pair a b => _ end] ] => progress eta_expand
+ | [ |- expr.interp_related_gen ?ident_interp ?R ?f ?v ]
+ => do_replace v
+ | [ |- exists (fv : ?T1 -> ?T2) (ev : ?T1),
+ _ /\ _ /\ fv ev = ?x ]
+ => lazymatch T1 with Z => idtac | (Z * Z)%type => idtac end;
+ lazymatch T2 with Z => idtac | (Z * Z)%type => idtac end;
+ first [ do_replace x
+ | is_evar x; do 2 eexists; repeat apply conj; [ | | reflexivity ] ]
+ | _ => progress intros
+ | [ |- expr.interp_related_gen _ _ _ ?ev ] => is_evar ev; eassumption
+ | [ |- expr.interp_related_gen _ _ (?f @ ?x) ?ev ]
+ => is_evar ev;
+ let fh := fresh in
+ let xh := fresh in
+ set (fh := f); set (xh := x); cbn [expr.interp_related_gen]; subst fh xh;
+ do 2 eexists; repeat apply conj; [ | | reflexivity ]
+ | [ |- expr.interp_related_gen _ _ (expr.Abs ?f) _ ]
+ => let fh := fresh in set (fh := f); cbn [expr.interp_related_gen]; subst fh
+ | [ |- expr.interp_related_gen _ _ (expr.Ident ?idc) ?ev ]
+ => is_evar ev;
+ cbn [expr.interp_related_gen]; apply ident.gen_interp_Proper; reflexivity
+ | [ |- _ = _ :> ?T ]
+ => lazymatch T with
+ | BinInt.Z => idtac
+ | (BinInt.Z * BinInt.Z)%type => idtac
+ end;
+ progress cbn [ident_interp fst snd]
+ | [ |- ?x = ?y ] => tryif first [ has_evar x | has_evar y ] then fail else (progress subst)
+ | [ |- ?x = ?x ] => tryif has_evar x then fail else reflexivity
+ | [ |- ?ev = _ ] => is_evar ev; reflexivity
+ | [ |- _ = ?ev ] => is_evar ev; reflexivity
+ end.
+
+ Local Ltac interp_good_t_step_related :=
+ first [ lazymatch goal with
+ | [ |- ?x = ?x ] => reflexivity
+ | [ |- True ] => exact I
+ | [ H : ?x = true, H' : ?x = false |- _ ] => exfalso; clear -H H'; congruence
+ | [ |- ?G ] => has_evar G; reflexivity
+ | [ |- context[expr.interp_related_gen _ _ _ _] ] => reflexivity
+ | [ |- context[_ == _] ] => reflexivity
+ (*| [ |- context[(fst ?x, snd ?x)] ] => progress eta_expand
+ | [ |- context[match ?x with pair a b => _ end] ] => progress eta_expand*)
+ end
+ | progress cbn [expr.interp ident.gen_interp fst snd Compile.reify Compile.reflect Compile.wf_value' Compile.value' Option.bind UnderLets.interp list_case type.interp base.interp base.base_interp ident.to_fancy invert_Some ident.fancy.interp ident.fancy.interp_with_wordmax Compile.reify_expr bool_rect UnderLets.interp_related type.related] in *
+ | progress cbv [Compile.option_bind' respectful expr.interp_related] in *
+ | progress fold (@type.interp _ base.interp)
+ | progress fold (@base.interp)
+ | match goal with
+ | [ |- context[List.map _ (Lists.List.repeat _ _)] ] => rewrite map_repeat
+ | [ |- context[List.map _ (List.map _ _)] ] => rewrite map_map
+ | [ |- context[List.map (fun x => x) _] ] => rewrite map_id
+ | [ |- context[List.map _ (List.rev _)] ] => rewrite map_rev
+ | [ |- context[List.map _ (firstn _ _)] ] => rewrite <- firstn_map
+ | [ |- context[List.map _ (skipn _ _)] ] => rewrite <- skipn_map
+ | [ |- context[List.length (List.map _ _)] ] => rewrite map_length
+ | [ |- context[List.combine (List.map _ _) _] ] => rewrite combine_map_l
+ | [ |- context[List.combine _ (List.map _ _)] ] => rewrite combine_map_r
+ | [ |- context[expr.interp _ (reify_list _)] ] => rewrite expr.interp_reify_list
+ | [ |- context[expr.interp _ (UnderLets.to_expr ?e)] ] => rewrite UnderLets.interp_to_expr
+ | [ |- context[UnderLets.interp _ (UnderLets.splice_list _ _)] ] => rewrite UnderLets.interp_splice_list
+ | [ |- context[rlist_rect] ] => rewrite rlist_rect_eq
+ | [ |- context[UnderLets.interp _ (list_rect _ _ _ _)] ] => rewrite UnderLets_interp_list_rect
+ | [ |- context[UnderLets.interp _ (UnderLets.splice _ _)] ] => rewrite UnderLets.interp_splice
+ | [ |- context[list_rect _ _ _ (List.map _ _)] ] => rewrite list_rect_map
+ | [ |- UnderLets.interp_related _ _ (list_rect _ _ _ _) (List.app ?ls1 ?ls2) ]
+ => rewrite (eq_app_list_rect ls1 ls2)
+ | [ |- UnderLets.interp_related _ _ (list_rect _ _ _ _) (@flat_map ?A ?B ?f ?ls) ]
+ => rewrite (@eq_flat_map_list_rect A B f ls)
+ | [ |- UnderLets.interp_related _ _ (list_rect _ _ _ _) (@partition ?A ?f ?ls) ]
+ => rewrite (@eq_partition_list_rect A f ls)
+ | [ |- UnderLets.interp_related _ _ (list_rect _ _ _ _) (@List.map ?A ?B ?f ?ls) ]
+ => rewrite (@eq_map_list_rect A B f ls)
+ | [ |- UnderLets.interp_related _ _ _ (@fold_right ?A ?B ?f ?v ?ls) ]
+ => rewrite (@eq_fold_right_list_rect A B f v ls)
+ | [ |- context[expr.interp_related_gen _ _ (reify_list _)] ]
+ => rewrite expr.reify_list_interp_related_gen_iff
+ | [ H : context[expr.interp_related_gen _ _ (reify_list _)] |- _ ]
+ => rewrite expr.reify_list_interp_related_gen_iff in H
+ | [ |- context[Forall2 _ (List.map _ _) _] ] => rewrite Forall2_map_l_iff
+ | [ |- context[Forall2 _ _ (List.map _ _)] ] => rewrite Forall2_map_r_iff
+ | [ |- context[Forall2 _ (List.repeat _ _) (List.repeat _ _)] ] => rewrite Forall2_repeat_iff
+ | [ |- context[Forall2 _ (List.rev _) (List.rev _)] ] => rewrite Forall2_rev_iff
+ | [ |- context[Forall2 _ ?x ?x] ] => rewrite Forall2_Forall; cbv [Proper]
+ | [ |- context[Forall _ (seq _ _)] ] => rewrite Forall_seq
+ | [ H : Forall2 ?R ?l1 ?l2 |- Forall2 ?R (List.firstn ?n ?l1) (List.firstn ?n ?l2) ]
+ => apply Forall2_firstn, H
+ | [ H : Forall2 ?R ?l1 ?l2 |- Forall2 ?R (List.skipn ?n ?l1) (List.skipn ?n ?l2) ]
+ => apply Forall2_skipn, H
+ | [ |- Forall2 ?R (List.combine _ _) (List.combine _ _) ]
+ => eapply Forall2_combine; [ | eassumption | eassumption ]
+ | [ H : List.Forall2 _ ?l1 ?l2, H' : ?R ?v1 ?v2 |- ?R (nth_default ?v1 ?l1 ?x) (nth_default ?v2 ?l2 ?x) ]
+ => apply Forall2_forall_iff''; split; assumption
+ | [ H : List.Forall2 _ ?x ?y |- List.length ?x = List.length ?y ]
+ => eapply eq_length_Forall2, H
+ | [ |- exists fv xv, _ /\ _ /\ fv xv = ?f ?x ]
+ => exists f, x; repeat apply conj; [ solve [ repeat interp_good_t_step_related ] | | reflexivity ]
+ | [ |- _ /\ ?x = ?x ] => split; [ | reflexivity ]
+ | [ |- UnderLets.interp_related
+ ?ident_interp ?R
+ (list_rect
+ (fun _ : list (expr ?A) => UnderLets.UnderLets _ _ _ ?B)
+ ?Pnil
+ ?Pcons
+ ?ls)
+ (list_rect
+ (fun _ : list _ => ?B')
+ ?Pnil'
+ ?Pcons'
+ ?ls') ]
+ => apply (@UnderLets.list_rect_interp_related _ _ _ ident_interp A B Pnil Pcons ls B' Pnil' Pcons' ls' R)
+ | [ |- UnderLets.interp_related _ _ (nat_rect _ _ _ _) (nat_rect _ _ _ _) ]
+ => apply UnderLets.nat_rect_interp_related
+ | [ |- UnderLets.interp_related _ _ (nat_rect _ _ _ _ _) (nat_rect _ _ _ _ _) ]
+ => eapply UnderLets.nat_rect_arrow_interp_related; [ .. | eassumption ]
+ | [ |- UnderLets.interp_related _ _ (UnderLets.splice _ _) _ ]
+ => rewrite UnderLets.splice_interp_related_iff
+ | [ |- UnderLets.interp_related ?ident_interp _ (UnderLets.splice_list _ _) _ ]
+ => apply UnderLets.splice_list_interp_related_of_ex with (RA:=expr.interp_related ident_interp); exists (fun x => x); eexists; repeat apply conj; [ | | reflexivity ]
+ | [ H : UnderLets.interp_related _ _ ?e ?v1 |- UnderLets.interp_related _ _ ?e ?f ]
+ => let f := match (eval pattern v1 in f) with ?f _ => f end in
+ eapply (@UnderLets.interp_related_Proper_impl_same_UnderLets _ _ _ _ _ _ _ _ _ e v1 f); [ | exact H ]; cbv beta
+ | [ H : forall x y, ?R x y -> UnderLets.interp_related _ _ (?e x) (?v1 y) |- UnderLets.interp_related _ _ (?e ?xv) ?f ]
+ => lazymatch f with
+ | context[v1 ?yv]
+ => let f := match (eval pattern (v1 yv) in f) with ?f _ => f end in
+ eapply (@UnderLets.interp_related_Proper_impl_same_UnderLets _ _ _ _ _ _ _ _ _ (e xv) (v1 yv) f); [ | eapply H; assumption ]
+ end
+ | [ |- expr.interp_related_gen
+ _ _
+ (#(ident.prod_rect) @ ?f @ ?e)%expr
+ match ?e' with pair a b => @?f' a b end ]
+ => let fh := fresh in
+ let eh := fresh in
+ set (fh := f); set (eh := e); cbn [expr.interp_related_gen]; subst fh eh;
+ exists (fun ev => match ev with pair a b => f' a b end), e';
+ repeat apply conj;
+ [ | assumption | reflexivity ];
+ exists (fun fv ev => match ev with pair a b => fv a b end), f';
+ repeat apply conj;
+ [ cbn [type.interp type.related ident_interp]; cbv [respectful]; intros; subst; eta_expand; auto | | reflexivity ]
+ | [ |- expr.interp_related_gen
+ _ _
+ (#(ident.bool_rect) @ ?t @ ?f @ ?b)%expr
+ (bool_rect ?P ?t' ?f' ?b') ]
+ => let th := fresh in
+ let fh := fresh in
+ let bh := fresh in
+ set (th := t); set (fh := f); set (bh := b); cbn [expr.interp_related_gen]; subst th fh bh;
+ unshelve
+ ((exists (bool_rect P t' f'), b'); repeat apply conj;
+ [ | shelve | reflexivity ];
+ (exists (fun fv => bool_rect P t' (fv tt)), (fun _ => f')); repeat apply conj;
+ [ | shelve | reflexivity ];
+ (exists (fun tv fv => bool_rect P (tv tt) (fv tt)), (fun _ => t')); repeat apply conj;
+ [ | shelve | reflexivity ])
+ | [ |- @expr.interp_related_gen _ _ _ _ _ _ (type.base ?t) _ _ ]
+ => lazymatch t with
+ | base.type.type_base base.type.Z => idtac
+ | base.type.prod (base.type.type_base base.type.Z) (base.type.type_base base.type.Z) => idtac
+ end;
+ progress repeat recurse_interp_related_step
+ | [ |- exists (fv : ?T1 -> ?T2) (ev : ?T1),
+ _ /\ _ /\ fv ev = ?x ]
+ => lazymatch T1 with Z => idtac | (Z * Z)%type => idtac end;
+ lazymatch T2 with Z => idtac | (Z * Z)%type => idtac end;
+ progress repeat recurse_interp_related_step
+ | [ |- expr.interp_related_gen _ _ (expr.Abs ?f) _ ]
+ => let fh := fresh in set (fh := f); cbn [expr.interp_related_gen]; subst fh
+ | [ H : expr.interp_related_gen _ _ ?x ?x' |- expr.interp_related_gen _ _ (?f @ ?x) (?f' ?x') ]
+ => let fh := fresh in
+ let xh := fresh in
+ set (fh := f); set (xh := x); cbn [expr.interp_related_gen]; subst fh xh;
+ exists f', x'; repeat apply conj;
+ [ | exact H | reflexivity ]
+ | [ |- List.Forall2 _ (update_nth _ _ _) (update_nth _ _ _) ] => apply Forall2_update_nth
+ | [ H : zrange * zrange |- _ ] => destruct H
+ end
+ | progress intros
+ | progress subst
+ | assumption
+ | progress inversion_option
+ | progress destruct_head'_and
+ | progress split_andb
+ | match goal with
+ | [ |- Lists.List.repeat _ _ = Lists.List.repeat _ _ ] => apply f_equal2
+ | [ |- firstn _ _ = firstn _ _ ] => apply f_equal2
+ | [ |- skipn _ _ = skipn _ _ ] => apply f_equal2
+ | [ |- rev _ = rev _ ] => apply f_equal
+ | [ |- List.app ?l1 ?l2 = List.app ?l1' ?l2 ] => apply f_equal2
+ | [ |- List.app ?l1 ?l2 = List.app ?l1 ?l2' ] => apply f_equal2
+ | [ |- cons _ _ = cons _ _ ] => apply f_equal2
+ | [ |- list_rect _ ?Pnil ?Pcons ?ls = list_rect _ ?Pnil ?Pcons' ?ls ]
+ => apply list_rect_Proper; [ reflexivity | repeat intro | reflexivity ]
+ | [ |- bool_rect _ ?x ?y ?b = bool_rect _ ?x ?y ?b' ]
+ => apply f_equal3; [ reflexivity | reflexivity | solve [ repeat interp_good_t_step_related ] ]
+ | [ H : expr.wf _ ?v1 ?v2 |- expr.interp _ ?v1 = expr.interp _ ?v2 ]
+ => apply (expr.wf_interp_Proper _ _ _ H ltac:(assumption))
+ | [ |- ?R (?f (?g (if ?b then ?x else ?y))) (bool_rect ?A ?B ?C ?D) ]
+ => rewrite <- (@Bool.pull_bool_if _ _ g b), <- (@Bool.pull_bool_if _ _ f b);
+ change (R (bool_rect _ (f (g x)) (f (g y)) b) (bool_rect A B C D))
+ | [ |- context[invert_expr.reflect_list ?ls] ]
+ => destruct (invert_expr.reflect_list ls) eqn:?; expr.invert_subst
+ | [ |- ?f (nth_default _ _ _) = _ ]
+ => rewrite <- (@map_nth_default_always _ _ f)
+ | [ |- map ?f ?ls = map ?g ?ls ] => apply map_ext_in
+ | [ |- List.map _ (update_nth _ _ _) = update_nth _ _ _ ] => apply map_update_nth_ext
+ | [ H : ?x = ?x -> _ |- _ ] => specialize (H eq_refl)
+ | [ H : forall v : unit, _ |- _ ] => specialize (H tt)
+ | [ H : _ = expr.interp ?ii ?v |- _ ] => is_var v; generalize dependent (expr.interp ii v); clear v
+ | [ |- bool_rect _ _ _ ?b = bool_rect _ _ _ ?b ]
+ => is_var b; destruct b; cbv [bool_rect]
+ | [ H : (forall x y, _ -> expr.interp _ (UnderLets.interp _ (?f1 x)) = expr.interp _ (UnderLets.interp _ (?f2 y)))
+ |- expr.interp _ (UnderLets.interp _ (?f1 ?x1)) = expr.interp _ (UnderLets.interp _ (?f2 ?x2)) ]
+ => apply H
+ | [ H : (forall x y, _ -> forall x' y', _ -> expr.interp _ (UnderLets.interp _ (?f1 x x')) = expr.interp _ (UnderLets.interp _ (?f2 y y')))
+ |- expr.interp _ (UnderLets.interp _ (?f1 ?x1 ?y1)) = expr.interp _ (UnderLets.interp _ (?f2 ?x2 ?y2)) ]
+ => apply H
+ | [ |- context G[rwhen ?v ?b] ]
+ => let c := constr:(rwhen v b) in
+ let c := (eval cbv [rwhen] in c) in
+ let G' := context G[c] in
+ change G';
+ destruct b eqn:?
+ | [ |- context G[rwhenl ?v ?b] ]
+ => let c := constr:(rwhenl v b) in
+ let c := (eval cbv [rwhenl] in c) in
+ let G' := context G[c] in
+ change G';
+ destruct b eqn:?
+ | [ H : negb ?b = true |- _ ] => rewrite (@Bool.negb_true_iff b) in H
+ | [ |- context[expr.interp ?ii ?v] ]
+ => is_var v; generalize dependent (expr.interp ii v); clear v; intro v
+ | [ |- context[Z.mul_split ?a ?b ?c] ]
+ => rewrite (surjective_pairing (Z.mul_split a b c)), Z.mul_split_div, Z.mul_split_mod
+ | [ |- context[Z.zselect] ] => rewrite Z.zselect_correct
+ | [ |- context[Z.sub_get_borrow_full ?a ?b ?c] ]
+ => rewrite (surjective_pairing (Z.sub_get_borrow_full a b c)), Z.sub_get_borrow_full_div, Z.sub_get_borrow_full_mod
+ | [ |- context[Z.sub_with_get_borrow_full ?a ?b ?c ?d] ]
+ => rewrite (surjective_pairing (Z.sub_with_get_borrow_full a b c d)), Z.sub_with_get_borrow_full_div, Z.sub_with_get_borrow_full_mod
+ | [ |- context[Z.add_get_carry_full ?a ?b ?c] ]
+ => rewrite (surjective_pairing (Z.add_get_carry_full a b c)), Z.add_get_carry_full_div, Z.add_get_carry_full_mod
+ | [ |- context[Z.add_with_get_carry_full ?a ?b ?c ?d] ]
+ => rewrite (surjective_pairing (Z.add_with_get_carry_full a b c d)), Z.add_with_get_carry_full_div, Z.add_with_get_carry_full_mod
+ | [ |- pair _ _ = pair _ _ ] => apply f_equal2
+ | [ |- ?a mod ?b = ?a' mod ?b ] => apply f_equal2; lia
+ | [ |- ?a / ?b = ?a' / ?b ] => apply f_equal2; lia
+ | [ |- Z.opp _ = Z.opp _ ] => apply f_equal
+ end
+ | match goal with
+ | [ |- context[?f (list_rect _ _ _ _)] ]
+ => match f with
+ | expr.interp _ => idtac
+ | Compile.reify_expr => idtac
+ end;
+ erewrite (@push_f_list_rect _ _ f)
+ by (intros;
+ repeat first [ progress cbn [expr.interp ident.gen_interp UnderLets.interp Compile.reify_expr]
+ | rewrite UnderLets.interp_splice ];
+ match goal with
+ | [ |- ?LHS = ?Pcons' ?x ?xs ?rec ]
+ => let LHS' := match (eval pattern x, xs, rec in LHS) with ?f _ _ _ => f end in
+ unify Pcons' LHS'; reflexivity
+ end)
+ | [ |- context[?f (nat_rect _ _ _ _)] ]
+ => match f with
+ | expr.interp _ => idtac
+ | UnderLets.interp _ => idtac
+ | Compile.reify_expr => idtac
+ end;
+ erewrite (@push_f_nat_rect _ _ f)
+ by (intros;
+ repeat first [ progress cbn [expr.interp ident.gen_interp UnderLets.interp Compile.reify_expr]
+ | rewrite UnderLets.interp_splice ];
+ match goal with
+ | [ |- ?LHS = ?PS' ?x ?rec ]
+ => let LHS' := match (eval pattern x, rec in LHS) with ?f _ _ => f end in
+ unify PS' LHS'; reflexivity
+ end)
+ | [ |- ?f (list_rect _ _ _ _) = list_rect _ _ _ _ ]
+ => match f with
+ | expr.interp _ => idtac
+ | Compile.reify_expr => idtac
+ end;
+ erewrite (@push_f_list_rect _ _ f);
+ [ apply list_rect_Proper; repeat intro; try reflexivity | ]
+ | [ |- ?f (nat_rect _ _ _ _) = nat_rect _ _ _ _ ]
+ => match f with
+ | expr.interp _ => idtac
+ | UnderLets.interp _ => idtac
+ | Compile.reify_expr => idtac
+ end;
+ erewrite (@push_f_nat_rect _ _ f);
+ [ apply nat_rect_Proper_nondep; repeat intro; try reflexivity | ]
+ end
+ | break_innermost_match_step
+ | break_innermost_match_hyps_step
+ | progress destruct_head'_or
+ | progress cbn [expr.interp_related_gen] in *
+ | match goal with
+ | [ H : context[expr.interp _ (UnderLets.interp _ (?f _ _ _))]
+ |- expr.interp _ (UnderLets.interp _ (?f _ _ _)) = _ ]
+ => apply H
+ | [ H : forall x1 x2, ?R1 x1 x2 -> ?R2 (?f1 x1) (?f2 x2) |- ?R2 (?f1 _) (?f2 _) ]
+ => apply H
+ | [ H : forall x1 x2, ?R1 x1 x2 -> forall y1 y2, ?R2 y1 y2 -> ?R3 (?f1 x1 y1) (?f2 x2 y2) |- ?R3 (?f1 _ _) (?f2 _ _) ]
+ => apply H
+ | [ H : forall x x', ?Rx x x' -> forall y y', _ -> forall z z', ?Rz z z' -> ?R (?f x y z) (?f' x' y' z') |- ?R (?f _ _ _) (?f' _ _ _) ]
+ => apply H; clear H
+ end
+ | progress cbv [Option.bind] in *
+ | match goal with
+ | [ H : expr.interp_related_gen _ _ ?e ?v |- _ ] => is_var e; clear H e
+ end ].
+
+ Local Ltac interp_good_t_step_arith :=
+ first [ lazymatch goal with
+ | [ |- ?x = ?x ] => reflexivity
+ | [ |- True ] => exact I
+ | [ H : ?x = true, H' : ?x = false |- _ ] => exfalso; clear -H H'; congruence
+ end
+ | match goal with
+ | [ H : context[ZRange.normalize (ZRange.normalize _)] |- _ ]
+ => rewrite ZRange.normalize_idempotent in H
+ | [ |- context[ZRange.normalize (ZRange.normalize _)] ]
+ => rewrite ZRange.normalize_idempotent
+ | [ |- context[ident.cast (ZRange.normalize ?r)] ]
+ => rewrite ident.cast_normalize
+ | [ H : context[ident.cast (ZRange.normalize ?r)] |- _ ]
+ => rewrite ident.cast_normalize in H
+ | [ H : ?T, H' : ?T |- _ ] => clear H'
+ | [ H : context[is_bounded_by_bool _ (ZRange.normalize (-_))] |- _ ]
+ => rewrite ZRange.is_bounded_by_bool_move_opp_normalize in H
+ | [ |- context[is_bounded_by_bool _ (ZRange.normalize (-_))] ]
+ => rewrite ZRange.is_bounded_by_bool_move_opp_normalize
+ | [ H : is_bounded_by_bool ?v (ZRange.normalize ?r) = true |- context[ident.cast _ ?r ?v] ]
+ => rewrite (@ident.cast_in_normalized_bounds _ r v) by exact H
+ | [ H : is_bounded_by_bool ?v (ZRange.normalize ?r) = true |- context[ident.cast _ (-?r) (-?v)] ]
+ => rewrite (@ident.cast_in_normalized_bounds _ (-r) (-v));
+ [ | clear -H ]
+ | [ |- context[ident.cast _ ?r (-ident.cast _ (-?r) ?v)] ]
+ => rewrite (ident.cast_in_normalized_bounds r (-ident.cast _ (-r) v))
+ by (rewrite <- ZRange.is_bounded_by_bool_move_opp_normalize; apply ident.cast_always_bounded)
+ | [ |- context[ident.cast _ ?r (ident.cast _ ?r _)] ]
+ => rewrite (@ident.cast_idempotent _ _ r)
+ | [ H : is_bounded_by_bool _ ?r = true |- _]
+ => is_var r; unique pose proof (ZRange.is_bounded_by_normalize _ _ H)
+
+ end
+ | progress intros
+ | progress subst
+ | assumption
+ | progress destruct_head'_and
+ | progress Z.ltb_to_lt
+ | progress split_andb
+ | match goal with
+ | [ |- ?a mod ?b = ?a' mod ?b ] => apply f_equal2; lia
+ | [ |- ?a / ?b = ?a' / ?b ] => apply f_equal2; lia
+ | [ |- Z.opp _ = Z.opp _ ] => apply f_equal
+ end
+ | break_innermost_match_step
+ | break_innermost_match_hyps_step
+ | progress destruct_head'_or
+ | match goal with
+ | [ |- context[-ident.cast _ (-?r) (-?v)] ] => rewrite (ident.cast_opp' r v)
+ | [ |- context[ident.cast ?coor ?r ?v] ]
+ => is_var v;
+ pose proof (@ident.cast_always_bounded coor r v);
+ generalize dependent (ident.cast coor r v); clear v; intro v; intros
+ | [ |- context[ident.cast ?coor ?r ?v] ]
+ => is_var v; is_var coor;
+ pose proof (@ident.cast_cases coor r v);
+ generalize dependent (ident.cast coor r v); intros
+ | [ H : is_bounded_by_bool ?v ?r = true, H' : is_tighter_than_bool ?r ?r' = true |- _ ]
+ => unique assert (is_bounded_by_bool v r' = true) by (eauto 2 using ZRange.is_bounded_by_of_is_tighter_than)
+ | [ H : is_bounded_by_bool (-?v) ?r = true, H' : (-?r <=? ?r')%zrange = true |- _ ]
+ => unique assert (is_bounded_by_bool v r' = true)
+ by (apply (@ZRange.is_bounded_by_of_is_tighter_than _ _ H');
+ rewrite <- ZRange.is_bounded_by_bool_opp, ZRange.opp_involutive; exact H)
+ | [ H : is_bounded_by_bool ?v (-?r) = true |- _ ]
+ => is_var v;
+ unique assert (is_bounded_by_bool (-v) r = true)
+ by now rewrite <- ZRange.is_bounded_by_bool_move_opp_normalize, ZRange.normalize_opp
+ | [ H : is_bounded_by_bool ?x r[0~>?v-1] = true |- _ ]
+ => progress (try unique assert (0 <= x); try unique assert (x <= v - 1));
+ [ clear -H; cbv [is_bounded_by_bool] in H; cbn [lower upper] in H; Bool.split_andb; Z.ltb_to_lt; lia..
+ | ]
+ end
+ | progress cbn [expr.interp_related_gen] in *
+ | match goal with
+ | [ |- context[Z.shiftl] ] => rewrite Z.shiftl_mul_pow2 by auto with zarith
+ | [ |- context[Z.shiftr] ] => rewrite Z.shiftr_div_pow2 by auto with zarith
+ | [ |- context[Z.shiftl _ (-_)] ] => rewrite Z.shiftl_opp_r
+ | [ |- context[Z.land _ (Z.ones _)] ] => rewrite Z.land_ones by auto using Z.log2_nonneg
+ | [ |- context[- - _] ] => rewrite Z.opp_involutive
+ | [ H : ?x = 2^Z.log2 ?x |- context[2^Z.log2 ?x] ] => rewrite <- H
+ | [ H : ?x = 2^?n |- context[Z.land _ (?x - 1)] ]
+ => rewrite !Z.sub_1_r, H, <- Z.ones_equiv, Z.land_ones by auto with zarith
+ | [ |- _ = _ :> BinInt.Z ] => progress normalize_commutative_identifier Z.land Z.land_comm
+ | [ H : ?x = ?y, H' : ?x <> ?y |- _ ] => exfalso; apply H', H
+ | [ H : ?x = 2^Z.log2_up ?x - 1 |- context[2^Z.log2_up ?x - 1] ] => rewrite <- H
+ | [ H : ?x = 2^Z.log2 ?x, H' : context[2^Z.log2 ?x] |- _ = _ :> BinInt.Z ]
+ => rewrite <- H in H'
+ | [ |- _ = _ :> BinInt.Z ] => progress autorewrite with zsimplify_const
+ | [ H : 0 <= ?x, H' : ?x <= ?r - 1 |- context[?x mod ?r] ]
+ => rewrite (Z.mod_small x r) by (clear -H H'; lia)
+ | [ H : 0 <= ?x, H' : ?x <= ?y - 1 |- context[?x / ?y] ]
+ => rewrite (Z.div_small x y) by (clear -H H'; lia)
+ | [ H : ?x = 2^Z.log2 ?x |- _ ]
+ => unique assert (0 <= x) by (rewrite H; auto with zarith)
+ | [ |- _ mod ?x = _ mod ?x ]
+ => progress (push_Zmod; pull_Zmod)
+ | [ |- ?f (_ mod ?x) = ?f (_ mod ?x) ]
+ => progress (push_Zmod; pull_Zmod)
+ | [ |- _ mod ?x = _ mod ?x ]
+ => apply f_equal2; (lia + nia)
+ | _ => rewrite !Z.shiftl_mul_pow2 in * by auto using Z.log2_nonneg
+ | _ => rewrite !Z.land_ones in * by auto using Z.log2_nonneg
+ | H : ?x mod ?b * ?y <= _
+ |- context [ (?x * ?y) mod ?b ] =>
+ rewrite (PullPush.Z.mul_mod_l x y b);
+ rewrite (Z.mod_small (x mod b * y) b) by omega
+ | [ |- context[_ - ?x + ?x] ] => rewrite !Z.sub_add
+ | [ |- context[_ mod (2^_) * 2^_] ] => rewrite <- !Z.mul_mod_distr_r_full
+ | [ |- context[Z.land _ (Z.ones _)] ] => rewrite !Z.land_ones by lia
+ | [ |- context[2^?a * 2^?b] ] => rewrite <- !Z.pow_add_r by lia
+ | [ |- context[-?x + ?y] ] => rewrite !Z.add_opp_l
+ | [ |- context[?n + - ?m] ] => rewrite !Z.add_opp_r
+ | [ |- context[?n - - ?m] ] => rewrite !Z.sub_opp_r
+ | [ |- context[Zpos ?p * ?x / Zpos ?p] ]
+ => rewrite (@Z.div_mul' x (Zpos p)) in * by (clear; lia)
+ | [ H : context[Zpos ?p * ?x / Zpos ?p] |- _ ]
+ => rewrite (@Z.div_mul' x (Zpos p)) in * by (clear; lia)
+ | [ |- ?f (?a mod ?r) = ?f (?b mod ?r) ] => apply f_equal; apply f_equal2; lia
+ | [ |- context[-?a - ?b + ?c] ] => replace (-a - b + c) with (c - a - b) by (clear; lia)
+ | [ |- context[?x - ?y + ?z] ]
+ => lazymatch goal with
+ | [ |- context[z - y + x] ]
+ => progress replace (z - y + x) with (x - y + z) by (clear; lia)
+ end
+ | [ |- context[?x - ?y - ?z] ]
+ => lazymatch goal with
+ | [ |- context[x - z - y] ]
+ => progress replace (x - z - y) with (x - y - z) by (clear; lia)
+ end
+ | [ |- context[?x + ?y] ]
+ => lazymatch goal with
+ | [ |- context[y + x] ]
+ => progress replace (y + x) with (x + y) by (clear; lia)
+ end
+ | [ |- context[?x + ?y + ?z] ]
+ => lazymatch goal with
+ | [ |- context[x + z + y] ]
+ => progress replace (x + z + y) with (x + y + z) by (clear; lia)
+ | [ |- context[z + x + y] ]
+ => progress replace (z + x + y) with (x + y + z) by (clear; lia)
+ | [ |- context[z + y + x] ]
+ => progress replace (z + y + x) with (x + y + z) by (clear; lia)
+ | [ |- context[y + x + z] ]
+ => progress replace (y + x + z) with (x + y + z) by (clear; lia)
+ | [ |- context[y + z + x] ]
+ => progress replace (y + z + x) with (x + y + z) by (clear; lia)
+ end
+ | [ |- - ident.cast _ (-?r) (- (?x / ?y)) = ident.cast _ ?r (?x' / ?y) ]
+ => tryif constr_eq x x' then fail else replace x with x' by lia
+ | [ |- _ = _ :> BinInt.Z ] => progress autorewrite with zsimplify_fast
+ end ].
+
+ Local Ltac remove_casts :=
+ repeat match goal with
+ | [ |- context[ident.cast _ ?r (ident.cast _ ?r _)] ]
+ => rewrite ident.cast_idempotent
+ | [ H : context[ident.cast _ ?r (ident.cast _ ?r _)] |- _ ]
+ => rewrite ident.cast_idempotent in H
+ | [ |- context[ident.cast ?coor ?r ?v] ]
+ => is_var v;
+ pose proof (@ident.cast_always_bounded coor r v);
+ generalize dependent (ident.cast coor r v);
+ clear v; intro v; intros
+ | [ H : context[ident.cast ?coor ?r ?v] |- _ ]
+ => is_var v;
+ pose proof (@ident.cast_always_bounded coor r v);
+ generalize dependent (ident.cast coor r v);
+ clear v; intro v; intros
+ | [ H : context[ZRange.constant ?v] |- _ ] => unique pose proof (ZRange.is_bounded_by_bool_normalize_constant v)
+ | [ H : is_tighter_than_bool (?ZRf ?r1 ?r2) (ZRange.normalize ?rs) = true,
+ H1 : is_bounded_by_bool ?v1 ?r1 = true,
+ H2 : is_bounded_by_bool ?v2 ?r2 = true
+ |- _ ]
+ => let cst := multimatch goal with
+ | [ |- context[ident.cast ?coor rs (?Zf v1 v2)] ] => constr:(ident.cast coor rs (Zf v1 v2))
+ | [ H : context[ident.cast ?coor rs (?Zf v1 v2)] |- _ ] => constr:(ident.cast coor rs (Zf v1 v2))
+ end in
+ lazymatch cst with
+ | ident.cast ?coor rs (?Zf v1 v2)
+ => let lem := lazymatch constr:((ZRf, Zf)%core) with
+ | (ZRange.shiftl, Z.shiftl)%core => constr:(@ZRange.is_bounded_by_bool_shiftl v1 r1 v2 r2 H1 H2)
+ | (ZRange.shiftr, Z.shiftr)%core => constr:(@ZRange.is_bounded_by_bool_shiftr v1 r1 v2 r2 H1 H2)
+ | (ZRange.land, Z.land)%core => constr:(@ZRange.is_bounded_by_bool_land v1 r1 v2 r2 H1 H2)
+ end in
+ try unique pose proof (@ZRange.is_bounded_by_of_is_tighter_than _ _ H _ lem);
+ clear H;
+ rewrite (@ident.cast_in_normalized_bounds coor rs (Zf v1 v2)) in * by assumption
+ end
+ | [ H : is_tighter_than_bool (?ZRf ?r1) (ZRange.normalize ?rs) = true,
+ H1 : is_bounded_by_bool ?v1 ?r1 = true
+ |- _ ]
+ => let cst := multimatch goal with
+ | [ |- context[ident.cast ?coor rs (?Zf v1)] ] => constr:(ident.cast coor rs (Zf v1))
+ | [ H : context[ident.cast ?coor rs (?Zf v1)] |- _ ] => constr:(ident.cast coor rs (Zf v1))
+ end in
+ lazymatch cst with
+ | ident.cast ?coor rs (?Zf v1)
+ => let lem := lazymatch constr:((ZRf, Zf)%core) with
+ | (ZRange.cc_m ?s, Z.cc_m ?s)%core => constr:(@ZRange.is_bounded_by_bool_cc_m s v1 r1 H1)
+ end in
+ try unique pose proof (@ZRange.is_bounded_by_of_is_tighter_than _ _ H _ lem);
+ clear H;
+ rewrite (@ident.cast_in_normalized_bounds coor rs (Zf v1)) in * by assumption
+ end
+ | [ H : is_bounded_by_bool ?v (ZRange.normalize ?r) |- context[ident.cast ?coor ?r ?v] ]
+ => rewrite (@ident.cast_in_normalized_bounds coor r v) in * by assumption
+ | [ H : is_bounded_by_bool ?v (ZRange.normalize ?r), H' : context[ident.cast ?coor ?r ?v] |- _ ]
+ => rewrite (@ident.cast_in_normalized_bounds coor r v) in * by assumption
+ | [ H : is_bounded_by_bool ?v ?r = true,
+ H' : is_tighter_than_bool ?r r[0~>?x-1]%zrange = true,
+ H'' : Z.eqb ?x ?m = true
+ |- context[?v mod ?m] ]
+ => unique assert (is_bounded_by_bool v r[0~>x-1] = true)
+ by (eapply ZRange.is_bounded_by_of_is_tighter_than; eassumption)
+ end.
+
+ Local Ltac unfold_cast_lemmas :=
+ repeat match goal with
+ | [ H : context[ZRange.normalize (ZRange.constant _)] |- _ ]
+ => rewrite ZRange.normalize_constant in H
+ | [ H : is_bounded_by_bool _ (ZRange.normalize ?r) = true |- _ ]
+ => is_var r; generalize dependent (ZRange.normalize r); clear r; intro r; intros
+ | [ H : is_bounded_by_bool ?x (ZRange.constant ?x) = true |- _ ]
+ => clear H
+ | [ H : is_bounded_by_bool ?x ?r = true |- _ ]
+ => is_var r; apply unfold_is_bounded_by_bool in H
+ | [ H : is_bounded_by_bool ?x r[_~>_] = true |- _ ]
+ => apply unfold_is_bounded_by_bool in H
+ | [ H : is_tighter_than_bool r[_~>_] r[_~>_] = true |- _ ]
+ => apply unfold_is_tighter_than_bool in H
+ | _ => progress cbn [lower upper] in *
+ | [ H : context[lower ?r] |- _ ]
+ => is_var r; let l := fresh "l" in let u := fresh "u" in destruct r as [l u]
+ | [ H : context[upper ?r] |- _ ]
+ => is_var r; let l := fresh "l" in let u := fresh "u" in destruct r as [l u]
+ | _ => progress Z.ltb_to_lt
+ end.
+
+ Local Ltac systematically_handle_casts :=
+ remove_casts; unfold_cast_lemmas.
+
+ Local Ltac fin_with_nia :=
+ lazymatch goal with
+ | [ |- ident.cast _ ?r _ = ident.cast _ ?r _ ] => apply f_equal; Z.div_mod_to_quot_rem; nia
+ | _ => reflexivity || (Z.div_mod_to_quot_rem; (lia + nia))
+ end.
+
+ Lemma nbe_rewrite_rules_interp_good
+ : rewrite_rules_interp_goodT nbe_rewrite_rules.
+ Proof using Type.
+ Time start_interp_good.
+ Time all: try solve [ repeat interp_good_t_step_related ].
+ Qed.
+
+ Lemma arith_rewrite_rules_interp_good max_const
+ : rewrite_rules_interp_goodT (arith_rewrite_rules max_const).
+ Proof using Type.
+ Time start_interp_good.
+ Time all: try solve [ repeat interp_good_t_step_related; repeat interp_good_t_step_arith; fin_with_nia ].
+ Qed.
+
+ Lemma arith_with_casts_rewrite_rules_interp_good
+ : rewrite_rules_interp_goodT arith_with_casts_rewrite_rules.
+ Proof using Type.
+ Time start_interp_good.
+ Time all: try solve [ repeat interp_good_t_step_related; repeat interp_good_t_step_arith; fin_with_nia ].
+ Qed.
+
+ Local Ltac fancy_local_t :=
+ repeat match goal with
+ | [ H : forall s v v', ?invert_low s v = Some v' -> v = _,
+ H' : ?invert_low _ _ = Some _ |- _ ] => apply H in H'
+ | [ H : forall s v v', ?invert_low s v = Some v' -> v = _ |- _ ]
+ => clear invert_low H
+ end.
+ Local Ltac more_fancy_arith_t := repeat autorewrite with zsimplify in *.
+
+ Lemma fancy_rewrite_rules_interp_good
+ (invert_low invert_high : Z -> Z -> option Z)
+ (Hlow : forall s v v', invert_low s v = Some v' -> v = Z.land v' (2^(s/2)-1))
+ (Hhigh : forall s v v', invert_high s v = Some v' -> v = Z.shiftr v' (s/2))
+ : rewrite_rules_interp_goodT fancy_rewrite_rules.
+ Proof using Type.
+ Time start_interp_good.
+ Time all: try solve [ repeat interp_good_t_step_related ].
+ Qed.
+
+ Lemma fancy_with_casts_rewrite_rules_interp_good
+ (invert_low invert_high : Z -> Z -> option Z)
+ (value_range flag_range : zrange)
+ (Hlow : forall s v v', invert_low s v = Some v' -> v = Z.land v' (2^(s/2)-1))
+ (Hhigh : forall s v v', invert_high s v = Some v' -> v = Z.shiftr v' (s/2))
+ : rewrite_rules_interp_goodT (fancy_with_casts_rewrite_rules invert_low invert_high value_range flag_range).
+ Proof using Type.
+ Time start_interp_good. (* Finished transaction in 1.206 secs (1.207u,0.s) (successful) *)
+ Set Ltac Profiling.
+ Reset Ltac Profile.
+ Time all: repeat interp_good_t_step_related. (* Finished transaction in 13.259 secs (13.128u,0.132s) (successful) *)
+ Reset Ltac Profile.
+ Time all: fancy_local_t. (* Finished transaction in 0.051 secs (0.052u,0.s) (successful) *)
+ Time all: systematically_handle_casts. (* Finished transaction in 2.004 secs (1.952u,0.052s) (successful) *)
+ Time all: try solve [ repeat interp_good_t_step_arith ]. (* Finished transaction in 44.411 secs (44.004u,0.411s) (successful) *)
+ Admitted.
+ End with_cast.
+ End RewriteRules.
+End Compilers.