From 067d1f14b03d83dcb1c0a60808919ceff6205836 Mon Sep 17 00:00:00 2001 From: Jason Gross Date: Wed, 3 Apr 2019 16:43:48 -0400 Subject: Automate more of the rewriter reification, proof Now we actually make use of the rewrite-rule-specific proofs, rather than duplicating them inline. We now support reifying `ident.gets_inlined` to `SubstVarLike.is_var_fst_snd_pair_opp_cast`. We also now fix a bug where we previously incorrectly substituted context variables when reifying side conditions (needed for correct reification of split-mul things, coming up soon). Things are unfortunately a bit slow. I'm not sure what's up with my proof of `reflect_ident_iota_interp_related`; it seems more complicated than it should be (maybe partly due to funext concerns). Next up is to split out the rewrite rule generation bits into separate files and have a single tactic that builds the entire package for us (in prep for making the rewriter builder a vernacular). After that I want to more fully parameterize things over `ident`, and then also over the non-container base-types (which will require some reworking of how we handle special identifiers). Additionally, I want to make the rewrite rule definitions not depend on Language.v. After | File Name | Before || Change | % Change ----------------------------------------------------------------------------------------------- 20m50.18s | Total | 23m01.24s || -2m11.06s | -9.48% ----------------------------------------------------------------------------------------------- 0m27.24s | RewriterRulesGood.vo | 1m34.94s || -1m07.70s | -71.30% 0m54.89s | RewriterRulesInterpGood.vo | 1m57.72s || -1m02.82s | -53.37% 1m37.88s | RewriterWf2.vo | 1m47.69s || -0m09.81s | -9.10% 1m16.71s | Rewriter.vo | 1m12.61s || +0m04.10s | +5.64% 0m37.14s | ExtractionHaskell/unsaturated_solinas | 0m40.06s || -0m02.92s | -7.28% 0m36.10s | RewriterWf1.vo | 0m33.12s || +0m02.98s | +8.99% 0m18.31s | p256_32.c | 0m20.70s || -0m02.39s | -11.54% 1m43.31s | Fancy/Barrett256.vo | 1m42.09s || +0m01.21s | +1.19% 0m32.46s | ExtractionHaskell/saturated_solinas | 0m30.92s || +0m01.53s | +4.98% 0m23.44s | ExtractionOCaml/word_by_word_montgomery | 0m22.26s || +0m01.17s | +5.30% 0m12.17s | ExtractionOCaml/word_by_word_montgomery.ml | 0m13.58s || -0m01.41s | -10.38% 0m10.04s | p224_32.c | 0m08.20s || +0m01.83s | +22.43% 0m09.98s | ExtractionOCaml/saturated_solinas | 0m11.67s || -0m01.68s | -14.48% 0m07.80s | ExtractionOCaml/saturated_solinas.ml | 0m06.16s || +0m01.63s | +26.62% 0m06.87s | ExtractionHaskell/saturated_solinas.hs | 0m04.98s || +0m01.88s | +37.95% 3m23.11s | p384_32.c | 3m22.61s || +0m00.50s | +0.24% 0m59.32s | ExtractionHaskell/word_by_word_montgomery | 0m58.76s || +0m00.56s | +0.95% 0m46.19s | p521_32.c | 0m47.16s || -0m00.96s | -2.05% 0m45.26s | RewriterInterpProofs1.vo | 0m45.64s || -0m00.38s | -0.83% 0m39.50s | p521_64.c | 0m38.97s || +0m00.53s | +1.36% 0m36.38s | PushButtonSynthesis/UnsaturatedSolinas.vo | 0m36.00s || +0m00.38s | +1.05% 0m34.40s | Fancy/Montgomery256.vo | 0m34.63s || -0m00.23s | -0.66% 0m26.95s | PushButtonSynthesis/WordByWordMontgomery.vo | 0m26.44s || +0m00.50s | +1.92% 0m25.62s | SlowPrimeSynthesisExamples.vo | 0m26.04s || -0m00.41s | -1.61% 0m24.39s | RewriterRulesProofs.vo | 0m24.18s || +0m00.21s | +0.86% 0m20.49s | PushButtonSynthesis/BarrettReduction.vo | 0m20.62s || -0m00.13s | -0.63% 0m18.54s | p448_solinas_64.c | 0m19.15s || -0m00.60s | -3.18% 0m17.37s | secp256k1_32.c | 0m17.70s || -0m00.32s | -1.86% 0m14.80s | p434_64.c | 0m14.16s || +0m00.64s | +4.51% 0m14.05s | ExtractionOCaml/unsaturated_solinas | 0m14.28s || -0m00.22s | -1.61% 0m09.17s | ExtractionOCaml/unsaturated_solinas.ml | 0m09.58s || -0m00.41s | -4.27% 0m08.47s | ExtractionHaskell/word_by_word_montgomery.hs | 0m08.22s || +0m00.25s | +3.04% 0m07.69s | p384_64.c | 0m07.72s || -0m00.02s | -0.38% 0m06.80s | BoundsPipeline.vo | 0m06.65s || +0m00.14s | +2.25% 0m06.49s | ExtractionHaskell/unsaturated_solinas.hs | 0m05.59s || +0m00.90s | +16.10% 0m03.54s | PushButtonSynthesis/Primitives.vo | 0m03.46s || +0m00.08s | +2.31% 0m03.35s | PushButtonSynthesis/SmallExamples.vo | 0m03.36s || -0m00.00s | -0.29% 0m03.19s | PushButtonSynthesis/SaturatedSolinas.vo | 0m03.15s || +0m00.04s | +1.26% 0m02.79s | curve25519_32.c | 0m03.32s || -0m00.52s | -15.96% 0m02.66s | PushButtonSynthesis/FancyMontgomeryReduction.vo | 0m02.73s || -0m00.06s | -2.56% 0m02.55s | RewriterRules.vo | 0m02.52s || +0m00.02s | +1.19% 0m01.98s | curve25519_64.c | 0m01.57s || +0m00.40s | +26.11% 0m01.78s | p224_64.c | 0m01.30s || +0m00.48s | +36.92% 0m01.60s | secp256k1_64.c | 0m01.74s || -0m00.13s | -8.04% 0m01.45s | p256_64.c | 0m01.55s || -0m00.10s | -6.45% 0m01.34s | RewriterProofs.vo | 0m01.16s || +0m00.18s | +15.51% 0m01.33s | CLI.vo | 0m01.40s || -0m00.06s | -4.99% 0m01.12s | StandaloneOCamlMain.vo | 0m01.09s || +0m00.03s | +2.75% 0m01.10s | CompilersTestCases.vo | 0m01.08s || +0m00.02s | +1.85% 0m01.08s | StandaloneHaskellMain.vo | 0m01.02s || +0m00.06s | +5.88% --- src/RewriterRulesInterpGood.v | 1064 ++++++++++------------------------------- 1 file changed, 252 insertions(+), 812 deletions(-) (limited to 'src/RewriterRulesInterpGood.v') diff --git a/src/RewriterRulesInterpGood.v b/src/RewriterRulesInterpGood.v index c73867339..6ff9ef672 100644 --- a/src/RewriterRulesInterpGood.v +++ b/src/RewriterRulesInterpGood.v @@ -11,33 +11,11 @@ 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.UniquePose. 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. @@ -45,7 +23,6 @@ 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. @@ -70,81 +47,81 @@ Module Compilers. 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 pattern.base.lookup_default PositiveMap.find Compile.rewrite_ruleTP ident.smart_Literal Compile.value_interp_related - Reify.expr_value_to_rewrite_rule_replacement UnderLets.flat_map Compile.reify_expr_beta_iota Compile.reflect_expr_beta_iota Compile.reflect_ident_iota Compile.reify_to_UnderLets UnderLets.of_expr Compile.Base_value]; - cbn [UnderLets.splice Compile.reflect invert_expr.invert_Literal invert_expr.ident.invert_Literal Compile.splice_under_lets_with_value]. - 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; + cbv [List.skipn] in *; 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] + | [ |- @Compile.rewrite_rules_interp_goodT ?ident ?pident ?pident_arg_types ?pident_to_typed ?ident_interp (rewrite_rules ?data ?var) ] + => let H := fresh in + pose proof (@Compile.rewrite_rules_interp_goodT_by_curried + _ _ _ pident_to_typed ident_interp (rewrite_rules data var) (rewrite_rules_specs data)) as H; + let h := head data in + cbv [rewrite_rules dummy_count rewrite_rules_specs h] in * |- ; + let h' := lazymatch type of H with context[Compile.rewrite_rules_interp_goodT_curried_cps _ _ _ ?v] => head v end in + unfold h' in H at 1; + cbv [Compile.rewrite_rules_interp_goodT_curried_cps pident_arg_types pident_to_typed] in H; + cbn [snd hd tl projT1 projT2] in H; + (* make [Qed] not take forever by explicitly recording a cast node *) + let H' := fresh in + pose proof H as H'; clear H; + apply H'; clear H' 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 UnderLets.interp_related_gen] in *. + [ try assumption; + cbn [PrimitiveHList.hlist snd]; + repeat lazymatch goal with + | [ |- PrimitiveProd.Primitive.prod _ _ ] => constructor + | [ |- forall A x, x = x ] => reflexivity + end; + try assumption + | try match goal with + | [ H : PrimitiveHList.hlist _ _ |- _ ] => clear H + end; + let H := fresh in + intro H; hnf in H; + repeat first [ progress intros + | match goal with + | [ |- { pf : ?x = ?x | _ } ] => (exists eq_refl) + | [ |- True /\ _ ] => split; [ exact I | ] + | [ |- _ /\ _ ] => split; [ intros; exact I | ] + | [ |- match (if ?b then _ else _) with Some _ => _ | None => _ end ] + => destruct b eqn:? + | [ |- True ] => exact I + end + | progress eta_expand + | 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] in *; + cbn [fst snd] in *; + eta_expand; + split_andb; + repeat match goal with + | [ H : ?b = true |- _ ] => unique pose proof (@Reflect.reflect_bool _ b _ H) + | [ H : negb _ = false |- _ ] => rewrite Bool.negb_false_iff in H + | [ H : _ = false |- _ ] => rewrite <- Bool.negb_true_iff in H + end; + subst; cbv [ident.gets_inlined ident.literal] in *; + lazymatch goal with + | [ |- ?R ?v ] + => let v' := open_constr:(_) in + replace v with v'; + [ | symmetry; + unshelve eapply H; shelve_unifiable; + try eassumption; + try (repeat apply conj; assumption); + try match goal with + | [ |- ?A = ?B ] => first [ is_evar A | is_evar B ]; reflexivity + | [ |- ?T ] => is_evar T; exact I + | [ |- ?P ] (* TODO: Maybe we shouldn't simplify boolean expressions in rewriter reification, since we end up just having to undo it here in a kludgy way....... *) + => apply (proj2 (@Bool.reflect_iff P _ _)); + progress rewrite ?Bool.eqb_true_l, ?Bool.eqb_true_r, ?Bool.eqb_false_l, ?Bool.eqb_false_r; + let b := lazymatch goal with |- ?b = true => b end in + apply (proj1 (@Bool.reflect_iff _ b _)); + tauto + end ]; + clear H + end; + fold (@base.interp) in * + .. ]. Ltac recurse_interp_related_step := let do_replace v := @@ -192,767 +169,230 @@ Module Compilers. end. (* TODO: MOVE ME? *) - Local Ltac recursive_match_to_list_case term := + Local Ltac recursive_match_to_case term := + let contains_match x + := lazymatch x with + | context[match _ with nil => _ | _ => _ end] => true + | context[match _ with pair a b => _ end] => true + | context[match _ with true => _ | false => _ end] => true + | _ => false + end in lazymatch term with | context G[match ?ls with nil => ?N | cons x xs => @?C x xs end] => let T := type of N in let term := context G[list_case (fun _ => T) N C ls] in - recursive_match_to_list_case term - | context[match _ with nil => _ | _ => _ end] - => let G_f - := match term with - | context G[fun x : ?T => @?f x] - => lazymatch f with - | context[match _ with nil => _ | _ => _ end] - => let f' := fresh in - let T' := type of f in - constr:(((fun f' : T' => ltac:(let G' := context G[f'] in exact G')), - f)) - end - end in - lazymatch G_f with - | ((fun f' => ?G), (fun x : ?T => ?f)) - => let x' := fresh in - let rep := constr:(fun x' : T - => ltac:(let f := constr:(match x' with x => f end) in - let f := recursive_match_to_list_case f in - exact f)) in - let term := constr:(match rep with f' => G end) in - recursive_match_to_list_case term - end - | _ => term + recursive_match_to_case term + | context G[match ?v with pair a b => @?P a b end] + => let T := lazymatch type of P with forall a b, @?T a b => T end in + let term := context G[prod_rect (fun ab => T (fst ab) (snd ab)) P v] in + recursive_match_to_case term + | context G[match ?b with true => ?t | false => ?f end] + => let T := type of t in + let term := context G[bool_rect (fun _ => T) t f b] in + recursive_match_to_case term + | _ => let has_match := contains_match term in + match has_match with + | true + => let G_f + := match term with + | context G[fun x : ?T => @?f x] + => let has_match := contains_match f in + lazymatch has_match with + | true + => let f' := fresh in + let T' := type of f in + constr:(((fun f' : T' => ltac:(let G' := context G[f'] in exact G')), + f)) + end + end in + lazymatch G_f with + | ((fun f' => ?G), (fun x : ?T => ?f)) + => let x' := fresh in + let rep := constr:(fun x' : T + => ltac:(let f := constr:(match x' with x => f end) in + let f := recursive_match_to_case f in + exact f)) in + let term := constr:(match rep with f' => G end) in + recursive_match_to_case term + end + | false + => term + end end. - Local Ltac recursive_match_to_list_case_in_goal := + Local Ltac recursive_match_to_case_in_goal := let G := match goal with |- ?G => G end in - let G := recursive_match_to_list_case G in + let G := recursive_match_to_case G in change G. - 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 - | match goal with - | [ |- UnderLets.interp_related ?ii ?R (UnderLets.Base (#ident.list_rect @ _ @ _ @ _)%expr) (@list_rect ?A (fun _ => ?P) ?N ?C ?ls) ] - => progress change (@list_rect A (fun _ => P) N C ls) with (@ident.Thunked.list_rect A P (fun _ => N) C ls) - | [ |- expr.interp_related_gen ?ii ?R (#ident.list_rect @ _ @ _ @ _)%expr (@list_rect ?A (fun _ => ?P) ?N ?C ?ls) ] - => progress change (@list_rect A (fun _ => P) N C ls) with (@ident.Thunked.list_rect A P (fun _ => N) C ls) - | [ |- expr.interp_related_gen ?ii ?R (#ident.list_case @ _ @ _ @ _)%expr (@list_case ?A (fun _ => ?P) ?N ?C ?ls) ] - => progress change (@list_case A (fun _ => P) N C ls) with (@ident.Thunked.list_case A P (fun _ => N) C ls) - | [ |- 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 _ _ (list_rect _ _ _ _ _) (@List.combine ?A ?B ?xs ?ys) ] - => rewrite (@eq_combine_list_rect A B xs ys) - | [ |- UnderLets.interp_related _ _ (nat_rect _ _ _ _) (List.repeat ?x ?n) ] - => rewrite (eq_repeat_nat_rect x n) - | [ |- ?R (nat_rect _ _ _ _ _) (@List.firstn ?A ?n ?ls) ] - => rewrite (@eq_firstn_nat_rect A n ls) - | [ |- ?R (nat_rect _ _ _ _ _) (@List.skipn ?A ?n ?ls) ] - => rewrite (@eq_skipn_nat_rect A n ls) - | [ |- ?R (list_rect _ _ _ _) (@List.rev ?A ?xs) ] - => rewrite (@eq_rev_list_rect A xs) - | [ |- ?R (list_rect _ _ _ _) (@List.length ?A ?xs) ] - => rewrite (@eq_length_list_rect A xs) - | [ |- ?R (list_rect _ _ _ _) (@List.flat_map ?A ?B ?f ?xs) ] - => rewrite (@eq_flat_map_list_rect A B f xs) - | [ |- ?R (list_rect _ _ _ _) (@List.partition ?A ?f ?xs) ] - => rewrite (@eq_partition_list_rect A f xs) - | [ |- ?R (nat_rect _ _ _ _ _) (@update_nth ?A ?n ?f ?xs) ] - => rewrite (@eq_update_nth_nat_rect A n f xs) - - | [ |- UnderLets.interp_related _ _ (UnderLets.Base (#ident.list_rect @ _ @ _ @ _)%expr) (List.app ?ls1 ?ls2) ] - => rewrite (eq_app_list_rect ls1 ls2) - | [ |- UnderLets.interp_related _ _ (UnderLets.Base (#ident.list_rect @ _ @ _ @ _)%expr) (List.app ?ls1 ?ls2) ] - => rewrite (eq_app_list_rect ls1 ls2) - | [ |- UnderLets.interp_related _ _ (UnderLets.Base (#ident.list_rect @ _ @ _ @ _)%expr) (@flat_map ?A ?B ?f ?ls) ] - => rewrite (@eq_flat_map_list_rect A B f ls) - | [ |- UnderLets.interp_related _ _ (UnderLets.Base (#ident.list_rect @ _ @ _ @ _)%expr) (@partition ?A ?f ?ls) ] - => rewrite (@eq_partition_list_rect A f ls) - | [ |- UnderLets.interp_related _ _ (UnderLets.Base (#ident.list_rect @ _ @ _ @ _)%expr) (@List.map ?A ?B ?f ?ls) ] - => rewrite (@eq_map_list_rect A B f ls) - | [ |- UnderLets.interp_related _ _ (UnderLets.Base (#ident.list_rect_arrow @ _ @ _ @ _ @ _)%expr) (@List.combine ?A ?B ?xs ?ys) ] - => rewrite (@eq_combine_list_rect A B xs ys) - | [ |- UnderLets.interp_related _ _ _ (@fold_right ?A ?B ?f ?v ?ls) ] - => rewrite (@eq_fold_right_list_rect A B f v ls) - | [ |- ?R (#ident.nat_rect_arrow @ _ @ _ @ _ @ _)%expr (@List.firstn ?A ?n ?ls) ] - => rewrite (@eq_firstn_nat_rect A n ls) - | [ |- ?R (#ident.nat_rect_arrow @ _ @ _ @ _ @ _)%expr (@List.skipn ?A ?n ?ls) ] - => rewrite (@eq_skipn_nat_rect A n ls) - | [ |- ?R (#ident.list_rect @ _ @ _ @ _)%expr (@List.rev ?A ?xs) ] - => rewrite (@eq_rev_list_rect A xs) - | [ |- ?R (#ident.list_rect @ _ @ _ @ _)%expr (@List.length ?A ?xs) ] - => rewrite (@eq_length_list_rect A xs) - | [ |- ?R (#ident.list_rect @ _ @ _ @ _)%expr (@List.flat_map ?A ?B ?f ?xs) ] - => rewrite (@eq_flat_map_list_rect A B f xs) - | [ |- ?R (#ident.list_rect @ _ @ _ @ _)%expr (@List.partition ?A ?f ?xs) ] - => rewrite (@eq_partition_list_rect A f xs) - | [ |- ?R (#ident.nat_rect_arrow @ _ @ _ @ _ @ _)%expr (@update_nth ?A ?n ?f ?xs) ] - => rewrite (@eq_update_nth_nat_rect A n f xs) - | [ |- ?R (#ident.list_rect_arrow @ _ @ _ @ _ @ _)%expr (@List.combine ?A ?B ?xs ?ys) ] - => rewrite (@eq_combine_list_rect A B xs ys) - - - | [ |- expr.interp_related_gen _ _ (#ident.list_rect @ _ @ _ @ _)%expr (ident.Thunked.list_rect _ _ _ _) ] - => recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ] - | ] - | ] - | ] - | [ |- expr.interp_related_gen _ _ (#ident.list_rect_arrow @ _ @ _ @ _ @ _)%expr (list_rect _ _ _ _ _) ] - => recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ] - | ] - | ] - | ] - | ] - | [ |- expr.interp_related_gen _ _ (#ident.nat_rect @ _ @ _ @ _)%expr (ident.Thunked.nat_rect _ _ _ _) ] - => recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ] - | ] - | ] - | ] - | [ |- expr.interp_related_gen _ _ (#ident.nat_rect_arrow @ _ @ _ @ _ @ _)%expr (nat_rect _ _ _ _ _) ] - => recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ] - | ] - | ] - | ] - | ] - | [ |- expr.interp_related_gen _ _ (#ident.list_case @ _ @ _ @ _)%expr (ident.Thunked.list_case _ _ _ _) ] - => recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ]; - [ recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ] - | ] - | ] - | ] - | [ |- context[match _ with nil => _ | _ => _ end] ] => progress recursive_match_to_list_case_in_goal - 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 UnderLets.interp_related_gen type.related] in * - | progress cbv [Compile.option_bind' respectful expr.interp_related] in * - | progress fold (@type.interp _ base.interp) - | progress fold (@base.interp) - | progress change S with Nat.succ - | 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 - | [ |- 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 - | [ |- expr.interp_related_gen ?ident_interp _ (UnderLets.to_expr ?x) ?y ] - => change (expr.interp_related ident_interp (UnderLets.to_expr x) y); - rewrite <- UnderLets.to_expr_interp_related_iff - | [ |- 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 - ?ident_interp ?R - (list_rect - (fun _ : list (expr ?A) => ?B -> UnderLets.UnderLets _ _ _ ?C) - ?Pnil - ?Pcons - ?ls - ?x) - (list_rect - (fun _ : list _ => ?B' -> ?C') - ?Pnil' - ?Pcons' - ?ls' - ?x') ] - => apply (@UnderLets.list_rect_arrow_interp_related _ _ _ ident_interp A B C Pnil Pcons ls x B' C' Pnil' Pcons' ls' x' R (expr.interp_related ident_interp)) - | [ |- 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 destruct_head'_unit - | 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 - | [ H : forall x x', _ -> forall y y', _ -> forall z z', _ -> forall w w', _ -> ?R (?f x y z w) (?f' x' y' z' w') |- ?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 - | [ H : true = false |- _ ]=> exfalso; clear -H; congruence - | [ H : false = true |- _ ]=> exfalso; clear -H; congruence - end - | progress cbv [option_beq] in * - | 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) - | [ H : lower ?x = upper ?x |- _ ] => is_var x; destruct x; cbn [upper lower] in * - | [ H : is_bounded_by_bool ?x (ZRange.normalize r[?y~>?y]) = true |- _ ] - => apply ZRange.is_bounded_by_bool_normalize_constant_iff in H - | [ H : is_bounded_by_bool ?x r[?y~>?y] = true |- _ ] - => apply ZRange.is_bounded_by_bool_constant_iff in H - end + Local Ltac preprocess_step := + first [ progress cbv [expr.interp_related respectful ident.literal ident.eagerly] in * + | progress cbn [fst snd base.interp base.base_interp Compile.value'] in * | 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 + | [ |- context[match _ with nil => _ | _ => _ end] ] => progress recursive_match_to_case_in_goal + | [ |- context[match _ with pair a b => _ end] ] => progress recursive_match_to_case_in_goal + | [ |- context[match _ with true => _ | false => _ end] ] => progress recursive_match_to_case_in_goal + | [ |- context[match invert_expr.reflect_list ?ls with _ => _ end] ] + => destruct (invert_expr.reflect_list ls) eqn:? + | [ |- context G[expr.interp_related_gen ?ident_interp (fun t : ?T => ?vii t ?b)] ] + => progress change (fun t : T => vii t b) with (fun t : T => @Compile.value_interp_related _ ident_interp t b) end ]. - - Local Ltac remove_casts := + Local Ltac preprocess := repeat preprocess_step. + Local Ltac handle_extra_nbe := 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) = true |- 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) = true, 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) - | _ => progress Z.ltb_to_lt - | _ => progress subst + | [ |- UnderLets.interp_related _ _ (UnderLets.Base (expr.Ident _)) _ ] + => cbn [UnderLets.interp_related UnderLets.interp_related_gen expr.interp_related_gen ident_interp type.related]; reflexivity + | [ |- UnderLets.interp_related _ _ (UnderLets.Base (reify_list _)) _ ] + => cbn [UnderLets.interp_related UnderLets.interp_related_gen]; rewrite expr.reify_list_interp_related_gen_iff + | [ |- UnderLets.interp_related _ _ (UnderLets.Base (_, _)%expr) ?x ] + => cbn [UnderLets.interp_related UnderLets.interp_related_gen]; + recurse_interp_related_step; + [ recurse_interp_related_step + | lazymatch x with + | (_, _) => reflexivity + | _ => etransitivity; [ | symmetry; apply surjective_pairing ]; reflexivity + end ]; + [ | reflexivity ]; cbn [fst snd]; + recurse_interp_related_step; [ recurse_interp_related_step | reflexivity ] + | [ |- List.Forall2 _ (List.map _ _) _ ] + => rewrite Forall2_map_l_iff + | [ |- List.Forall2 _ ?x ?x ] => rewrite Forall2_Forall; cbv [Proper] + | [ |- List.Forall _ _ ] => rewrite Forall_forall; intros + | [ |- expr.interp_related_gen _ _ (expr.Ident _) _ ] + => cbn [expr.interp_related_gen ident_interp type.related]; reflexivity end. + Local Ltac fin_tac := + repeat first [ assumption + | progress change S with Nat.succ + | progress cbn [base.interp base.base_interp type.interp] in * + | progress fold (@type.interp _ base.interp) + | progress fold (@base.interp) + | progress subst + | progress cbv [respectful ident.Thunked.bool_rect ident.Thunked.list_case ident.Thunked.option_rect pointwise_relation] + | progress intros + | solve [ auto ] + | match goal with + | [ |- ?x = ?x ] => reflexivity + | [ |- list_rect _ _ _ _ = ident.Thunked.list_rect _ _ _ _ ] + => cbv [ident.Thunked.list_rect]; apply list_rect_Proper; cbv [pointwise_relation]; intros + | [ |- list_rect (fun _ => ?A -> ?B) _ _ _ _ = list_rect _ _ _ _ _ ] + => apply list_rect_arrow_Proper; cbv [respectful]; intros + | [ |- nat_rect _ _ _ _ = ident.Thunked.nat_rect _ _ _ _ ] + => apply nat_rect_Proper_nondep; cbv [respectful] + | [ |- nat_rect (fun _ => ?A -> ?B) _ _ _ _ = nat_rect _ _ _ _ _ ] + => apply (@nat_rect_Proper_nondep_gen (A -> B) (eq ==> eq)%signature); cbv [respectful]; intros + | [ |- list_case _ _ _ ?ls = list_case _ _ _ ?ls ] + => is_var ls; destruct ls; cbn [list_case] + | [ |- bool_rect _ _ _ ?b = bool_rect _ _ _ ?b ] + => is_var b; destruct b; cbn [bool_rect] + | [ |- _ = ident.cast2 _ _ _ ] => cbv [ident.cast2]; break_innermost_match + end ]. + Local Ltac handle_reified_rewrite_rules_interp := + repeat first [ assumption + | match goal with + | [ |- UnderLets.interp_related _ _ (Reify.expr_value_to_rewrite_rule_replacement _ ?sda _) _ ] + => apply (@Reify.expr_value_to_rewrite_rule_replacement_interp_related cast_outside_of_range _ (@Reify.reflect_ident_iota_interp_related cast_outside_of_range) sda) - 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. + | [ |- UnderLets.interp_related_gen ?ii ?R (UnderLets.Base (#ident.list_rect @ _ @ _ @ _)%expr) (@list_rect ?A (fun _ => ?P) ?N ?C ?ls) ] + => progress change (@list_rect A (fun _ => P) N C ls) with (@ident.Thunked.list_rect A P (fun _ => N) C ls) + | [ |- expr.interp_related_gen ?ii ?R (#ident.list_rect @ _ @ _ @ _)%expr (@list_rect ?A (fun _ => ?P) ?N ?C ?ls) ] + => progress change (@list_rect A (fun _ => P) N C ls) with (@ident.Thunked.list_rect A P (fun _ => N) C ls) + | [ |- expr.interp_related_gen ?ii ?R (#ident.eager_list_rect @ _ @ _ @ _)%expr (@list_rect ?A (fun _ => ?P) ?N ?C ?ls) ] + => progress change (@list_rect A (fun _ => P) N C ls) with (@ident.Thunked.list_rect A P (fun _ => N) C ls) + | [ |- expr.interp_related_gen ?ii ?R (#ident.list_case @ _ @ _ @ _)%expr (@list_case ?A (fun _ => ?P) ?N ?C ?ls) ] + => progress change (@list_case A (fun _ => P) N C ls) with (@ident.Thunked.list_case A P (fun _ => N) C ls) + | [ |- expr.interp_related_gen ?ii ?R (#ident.nat_rect @ _ @ _ @ _)%expr (@nat_rect (fun _ => ?P) ?N ?C ?ls) ] + => progress change (@nat_rect (fun _ => P) N C ls) with (@ident.Thunked.nat_rect P (fun _ => N) C ls) + | [ |- expr.interp_related_gen ?ii ?R (#ident.eager_nat_rect @ _ @ _ @ _)%expr (@nat_rect (fun _ => ?P) ?N ?C ?ls) ] + => progress change (@nat_rect (fun _ => P) N C ls) with (@ident.Thunked.nat_rect P (fun _ => N) C ls) + | [ |- expr.interp_related_gen ?ii ?R (#ident.bool_rect @ _ @ _ @ _)%expr (@bool_rect (fun _ => ?P) ?T ?F ?b) ] + => progress change (@bool_rect (fun _ => P) T F b) with (@ident.Thunked.bool_rect P (fun _ => T) (fun _ => F) b) + | [ |- expr.interp_related_gen ?ii ?R (#ident.option_rect @ _ @ _ @ _)%expr (@option_rect ?A (fun _ => ?P) ?S ?N ?o) ] + => progress change (@option_rect A (fun _ => P) S N o) with (@ident.Thunked.option_rect A P S (fun _ => N) o) - Local Ltac systematically_handle_casts := - remove_casts; unfold_cast_lemmas. + | [ |- match ?x with pair _ _ => _ end = prod_rect _ _ _ ] + => cbv [prod_rect]; eta_expand + + | [ |- expr.interp_related_gen _ _ (expr.Var _) _ ] + => cbn [expr.interp_related_gen] + | [ |- expr.interp_related_gen _ _ (expr.Ident _) _ ] + => cbn [expr.interp_related_gen ident_interp type.related]; fin_tac + | [ |- expr.interp_related_gen _ _ (expr.Abs ?f) _ ] + => let fh := fresh in set (fh := f); cbn [expr.interp_related_gen]; subst fh; cbv beta; intros + | [ |- expr.interp_related_gen _ _ (expr.LetIn ?v ?f) (LetIn.Let_In ?V ?F) ] + => let vh := fresh in + set (vh := v); + let fh := fresh in + set (fh := f); + cbn [expr.interp_related_gen]; subst fh vh; cbv beta; + exists F, V; repeat apply conj; intros + | [ |- expr.interp_related_gen _ _ (?f @ ?x)%expr (?F ?X) ] + => let fh := fresh in + set (fh := f); + let xh := fresh in + set (xh := x); + cbn [expr.interp_related_gen]; subst fh xh; + exists F, X; repeat apply conj; [ | | reflexivity ] + + | [ |- _ = _ ] => solve [ fin_tac ] + end ]. - 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. + Local Notation specT rewriter_data + := (PrimitiveHList.hlist (@snd bool Prop) (List.skipn (dummy_count rewriter_data) (rewrite_rules_specs rewriter_data))) + (only parsing). + + Lemma nbe_rewrite_rules_interp_good (H : specT nbe_rewriter_data) + : rewrite_rules_interp_goodT (rewrite_rules nbe_rewriter_data _). Proof using Type. Time start_interp_good. - Time all: try solve [ repeat interp_good_t_step_related ]. - Qed. + Time all: preprocess; handle_extra_nbe; handle_reified_rewrite_rules_interp. + Time Qed. - Lemma arith_rewrite_rules_interp_good max_const - : rewrite_rules_interp_goodT (arith_rewrite_rules max_const). + Lemma arith_rewrite_rules_interp_good max_const (H : specT (arith_rewriter_data max_const)) + : rewrite_rules_interp_goodT (rewrite_rules (arith_rewriter_data 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. + Time all: preprocess; handle_reified_rewrite_rules_interp. + Time Qed. - Lemma arith_with_casts_rewrite_rules_interp_good - : rewrite_rules_interp_goodT arith_with_casts_rewrite_rules. + Lemma arith_with_casts_rewrite_rules_interp_good (H : specT arith_with_casts_rewriter_data) + : rewrite_rules_interp_goodT (rewrite_rules arith_with_casts_rewriter_data _). 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. + Time all: preprocess; handle_reified_rewrite_rules_interp. + Time Qed. - Lemma strip_literal_casts_rewrite_rules_interp_good - : rewrite_rules_interp_goodT strip_literal_casts_rewrite_rules. + Lemma strip_literal_casts_rewrite_rules_interp_good (H : specT strip_literal_casts_rewriter_data) + : rewrite_rules_interp_goodT (rewrite_rules strip_literal_casts_rewriter_data _). Proof using Type. Time start_interp_good. - Time all: try solve [ repeat interp_good_t_step_related; repeat interp_good_t_step_arith ]. - 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 *. + Time all: preprocess; handle_reified_rewrite_rules_interp. + Time Qed. 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. + (H : specT (fancy_rewriter_data invert_low invert_high)) + : rewrite_rules_interp_goodT (rewrite_rules (fancy_rewriter_data invert_low invert_high) _). Proof using Type. Time start_interp_good. - Time all: try solve [ repeat interp_good_t_step_related ]. - Qed. + Time all: preprocess; handle_reified_rewrite_rules_interp. + Time 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). + (H : specT (fancy_with_casts_rewriter_data invert_low invert_high value_range flag_range)) + : rewrite_rules_interp_goodT (rewrite_rules (fancy_with_casts_rewriter_data 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) *) - Qed. + Time start_interp_good. + Time all: preprocess; handle_reified_rewrite_rules_interp. + Time Qed. End with_cast. End RewriteRules. End Compilers. -- cgit v1.2.3