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/RewriterWf1.v | 496 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 445 insertions(+), 51 deletions(-) (limited to 'src/RewriterWf1.v') diff --git a/src/RewriterWf1.v b/src/RewriterWf1.v index 420b5dc90..d3d640dc0 100644 --- a/src/RewriterWf1.v +++ b/src/RewriterWf1.v @@ -35,6 +35,7 @@ Require Import Crypto.Util.CPSNotations. Require Import Crypto.Util.Notations. Require Import Crypto.Util.HProp. Require Import Crypto.Util.Decidable. +Require Crypto.Util.PrimitiveHList. Import Coq.Lists.List ListNotations. Local Open Scope list_scope. Local Open Scope Z_scope. @@ -299,8 +300,8 @@ Module Compilers. revert v evm T k. induction t; cbn in *; intros; break_innermost_match; try reflexivity; auto. - repeat match goal with H : _ |- _ => etransitivity; rewrite H; clear H; [ | reflexivity ] end. - reflexivity. + repeat match goal with H : _ |- _ => (rewrite H; reflexivity) + (etransitivity; rewrite H; clear H; [ | reflexivity ]) end; + reflexivity. Qed. Ltac add_var_types_cps_id := @@ -386,8 +387,8 @@ Module Compilers. revert v evm T k. induction t; cbn in *; intros; break_innermost_match; try reflexivity; auto using base.add_var_types_cps_id. - repeat match goal with H : _ |- _ => etransitivity; rewrite H; clear H; [ | reflexivity ] end. - reflexivity. + repeat match goal with H : _ |- _ => (rewrite H; reflexivity) + (etransitivity; rewrite H; clear H; [ | reflexivity ]) end; + reflexivity. Qed. Ltac add_var_types_cps_id := @@ -2110,27 +2111,52 @@ Module Compilers. : Prop := wf_with_unif_rewrite_ruleTP_gen_curried G (rew_replacement r1) (rew_replacement r2). - Definition rewrite_rules_goodT_curried - (rew1 : rewrite_rulesT1) (rew2 : rewrite_rulesT2) + Fixpoint rewrite_rules_goodT_curried_cps_folded + (rew1 : rewrite_rulesT1) (rew2 : rewrite_rulesT2) + (H : List.map (@projT1 _ _) rew1 = List.map (@projT1 _ _) rew2) + (final : Prop) : Prop - := length rew1 = length rew2 - /\ (forall p1 r1 p2 r2, - List.In (existT _ p1 r1, existT _ p2 r2) (combine rew1 rew2) - -> { pf : p1 = p2 - | forall G, - wf_rewrite_rule_data_curried - G - (rew [fun tp => @rewrite_rule_data1 _ (pattern.pattern_of_anypattern tp)] pf in r1) - r2 }). + := match rew1, rew2 return List.map _ rew1 = List.map _ rew2 -> Prop with + | nil, nil => fun _ => final + | nil, _ | _, nil => fun _ => False -> final + | rew1 :: rew1s, rew2 :: rew2s + => fun pf : projT1 rew1 :: List.map _ rew1s = projT1 rew2 :: List.map _ rew2s + => let pfs := f_equal (@tl _) pf in + let pf := f_equal (hd (projT1 rew1)) pf in + (forall G, + wf_rewrite_rule_data_curried + G + (rew [fun tp => @rewrite_rule_data1 _ (pattern.pattern_of_anypattern tp)] pf in projT2 rew1) + (projT2 rew2)) + -> rewrite_rules_goodT_curried_cps_folded rew1s rew2s pfs final + end H. + + Definition rewrite_rules_goodT_curried_cps + := Eval cbv [id + rewrite_rules_goodT_curried_cps_folded + eq_rect f_equal hd tl List.map + wf_deep_rewrite_ruleTP_gen wf_rewrite_rule_data_curried rew_replacement rew_should_do_again rew_with_opt rew_under_lets wf_with_unif_rewrite_ruleTP_gen_curried wf_with_unification_resultT pattern.pattern_of_anypattern pattern.type_of_anypattern wf_maybe_under_lets_expr wf_maybe_do_again_expr wf_with_unification_resultT pattern.type.under_forall_vars_relation with_unification_resultT' pattern.collect_vars pattern.type.collect_vars pattern.base.collect_vars PositiveSet.empty PositiveSet.elements under_type_of_list_relation_cps pattern.ident.arg_types pattern.type.subst_default pattern.base.subst_default pattern.base.lookup_default PositiveSet.rev PositiveMap.empty under_with_unification_resultT_relation_hetero under_with_unification_resultT'_relation_hetero maybe_option_eq + List.map List.fold_right PositiveSet.union PositiveSet.xelements List.rev List.app projT1 projT2 list_rect PositiveSet.add PositiveSet.rev PositiveSet.rev_append PositiveMap.add PositiveMap.find orb] in + rewrite_rules_goodT_curried_cps_folded. + + Lemma rewrite_rules_goodT_curried_cps_folded_Proper_impl rews1 rews2 H + : Proper (Basics.impl ==> Basics.impl) (rewrite_rules_goodT_curried_cps_folded rews1 rews2 H). + Proof using Type. + cbv [impl]; intros P Q H'. + revert dependent rews2; induction rews1, rews2; cbn; auto. + Qed. + Lemma rewrite_rules_goodT_curried_cps_Proper_impl rews1 rews2 H + : Proper (Basics.impl ==> Basics.impl) (rewrite_rules_goodT_curried_cps rews1 rews2 H). + Proof using Type. + apply rewrite_rules_goodT_curried_cps_folded_Proper_impl. + Qed. - Lemma rewrite_rules_goodT_by_curried rew1 rew2 - : rewrite_rules_goodT_curried rew1 rew2 -> rewrite_rules_goodT rew1 rew2. + Lemma wf_rewrite_rule_data_by_curried G t p r1 r2 + : @wf_rewrite_rule_data_curried G t p r1 r2 + -> @wf_rewrite_rule_data G t p r1 r2. Proof using Type. - cbv [rewrite_rules_goodT rewrite_rules_goodT_curried wf_rewrite_rule_data_curried wf_rewrite_rule_data wf_with_unif_rewrite_ruleTP_gen wf_with_unif_rewrite_ruleTP_gen_curried]. - intros [Hlen H]; split; [ exact Hlen | clear Hlen ]. - repeat (let x := fresh "x" in intro x; specialize (H x)). - destruct H as [H0 H]; exists H0. - repeat (let x := fresh "x" in intro x; specialize (H x)). + cbv [wf_rewrite_rule_data_curried wf_rewrite_rule_data wf_with_unif_rewrite_ruleTP_gen wf_with_unif_rewrite_ruleTP_gen_curried]. + intro H. intros X Y HXY. pose proof (wf_app_with_unification_resultT _ _ _ _ _ _ ltac:(eassumption) ltac:(eassumption)) as H'. cps_id'_with_option app_with_unification_resultT_cps_id. @@ -2147,6 +2173,34 @@ Module Compilers. | exfalso; assumption | assumption ]. Qed. + + Lemma rewrite_rules_goodT_by_curried + (rews1 : rewrite_rulesT1) (rews2 : rewrite_rulesT2) + (H : List.map (@projT1 _ _) rews1 = List.map (@projT1 _ _) rews2) + : rewrite_rules_goodT_curried_cps rews1 rews2 H (rewrite_rules_goodT rews1 rews2). + Proof using Type. + change rewrite_rules_goodT_curried_cps with rewrite_rules_goodT_curried_cps_folded. + cbv [rewrite_rules_goodT]. + revert rews2 H; induction rews1 as [|[r p] rews1 IHrews], rews2 as [|[? ?] ?]; intro H. + all: try solve [ cbn; tauto ]. + all: cbn [rewrite_rules_goodT_curried_cps_folded List.In projT2 projT1 Datatypes.fst Datatypes.snd] in *. + all: intro H'; eapply rewrite_rules_goodT_curried_cps_folded_Proper_impl; [ | eapply IHrews ]. + all: repeat first [ progress cbv [impl] + | progress destruct_head'_or + | progress inversion_sigma + | progress subst + | progress destruct_head'_and + | progress destruct_head'_sig + | progress destruct_head'_or + | progress inversion_prod + | progress inversion_sigma + | (exists eq_refl) + | apply conj + | apply (f_equal S) + | progress cbn [eq_rect Datatypes.snd List.length List.In List.combine] in * + | solve [ eauto using wf_rewrite_rule_data_by_curried ] + | progress intros ]. + Qed. End with_var2. Section with_interp. @@ -2165,16 +2219,13 @@ Module Compilers. := (if with_lets as with_lets' return (if with_lets' then UnderLets var _ else _) -> _ then UnderLets.interp ident_interp else (fun x => x)). - Local Notation UnderLets_maybe_wf with_lets G := (if with_lets as with_lets' return (if with_lets' then UnderLets var _ else _) -> (if with_lets' then UnderLets var _ else _) -> _ then UnderLets.wf (fun G' => expr.wf G') G else expr.wf G). - Definition value'_interp {with_lets t} (v : @value' var with_lets t) : var t := expr.interp ident_interp (reify v). - Local Notation expr_interp_related := (@expr.interp_related _ ident _ ident_interp). Local Notation UnderLets_interp_related := (@UnderLets.interp_related _ ident _ ident_interp _ _ expr_interp_related). @@ -2188,7 +2239,6 @@ Module Compilers. @value_interp_related s _ x1 x2 -> @value_interp_related d _ (f1 x1) (f2 x2) end. - Fixpoint rawexpr_interp_related (r1 : rawexpr) : type.interp base.interp (type_of_rawexpr r1) -> Prop := match r1 return type.interp base.interp (type_of_rawexpr r1) -> Prop with | rExpr _ e1 @@ -2213,15 +2263,12 @@ Module Compilers. | _ => fun _ => False end end. - Definition unification_resultT'_interp_related {t p evm} : @unification_resultT' (@value var) t p evm -> @unification_resultT' var t p evm -> Prop := related_unification_resultT' (fun t => value_interp_related). - Definition unification_resultT_interp_related {t p} : @unification_resultT (@value var) t p -> @unification_resultT var t p -> Prop := related_unification_resultT (fun t => value_interp_related). - Lemma interp_reify_reflect {with_lets t} e v : expr.interp ident_interp e == v -> expr.interp ident_interp (@reify _ with_lets t (reflect e)) == v. Proof using Type. @@ -2232,7 +2279,6 @@ Module Compilers. intros Hf ? ? Hx. apply IHd; cbn [expr.interp]; auto. Qed. - Lemma interp_of_wf_reify_expr G {t} (HG : forall t v1 v2, List.In (existT _ t (v1, v2)) G -> expr.interp ident_interp (reify v1) == v2) e1 e2 @@ -2253,7 +2299,6 @@ Module Compilers. | apply interp_reify_reflect | solve [ auto ] ]. Qed. - Fixpoint reify_interp_related {t with_lets} v1 v2 {struct t} : @value_interp_related t with_lets v1 v2 -> expr_interp_related (reify v1) v2 @@ -2287,7 +2332,6 @@ Module Compilers. | match goal with H : _ |- _ => apply H; clear H end | progress repeat esplit ]. Qed. - Lemma expr_of_rawexpr_interp_related r v : rawexpr_interp_related r v -> expr_interp_related (expr_of_rawexpr r) v. @@ -2305,7 +2349,6 @@ Module Compilers. | solve [ eauto ] | apply reify_interp_related ]. Qed. - Lemma value_of_rawexpr_interp_related {e v} : rawexpr_interp_related e v -> value_interp_related (value_of_rawexpr e) v. Proof using Type. @@ -2323,7 +2366,6 @@ Module Compilers. | progress cbv [expr.interp_related] | solve [ eauto ] ]. Qed. - Lemma rawexpr_interp_related_Proper_rawexpr_equiv_expr {t e re v} (H : rawexpr_equiv_expr e re) : @expr_interp_related t e v @@ -2358,7 +2400,6 @@ Module Compilers. => do 4 eexists; repeat apply conj; [ eassumption | eassumption | | | reflexivity ] end ]. Qed. - Lemma rawexpr_interp_related_Proper_rawexpr_equiv_expr_no_rew {re e v} (H : rawexpr_equiv_expr e re) : @expr_interp_related _ e v @@ -2369,7 +2410,6 @@ Module Compilers. generalize (eq_type_of_rawexpr_equiv_expr H); intro; eliminate_hprop_eq. exact id. Qed. - Lemma rawexpr_interp_related_Proper_rawexpr_equiv_expr_rew_gen {t e re v} (H : rawexpr_equiv_expr e re) : forall pf, @@ -2378,7 +2418,6 @@ Module Compilers. Proof using Type. intro; subst; apply rawexpr_interp_related_Proper_rawexpr_equiv_expr_no_rew; assumption. Qed. - Lemma rawexpr_interp_related_Proper_rawexpr_equiv {re1 re2 v} (H : rawexpr_equiv re1 re2) : rawexpr_interp_related re1 v @@ -2453,6 +2492,52 @@ Module Compilers. => k (ef ex))) end. + Lemma interp_Base_value {t v1 v2} + : value_interp_related v1 v2 + -> value_interp_related (@Base_value var t v1) v2. + Proof using Type. + cbv [Base_value]; destruct t; exact id. + Qed. + + Lemma interp_splice_under_lets_with_value_of_ex {T T' t R e f v} + : (exists fv (xv : T'), + UnderLets.interp_related ident_interp R e xv + /\ (forall x1 x2, + R x1 x2 + -> value_interp_related (f x1) (fv x2)) + /\ fv xv = v) + -> value_interp_related (@splice_under_lets_with_value var T t e f) v. + Proof using Type. + induction t as [|s IHs d IHd]. + all: repeat first [ progress cbn [value_interp_related splice_under_lets_with_value] in * + | progress intros + | progress destruct_head'_ex + | progress destruct_head'_and + | progress subst + | eassumption + | solve [ eauto ] + | now (eapply UnderLets.splice_interp_related_of_ex; eauto) + | match goal with + | [ H : _ |- _ ] => eapply H; clear H + | [ |- exists fv xv, _ /\ _ /\ _ ] + => do 2 eexists; repeat apply conj; [ eassumption | | ] + end ]. + Qed. + + Lemma interp_splice_value_with_lets_of_ex {t t' e f v} + : (exists fv xv, + value_interp_related e xv + /\ (forall x1 x2, + value_interp_related x1 x2 + -> value_interp_related (f x1) (fv x2)) + /\ fv xv = v) + -> value_interp_related (@splice_value_with_lets var t t' e f) v. + Proof using Type. + cbv [splice_value_with_lets]; break_innermost_match. + { apply interp_splice_under_lets_with_value_of_ex. } + { intros; destruct_head'_ex; destruct_head'_and; subst; eauto. } + Qed. + Definition pattern_default_interp {t} (p : pattern t) : @with_unification_resultT var t p var (*: @with_unif_rewrite_ruleTP_gen var t p false false false*) @@ -2542,17 +2627,44 @@ Module Compilers. (rew_replacement r) (pattern_default_interp p). - Definition rewrite_rules_interp_goodT_curried - (rews : rewrite_rulesT) - : Prop - := forall p r, - List.In (existT _ p r) rews - -> rewrite_rule_data_interp_goodT_curried r. + Fixpoint rewrite_rules_interp_goodT_curried_cps_folded + (rews : rewrite_rulesT) + (specs : list (bool * Prop)) + (final : Prop) + := match rews with + | r :: rews + => (snd (hd (true, True) specs) + -> rewrite_rule_data_interp_goodT_curried (projT2 r)) + -> rewrite_rules_interp_goodT_curried_cps_folded rews (tl specs) final + | nil => final + end. + + Definition rewrite_rules_interp_goodT_curried_cps + := Eval cbv [id + rewrite_rules_interp_goodT_curried_cps_folded snd hd tl projT2 rewrite_rule_data_interp_goodT_curried + rewrite_rule_data_interp_goodT_curried under_with_unification_resultT_relation_hetero under_with_unification_resultT'_relation_hetero wf_with_unification_resultT under_type_of_list_relation_cps under_type_of_list_relation1_cps pattern.pattern_of_anypattern pattern.type_of_anypattern rew_replacement rew_should_do_again rew_with_opt rew_under_lets wf_with_unification_resultT pattern_default_interp pattern.type.under_forall_vars_relation pattern.type.under_forall_vars_relation1 deep_rewrite_ruleTP_gen with_unification_resultT' pattern.ident.arg_types pattern.type.lam_forall_vars Compilers.pattern.type.lam_forall_vars_gen pattern_default_interp' pattern.collect_vars PositiveMap.empty pattern.type.collect_vars PositiveSet.elements PositiveSet.union pattern.base.collect_vars PositiveSet.empty PositiveSet.xelements lam_type_of_list id pattern.ident.to_typed under_type_of_list_relation_cps deep_rewrite_ruleTP_gen_good_relation normalize_deep_rewrite_rule pattern.type.subst_default PositiveSet.add PositiveSet.rev PositiveSet.rev_append PositiveMap.add option_bind' wf_value value pattern.base.subst_default pattern.base.lookup_default PositiveMap.find rewrite_ruleTP ident.smart_Literal value_interp_related + Reify.expr_value_to_rewrite_rule_replacement UnderLets.flat_map reify_expr_beta_iota reflect_expr_beta_iota reflect_ident_iota Compile.reify_to_UnderLets UnderLets.of_expr Compile.Base_value + List.map List.fold_right List.rev list_rect orb List.app + ] in + rewrite_rules_interp_goodT_curried_cps_folded. + + Lemma rewrite_rules_interp_goodT_curried_cps_folded_Proper_impl rews specs + : Proper (Basics.impl ==> Basics.impl) (rewrite_rules_interp_goodT_curried_cps_folded rews specs). + Proof using Type. + cbv [impl]; intros P Q H. + revert specs; induction rews, specs; cbn; auto. + Qed. + Lemma rewrite_rules_interp_goodT_curried_cps_Proper_impl rews specs + : Proper (Basics.impl ==> Basics.impl) (rewrite_rules_interp_goodT_curried_cps rews specs). + Proof using Type. + apply rewrite_rules_interp_goodT_curried_cps_folded_Proper_impl. + Qed. - Lemma rewrite_rules_interp_goodT_by_curried rews - : rewrite_rules_interp_goodT_curried rews -> rewrite_rules_interp_goodT rews. + Lemma rewrite_rule_data_interp_goodT_by_curried t p r + : @rewrite_rule_data_interp_goodT_curried t p r + -> @rewrite_rule_data_interp_goodT t p r. Proof using Type. - cbv [rewrite_rules_interp_goodT rewrite_rules_interp_goodT_curried rewrite_rule_data_interp_goodT rewrite_rule_data_interp_goodT_curried]. + cbv [rewrite_rule_data_interp_goodT rewrite_rule_data_interp_goodT_curried]. intro H. repeat (let x := fresh "x" in intro x; specialize (H x)). intros X Y HXY. @@ -2567,13 +2679,36 @@ Module Compilers. | exfalso; assumption | assumption ]. Qed. + + Lemma rewrite_rules_interp_goodT_by_curried rews specs + (proofs : PrimitiveHList.hlist (@snd bool Prop) specs) + : rewrite_rules_interp_goodT_curried_cps rews specs (rewrite_rules_interp_goodT rews). + Proof using Type. + change rewrite_rules_interp_goodT_curried_cps with rewrite_rules_interp_goodT_curried_cps_folded. + cbv [rewrite_rules_interp_goodT]. + revert specs proofs. + induction rews as [|[r p] rews IHrews], specs as [|[? ?] specs]; + cbn [PrimitiveHList.hlist]; + intro proofs; destruct_head' PrimitiveProd.Primitive.prod. + all: try solve [ cbn; tauto ]. + all: cbn [rewrite_rules_interp_goodT_curried_cps_folded List.In projT2 projT1 Datatypes.fst Datatypes.snd] in *. + all: intro H; eapply rewrite_rules_interp_goodT_curried_cps_folded_Proper_impl; [ | eapply IHrews ]. + all: repeat first [ progress cbv [impl] + | progress destruct_head'_or + | progress inversion_sigma + | progress subst + | progress cbn [eq_rect Datatypes.snd hd tl] in * + | solve [ eauto using rewrite_rule_data_interp_goodT_by_curried ] + | progress intros ]. + Qed. End with_interp. End with_var. End Compile. - (** Now we prove the [wf] properties about definitions used only - in reification of rewrite rules, which are used to make proving - [wf] of concrete rewrite rules easier. *) + (** Now we prove the [wf] and [interp] properties about + definitions used only in reification of rewrite rules, which + are used to make proving [wf] / [interp] of concrete rewrite + rules easier. *) Module Reify. Import Compile. Import Rewriter.Compilers.RewriteRules.Compile. @@ -2713,7 +2848,7 @@ Module Compilers. | progress handle_wf_rec ltac:(fun tac => try tac (); tac ()) ]. Ltac reify_wf_t := repeat reify_wf_t_step. - Section with_var. + Section with_var2. Context {var1 var2 : type -> Type}. Lemma wf_reflect_ident_iota G {t} (idc : ident t) @@ -2871,7 +3006,266 @@ Module Compilers. | constructor | solve [ eauto ] ]. } Qed. - End with_var. + End with_var2. + + Section with_interp. + Context (cast_outside_of_range : ZRange.zrange -> Z -> Z). + + Local Notation ident_interp := (@ident.gen_interp cast_outside_of_range). + Local Notation var := (type.interp base.interp) (only parsing). + Local Notation expr := (@expr.expr base.type ident var). + Local Notation expr_interp_related := (@expr.interp_related _ ident _ (@ident_interp)). + Local Notation UnderLets_interp_related := (@UnderLets.interp_related _ ident _ (@ident_interp) _ _ expr_interp_related). + Local Notation value_interp_related := (@value_interp_related ident (@ident_interp)). + + Local Ltac fin_t := + repeat first [ reflexivity + | progress intros + | progress subst + | progress destruct_head'_unit + | solve [ eauto ] + | match goal with + | [ |- expr.interp_related _ (reify_list _) _ ] + => rewrite expr.reify_list_interp_related_iff + end + | match goal with H : _ |- _ => apply H end ]. + + (** TODO: MOVE ME *) + Local Ltac specialize_refls H := + lazymatch type of H with + | forall x y : ?T, x = y -> _ + => let H' := fresh in + constr:(fun x : T + => match H x x eq_refl return _ with + | H' + => ltac:(let v := specialize_refls H' in + exact v) + end) + | forall x : ?T, _ + => let H' := fresh in + constr:(fun x : T + => match H x return _ with + | H' => ltac:(let v := specialize_refls H' in exact v) + end) + | _ => H + end. + + Lemma reflect_ident_iota_interp_related {t} (idc : ident t) v1 v2 + : @reflect_ident_iota var t idc = Some v1 + -> ident_interp idc == v2 + -> value_interp_related v1 v2. + Proof using Type. + destruct idc; cbv [reflect_ident_iota]; intro; inversion_option; subst. + all: repeat + repeat + first [ progress expr.invert_subst + | progress cbn [type.related type.interp base.interp base.base_interp ident_interp value_interp_related expr.interp_related expr.interp_related_gen reify reflect value'] in * + | progress cbv [respectful value] in * + | progress intros + | progress subst + | break_innermost_match_step + | match goal with + | [ 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 : context[expr.interp_related _ (reify_list _)] |- _ ] + => rewrite expr.reify_list_interp_related_iff in H + | [ |- expr.interp_related_gen _ _ (reify_list _) _ ] + => rewrite expr.reify_list_interp_related_gen_iff + | [ |- UnderLets_interp_related (nat_rect _ _ _ _) (?f ?x ?y ?z) ] + => let v' := open_constr:(ident.Thunked.nat_rect _ x y z) in + replace (f x y z) with v'; + [ apply UnderLets.nat_rect_interp_related + | cbv [ident.Thunked.nat_rect]; solve [ fin_t ] ]; + try solve [ fin_t ]; intros + | [ |- UnderLets_interp_related (nat_rect _ _ _ _ _) (?f ?x ?y ?z ?w) ] + => let v' := open_constr:(nat_rect _ x y z w) in + replace (f x y z w) with v'; + [ eapply UnderLets.nat_rect_arrow_interp_related + | try solve [ fin_t ] ]; + try solve [ fin_t ]; intros + | [ H : context[list_rect (fun _ => ?B') _ _ _ = ?f _ _ _] + |- UnderLets.interp_related + ?ident_interp ?R + (list_rect + (fun _ : list (expr ?A) => UnderLets _ ?B) + ?Pnil + ?Pcons + ?ls) + (?f ?Pnil' ?Pcons' ?ls') ] + => erewrite <- H; + [ eapply (@UnderLets.list_rect_interp_related _ _ _ ident_interp A B Pnil Pcons ls B' (Pnil' tt) Pcons' ls' R) + | .. ]; try solve [ fin_t ]; intros + | [ H : context[list_rect (fun _ => ?B' -> ?C') _ _ _ _ = ?f _ _ _ _] + |- UnderLets.interp_related + ?ident_interp ?R + (list_rect + (fun _ : list (expr ?A) => ?B -> UnderLets _ ?C) + ?Pnil + ?Pcons + ?ls + ?x) + (?f ?Pnil' ?Pcons' ?ls' ?x') ] + => erewrite <- H; + [ eapply (@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)) + | .. ]; try solve [ fin_t ]; intros + end + | rewrite <- UnderLets.to_expr_interp_related_gen_iff + | eapply UnderLets.splice_interp_related_of_ex; + do 2 eexists; repeat apply conj; + [ now eauto | intros | reflexivity ]; + try solve [ fin_t ] + | progress (cbn [UnderLets.interp_related UnderLets.interp_related_gen expr.interp_related expr.interp_related_gen]; + repeat (do 2 eexists; repeat apply conj; intros)) + | solve + [ repeat + first + [ progress fin_t + | progress cbn [UnderLets.interp_related UnderLets.interp_related_gen expr.interp_related expr.interp_related_gen type.related] + | progress cbv [respectful] + | progress repeat (do 2 eexists; repeat apply conj; intros) ] ] + | match goal with + | [ H : context[forall x y, x = y -> _] |- _ ] + => let H' := specialize_refls H in + specialize H' + | [ H : forall x y z, nth_default x y z = ?f x y z |- ?R (nth_default _ _ _) (?f _ _ _) ] + => rewrite <- H; clear f H + end + | progress fin_t ]. + all: repeat first [ progress fin_t + | match goal with + | [ H : context[forall x y, x = y -> _] |- _ ] + => let H' := specialize_refls H in + specialize H' + end ]. + all: repeat match goal with + | [ H : forall x x' Hx y y' Hy z z' Hz, UnderLets_interp_related _ (?f _ _ _) |- ?f _ _ _ = ?f _ _ _ ] + => etransitivity; [ symmetry | ]; + apply (fun x x' Hx y y' Hy z z' Hz => UnderLets.eqv_of_interp_related _ (H x x' Hx y y' Hy z z' Hz)) + | [ H : forall x x' Hx y y' Hy z z' Hz w w' Hw, UnderLets_interp_related _ (?f _ _ _ _) |- ?f _ _ _ _ = ?f _ _ _ _ ] + => etransitivity; [ symmetry | ]; + apply (fun x x' Hx y y' Hy z z' Hz w w' Hw => UnderLets.eqv_of_interp_related _ (H x x' Hx y y' Hy z z' Hz w w' Hw)) + end. + all: cbn [type.interp base.interp base.base_interp]; intros. + all: repeat first [ progress cbn [UnderLets_interp_related UnderLets.interp_related_gen type.related] in * + | progress cbv [GallinaReify.Reify_as GallinaReify.reify] + | progress subst + | match goal with + | [ |- expr_interp_related ?ev ?v ] + => is_evar ev; instantiate (1:=GallinaReify.Reify v _); + cbn [expr_interp_related expr.interp_related_gen] + | [ |- UnderLets_interp_related (?f _) (?g _) ] + => is_evar f; + instantiate (1:=fun e => UnderLets.Base (GallinaReify.Reify (g (expr.interp (@ident_interp) e)) _)) + | [ |- expr_interp_related (GallinaReify.base.reify _) _ ] + => apply expr.reify_interp_related + | [ H : forall x, ?f x = ?g x |- expr_interp_related _ (?g _) ] + => rewrite <- H + | [ H : expr_interp_related _ _ |- _ ] => apply expr.eqv_of_interp_related in H + end ]. + Qed. + + Lemma reflect_expr_beta_iota_interp_related + {reflect_ident_iota} + (Hreflect_ident_iota + : forall t idc v1 v2, + reflect_ident_iota t idc = Some v1 + -> ident_interp idc == v2 + -> value_interp_related v1 v2) + {t} e v + (He : expr.interp_related_gen (@ident_interp) (fun t => value_interp_related) e v) + : UnderLets.interp_related + (@ident_interp) value_interp_related + (@reflect_expr_beta_iota ident _ reflect_ident_iota t e) + v. + Proof using Type. + revert dependent v; induction e; cbn [reflect_expr_beta_iota]; intros. + all: repeat first [ assumption + | match goal with + | [ |- UnderLets.interp_related_gen _ _ _ (UnderLets.splice (reflect_expr_beta_iota _ _) _) _ ] + => eapply UnderLets.splice_interp_related_gen_of_ex; + do 2 eexists; repeat apply conj; + [ match goal with + | [ IH : context[UnderLets.interp_related _ _ (reflect_expr_beta_iota _ _) _] |- _ ] + => eapply IH; eassumption + end + | intros | ] + | [ |- UnderLets.interp_related_gen _ _ _ (UnderLets.UnderLet (reify _) _) _ ] + => cbn [UnderLets.interp_related_gen]; + do 2 eexists; repeat apply conj; + [ apply reify_interp_related; eassumption + | intros | reflexivity ] + | [ |- UnderLets.interp_related _ _ (UnderLets.Base _) _ ] + => cbn [UnderLets.interp_related UnderLets.interp_related_gen] + | [ |- value_interp_related (splice_under_lets_with_value _ _) _ ] + => eapply interp_splice_under_lets_with_value_of_ex; + do 2 eexists; repeat apply conj; intros + | [ |- value_interp_related (Base_value _) _ ] + => apply interp_Base_value + | [ |- value_interp_related (reflect _) _ ] => apply reflect_interp_related + end + | break_innermost_match_step + | solve [ eauto ] + | progress cbn [value_interp_related]; intros + | progress cbn [expr.interp_related_gen] in * + | progress destruct_head'_ex + | progress destruct_head'_and + | progress subst + | progress cbv [UnderLets.interp_related] + | solve [ cbn [value_interp_related UnderLets.interp_related_gen] in *; eauto; repeat match goal with H : _ |- _ => eapply H end ] + | reflexivity + | match goal with H : _ |- _ => apply H end ]. + Qed. + + Lemma reify_expr_beta_iota_interp_related + {reflect_ident_iota} + (Hreflect_ident_iota + : forall t idc v1 v2, + reflect_ident_iota t idc = Some v1 + -> ident_interp idc == v2 + -> value_interp_related v1 v2) + {t} e v + (He : expr.interp_related_gen (@ident_interp) (fun t => value_interp_related) e v) + : UnderLets_interp_related + (@reify_expr_beta_iota ident _ reflect_ident_iota t e) + v. + Proof using Type. + cbv [reify_expr_beta_iota reify_to_UnderLets]. + eapply UnderLets.splice_interp_related_of_ex; do 2 eexists; repeat apply conj; + [ eapply reflect_expr_beta_iota_interp_related; eauto | | instantiate (1:=fun x => x); reflexivity ]; cbv beta. + intros; break_innermost_match; cbn [UnderLets.interp_related UnderLets.interp_related_gen value_interp_related] in *; try eassumption. + apply reify_interp_related; eauto. + Qed. + + Lemma expr_value_to_rewrite_rule_replacement_interp_related + {reflect_ident_iota} + (Hreflect_ident_iota + : forall t idc v1 v2, + reflect_ident_iota t idc = Some v1 + -> ident_interp idc == v2 + -> value_interp_related v1 v2) + (should_do_again : bool) + {t} e v + (He : expr.interp_related_gen (@ident_interp) (fun t => value_interp_related) e v) + : UnderLets.interp_related + (@ident_interp) (if should_do_again + return (@expr.expr base.type ident (if should_do_again then @value var else var) t) -> type.interp base.interp t -> Prop + then expr.interp_related_gen (@ident_interp) (fun t => value_interp_related) + else expr_interp_related) + (@expr_value_to_rewrite_rule_replacement ident var reflect_ident_iota should_do_again t e) + v. + Proof using Type. + cbv [expr_value_to_rewrite_rule_replacement]. + apply UnderLets.splice_interp_related_of_ex + with (RA:=expr.interp_related_gen (@ident_interp) (fun t => value_interp_related)); + do 2 eexists; repeat apply conj; intros; [ | | instantiate (2:=fun x => x); reflexivity ]; cbv beta. + { apply UnderLets.flat_map_interp_related_iff with (R'':=fun t => value_interp_related); + [ intros; now apply reify_expr_beta_iota_interp_related + | intros; apply reflect_interp_related; cbn; assumption + | now rewrite UnderLets.of_expr_interp_related_gen_iff ]. } + { break_innermost_match; cbn [UnderLets.interp_related UnderLets.interp_related_gen]; + now try apply reify_expr_beta_iota_interp_related. } + Qed. + End with_interp. End Reify. End RewriteRules. End Compilers. -- cgit v1.2.3