aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jason Gross <jgross@mit.edu>2019-02-01 17:21:39 -0500
committerGravatar Jason Gross <jasongross9@gmail.com>2019-03-07 13:33:20 -0500
commit0774eb4535eff89d0fd4eba3bc4c4f89864812b1 (patch)
treea398fc064bdd52274b2efdab1629f0ff7157d256
parentc1a5679d5b5c5ef0c07d618b4bb48451a8cb7a7a (diff)
Reify most rewrite rules
Currently we don't handle rules that require "concrete list of cons cells" nor rules that require "concrete nat literal to do recursion on"; both of these require special treatment, to be implemented in an upcoming commit. The reifier is kind-of slow, alas. After | File Name | Before || Change | % Change -------------------------------------------------------------------------------------------- 21m52.72s | Total | 21m20.90s || +0m31.82s | +2.48% -------------------------------------------------------------------------------------------- 1m12.22s | Rewriter.vo | 0m47.38s || +0m24.83s | +52.42% 3m14.35s | p384_32.c | 3m19.59s || -0m05.24s | -2.62% 1m45.12s | RewriterRulesGood.vo | 1m39.44s || +0m05.68s | +5.71% 0m40.82s | ExtractionHaskell/unsaturated_solinas | 0m37.58s || +0m03.24s | +8.62% 1m35.04s | RewriterRulesInterpGood.vo | 1m32.48s || +0m02.56s | +2.76% 0m59.49s | ExtractionHaskell/word_by_word_montgomery | 0m56.71s || +0m02.78s | +4.90% 1m45.10s | Fancy/Barrett256.vo | 1m47.00s || -0m01.90s | -1.77% 0m40.21s | p521_64.c | 0m38.97s || +0m01.24s | +3.18% 0m24.42s | SlowPrimeSynthesisExamples.vo | 0m25.67s || -0m01.25s | -4.86% 0m20.48s | secp256k1_32.c | 0m19.27s || +0m01.21s | +6.27% 1m47.10s | RewriterWf2.vo | 1m47.22s || -0m00.12s | -0.11% 0m47.85s | p521_32.c | 0m47.47s || +0m00.38s | +0.80% 0m45.66s | RewriterInterpProofs1.vo | 0m45.74s || -0m00.08s | -0.17% 0m37.18s | Fancy/Montgomery256.vo | 0m37.14s || +0m00.03s | +0.10% 0m36.26s | PushButtonSynthesis/UnsaturatedSolinas.vo | 0m36.14s || +0m00.11s | +0.33% 0m28.38s | ExtractionHaskell/saturated_solinas | 0m28.04s || +0m00.33s | +1.21% 0m26.80s | PushButtonSynthesis/WordByWordMontgomery.vo | 0m26.83s || -0m00.02s | -0.11% 0m24.00s | RewriterWf1.vo | 0m23.96s || +0m00.03s | +0.16% 0m19.82s | ExtractionOCaml/word_by_word_montgomery | 0m20.34s || -0m00.51s | -2.55% 0m19.65s | p256_32.c | 0m19.24s || +0m00.41s | +2.13% 0m18.54s | p448_solinas_64.c | 0m19.24s || -0m00.69s | -3.63% 0m16.18s | p434_64.c | 0m16.49s || -0m00.30s | -1.87% 0m13.67s | ExtractionOCaml/word_by_word_montgomery.ml | 0m14.47s || -0m00.80s | -5.52% 0m13.22s | ExtractionOCaml/unsaturated_solinas | 0m13.72s || -0m00.50s | -3.64% 0m09.91s | p224_32.c | 0m09.89s || +0m00.01s | +0.20% 0m09.85s | ExtractionOCaml/saturated_solinas | 0m09.83s || +0m00.01s | +0.20% 0m08.66s | ExtractionHaskell/word_by_word_montgomery.hs | 0m07.86s || +0m00.79s | +10.17% 0m08.36s | p384_64.c | 0m08.46s || -0m00.10s | -1.18% 0m07.72s | ExtractionOCaml/unsaturated_solinas.ml | 0m08.29s || -0m00.56s | -6.87% 0m06.66s | BoundsPipeline.vo | 0m06.73s || -0m00.07s | -1.04% 0m06.50s | ExtractionHaskell/unsaturated_solinas.hs | 0m06.56s || -0m00.05s | -0.91% 0m06.22s | ExtractionOCaml/saturated_solinas.ml | 0m05.69s || +0m00.52s | +9.31% 0m05.50s | ExtractionHaskell/saturated_solinas.hs | 0m05.88s || -0m00.37s | -6.46% 0m03.51s | PushButtonSynthesis/Primitives.vo | 0m03.48s || +0m00.02s | +0.86% 0m03.34s | PushButtonSynthesis/SmallExamples.vo | 0m03.32s || +0m00.02s | +0.60% 0m03.31s | curve25519_32.c | 0m03.13s || +0m00.18s | +5.75% 0m03.15s | PushButtonSynthesis/SaturatedSolinas.vo | 0m03.12s || +0m00.02s | +0.96% 0m03.11s | PushButtonSynthesis/BarrettReduction.vo | 0m03.08s || +0m00.02s | +0.97% 0m02.80s | PushButtonSynthesis/MontgomeryReduction.vo | 0m02.86s || -0m00.06s | -2.09% 0m02.13s | curve25519_64.c | 0m02.02s || +0m00.10s | +5.44% 0m01.58s | p256_64.c | 0m01.66s || -0m00.07s | -4.81% 0m01.53s | p224_64.c | 0m01.60s || -0m00.07s | -4.37% 0m01.49s | secp256k1_64.c | 0m01.72s || -0m00.23s | -13.37% 0m01.34s | CLI.vo | 0m01.23s || +0m00.11s | +8.94% 0m01.16s | RewriterProofs.vo | 0m01.10s || +0m00.05s | +5.45% 0m01.16s | StandaloneOCamlMain.vo | 0m01.13s || +0m00.03s | +2.65% 0m01.10s | CompilersTestCases.vo | 0m01.09s || +0m00.01s | +0.91% 0m01.07s | StandaloneHaskellMain.vo | 0m01.04s || +0m00.03s | +2.88%
-rw-r--r--src/Rewriter.v1694
-rw-r--r--src/RewriterRulesInterpGood.v5
2 files changed, 1264 insertions, 435 deletions
diff --git a/src/Rewriter.v b/src/Rewriter.v
index c39b2fe9f..1aefc35e8 100644
--- a/src/Rewriter.v
+++ b/src/Rewriter.v
@@ -5,9 +5,11 @@ Require Import Crypto.Util.ListUtil Coq.Lists.List Crypto.Util.ListUtil.FoldBool
Require Import Crypto.Util.Option.
Require Import Crypto.Util.OptionList.
Require Import Crypto.Util.CPSNotations.
+Require Import Crypto.Util.Bool.Reflect.
Require Import Crypto.Util.ZRange.
Require Import Crypto.Util.ZRange.Operations.
Require Import Crypto.Util.ZUtil.Definitions.
+Require Import Crypto.Util.ZUtil.Notations.
Require Crypto.Util.PrimitiveProd.
Require Crypto.Util.PrimitiveHList.
Require Import Crypto.Language.
@@ -72,6 +74,22 @@ Module Compilers.
=> @subst_default_relax (fun t => P (Compilers.base.type.option t)) A evm
end.
+ Fixpoint unsubst_default_relax P {t evm} : P (subst_default (relax t) evm) -> P t
+ := match t return P (subst_default (relax t) evm) -> P t with
+ | Compilers.base.type.type_base t => fun x => x
+ | Compilers.base.type.prod A B
+ => fun v
+ => @unsubst_default_relax
+ (fun A' => P (Compilers.base.type.prod A' _)) A evm
+ (@unsubst_default_relax
+ (fun B' => P (Compilers.base.type.prod _ B')) B evm
+ v)
+ | Compilers.base.type.list A
+ => @unsubst_default_relax (fun t => P (Compilers.base.type.list t)) A evm
+ | Compilers.base.type.option A
+ => @unsubst_default_relax (fun t => P (Compilers.base.type.option t)) A evm
+ end.
+
Fixpoint var_types_of (t : type) : Set
:= match t with
| type.var _ => Compilers.base.type
@@ -146,6 +164,18 @@ Module Compilers.
v)
end.
+ Fixpoint unsubst_default_relax P {t evm} : P (type.subst_default (type.relax t) evm) -> P t
+ := match t return P (type.subst_default (type.relax t) evm) -> P t with
+ | type.base t => base.unsubst_default_relax (fun t => P (type.base t))
+ | type.arrow A B
+ => fun v
+ => @unsubst_default_relax
+ (fun A' => P (type.arrow A' _)) A evm
+ (@unsubst_default_relax
+ (fun B' => P (type.arrow _ B')) B evm
+ v)
+ end.
+
Fixpoint var_types_of (t : type) : Set
:= match t with
| type.base t => base.var_types_of t
@@ -542,6 +572,44 @@ Module Compilers.
| expr.LetIn A B x f => expr.LetIn (@reify_expr _ x) (fun xv => @reify_expr _ (f (reflect (expr.Var xv))))
end.
+ (** N.B. In order to preserve the (currently unstated)
+ invariant that ensures that the rewriter does enough
+ rewriting, when we reify rewrite rules, we have to perform β
+ on the RHS to ensure that there are no var nodes holding
+ values which show up in the heads of app nodes. *)
+ Fixpoint reflect_expr_beta {t} (e : @expr.expr base.type ident value t)
+ : UnderLets (value t)
+ := match e in expr.expr t return UnderLets (value t) with
+ | expr.Var t v => UnderLets.Base v
+ | expr.Abs s d f => UnderLets.Base (fun x : value s => fx <----- @reflect_expr_beta d (f x); Base_value fx)
+ | expr.App s (type.base d) f x
+ => f <-- @reflect_expr_beta _ f;
+ x <-- @reflect_expr_beta _ x;
+ f x
+ | expr.App s (type.arrow _ _) f x
+ => f <-- @reflect_expr_beta _ f;
+ x <-- @reflect_expr_beta _ x;
+ UnderLets.Base (f x)
+ | expr.LetIn A B x f
+ => x <-- @reflect_expr_beta _ x;
+ UnderLets.UnderLet
+ (reify x)
+ (fun xv => @reflect_expr_beta _ (f (reflect (expr.Var xv))))
+ | expr.Ident t idc => UnderLets.Base (reflect (expr.Ident idc))
+ end%under_lets.
+
+ Definition reify_to_UnderLets {with_lets} {t} : value' with_lets t -> UnderLets (expr t)
+ := match t, with_lets return value' with_lets t -> UnderLets (expr t) with
+ | type.base _, false => fun v => UnderLets.Base v
+ | type.base _, true => fun v => v
+ | type.arrow s d, _
+ => fun f => UnderLets.Base (reify f)
+ end.
+
+ Definition reify_expr_beta {t} (e : @expr.expr base.type ident value t)
+ : UnderLets (@expr.expr base.type ident var t)
+ := e <-- @reflect_expr_beta t e; reify_to_UnderLets e.
+
Definition reify_and_let_binds_cps {with_lets} {t} : value' with_lets t -> forall T, (expr t -> UnderLets T) -> UnderLets T
:= match t, with_lets return value' with_lets t -> forall T, (expr t -> UnderLets T) -> UnderLets T with
| type.base _, false => reify_and_let_binds_base_cps _
@@ -643,6 +711,20 @@ Module Compilers.
(snd xy)
end.
+ Fixpoint lam_unification_resultT' {var t p evm K} {struct p}
+ : (@unification_resultT' var t p evm -> K) -> @with_unification_resultT' var t p evm K
+ := match p return (unification_resultT' p evm -> K) -> with_unification_resultT' p evm K with
+ | pattern.Wildcard t => fun f x => f x
+ | pattern.Ident t idc => lam_type_of_list
+ | pattern.App s d f x
+ => fun (F : unification_resultT' f _ * unification_resultT' x _ -> _)
+ => @lam_unification_resultT'
+ _ _ f _ _
+ (fun fv
+ => @lam_unification_resultT'
+ _ _ x _ _ (fun xv => F (fv, xv)))
+ end.
+
(** TODO: Maybe have a fancier version of this that doesn't
actually need to insert casts, by doing a fixpoint on the
list of elements / the evar map *)
@@ -696,6 +778,19 @@ Module Compilers.
(fun fx
=> k (existT _ _ fx)))%option.
+ Definition lam_unification_resultT {var' t p K}
+ : (forall v : @unification_resultT var' t p, K (pattern.type.subst_default t (projT1 v))) -> @with_unification_resultT var' t p K
+ := fun f
+ => pattern.type.lam_forall_vars
+ (fun evm
+ => lam_unification_resultT'
+ (K:=K (pattern.type.subst_default t evm))
+ (fun x' => f (existT (unification_resultT' p) evm x'))).
+
+ Definition partial_lam_unification_resultT {var' t p K}
+ : (forall evm, @with_unification_resultT' var' t p evm (K (pattern.type.subst_default t evm))) -> @with_unification_resultT var' t p K
+ := pattern.type.lam_forall_vars.
+
Definition under_with_unification_resultT {var t p K1 K2}
(F : forall evm, K1 (pattern.type.subst_default t evm) -> K2 (pattern.type.subst_default t evm))
: @with_unification_resultT var t p K1 -> @with_unification_resultT var t p K2
@@ -913,8 +1008,11 @@ Module Compilers.
end
end%option.
+ Local Notation expr_maybe_do_again should_do_again
+ := (@expr.expr base.type ident (if should_do_again then value else var)).
+
Local Notation deep_rewrite_ruleTP_gen' should_do_again with_opt under_lets t
- := (match (@expr.expr base.type ident (if should_do_again then value else var) t) with
+ := (match (expr_maybe_do_again should_do_again t) with
| x0 => match (if under_lets then UnderLets x0 else x0) with
| x1 => if with_opt then option x1 else x1
end
@@ -933,9 +1031,20 @@ Module Compilers.
| false, false => fun x => Some (UnderLets.Base x)
end%cps.
+ Definition with_unif_rewrite_ruleTP_gen' {var t} (p : pattern t) (should_do_again : bool) (with_opt : bool) (under_lets : bool) evm
+ := @with_unification_resultT' var t p evm (deep_rewrite_ruleTP_gen' should_do_again with_opt under_lets (pattern.type.subst_default t evm)).
+
Definition with_unif_rewrite_ruleTP_gen {var t} (p : pattern t) (should_do_again : bool) (with_opt : bool) (under_lets : bool)
:= @with_unification_resultT var t p (fun t => deep_rewrite_ruleTP_gen' should_do_again with_opt under_lets t).
+ Definition lam_unif_rewrite_ruleTP_gen {var t} (p : pattern t) (should_do_again : bool) (with_opt : bool) (under_lets : bool)
+ : _ -> @with_unif_rewrite_ruleTP_gen var t p should_do_again with_opt under_lets
+ := lam_unification_resultT.
+
+ Definition partial_lam_unif_rewrite_ruleTP_gen {var t} (p : pattern t) (should_do_again : bool) (with_opt : bool) (under_lets : bool)
+ : (forall evm, @with_unif_rewrite_ruleTP_gen' var t p should_do_again with_opt under_lets evm) -> @with_unif_rewrite_ruleTP_gen var t p should_do_again with_opt under_lets
+ := partial_lam_unification_resultT.
+
Record rewrite_rule_data {t} {p : pattern t} :=
{ rew_should_do_again : bool;
rew_with_opt : bool;
@@ -1209,6 +1318,559 @@ Module Compilers.
:= fun var => @rewrite var (rewrite_head var) fuel t (e _).
End Compile.
+ Module Reify.
+ Import Compile.
+ Local Notation EvarMap := pattern.EvarMap.
+
+ Inductive dynlist := dynnil | dyncons {T} (x : T) (xs : dynlist).
+
+ Section with_var.
+ Local Notation type_of_list
+ := (fold_right (fun a b => prod a b) unit).
+ Local Notation type_of_list_cps
+ := (fold_right (fun a K => a -> K)).
+ Context {ident var : type.type base.type -> Type}
+ {pident : type.type pattern.base.type -> Type}
+ (pident_arg_types : forall t, pident t -> list Type)
+ (pident_type_of_list_arg_types_beq : forall t idc, type_of_list (pident_arg_types t idc) -> type_of_list (pident_arg_types t idc) -> bool)
+ (pident_of_typed_ident : forall t, ident t -> pident (pattern.type.relax t))
+ (pident_arg_types_of_typed_ident : forall t (idc : ident t), type_of_list (pident_arg_types _ (pident_of_typed_ident t idc))).
+
+ Local Notation type := (type.type base.type).
+ Local Notation expr := (@expr.expr base.type ident var).
+ Local Notation pattern := (@pattern.pattern pident).
+ Local Notation ptype := (type.type pattern.base.type).
+ Local Notation value := (@Compile.value base.type ident var).
+ Local Notation value_with_lets := (@Compile.value_with_lets base.type ident var).
+ Local Notation UnderLets := (UnderLets.UnderLets base.type ident var).
+ Local Notation reify_expr_beta := (@reify_expr_beta ident var).
+ Local Notation unification_resultT' := (@unification_resultT' pident pident_arg_types).
+ Local Notation with_unif_rewrite_ruleTP_gen' := (@with_unif_rewrite_ruleTP_gen' ident var pident pident_arg_types value).
+ Local Notation lam_unification_resultT' := (@lam_unification_resultT' pident pident_arg_types).
+
+ Local Notation expr_maybe_do_again should_do_again
+ := (@expr.expr base.type ident (if should_do_again then value else var)).
+
+ Fixpoint pattern_of_expr (var' := fun _ => positive) evm (invalid : forall t, @expr.expr base.type ident var' t -> { p : pattern (pattern.type.relax t) & @unification_resultT' var' _ p evm })
+ {t} (e : @expr.expr base.type ident var' t)
+ : { p : pattern (pattern.type.relax t) & @unification_resultT' var' _ p evm }
+ := match e in expr.expr t return { p : pattern (pattern.type.relax t) & @unification_resultT' var' _ p evm } with
+ | expr.Ident t idc
+ => existT _ (pattern.Ident (pident_of_typed_ident _ idc))
+ (pident_arg_types_of_typed_ident _ idc)
+ | expr.Var t v
+ => existT _ (pattern.Wildcard _) v
+ | expr.App s d f x
+ => let 'existT fp fv := @pattern_of_expr evm invalid _ f in
+ let 'existT xp xv := @pattern_of_expr evm invalid _ x in
+ existT _ (pattern.App fp xp)
+ (fv, xv)
+ | expr.Abs _ _ _ as e
+ | expr.LetIn _ _ _ _ as e
+ => invalid _ e
+ end.
+
+ Definition expr_value_to_rewrite_rule_replacement (should_do_again : bool) {t} (e : @expr.expr base.type ident value t)
+ : UnderLets (expr_maybe_do_again should_do_again t)
+ := (e <-- UnderLets.flat_map (@reify_expr_beta) (fun t v => reflect (expr.Var v)) (UnderLets.of_expr e);
+ if should_do_again return UnderLets (expr_maybe_do_again should_do_again t)
+ then UnderLets.Base e
+ else reify_expr_beta e)%under_lets.
+
+ Fixpoint pair'_unification_resultT' {evm t p}
+ : @unification_resultT' (fun _ => positive) t p evm -> @unification_resultT' value t p evm -> PositiveMap.t { t : _ & value t } * list bool -> PositiveMap.t { t : _ & value t } * list bool
+ := match p return @unification_resultT' (fun _ => positive) _ p evm -> @unification_resultT' value _ p evm -> PositiveMap.t { t : _ & value t } * list bool -> PositiveMap.t { t : _ & value t } * list bool with
+ | pattern.Wildcard t => fun p v '(m, l) => (PositiveMap.add p (existT value _ v) m, l)
+ | pattern.Ident t idc => fun v1 v2 '(m, l) => (m, pident_type_of_list_arg_types_beq t idc v2 v1 :: l)
+ | pattern.App _ _ F X
+ => fun x y '(m, l)
+ => let '(m, l) := @pair'_unification_resultT' _ _ F (fst x) (fst y) (m, l) in
+ let '(m, l) := @pair'_unification_resultT' _ _ X (snd x) (snd y) (m, l) in
+ (m, l)
+ end.
+
+ Fixpoint expr_pos_to_expr_value
+ (invalid : forall t, positive * type * PositiveMap.t { t : _ & value t } -> @expr.expr base.type ident value t)
+ {t} (e : @expr.expr base.type ident (fun _ => positive) t) (m : PositiveMap.t { t : _ & value t }) (cur_i : positive)
+ : @expr.expr base.type ident value t
+ := match e in expr.expr t return expr.expr t with
+ | expr.Ident t idc => expr.Ident idc
+ | expr.App s d f x
+ => expr.App (@expr_pos_to_expr_value invalid _ f m cur_i)
+ (@expr_pos_to_expr_value invalid _ x m cur_i)
+ | expr.Var t v
+ => match option_map
+ (fun tv => type.try_transport base.try_make_transport_cps value _ t (projT2 tv))
+ (PositiveMap.find v m) with
+ | Some (Some res) => expr.Var res
+ | Some None | None => invalid _ (v, t, m)
+ end
+ | expr.Abs s d f
+ => expr.Abs (fun v => @expr_pos_to_expr_value invalid _ (f cur_i) (PositiveMap.add cur_i (existT value _ v) m) (Pos.succ cur_i))
+ | expr.LetIn A B x f
+ => expr.LetIn (@expr_pos_to_expr_value invalid _ x m cur_i)
+ (fun v => @expr_pos_to_expr_value invalid _ (f cur_i) (PositiveMap.add cur_i (existT value _ v) m) (Pos.succ cur_i))
+ end.
+
+ Definition expr_to_pattern_and_replacement
+ (should_do_again : bool) evm
+ (invalid : forall A B, A -> B)
+ {t} (lhs rhs : @expr.expr base.type ident (fun _ => positive) t)
+ (side_conditions : list bool)
+ : { p : pattern (pattern.type.relax t) & @with_unif_rewrite_ruleTP_gen' _ p should_do_again true true evm }
+ := let (p, unif_data_lhs) := @pattern_of_expr evm (fun _ => invalid _ _) t lhs in
+ existT
+ _
+ p
+ (pattern.type.subst_default_relax
+ (fun t'
+ => with_unification_resultT'
+ pident_arg_types p evm
+ (option (UnderLets (expr_maybe_do_again should_do_again t'))))
+ (lam_unification_resultT'
+ (fun unif_data_new
+ => let '(value_map, side_conditions) := pair'_unification_resultT' unif_data_lhs unif_data_new (PositiveMap.empty _, side_conditions) in
+ let start_i := Pos.succ (PositiveMap.fold (fun k _ max => Pos.max k max) value_map 1%positive) in
+ let replacement := expr_pos_to_expr_value (fun _ => invalid _ _) rhs value_map start_i in
+ let replacement := expr_value_to_rewrite_rule_replacement should_do_again replacement in
+ if fold_left andb (List.rev side_conditions) true
+ then Some replacement
+ else None))).
+
+
+ Definition expr_to_pattern_and_replacement_unfolded should_do_again evm invalid {t} lhs rhs side_conditions
+ := Eval cbv beta iota delta [expr_to_pattern_and_replacement pattern_of_expr lam_unification_resultT' Pos.succ pair'_unification_resultT' PositiveMap.empty PositiveMap.fold Pos.max expr_pos_to_expr_value expr_value_to_rewrite_rule_replacement fold_left List.rev List.app value PositiveMap.add PositiveMap.xfoldi Pos.compare Pos.compare_cont FMapPositive.append projT1 projT2 PositiveMap.find Base_value (*UnderLets.map reify_expr_beta reflect_expr_beta*) lam_type_of_list fold_right list_rect pattern.type.relax pattern.type.subst_default pattern.type.subst_default_relax pattern.type.unsubst_default_relax option_map unification_resultT' with_unification_resultT' with_unif_rewrite_ruleTP_gen']
+ in @expr_to_pattern_and_replacement should_do_again evm invalid t lhs rhs side_conditions.
+
+ Definition partial_lam_unif_rewrite_ruleTP_gen_unfolded should_do_again {t} p
+ := Eval cbv beta iota delta [partial_lam_unif_rewrite_ruleTP_gen pattern.collect_vars pattern.type.lam_forall_vars partial_lam_unification_resultT pattern.type.collect_vars pattern.base.collect_vars PositiveSet.union PositiveSet.add PositiveSet.empty pattern.type.lam_forall_vars_gen List.rev PositiveSet.elements PositiveSet.xelements PositiveSet.rev PositiveSet.rev_append List.app orb fold_right PositiveMap.add PositiveMap.empty]
+ in @partial_lam_unif_rewrite_ruleTP_gen ident var pident pident_arg_types value t p should_do_again true true.
+ End with_var.
+
+ Ltac strip_functional_dependency term :=
+ lazymatch term with
+ | fun _ => ?P => P
+ | _ => let __ := match goal with _ => idtac "Cannot eliminate functional dependencies of" term; fail 1 "Cannot eliminate functional dependencies of" term end in
+ constr:(I : I)
+ end.
+
+ Ltac reify_under_forall_types' ty_ctx cur_i lem cont :=
+ lazymatch lem with
+ | forall T : Type, ?P
+ => let P' := fresh in
+ let ty_ctx' := fresh "ty_ctx" in
+ let t := fresh "t" in
+ strip_functional_dependency
+ (fun t : Compilers.base.type
+ => match PositiveMap.add cur_i t ty_ctx return _ with
+ | ty_ctx'
+ => match Compilers.base.interp (pattern.base.lookup_default cur_i ty_ctx') return _ with
+ | T
+ => match P return _ with
+ | P'
+ => ltac:(let P := (eval cbv delta [P' T ty_ctx'] in P') in
+ let ty_ctx := (eval cbv delta [ty_ctx'] in ty_ctx') in
+ clear P' T ty_ctx';
+ let cur_i := (eval vm_compute in (Pos.succ cur_i)) in
+ let res := reify_under_forall_types' ty_ctx cur_i P cont in
+ exact res)
+ end
+ end
+ end)
+ | ?lem => cont ty_ctx cur_i lem
+ end.
+
+ Ltac prop_to_bool H := eval cbv [decb] in (decb H).
+
+
+ Ltac push_side_conditions H side_conditions :=
+ constr:(H :: side_conditions).
+
+ Ltac equation_to_parts' lem side_conditions :=
+ lazymatch lem with
+ | ?H -> ?P
+ => let H := prop_to_bool H in
+ let side_conditions := push_side_conditions H side_conditions in
+ equation_to_parts' P side_conditions
+ | forall x : ?T, ?P
+ => let P' := fresh in
+ constr:(
+ fun x : T
+ => match P return _ with
+ | P'
+ => ltac:(let P := (eval cbv delta [P'] in P') in
+ clear P';
+ let res := equation_to_parts' P side_conditions in
+ exact res)
+ end)
+ | @eq ?T ?A ?B
+ => constr:((@eq T A B, side_conditions))
+ | ?T => let __ := match goal with _ => fail 1 "Invalid type of equation:" T end in
+ constr:(I : I)
+ end.
+ Ltac equation_to_parts lem :=
+ equation_to_parts' lem (@nil bool).
+
+ Ltac reify_under_forall_types lem cont :=
+ reify_under_forall_types' (@PositiveMap.empty Compilers.base.type) (1%positive) lem cont.
+
+ Ltac preadjust_pattern_type_variables pat :=
+ let pat := (eval cbv [pattern.type.relax pattern.type.subst_default pattern.type.subst_default_relax pattern.type.unsubst_default_relax] in pat) in
+ let pat := (eval cbn [pattern.base.relax pattern.base.subst_default pattern.base.subst_default_relax pattern.base.unsubst_default_relax] in pat) in
+ pat.
+
+ Ltac adjust_pattern_type_variables' pat :=
+ lazymatch pat with
+ | context[pattern.base.relax (pattern.base.lookup_default ?p ?evm')]
+ => let t := constr:(pattern.base.relax (pattern.base.lookup_default p evm')) in
+ let T := fresh in
+ let pat :=
+ lazymatch (eval pattern t in pat) with
+ | ?pat _
+ => let P := match type of pat with forall x, @?P x => P end in
+ lazymatch pat with
+ | fun T => ?pat
+ => constr:(match pattern.base.type.var p as T return P T with
+ | T => pat
+ end)
+ end
+ end in
+ adjust_pattern_type_variables' pat
+ | ?pat => pat
+ end.
+
+ Ltac adjust_pattern_type_variables pat :=
+ let pat := preadjust_pattern_type_variables pat in
+ adjust_pattern_type_variables' pat.
+
+ Ltac strip_invalid_or_fail term :=
+ lazymatch term with
+ | fun _ => ?f => f
+ | fun invalid : ?T => ?f
+ => let f' := fresh in
+ constr:(fun invalid : T
+ => match f return _ with
+ | f'
+ => ltac:(lazymatch (eval cbv [f'] in f') with
+ | context[invalid _ _ ?x]
+ => fail 0 "Invalid:" x
+ | context[invalid _ ?x]
+ => fail 0 "Invalid:" x
+ end)
+ end)
+ end.
+
+ Definition pattern_base_subst_default_relax' t evm P
+ := @pattern.base.subst_default_relax P t evm.
+ Definition pattern_base_unsubst_default_relax' t evm P
+ := @pattern.base.unsubst_default_relax P t evm.
+
+ Ltac change_pattern_base_subst_default_relax term :=
+ lazymatch (eval pattern (@pattern.base.subst_default_relax), (@pattern.base.unsubst_default_relax) in term) with
+ | ?f _ _
+ => let P := fresh "P" in
+ let t := fresh "t" in
+ let evm := fresh "evm" in
+ (eval cbv beta in (f (fun P t evm => @pattern_base_subst_default_relax' t evm P) (fun P t evm => @pattern_base_unsubst_default_relax' t evm P)))
+ end.
+
+ Ltac adjust_lookup_default rewr :=
+ lazymatch (eval pattern pattern.base.lookup_default in rewr) with
+ | ?rewr _
+ => let p := fresh "p" in
+ let evm := fresh "evm" in
+ (eval cbv beta in (rewr (fun p evm => pattern.base.subst_default (pattern.base.type.var p) evm)))
+ end.
+
+ Ltac replace_evar_map evm rewr :=
+ let evm' := match rewr with
+ | context[pattern.base.lookup_default _ ?evm']
+ => let __ := match goal with _ => tryif constr_eq evm evm' then fail else idtac end in
+ evm'
+ | context[pattern.base.subst_default _ ?evm']
+ => let __ := match goal with _ => tryif constr_eq evm evm' then fail else idtac end in
+ evm'
+ | _ => tt
+ end in
+ lazymatch evm' with
+ | tt => rewr
+ | _
+ => let rewr := lazymatch (eval pattern evm' in rewr) with
+ | ?rewr _ => (eval cbv beta in (rewr evm))
+ end in
+ replace_evar_map evm rewr
+ end.
+
+ Ltac adjust_type_variables rewr :=
+ lazymatch rewr with
+ | context[pattern.base.subst_default (pattern.base.relax ?t) ?evm'']
+ => let t' := constr:(pattern.base.subst_default (pattern.base.relax t) evm'') in
+ let rewr :=
+ lazymatch (eval pattern
+ t',
+ (pattern_base_subst_default_relax' t evm''),
+ (pattern_base_unsubst_default_relax' t evm'')
+ in rewr)
+ with
+ | ?rewr _ _ _
+ => (eval cbv beta in (rewr t (fun P x => x) (fun P x => x)))
+ end in
+ adjust_type_variables rewr
+ | _ => rewr
+ end.
+
+ Ltac replace_type_try_transport term :=
+ lazymatch term with
+ | context[@type.try_transport ?base_type ?try_make_transport_base_type_cps ?P ?t ?t]
+ => let v := constr:(@type.try_transport base_type try_make_transport_base_type_cps P t t) in
+ let term := lazymatch (eval pattern v in term) with
+ | ?term _ => (eval cbv beta in (term (@Some _)))
+ end in
+ replace_type_try_transport term
+ | _ => term
+ end.
+
+ Ltac under_binders term cont ctx :=
+ lazymatch term with
+ | (fun x : ?T => ?f)
+ => let ctx' := fresh in
+ let f' := fresh in
+ constr:(fun x : T
+ => match f, dyncons x ctx return _ with
+ | f', ctx'
+ => ltac:(let ctx := (eval cbv delta [ctx'] in ctx') in
+ let f := (eval cbv delta [f'] in f') in
+ clear f' ctx';
+ let res := under_binders f cont ctx in
+ exact res)
+ end)
+ | ?term => cont ctx term
+ end.
+ Ltac substitute_with term x y :=
+ lazymatch (eval pattern y in term) with
+ | (fun z => ?term) _ => constr:(match x return _ with z => term end)
+ end.
+ Ltac substitute_beq_with full_ctx term beq x :=
+ let is_good y :=
+ lazymatch full_ctx with
+ | context[dyncons y _] => fail
+ | _ => is_var y
+ end in
+ let y := match term with
+ | context term' [beq x ?y]
+ => let __ := is_good y in
+ constr:(Some (beq x y))
+ | context term' [@base.interp_beq ?t x ?y]
+ => let __ := is_good y in
+ constr:(Some (@base.interp_beq t x y))
+ | context term' [@base.base_interp_beq ?t x ?y]
+ => let __ := is_good y in
+ constr:(Some (@base.base_interp_beq t x y))
+ | _ => constr:(@None unit)
+ end in
+ lazymatch y with
+ | Some (?beq x ?y)
+ => lazymatch term with
+ | context term'[beq x y]
+ => let term := context term'[true] in
+ substitute_with term x y
+ end
+ | None => term
+ end.
+ Ltac remove_andb_true term :=
+ let term := lazymatch (eval pattern andb, (andb true) in term) with
+ | ?f _ _ => (eval cbn [andb] in (f (fun x y => andb y x) (fun b => b)))
+ end in
+ let term := lazymatch (eval pattern andb, (andb true) in term) with
+ | ?f _ _ => (eval cbn [andb] in (f (fun x y => andb y x) (fun b => b)))
+ end in
+ term.
+ Ltac adjust_if_negb term :=
+ lazymatch term with
+ | context term'[if negb ?x then ?a else ?b]
+ => let term := context term'[if x then b else a] in
+ adjust_if_negb term
+ | _ => term
+ end.
+ Ltac substitute_bool_eqb term :=
+ lazymatch term with
+ | context term'[Bool.eqb ?x true]
+ => let term := context term'[x] in
+ substitute_bool_eqb term
+ | context term'[Bool.eqb ?x false]
+ => let term := context term'[negb x] in
+ substitute_bool_eqb term
+ | context term'[Bool.eqb true ?x]
+ => let term := context term'[x] in
+ substitute_bool_eqb term
+ | context term'[Bool.eqb false ?x]
+ => let term := context term'[negb x] in
+ substitute_bool_eqb term
+ | _ => term
+ end.
+
+ Ltac substitute_beq full_ctx ctx term :=
+ lazymatch ctx with
+ | dynnil
+ => let term := (eval cbv [base.interp_beq base.base_interp_beq] in term) in
+ let term := substitute_bool_eqb term in
+ let term := remove_andb_true term in
+ let term := adjust_if_negb term in
+ term
+ | dyncons ?v ?ctx
+ => let term := substitute_beq_with full_ctx term zrange_beq v in
+ let term := substitute_beq_with full_ctx term Z.eqb v in
+ let term := match constr:(Set) with
+ | _ => let T := type of v in
+ let beq := (eval cbv beta delta [Reflect.decb_rel] in (Reflect.decb_rel (@eq T))) in
+ substitute_beq_with full_ctx term beq v
+ | _ => term
+ end in
+ substitute_beq full_ctx ctx term
+ end.
+
+ Ltac deep_substitute_beq term :=
+ lazymatch term with
+ | context term'[@Build_rewrite_rule_data ?ident ?var ?pident ?pident_arg_types ?t ?p ?sda ?wo ?ul ?subterm]
+ => let subterm := under_binders subterm ltac:(fun ctx term => substitute_beq ctx ctx term) dynnil in
+ let term := context term'[@Build_rewrite_rule_data ident var pident pident_arg_types t p sda wo ul subterm] in
+ term
+ end.
+
+ Ltac clean_beq term :=
+ let term := (eval cbn [Prod.prod_beq] in term) in
+ let term := (eval cbv [ident.literal] in term) in
+ let term := deep_substitute_beq term in
+ let term := (eval cbv [base.interp_beq base.base_interp_beq] in term) in
+ let term := remove_andb_true term in
+ term.
+
+
+ Ltac reify_to_pattern_and_replacement_in_context ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident type_ctx var should_do_again cur_i term value_ctx :=
+ let t := fresh "t" in
+ let p := fresh "p" in
+ let reify_rec_gen type_ctx := reify_to_pattern_and_replacement_in_context ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident type_ctx var should_do_again in
+ let var_pos := constr:(fun _ : type base.type => positive) in
+ let value := constr:(@value base.type ident var) in
+ let cexpr_to_pattern_and_replacement_unfolded := constr:(@expr_to_pattern_and_replacement_unfolded ident var pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident should_do_again type_ctx) in
+ let cpartial_lam_unif_rewrite_ruleTP_gen := constr:(@partial_lam_unif_rewrite_ruleTP_gen_unfolded ident var pident pident_arg_types should_do_again) in
+ let cwith_unif_rewrite_ruleTP_gen := constr:(fun t p => @with_unif_rewrite_ruleTP_gen ident var pident pident_arg_types value t p should_do_again true true) in
+ lazymatch term with
+ | (fun x : ?T => ?f)
+ => let rT := Compilers.type.reify ltac:(Compilers.base.reify) base.type T in
+ let not_x1 := fresh in
+ let not_x2 := fresh in
+ let next_i := (eval vm_compute in (Pos.succ cur_i)) in
+ let type_ctx' := fresh in (* COQBUG(https://github.com/coq/coq/issues/7210#issuecomment-470009463) *)
+ let rf0 :=
+ constr:(
+ match type_ctx return _ with
+ | type_ctx'
+ => fun (x : T)
+ => match f, @expr.var_context.cons base.type var_pos T rT x cur_i value_ctx return _ with (* c.f. COQBUG(https://github.com/coq/coq/issues/6252#issuecomment-347041995) for [return _] *)
+ | not_x1, not_x2
+ => ltac:(
+ let f := (eval cbv delta [not_x1] in not_x1) in
+ let value_ctx := (eval cbv delta [not_x2] in not_x2) in
+ let type_ctx := (eval cbv delta [type_ctx'] in type_ctx') in
+ clear not_x1 not_x2 type_ctx';
+ let rf := reify_rec_gen type_ctx next_i f value_ctx in
+ exact rf)
+ end
+ end) in
+ lazymatch rf0 with
+ | (fun _ => ?f) => f
+ | _
+ => let __ := match goal with
+ | _ => fail 1 "Failure to eliminate functional dependencies of" rf0
+ end in
+ constr:(I : I)
+ end
+ | (@eq ?T ?A ?B, ?side_conditions)
+ => let rA := expr.reify_in_context base.type ident ltac:(base.reify) reify_ident var_pos A value_ctx tt in
+ let rB := expr.reify_in_context base.type ident ltac:(base.reify) reify_ident var_pos B value_ctx tt in
+ let invalid := fresh "invalid" in
+ let res := constr:(fun invalid => cexpr_to_pattern_and_replacement_unfolded invalid _ rA rB side_conditions) in
+ let res := (eval cbv [expr_to_pattern_and_replacement_unfolded pident_arg_types pident_of_typed_ident pident_type_of_list_arg_types_beq pident_arg_types_of_typed_ident] in res) in
+ let res := (eval cbn [fst snd andb pattern.base.relax pattern.base.subst_default pattern.base.subst_default_relax] in res) in
+ let res := change_pattern_base_subst_default_relax res in
+ let p := (eval cbv [projT1] in (fun invalid => projT1 (res invalid))) in
+ let p := strip_invalid_or_fail p in
+ let p := adjust_pattern_type_variables p in
+ let res := (eval cbv [projT2] in (fun invalid => projT2 (res invalid))) in
+ let evm' := fresh "evm" in
+ let res' := fresh in
+ let res :=
+ constr:(
+ fun invalid (evm' : EvarMap)
+ => match res invalid return _ with
+ | res'
+ => ltac:(let res := (eval cbv beta delta [res'] in res') in
+ clear res';
+ let res := adjust_lookup_default res in
+ let res := adjust_type_variables res in
+ let res := replace_evar_map evm' res in
+ let res := replace_type_try_transport res in
+ exact res)
+ end) in
+ let res := (eval cbv [UnderLets.map UnderLets.flat_map reify_expr_beta reflect_expr_beta reify_to_UnderLets] in res) in
+ let res := (eval cbn [reify reflect UnderLets.of_expr UnderLets.to_expr UnderLets.splice value' Base_value] in res) in
+ let res := strip_invalid_or_fail res in
+ (* cbv here not strictly needed *)
+ let res := (eval cbv [partial_lam_unif_rewrite_ruleTP_gen_unfolded] in
+ (existT
+ (cwith_unif_rewrite_ruleTP_gen _)
+ p
+ (cpartial_lam_unif_rewrite_ruleTP_gen _ p res))) in
+ (* not strictly needed *)
+ let res := (eval cbn [pattern.base.subst_default pattern.base.lookup_default PositiveMap.find type.interp base.interp base.base_interp] in res) in
+ let res := (eval cbv [projT1 projT2] in
+ (existT
+ (@rewrite_ruleTP ident var pident pident_arg_types)
+ {| pattern.pattern_of_anypattern := projT1 res |}
+ {| rew_replacement := projT2 res |})) in
+ let res := clean_beq res in
+ res
+ end.
+
+ Ltac reify ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident var should_do_again lem :=
+ reify_under_forall_types
+ lem
+ ltac:(
+ fun ty_ctx cur_i lem
+ => let lem := equation_to_parts lem in
+ let res := reify_to_pattern_and_replacement_in_context ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident ty_ctx var should_do_again constr:(1%positive) lem (@expr.var_context.nil base.type (fun _ => positive)) in
+ res).
+
+ Ltac Reify ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident should_do_again lem :=
+ let var := fresh "var" in
+ constr:(fun var : Compilers.type.type Compilers.base.type -> Type
+ => ltac:(let res := reify ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident var should_do_again lem in
+ exact res)).
+
+ (* lems is either a list of [Prop]s, or a list of [bool (* should_do_again *) * Prop] *)
+ Ltac reify_list ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident var lems :=
+ let reify' := reify ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident var in
+ let reify_list_rec := reify_list ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident var in
+ lazymatch lems with
+ | (?b, ?lem) :: ?lems
+ => let rlem := reify' b lem in
+ let rlems := reify_list_rec lems in
+ constr:(rlem :: rlems)
+ | nil => constr:(@nil (@rewrite_ruleT ident var pident pident_arg_types))
+ | _
+ => let lems := (eval cbv beta iota delta [List.map] in
+ (List.map (fun p : Prop => (false, p)) lems)) in
+ reify_list_rec lems
+ end.
+
+ Ltac Reify_list ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident lems :=
+ let var := fresh "var" in
+ constr:(fun var : Compilers.type.type Compilers.base.type -> Type
+ => ltac:(let res := reify_list ident reify_ident pident pident_arg_types pident_type_of_list_arg_types_beq pident_of_typed_ident pident_arg_types_of_typed_ident var lems in
+ exact res)).
+ End Reify.
+
Module Make.
Section make_rewrite_rules.
Import Compile.
@@ -1479,6 +2141,14 @@ Module Compilers.
Definition invert_bind_args_unknown := @pattern.Raw.ident.invert_bind_args.
Local Notation assemble_identifier_rewriters := (@assemble_identifier_rewriters ident var (@pattern.ident.eta_ident_cps) (@pattern.ident) (@pattern.ident.arg_types) (@pattern.ident.unify) pident_unify_unknown pattern.Raw.ident (@pattern.Raw.ident.full_types) (@pattern.Raw.ident.invert_bind_args) invert_bind_args_unknown (@pattern.Raw.ident.type_of) (@pattern.Raw.ident.to_typed) pattern.Raw.ident.is_simple).
+ Ltac reify lems :=
+ Reify.reify_list ident ident.reify pattern.ident (@pattern.ident.arg_types) (@pattern.ident.type_of_list_arg_types_beq) (@pattern.ident.of_typed_ident) (@pattern.ident.arg_types_of_typed_ident) var lems.
+ (* Play games with [match] to get [lems] interpreted as a constr rather than an ident when it's not closed, to get better error messages *)
+ Local Notation reify lems
+ := (match lems return _ with
+ | _LEMS => ltac:(let LEMS := (eval cbv delta [_LEMS] in _LEMS) in let res := reify LEMS in exact res)
+ end) (only parsing).
+
Delimit Scope rewrite_scope with rewrite.
Delimit Scope rewrite_opt_scope with rewrite_opt.
Delimit Scope rewrite_lets_scope with rewrite_lets.
@@ -1553,6 +2223,7 @@ Module Compilers.
Local Notation ℕ := base.type.nat.
Local Notation bool := base.type.bool.
Local Notation list := pattern.base.type.list.
+ Local Notation "' x" := (ident.literal x).
(*
Local Arguments Make.interp_rewrite_rules / .
@@ -1595,16 +2266,25 @@ Module Compilers.
Local Arguments pattern.anypattern : clear implicits.
Local Arguments Make.interp_rewrite_rules / .
Let myapp {A} := Eval cbv [List.app] in @List.app A.
+ Let myflatten {A} := Eval cbv in List.fold_right myapp (@nil A).
+ Local Notation do_again P := (true, P) (only parsing).
+ Local Notation cstZ := (ident.cast ident.cast_outside_of_range).
+ Local Notation cstZZ := (ident.cast2 ident.cast_outside_of_range).
Definition nbe_rewrite_rules : rewrite_rulesT
- := Eval cbv [Make.interp_rewrite_rules myapp] in
+ := Eval cbv [Make.interp_rewrite_rules myapp myflatten] in
myapp
Make.interp_rewrite_rules
- [make_rewrite (#(@pattern.ident.fst '1 '2) @ (??, ??)) (fun _ _ x y => x)
- ; make_rewrite (#(@pattern.ident.snd '1 '2) @ (??, ??)) (fun _ x _ y => y)
- ; make_rewrite (#(@pattern.ident.List_repeat '1) @ ?? @ #?ℕ) (fun _ x n => reify_list (repeat x n))
- ; make_rewritel (#(@pattern.ident.bool_rect '1) @ ?? @ ?? @ #?𝔹) (fun _ t f b => if b then t ##tt else f ##tt)
- ; make_rewritel (#(@pattern.ident.prod_rect '1 '2 '3) @ ?? @ (??, ??)) (fun _ _ _ f x y => f x y)
- ; make_rewriteol (??{list '1} ++ ??{list '1}) (fun _ xs ys => rlist_rect ys (fun x _ xs_ys => x :: xs_ys) xs)
+ (myflatten
+ [
+ (reify
+ [(forall A B x y, @fst A B (x, y) = x)
+ ; (forall A B x y, @snd A B (x, y) = y)
+ ; (forall P t f, @ident.Thunked.bool_rect P t f true = t tt)
+ ; (forall P t f, @ident.Thunked.bool_rect P t f false = f tt)
+ ; (forall A B C f x y, @prod_rect A B (fun _ => C) f (x, y) = f x y)
+ ])
+ ; [make_rewrite (#(@pattern.ident.List_repeat '1) @ ?? @ #?ℕ) (fun _ x n => reify_list (repeat x n))
+ ; make_rewriteol (??{list '1} ++ ??{list '1}) (fun _ xs ys => rlist_rect ys (fun x _ xs_ys => x :: xs_ys) xs)
; make_rewriteol
(#(@pattern.ident.List_firstn '1) @ #?ℕ @ ??)
(fun _ n xs => xs <- reflect_list xs; reify_list (List.firstn n xs))
@@ -1641,14 +2321,14 @@ Module Compilers.
; make_rewriteol
(#(@pattern.ident.list_rect '1 '2) @ ?? @ ?? @ ??)
(fun _ _ Pnil Pcons xs
- => rlist_rect (Pnil ##tt) (fun x' xs' rec => Pcons x' (reify_list xs') rec) xs)
- ; make_rewritel
- (#(@pattern.ident.list_case '1 '2) @ ?? @ ?? @ [])
- (fun _ _ Pnil Pcons => Pnil ##tt)
- ; make_rewritel
- (#(@pattern.ident.list_case '1 '2) @ ?? @ ?? @ (?? :: ??))
- (fun _ _ Pnil Pcons x xs => Pcons x xs)
- ; make_rewriteol
+ => rlist_rect (Pnil ##tt) (fun x' xs' rec => Pcons x' (reify_list xs') rec) xs) ]
+
+ ; (reify
+ [(forall A P N C, @ident.Thunked.list_case A P N C nil = N tt)
+ ; (forall A P N C x xs, @ident.Thunked.list_case A P N C (x :: xs) = C x xs)
+ ])
+ ; [
+ make_rewriteol
(#(@pattern.ident.List_map '1 '2) @ ?? @ ??)
(fun _ _ f xs => rlist_rect [] (fun x _ fxs => fx <-- f x; fx :: fxs) xs)
; make_rewriteo
@@ -1680,71 +2360,92 @@ Module Compilers.
(fun x => x <-- x; f x)
(List.map UnderLets.Base ls));
reify_list retv)
- ].
+ ] ]).
Definition arith_rewrite_rules (max_const_val : Z) : rewrite_rulesT
- := [make_rewrite (#(@pattern.ident.fst '1 '2) @ (??, ??)) (fun _ _ x y => x)
- ; make_rewrite (#(@pattern.ident.snd '1 '2) @ (??, ??)) (fun _ x _ y => y)
- ; make_rewriteo (#?ℤ + ??) (fun z v => v when z =? 0)
- ; make_rewriteo (?? + #?ℤ ) (fun v z => v when z =? 0)
- ; make_rewriteo (#?ℤ + (-??)) (fun z v => ##z - v when z >? 0)
- ; make_rewriteo ((-??) + #?ℤ ) (fun v z => ##z - v when z >? 0)
- ; make_rewriteo (#?ℤ + (-??)) (fun z v => -(##((-z)%Z) + v) when z <? 0)
- ; make_rewriteo ((-??) + #?ℤ ) (fun v z => -(v + ##((-z)%Z)) when z <? 0)
- ; make_rewrite ((-??) + (-??)) (fun x y => -(x + y))
- ; make_rewrite ((-??) + ?? ) (fun x y => y - x)
- ; make_rewrite ( ?? + (-??)) (fun x y => x - y)
-
- ; make_rewriteo (#?ℤ - (-??)) (fun z v => v when z =? 0)
- ; make_rewriteo (#?ℤ - ?? ) (fun z v => -v when z =? 0)
- ; make_rewriteo (?? - #?ℤ ) (fun v z => v when z =? 0)
- ; make_rewriteo (#?ℤ - (-??)) (fun z v => ##z + v when z >? 0)
- ; make_rewriteo (#?ℤ - (-??)) (fun z v => v - ##((-z)%Z) when z <? 0)
- ; make_rewriteo (#?ℤ - ?? ) (fun z v => -(##((-z)%Z) + v) when z <? 0)
- ; make_rewriteo ((-??) - #?ℤ ) (fun v z => -(v + ##(z)) when z >? 0)
- ; make_rewriteo ((-??) - #?ℤ ) (fun v z => ##((-z)%Z) - v when z <? 0)
- ; make_rewriteo ( ?? - #?ℤ ) (fun v z => v + ##((-z)%Z) when z <? 0)
- ; make_rewrite ((-??) - (-??)) (fun x y => y - x)
- ; make_rewrite ((-??) - ?? ) (fun x y => -(x + y))
- ; make_rewrite ( ?? - (-??)) (fun x y => x + y)
-
- ; make_rewrite (#?ℤ * #?ℤ ) (fun x y => ##((x*y)%Z))
- ; make_rewriteo (#?ℤ * ??) (fun z v => ##0 when z =? 0)
- ; make_rewriteo (?? * #?ℤ ) (fun v z => ##0 when z =? 0)
- ; make_rewriteo (#?ℤ * ??) (fun z v => v when z =? 1)
- ; make_rewriteo (?? * #?ℤ ) (fun v z => v when z =? 1)
- ; make_rewriteo (#?ℤ * (-??)) (fun z v => v when z =? (-1))
- ; make_rewriteo ((-??) * #?ℤ ) (fun v z => v when z =? (-1))
- ; make_rewriteo (#?ℤ * ?? ) (fun z v => -v when z =? (-1))
- ; make_rewriteo (?? * #?ℤ ) (fun v z => -v when z =? (-1))
- ; make_rewriteo (#?ℤ * ?? ) (fun z v => -(##((-z)%Z) * v) when z <? 0)
- ; make_rewriteo (?? * #?ℤ ) (fun v z => -(v * ##((-z)%Z)) when z <? 0)
- ; make_rewrite ((-??) * (-??)) (fun x y => x * y)
- ; make_rewrite ((-??) * ?? ) (fun x y => -(x * y))
- ; make_rewrite ( ?? * (-??)) (fun x y => -(x * y))
-
- ; make_rewriteo (?? &' #?ℤ) (fun x mask => ##(0)%Z when mask =? 0)
- ; make_rewriteo (#?ℤ &' ??) (fun mask x => ##(0)%Z when mask =? 0)
-
- ; make_rewriteo (?? * #?ℤ) (fun x y => x << ##(Z.log2 y) when (y =? (2^Z.log2 y)) && (negb (y =? 2)))
- ; make_rewriteo (#?ℤ * ??) (fun y x => x << ##(Z.log2 y) when (y =? (2^Z.log2 y)) && (negb (y =? 2)))
- ; make_rewriteo (?? / #?ℤ) (fun x y => x when (y =? 1))
- ; make_rewriteo (?? mod #?ℤ) (fun x y => ##(0)%Z when (y =? 1))
- ; make_rewriteo (?? / #?ℤ) (fun x y => x >> ##(Z.log2 y) when (y =? (2^Z.log2 y)))
- ; make_rewriteo (?? mod #?ℤ) (fun x y => x &' ##(y-1)%Z when (y =? (2^Z.log2 y)))
- ; make_rewrite (-(-??)) (fun v => v)
-
- (* We reassociate some multiplication of small constants *)
- ; make_rewriteo (#?ℤ * (#?ℤ * (?? * ??))) (fun c1 c2 x y => (x * (y * (##c1 * ##c2))) when (Z.abs c1 <=? Z.abs max_const_val) && (Z.abs c2 <=? Z.abs max_const_val))
- ; make_rewriteo (#?ℤ * (?? * (?? * #?ℤ))) (fun c1 x y c2 => (x * (y * (##c1 * ##c2))) when (Z.abs c1 <=? Z.abs max_const_val) && (Z.abs c2 <=? Z.abs max_const_val))
- ; make_rewriteo (#?ℤ * (?? * ??)) (fun c x y => (x * (y * ##c)) when (Z.abs c <=? Z.abs max_const_val))
- ; make_rewriteo (#?ℤ * ??) (fun c x => (x * ##c) when (Z.abs c <=? Z.abs max_const_val))
-
- ; make_rewrite_step (* _step, so that if one of the arguments is concrete, we automatically get the rewrite rule for [Z_cast] applying to it *)
- (#pattern.ident.Z_cast2 @ (??, ??)) (fun r x y => (#(ident.Z_cast (fst r)) @ $x, #(ident.Z_cast (snd r)) @ $y))
-
- ; make_rewriteol (-??) (fun e => (llet v := e in -$v) when negb (SubstVarLike.is_var_fst_snd_pair_opp_cast e)) (* inline negation when the rewriter wouldn't already inline it *)
- ].
+ := Eval cbv [Make.interp_rewrite_rules myapp myflatten] in
+ myflatten
+ [reify
+ [(forall A B x y, @fst A B (x, y) = x)
+ ; (forall A B x y, @snd A B (x, y) = y)
+ ; (forall v, 0 + v = v)
+ ; (forall v, v + 0 = v)
+ ; (forall x y, (-x) + (-y) = -(x + y))
+ ; (forall x y, (-x) + y = y - x)
+ ; (forall x y, x + (-y) = x - y)
+
+ ; (forall v, 0 - (-v) = v)
+ ; (forall v, 0 - v = -v)
+ ; (forall v, v - 0 = v)
+ ; (forall x y, (-x) - (-y) = y - x)
+ ; (forall x y, (-x) - y = -(x + y))
+ ; (forall x y, x - (-y) = x + y)
+
+ ; (forall v, 0 * v = 0)
+ ; (forall v, v * 0 = 0)
+ ; (forall v, 1 * v = v)
+ ; (forall v, v * 1 = v)
+ ; (forall v, (-1) * (-v) = v)
+ ; (forall v, (-v) * (-1) = v)
+ ; (forall v, (-1) * v = -v)
+ ; (forall v, v * (-1) = -v)
+ ; (forall x y, (-x) * (-y) = x * y)
+ ; (forall x y, (-x) * y = -(x * y))
+ ; (forall x y, x * (-y) = -(x * y))
+
+ ; (forall x, x &' 0 = 0)
+
+ ; (forall x, x / 1 = x)
+ ; (forall x, x mod 1 = 0)
+
+ ; (forall v, -(-v) = v)
+
+ ; (forall z v, z > 0 -> 'z + (-v) = 'z - v)
+ ; (forall z v, z > 0 -> (-v) + 'z = 'z - v)
+ ; (forall z v, z < 0 -> 'z + (-v) = -('(-z) + v))
+ ; (forall z v, z < 0 -> (-v) + 'z = -(v + '(-z)))
+
+ ; (forall z v, z > 0 -> 'z - (-v) = 'z + v)
+ ; (forall z v, z < 0 -> 'z - (-v) = v - '(-z))
+ ; (forall z v, z < 0 -> 'z - v = -('(-z) + v))
+ ; (forall z v, z > 0 -> (-v) - 'z = -(v + 'z))
+ ; (forall z v, z < 0 -> (-v) - 'z = '(-z) - v)
+ ; (forall z v, z < 0 -> v - 'z = v + '(-z))
+
+ ; (forall x y, 'x * 'y = '(x*y))
+ ; (forall z v, z < 0 -> 'z * v = -('(-z) * v))
+ ; (forall z v, z < 0 -> v * 'z = -(v * '(-z)))
+
+ ; (forall x y, y = 2^Z.log2 y -> y <> 2 -> x * 'y = x << '(Z.log2 y))
+ ; (forall x y, y = 2^Z.log2 y -> y <> 2 -> 'y * x = x << '(Z.log2 y))
+
+ ; (forall x y, y = 2^Z.log2 y -> x / 'y = x >> '(Z.log2 y))
+ ; (forall x y, y = 2^Z.log2 y -> x mod 'y = x &' '(y-1))
+
+ (* We reassociate some multiplication of small constants *)
+ ; (forall c1 c2 x y,
+ Z.abs c1 <= Z.abs max_const_val
+ -> Z.abs c2 <= Z.abs max_const_val
+ -> 'c1 * ('c2 * (x * y)) = (x * (y * ('c1 * 'c2))))
+ ; (forall c1 c2 x y,
+ Z.abs c1 <= Z.abs max_const_val
+ -> Z.abs c2 <= Z.abs max_const_val
+ -> 'c1 * (x * (y * 'c2)) = (x * (y * ('c1 * 'c2))))
+ ; (forall c x y,
+ Z.abs c <= Z.abs max_const_val
+ -> 'c * (x * y) = x * (y * 'c))
+ ; (forall c x,
+ Z.abs c <= Z.abs max_const_val
+ -> 'c * x = x * 'c)
+ ]
+ ; reify
+ [ (* [do_again], so that if one of the arguments is concrete, we automatically get the rewrite rule for [Z_cast] applying to it *)
+ do_again (forall r x y, cstZZ r (x, y) = (cstZ (fst r) x, cstZ (snd r) y))
+ ]
+
+ ; [
+ make_rewriteol (-??) (fun e => (llet v := e in -$v) when negb (SubstVarLike.is_var_fst_snd_pair_opp_cast e)) (* inline negation when the rewriter wouldn't already inline it *)
+ ] ].
Let cst {var} (r : zrange) (e : @expr.expr _ _ var _) := (#(ident.Z_cast r) @ e)%expr.
Let cst' {var} (r : zrange) (e : @expr.expr _ _ var _) := (#(ident.Z_cast (-r)) @ e)%expr.
@@ -1764,186 +2465,189 @@ Module Compilers.
(cst (fst rvc) (#ident.fst @ (cst2 rvc ($vc))),
cst (snd rvc) (#ident.snd @ (cst2 rvc ($vc))))))%expr.
+ Local Notation "'plet' x := y 'in' z"
+ := (match y return _ with x => z end).
+
+ Local Notation dlet2_opp2 rvc e
+ := (plet rvc' := (fst rvc, -snd rvc)%zrange in
+ plet cst' := cstZZ rvc' in
+ plet cst1 := cstZ (fst rvc%zrange%zrange) in
+ plet cst2 := cstZ (snd rvc%zrange%zrange) in
+ plet cst2' := cstZ (-snd rvc%zrange%zrange) in
+ (dlet vc := cst' e in
+ (cst1 (fst (cst' vc)), cst2 (-(cst2' (snd (cst' vc))))))).
+
+ Local Notation dlet2 rvc e
+ := (dlet vc := cstZZ rvc e in
+ (cstZ (fst rvc) (fst (cstZZ rvc vc)),
+ cstZ (snd rvc) (snd (cstZZ rvc vc)))).
+
+
+ Local Notation "x '\in' y" := (is_bounded_by_bool x (ZRange.normalize y) = true) : zrange_scope.
+ Local Notation "x ∈ y" := (is_bounded_by_bool x (ZRange.normalize y) = true) : zrange_scope.
+ Local Notation "x <= y" := (is_tighter_than_bool (ZRange.normalize x) y = true) : zrange_scope.
+ Local Notation litZZ x := (ident.literal (fst x), ident.literal (snd x)) (only parsing).
+ Local Notation n r := (ZRange.normalize r) (only parsing).
+
Definition arith_with_casts_rewrite_rules : rewrite_rulesT
- := [make_rewrite (#(@pattern.ident.fst '1 '2) @ (??, ??)) (fun _ _ x y => x)
- ; make_rewrite (#(@pattern.ident.snd '1 '2) @ (??, ??)) (fun _ _ x y => y)
-
- ; make_rewriteo (??') (fun r v => cst r (##(lower r)) when lower r =? upper r)
-
- ; make_rewriteo
- (#?ℤ' + ?? )
- (fun rz z v => v when (z =? 0) && (is_bounded_by_bool z (ZRange.normalize rz)))
- ; make_rewriteo
- (?? + #?ℤ')
- (fun v rz z => v when (z =? 0) && (is_bounded_by_bool z (ZRange.normalize rz)))
-
- ; make_rewriteo
- (#?ℤ' - (-'??'))
- (fun rz z rnv rv v => cst rv v when (z =? 0) && (ZRange.normalize rv <=? -ZRange.normalize rnv)%zrange && (is_bounded_by_bool z rz))
- ; make_rewriteo (#?ℤ' - ?? ) (fun rz z v => -v when (z =? 0) && is_bounded_by_bool z (ZRange.normalize rz))
-
- ; make_rewriteo (#?ℤ' << ??) (fun rx x y => ##0 when (x =? 0) && is_bounded_by_bool x (ZRange.normalize rx))
-
- ; make_rewriteo (-(-'??')) (fun rnv rv v => cst rv v when (ZRange.normalize rv <=? -ZRange.normalize rnv)%zrange)
-
- ; make_rewriteo (#pattern.ident.Z_mul_split @ ?? @ #?ℤ' @ ??) (fun s rxx xx y => (cst r[0~>0] ##0, cst r[0~>0] ##0)%Z when (xx =? 0) && is_bounded_by_bool xx (ZRange.normalize rxx))
- ; make_rewriteo (#pattern.ident.Z_mul_split @ ?? @ ?? @ #?ℤ') (fun s y rxx xx => (cst r[0~>0] ##0, cst r[0~>0] ##0)%Z when (xx =? 0) && is_bounded_by_bool xx (ZRange.normalize rxx))
- ; make_rewriteo
- (#pattern.ident.Z_mul_split @ #?ℤ' @ #?ℤ' @ ??')
- (fun rs s rxx xx ry y => (cst ry y, cst r[0~>0] ##0)%Z when (xx =? 1) && (ZRange.normalize ry <=? r[0~>s-1])%zrange && is_bounded_by_bool s (ZRange.normalize rs) && is_bounded_by_bool xx (ZRange.normalize rxx))
- ; make_rewriteo
- (#pattern.ident.Z_mul_split @ #?ℤ' @ ??' @ #?ℤ')
- (fun rs s ry y rxx xx => (cst ry y, cst r[0~>0] ##0)%Z when (xx =? 1) && (ZRange.normalize ry <=? r[0~>s-1])%zrange && is_bounded_by_bool s (ZRange.normalize rs) && is_bounded_by_bool xx (ZRange.normalize rxx))
- (*
- ; make_rewriteo
- (#pattern.ident.Z_mul_split @ #?ℤ @ #?ℤ @ ??')
- (fun s xx ry y => (cst' ry (-cst ry y), ##0%Z) when (xx =? (-1)) && (ZRange.normalize ry <=? r[0~>s-1])%zrange)
- ; make_rewriteo
- (#pattern.ident.Z_mul_split @ #?ℤ @ ??' @ #?ℤ)
- (fun s ry y xx => (cst' ry (-cst ry y), ##0%Z) when (xx =? (-1)) && (ZRange.normalize ry <=? r[0~>s-1])%zrange)
- *)
-
-
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_get_carry @ ?? @ (-'??') @ ??))
- (fun rvc s rny ry y x
- => (llet2_opp2 rvc (#ident.Z_sub_get_borrow @ s @ x @ cst ry y))
- when (ZRange.normalize ry <=? -ZRange.normalize rny)%zrange)
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_get_carry @ ?? @ ?? @ (-'??')))
- (fun rvc s x rny ry y
- => (llet2_opp2 rvc (#ident.Z_sub_get_borrow @ s @ x @ cst ry y))
- when (ZRange.normalize ry <=? -ZRange.normalize rny)%zrange)
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_get_carry @ ?? @ #?ℤ' @ ??))
- (fun rvc s ryy yy x
- => (llet2_opp2 rvc (#ident.Z_sub_get_borrow @ s @ x @ cst (ZRange.opp ryy) ##(-yy)%Z))
- when (yy <? 0) && is_bounded_by_bool yy (ZRange.normalize ryy))
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_get_carry @ ?? @ ?? @ #?ℤ'))
- (fun rvc s x ryy yy => (llet2_opp2 rvc (#ident.Z_sub_get_borrow @ s @ x @ cst (ZRange.opp ryy) ##(-yy)%Z))
- when (yy <? 0) && is_bounded_by_bool yy (ZRange.normalize ryy))
-
-
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ (-'??') @ (-'??') @ ??))
- (fun rvc s rnc rc c rny ry y x
- => (llet2_opp2 rvc (#ident.Z_sub_with_get_borrow @ s @ (cst rc c) @ x @ (cst ry y)))
- when ((ZRange.normalize ry <=? -ZRange.normalize rny) && (ZRange.normalize rc <=? -ZRange.normalize rnc))%zrange)
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ (-'??') @ ?? @ (-'??')))
- (fun rvc s rnc rc c x rny ry y
- => (llet2_opp2 rvc (#ident.Z_sub_with_get_borrow @ s @ (cst rc c) @ x @ (cst ry y)))
- when ((ZRange.normalize ry <=? -ZRange.normalize rny) && (ZRange.normalize rc <=? -ZRange.normalize rnc))%zrange)
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ #?ℤ' @ (-'??') @ ??))
- (fun rvc s rcc cc rny ry y x
- => (llet2_opp2 rvc (#ident.Z_sub_get_borrow @ s @ x @ cst ry y))
- when (cc =? 0) && (ZRange.normalize ry <=? -ZRange.normalize rny)%zrange && is_bounded_by_bool cc (ZRange.normalize rcc))
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ #?ℤ' @ (-'??') @ ??))
- (fun rvc s rcc cc rny ry y x
- => (llet2_opp2 rvc (#ident.Z_sub_with_get_borrow @ s @ cst (ZRange.opp rcc) ##(-cc)%Z @ x @ cst ry y))
- when (cc <? 0) && (ZRange.normalize ry <=? -ZRange.normalize rny)%zrange && is_bounded_by_bool cc (ZRange.normalize rcc))
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ #?ℤ' @ ?? @ (-'??')))
- (fun rvc s rcc cc x rny ry y
- => (llet2_opp2 rvc (#ident.Z_sub_get_borrow @ s @ x @ cst ry y))
- when (cc =? 0) && (ZRange.normalize ry <=? -ZRange.normalize rny)%zrange && is_bounded_by_bool cc (ZRange.normalize rcc))
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ #?ℤ' @ ?? @ (-'??')))
- (fun rvc s rcc cc x rny ry y
- => (llet2_opp2 rvc (#ident.Z_sub_with_get_borrow @ s @ cst (ZRange.opp rcc) ##(-cc)%Z @ x @ cst ry y)
- when (cc <? 0) && (ZRange.normalize ry <=? -ZRange.normalize rny)%zrange && is_bounded_by_bool cc (ZRange.normalize rcc)))
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ (-'??') @ #?ℤ' @ ??))
- (fun rvc s rnc rc c ryy yy x
- => (llet2_opp2 rvc (#ident.Z_sub_with_get_borrow @ s @ cst rc c @ x @ cst (ZRange.opp ryy) ##(-yy)%Z))
- when (yy <=? 0) && (ZRange.normalize rc <=? -ZRange.normalize rnc)%zrange && is_bounded_by_bool yy (ZRange.normalize ryy))
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ (-'??') @ ?? @ #?ℤ'))
- (fun rvc s rnc rc c x ryy yy
- => (llet2_opp2 rvc (#ident.Z_sub_with_get_borrow @ s @ cst rc c @ x @ cst (ZRange.opp ryy) ##(-yy)%Z))
- when (yy <=? 0) && (ZRange.normalize rc <=? -ZRange.normalize rnc)%zrange && is_bounded_by_bool yy (ZRange.normalize ryy))
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ #?ℤ' @ #?ℤ' @ ??))
- (fun rvc s rcc cc ryy yy x
- => (llet2_opp2 rvc (#ident.Z_sub_with_get_borrow @ s @ cst (ZRange.opp rcc) ##(-cc)%Z @ x @ cst (ZRange.opp ryy) ##(-yy)%Z))
- when (yy <=? 0) && (cc <=? 0) && ((yy + cc) <? 0) && is_bounded_by_bool yy (ZRange.normalize ryy) && is_bounded_by_bool cc (ZRange.normalize rcc)) (* at least one must be strictly negative *)
- ; make_rewriteol
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ #?ℤ' @ ?? @ #?ℤ'))
- (fun rvc s rcc cc x ryy yy
- => (llet2_opp2 rvc (#ident.Z_sub_with_get_borrow @ s @ cst (ZRange.opp rcc) ##(-cc)%Z @ x @ cst (ZRange.opp ryy) ##(-yy)%Z))
- when (yy <=? 0) && (cc <=? 0) && ((yy + cc) <? 0) && is_bounded_by_bool yy (ZRange.normalize ryy) && is_bounded_by_bool cc (ZRange.normalize rcc)) (* at least one must be strictly negative *)
-
-
- ; make_rewriteo
- (#pattern.ident.Z_add_get_carry @ #?ℤ' @ #?ℤ' @ #?ℤ')
- (fun rs s rxx xx ryy yy => ##(Z.add_get_carry_full s xx yy) when is_bounded_by_bool s (ZRange.normalize rs) && is_bounded_by_bool xx (ZRange.normalize rxx) && is_bounded_by_bool yy (ZRange.normalize ryy))
- ; make_rewriteo
- (#pattern.ident.Z_add_get_carry @ #?ℤ' @ #?ℤ' @ ??')
- (fun rs s rxx xx ry y => (cst ry y, cst r[0~>0] ##0) when (xx =? 0) && (ZRange.normalize ry <=? r[0~>s-1])%zrange && is_bounded_by_bool xx (ZRange.normalize rxx) && is_bounded_by_bool s (ZRange.normalize rs))
- ; make_rewriteo
- (#pattern.ident.Z_add_get_carry @ #?ℤ' @ ??' @ #?ℤ')
- (fun rs s ry y rxx xx => (cst ry y, cst r[0~>0] ##0) when (xx =? 0) && (ZRange.normalize ry <=? r[0~>s-1])%zrange && is_bounded_by_bool xx (ZRange.normalize rxx) && is_bounded_by_bool s (ZRange.normalize rs))
-
- ; make_rewriteo (#pattern.ident.Z_add_with_carry @ #?ℤ' @ ?? @ ??) (fun rcc cc x y => x + y when (cc =? 0) && is_bounded_by_bool cc (ZRange.normalize rcc))
- (*; make_rewrite_step (#pattern.ident.Z_add_with_carry @ ?? @ ?? @ ??) (fun x y z => $x + $y + $z)*)
-
- ; make_rewriteo
- (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ #?ℤ' @ #?ℤ' @ #?ℤ')
- (fun rs s rcc cc rxx xx ryy yy => ##(Z.add_with_get_carry_full s cc xx yy) when is_bounded_by_bool s (ZRange.normalize rs) && is_bounded_by_bool cc (ZRange.normalize rcc) && is_bounded_by_bool xx (ZRange.normalize rxx) && is_bounded_by_bool yy (ZRange.normalize ryy))
- ; make_rewriteo
- (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ #?ℤ' @ #?ℤ' @ ??')
- (fun rs s rcc cc rxx xx ry y => (cst ry y, cst r[0~>0] ##0) when (cc =? 0) && (xx =? 0) && (ZRange.normalize ry <=? r[0~>s-1])%zrange && is_bounded_by_bool s (ZRange.normalize rs) && is_bounded_by_bool cc (ZRange.normalize rcc) && is_bounded_by_bool xx (ZRange.normalize rxx))
- ; make_rewriteo
- (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ #?ℤ' @ ??' @ #?ℤ')
- (fun rs s rcc cc ry y rxx xx => (cst ry y, cst r[0~>0] ##0) when (cc =? 0) && (xx =? 0) && (ZRange.normalize ry <=? r[0~>s-1])%zrange && is_bounded_by_bool s (ZRange.normalize rs) && is_bounded_by_bool cc (ZRange.normalize rcc) && is_bounded_by_bool xx (ZRange.normalize rxx))
- (*; make_rewriteo
- (#pattern.ident.Z_add_with_get_carry @ ?? @ ?? @ #?ℤ @ #?ℤ) (fun s c xx yy => (c, ##0) when (xx =? 0) && (yy =? 0))*)
- ; make_rewriteol (* carry = 0: ADC x y -> ADD x y *)
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ #?ℤ' @ ?? @ ??))
- (fun rvc s rcc cc x y
- => (llet2 rvc (#ident.Z_add_get_carry @ s @ x @ y))
- when (cc =? 0) && is_bounded_by_bool cc (ZRange.normalize rcc))
- ; make_rewriteol (* ADC 0 0 -> (ADX 0 0, 0) *) (* except we don't do ADX, because C stringification doesn't handle it *)
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ ??' @ #?ℤ' @ #?ℤ'))
- (fun rvc rs s rc c rxx xx ryy yy
- => (llet vc := cst2 rvc (#ident.Z_add_with_get_carry @ cst rs ##s @ cst rc c @ cst rxx ##xx @ cst ryy ##yy) in
- (cst (fst rvc) (#ident.fst @ cst2 rvc ($vc)), cst r[0~>0] ##0))
- when (xx =? 0) && (yy =? 0) && (ZRange.normalize rc <=? r[0~>s-1])%zrange && is_bounded_by_bool 0 (snd rvc) && is_bounded_by_bool s (ZRange.normalize rs) && is_bounded_by_bool xx (ZRange.normalize rxx) && is_bounded_by_bool yy (ZRange.normalize ryy))
-
-
- (* let-bind any adc/sbb/mulx *)
- ; make_rewritel
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_with_get_carry @ ?? @ ?? @ ?? @ ??))
- (fun rvc s c x y => llet2 rvc (#ident.Z_add_with_get_carry @ s @ c @ x @ y))
- ; make_rewritel
- (#pattern.ident.Z_cast @ (#pattern.ident.Z_add_with_carry @ ?? @ ?? @ ??))
- (fun rv c x y => (llet vc := cst rv (#ident.Z_add_with_carry @ c @ x @ y) in
- (cst rv ($vc))))
- ; make_rewritel
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_add_get_carry @ ?? @ ?? @ ??))
- (fun rvc s x y => llet2 rvc (#ident.Z_add_get_carry @ s @ x @ y))
- ; make_rewritel
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_sub_with_get_borrow @ ?? @ ?? @ ?? @ ??))
- (fun rvc s c x y => llet2 rvc (#ident.Z_sub_with_get_borrow @ s @ c @ x @ y))
- ; make_rewritel
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_sub_get_borrow @ ?? @ ?? @ ??))
- (fun rvc s x y => llet2 rvc (#ident.Z_sub_get_borrow @ s @ x @ y))
- ; make_rewritel
- (#pattern.ident.Z_cast2 @ (#pattern.ident.Z_mul_split @ ?? @ ?? @ ??))
- (fun rvc s x y => llet2 rvc (#ident.Z_mul_split @ s @ x @ y))
-
- ; make_rewrite_step (#pattern.ident.Z_cast2 @ (??, ??)) (fun r v1 v2 => (#(ident.Z_cast (fst r)) @ $v1, #(ident.Z_cast (snd r)) @ $v2))
-
- ; make_rewriteo
- (#pattern.ident.Z_cast @ (#pattern.ident.Z_cast @ ??))
- (fun r1 r2 x => #(ident.Z_cast r2) @ x when ZRange.is_tighter_than_bool (ZRange.normalize r2) (ZRange.normalize r1))
- ].
+ := Eval cbv [Make.interp_rewrite_rules myapp myflatten] in
+ myflatten
+ [reify
+ [(forall A B x y, @fst A B (x, y) = x)
+ ; (forall A B x y, @snd A B (x, y) = y)
+ ; (forall r v, lower r = upper r -> cstZ r v = cstZ r ('(lower r)))
+ ; (forall r0 v, 0 ∈ r0 -> cstZ r0 0 + v = v)
+ ; (forall r0 v, 0 ∈ r0 -> v + cstZ r0 0 = v)
+ ; (forall r0 v, 0 ∈ r0 -> cstZ r0 0 - v = -v)
+ ; (forall r0 v, 0 ∈ r0 -> cstZ r0 0 << v = 0)
+ ; (forall r0 rnv rv v,
+ (rv <= -n rnv)%zrange -> 0 ∈ r0
+ -> cstZ r0 0 - cstZ rnv (-(cstZ rv v)) = cstZ rv v)
+ ; (forall rnv rv v,
+ (rv <= -n rnv)%zrange
+ -> -(cstZ rnv (-(cstZ rv v))) = cstZ rv v)
+
+ ; (forall s r0 y, 0 ∈ r0 -> Z.mul_split s (cstZ r0 0) y = (cstZ r[0~>0] 0, cstZ r[0~>0] 0))
+ ; (forall s r0 y, 0 ∈ r0 -> Z.mul_split s y (cstZ r0 0) = (cstZ r[0~>0] 0, cstZ r[0~>0] 0))
+ ; (forall rs s r1 ry y,
+ 1 ∈ r1 -> s ∈ rs -> (ry <= r[0~>s-1])%zrange
+ -> Z.mul_split (cstZ rs ('s)) (cstZ r1 1) (cstZ ry y)
+ = (cstZ ry y, cstZ r[0~>0] 0))
+ ; (forall rs s r1 ry y,
+ 1 ∈ r1 -> s ∈ rs -> (ry <= r[0~>s-1])%zrange
+ -> Z.mul_split (cstZ rs ('s)) (cstZ ry y) (cstZ r1 1)
+ = (cstZ ry y, cstZ r[0~>0] 0))
+
+ ; (forall rvc s rny ry y x,
+ (ry <= -n rny)%zrange
+ -> cstZZ rvc (Z.add_get_carry_full s (cstZ rny (-cstZ ry y)) x)
+ = dlet2_opp2 rvc (Z.sub_get_borrow_full s x (cstZ ry y)))
+ ; (forall rvc s rny ry y x,
+ (ry <= -n rny)%zrange
+ -> cstZZ rvc (Z.add_get_carry_full s x (cstZ rny (-cstZ ry y)))
+ = dlet2_opp2 rvc (Z.sub_get_borrow_full s x (cstZ ry y)))
+ ; (forall rvc s ryy yy x,
+ yy ∈ ryy -> yy < 0
+ -> cstZZ rvc (Z.add_get_carry_full s (cstZ ryy ('yy)) x)
+ = dlet2_opp2 rvc (Z.sub_get_borrow_full s x (cstZ (-ryy) ('(-yy)))))
+ ; (forall rvc s ryy yy x,
+ yy ∈ ryy -> yy < 0
+ -> cstZZ rvc (Z.add_get_carry_full s x (cstZ ryy ('yy)))
+ = dlet2_opp2 rvc (Z.sub_get_borrow_full s x (cstZ (-ryy) ('(-yy)))))
+ ; (forall rvc s rnc rc c rny ry y x,
+ (ry <= -n rny)%zrange -> (rc <= -n rnc)%zrange
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ rnc (-cstZ rc c)) (cstZ rny (-cstZ ry y)) x)
+ = dlet2_opp2 rvc (Z.sub_with_get_borrow_full s (cstZ rc c) x (cstZ ry y)))
+ ; (forall rvc s rnc rc c rny ry y x,
+ (ry <= -n rny)%zrange -> (rc <= -n rnc)%zrange
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ rnc (-cstZ rc c)) x (cstZ rny (-cstZ ry y)))
+ = dlet2_opp2 rvc (Z.sub_with_get_borrow_full s (cstZ rc c) x (cstZ ry y)))
+ ; (forall rvc s r0 rny ry y x,
+ 0 ∈ r0 -> (ry <= -n rny)%zrange
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ r0 0) (cstZ rny (-cstZ ry y)) x)
+ = dlet2_opp2 rvc (Z.sub_get_borrow_full s x (cstZ ry y)))
+ ; (forall rvc s rcc cc rny ry y x,
+ cc < 0 -> cc ∈ rcc -> (ry <= -n rny)%zrange
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ rcc ('cc)) (cstZ rny (-cstZ ry y)) x)
+ = dlet2_opp2 rvc (Z.sub_with_get_borrow_full s (cstZ (-rcc) ('(-cc))) x (cstZ ry y)))
+ ; (forall rvc s r0 rny ry y x,
+ 0 ∈ r0 -> (ry <= -n rny)%zrange
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ r0 0) x (cstZ rny (-cstZ ry y)))
+ = dlet2_opp2 rvc (Z.sub_get_borrow_full s x (cstZ ry y)))
+ ; (forall rvc s rcc cc rny ry y x,
+ cc < 0 -> cc ∈ rcc -> (ry <= -n rny)%zrange
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ rcc ('cc)) x (cstZ rny (-cstZ ry y)))
+ = dlet2_opp2 rvc (Z.sub_with_get_borrow_full s (cstZ (-rcc) ('(-cc))) x (cstZ ry y)))
+ ; (forall rvc s rnc rc c ryy yy x,
+ yy <= 0 -> yy ∈ ryy -> (rc <= -n rnc)%zrange
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ rnc (-cstZ rc c)) (cstZ ryy ('yy)) x)
+ = dlet2_opp2 rvc (Z.sub_with_get_borrow_full s (cstZ rc c) x (cstZ (-ryy) ('(-yy)))))
+ ; (forall rvc s rnc rc c ryy yy x,
+ yy <= 0 -> yy ∈ ryy -> (rc <= -n rnc)%zrange
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ rnc (-cstZ rc c)) x (cstZ ryy ('yy)))
+ = dlet2_opp2 rvc (Z.sub_with_get_borrow_full s (cstZ rc c) x (cstZ (-ryy) ('(-yy)))))
+ ; (forall rvc s rcc cc ryy yy x,
+ yy <= 0 -> cc <= 0 -> yy + cc < 0 (* at least one must be strictly negative *) -> yy ∈ ryy -> cc ∈ rcc
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ rcc ('cc)) (cstZ ryy ('yy)) x)
+ = dlet2_opp2 rvc (Z.sub_with_get_borrow_full s (cstZ (-rcc) ('(-cc))) x (cstZ (-ryy) ('(-yy)))))
+ ; (forall rvc s rcc cc ryy yy x,
+ yy <= 0 -> cc <= 0 -> yy + cc < 0 (* at least one must be strictly negative *) -> yy ∈ ryy -> cc ∈ rcc
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ rcc ('cc)) x (cstZ ryy ('yy)))
+ = dlet2_opp2 rvc (Z.sub_with_get_borrow_full s (cstZ (-rcc) ('(-cc))) x (cstZ (-ryy) ('(-yy)))))
+
+
+ ; (forall rs s rxx xx ryy yy,
+ s ∈ rs -> xx ∈ rxx -> yy ∈ ryy
+ -> Z.add_get_carry_full (cstZ rs ('s)) (cstZ rxx ('xx)) (cstZ ryy ('yy))
+ = litZZ (Z.add_get_carry_full s xx yy))
+ ; (forall rs s r0 ry y,
+ s ∈ rs -> 0 ∈ r0 -> (ry <= r[0~>s-1])%zrange
+ -> Z.add_get_carry_full (cstZ rs ('s)) (cstZ r0 0) (cstZ ry y)
+ = (cstZ ry y, cstZ r[0~>0] 0))
+ ; (forall rs s r0 ry y,
+ s ∈ rs -> 0 ∈ r0 -> (ry <= r[0~>s-1])%zrange
+ -> Z.add_get_carry_full (cstZ rs ('s)) (cstZ ry y) (cstZ r0 0)
+ = (cstZ ry y, cstZ r[0~>0] 0))
+
+ ; (forall r0 x y, 0 ∈ r0 -> Z.add_with_carry (cstZ r0 0) x y = x + y)
+
+ ; (forall rs s rcc cc rxx xx ryy yy,
+ s ∈ rs -> cc ∈ rcc -> xx ∈ rxx -> yy ∈ ryy
+ -> Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ rcc ('cc)) (cstZ rxx ('xx)) (cstZ ryy ('yy))
+ = litZZ (Z.add_with_get_carry_full s cc xx yy))
+ ; (forall rs s r0c r0x ry y,
+ s ∈ rs -> 0 ∈ r0c -> 0 ∈ r0x -> (ry <= r[0~>s-1])%zrange
+ -> Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ r0c 0) (cstZ r0x 0) (cstZ ry y)
+ = (cstZ ry y, cstZ r[0~>0] 0))
+ ; (forall rs s r0c r0x ry y,
+ s ∈ rs -> 0 ∈ r0c -> 0 ∈ r0x -> (ry <= r[0~>s-1])%zrange
+ -> Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ r0c 0) (cstZ ry y) (cstZ r0x 0)
+ = (cstZ ry y, cstZ r[0~>0] 0))
+
+ ; (forall rvc s r0 x y, (* carry = 0: ADC x y -> ADD x y *)
+ 0 ∈ r0
+ -> cstZZ rvc (Z.add_with_get_carry_full s (cstZ r0 0) x y)
+ = dlet2 rvc (Z.add_get_carry_full s x y))
+ ; (forall rvc rs s rc c r0x r0y, (* ADC 0 0 -> (ADX 0 0, 0) *) (* except we don't do ADX, because C stringification doesn't handle it *)
+ 0 ∈ r0x -> 0 ∈ r0y -> (rc <= r[0~>s-1])%zrange -> 0 ∈ snd rvc -> s ∈ rs
+ -> cstZZ rvc (Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ rc c) (cstZ r0x 0) (cstZ r0y 0))
+ = (dlet vc := (cstZZ rvc (Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ rc c) (cstZ r0x 0) (cstZ r0y 0))) in
+ (cstZ (fst rvc) (fst (cstZZ rvc vc)),
+ cstZ r[0~>0] 0)))
+
+ (* let-bind any adc/sbb/mulx *)
+ ; (forall rvc s c x y,
+ cstZZ rvc (Z.add_with_get_carry_full s c x y)
+ = dlet2 rvc (Z.add_with_get_carry_full s c x y))
+ ; (forall rv c x y,
+ cstZ rv (Z.add_with_carry c x y)
+ = (dlet vc := cstZ rv (Z.add_with_carry c x y) in
+ cstZ rv vc))
+ ; (forall rvc s x y,
+ cstZZ rvc (Z.add_get_carry_full s x y)
+ = dlet2 rvc (Z.add_get_carry_full s x y))
+ ; (forall rvc s c x y,
+ cstZZ rvc (Z.sub_with_get_borrow_full s c x y)
+ = dlet2 rvc (Z.sub_with_get_borrow_full s c x y))
+ ; (forall rvc s x y,
+ cstZZ rvc (Z.sub_get_borrow_full s x y)
+ = dlet2 rvc (Z.sub_get_borrow_full s x y))
+ ; (forall rvc s x y,
+ cstZZ rvc (Z.mul_split s x y)
+ = dlet2 rvc (Z.mul_split s x y))
+ ]%Z%zrange
+ ; reify
+ [ (* [do_again], so that if one of the arguments is concrete, we automatically get the rewrite rule for [Z_cast] applying to it *)
+ do_again (forall r x y, cstZZ r (x, y) = (cstZ (fst r) x, cstZ (snd r) y))
+ ]
+ ; reify
+ [(forall r1 r2 x, (r2 <= n r1)%zrange -> cstZ r1 (cstZ r2 x) = cstZ r2 x)
+ ]%Z%zrange
+ ].
Definition strip_literal_casts_rewrite_rules : rewrite_rulesT
- := [make_rewriteo (#?ℤ') (fun rx x => ##x when is_bounded_by_bool x (ZRange.normalize rx))].
+ := reify
+ [(forall rx x, x ∈ rx -> cstZ rx ('x) = 'x)]%Z%zrange.
Definition nbe_dtree'
@@ -2017,12 +2721,14 @@ Module Compilers.
Local Notation pcst2 v := (#pattern.ident.Z_cast2 @ v)%pattern.
Local Coercion ZRange.constant : Z >-> zrange. (* for ease of use with sanity-checking bounds *)
- Let bounds1_good (f : zrange -> zrange) (output x_bs : zrange)
- := is_tighter_than_bool (f (ZRange.normalize x_bs)) (ZRange.normalize output).
- Let bounds2_good (f : zrange -> zrange -> zrange) (output x_bs y_bs : zrange)
- := is_tighter_than_bool (f (ZRange.normalize x_bs) (ZRange.normalize y_bs)) (ZRange.normalize output).
- Let range_in_bitwidth r s
- := is_tighter_than_bool (ZRange.normalize r) r[0~>s-1]%zrange.
+ Local Notation bounds1_good f
+ := (fun (output x_bs : zrange)
+ => is_tighter_than_bool (f (ZRange.normalize x_bs)) (ZRange.normalize output) = true).
+ Local Notation bounds2_good f
+ := (fun (output x_bs y_bs : zrange)
+ => is_tighter_than_bool (f (ZRange.normalize x_bs) (ZRange.normalize y_bs)) (ZRange.normalize output) = true).
+ Local Notation range_in_bitwidth r s
+ := (is_tighter_than_bool (ZRange.normalize r) r[0~>s-1]%zrange = true).
Local Notation shiftl_good := (bounds2_good ZRange.shiftl).
Local Notation shiftr_good := (bounds2_good ZRange.shiftr).
Local Notation land_good := (bounds2_good ZRange.land).
@@ -2031,203 +2737,321 @@ Module Compilers.
Local Notation lit_good x rx := (is_bounded_by_bool x (ZRange.normalize rx)).
Definition fancy_with_casts_rewrite_rules : rewrite_rulesT
- := [
- (*
+ := Eval cbv [Make.interp_rewrite_rules myapp myflatten] in
+ myflatten
+ [reify
+ [(*
(Z.add_get_carry_concrete 2^256) @@ (?x, ?y << 128) --> (add 128) @@ (x, y)
(Z.add_get_carry_concrete 2^256) @@ (?x << 128, ?y) --> (add 128) @@ (y, x)
(Z.add_get_carry_concrete 2^256) @@ (?x, ?y >> 128) --> (add (- 128)) @@ (x, y)
(Z.add_get_carry_concrete 2^256) @@ (?x >> 128, ?y) --> (add (- 128)) @@ (y, x)
(Z.add_get_carry_concrete 2^256) @@ (?x, ?y) --> (add 0) @@ (y, x)
-*)
- make_rewriteo
- (pcst2 (#pattern.ident.Z_add_get_carry @ #?ℤ' @ ??' @ (pcst (#pattern.ident.Z_shiftl @ (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ')) @ #?ℤ'))))
- (fun '((r1, r2)%core) rs s rx x rshiftl rland ry y rmask mask roffset offset => cst2 (r1, r2)%core (#(ident.fancy_add (Z.log2 s) offset) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftl_good rshiftl rland offset && land_good rland ry mask && range_in_bitwidth rshiftl s && (mask =? Z.ones (Z.log2 s - offset)) && (0 <=? offset) && (offset <=? Z.log2 s) && lit_good s rs && lit_good mask rmask && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_get_carry @ #?ℤ' @ (pcst (#pattern.ident.Z_shiftl @ (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ')) @ #?ℤ')) @ ??'))
- (fun '((r1, r2)%core) rs s rshiftl rland ry y rmask mask roffset offset rx x => cst2 (r1, r2)%core (#(ident.fancy_add (Z.log2 s) offset) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftl_good rshiftl rland offset && land_good rland ry mask && range_in_bitwidth rshiftl s && (mask =? Z.ones (Z.log2 s - offset)) && (0 <=? offset) && (offset <=? Z.log2 s) && lit_good s rs && lit_good mask rmask && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_get_carry @ #?ℤ' @ ??' @ (pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ'))))
- (fun '((r1, r2)%core) rs s rx x rshiftr ry y roffset offset => cst2 (r1, r2)%core (#(ident.fancy_add (Z.log2 s) (-offset)) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftr_good rshiftr ry offset && range_in_bitwidth rshiftr s && lit_good s rs && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_get_carry @ #?ℤ' @ pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ') @ ??'))
- (fun '((r1, r2)%core) rs s rshiftr ry y roffset offset rx x => cst2 (r1, r2)%core (#(ident.fancy_add (Z.log2 s) (-offset)) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftr_good rshiftr ry offset && range_in_bitwidth rshiftr s && lit_good s rs && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_get_carry @ #?ℤ' @ ??' @ ??'))
- (fun '((r1, r2)%core) rs s rx x ry y => cst2 (r1, r2)%core (#(ident.fancy_add (Z.log2 s) 0) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && range_in_bitwidth ry s && lit_good s rs)
-(*
+ *)
+ (forall r rs s rx x rshiftl rland ry y rmask mask roffset offset,
+ s = 2^Z.log2 s -> s ∈ rs -> offset ∈ roffset -> mask ∈ rmask -> shiftl_good rshiftl rland offset -> land_good rland ry mask -> range_in_bitwidth rshiftl s -> (mask = Z.ones (Z.log2 s - offset)) -> (0 <= offset <= Z.log2 s)
+ -> cstZZ r (Z.add_get_carry_full (cstZ rs ('s)) (cstZ rx x) (cstZ rshiftl ((cstZ rland (cstZ ry y &' cstZ rmask ('mask))) << cstZ roffset ('offset))))
+ = cstZZ r (ident.interp (ident.fancy_add (Z.log2 s) (offset)) (cstZ rx x, cstZ ry y)))
+ ; (forall r rs s rx x rshiftl rland ry y rmask mask roffset offset,
+ (s = 2^Z.log2 s) -> (mask = Z.ones (Z.log2 s - offset)) -> (0 <= offset <= Z.log2 s) -> s ∈ rs -> mask ∈ rmask -> offset ∈ roffset -> shiftl_good rshiftl rland offset -> land_good rland ry mask -> range_in_bitwidth rshiftl s
+ -> cstZZ r (Z.add_get_carry_full (cstZ rs ('s)) (cstZ rx x) (cstZ rshiftl (cstZ rland (cstZ ry y &' cstZ rmask ('mask)) << cstZ roffset ('offset))))
+ = cstZZ r (ident.interp (ident.fancy_add (Z.log2 s) offset) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rshiftl rland ry y rmask mask roffset offset rx x,
+ s ∈ rs -> mask ∈ rmask -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftl_good rshiftl rland offset -> land_good rland ry mask -> range_in_bitwidth rshiftl s -> (mask = Z.ones (Z.log2 s - offset)) -> (0 <= offset <= Z.log2 s)
+ -> cstZZ r (Z.add_get_carry_full (cstZ rs ('s)) (cstZ rshiftl (Z.shiftl (cstZ rland (Z.land (cstZ ry y) (cstZ rmask ('mask)))) (cstZ roffset ('offset)))) (cstZ rx x))
+ = cstZZ r (ident.interp (ident.fancy_add (Z.log2 s) offset) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rx x rshiftr ry y roffset offset,
+ s ∈ rs -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftr_good rshiftr ry offset -> range_in_bitwidth rshiftr s
+ -> cstZZ r (Z.add_get_carry_full (cstZ rs ('s)) (cstZ rx x) (cstZ rshiftr (Z.shiftr (cstZ ry y) (cstZ roffset ('offset)))))
+ = cstZZ r (ident.interp (ident.fancy_add (Z.log2 s) (-offset)) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rshiftr ry y roffset offset rx x,
+ s ∈ rs -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftr_good rshiftr ry offset -> range_in_bitwidth rshiftr s
+ -> cstZZ r (Z.add_get_carry_full (cstZ rs ('s)) (cstZ rshiftr (Z.shiftr (cstZ ry y) (cstZ roffset ('offset)))) (cstZ rx x))
+ = cstZZ r (ident.interp (ident.fancy_add (Z.log2 s) (-offset)) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rx x ry y,
+ s ∈ rs -> (s = 2^Z.log2 s) -> range_in_bitwidth ry s
+ -> cstZZ r (Z.add_get_carry_full (cstZ rs ('s)) (cstZ rx x) (cstZ ry y))
+ = cstZZ r (ident.interp (ident.fancy_add (Z.log2 s) 0) (cstZ rx x, cstZ ry y)))
+
+ (*
(Z.add_with_get_carry_concrete 2^256) @@ (?c, ?x, ?y << 128) --> (addc 128) @@ (c, x, y)
(Z.add_with_get_carry_concrete 2^256) @@ (?c, ?x << 128, ?y) --> (addc 128) @@ (c, y, x)
(Z.add_with_get_carry_concrete 2^256) @@ (?c, ?x, ?y >> 128) --> (addc (- 128)) @@ (c, x, y)
(Z.add_with_get_carry_concrete 2^256) @@ (?c, ?x >> 128, ?y) --> (addc (- 128)) @@ (c, y, x)
(Z.add_with_get_carry_concrete 2^256) @@ (?c, ?x, ?y) --> (addc 0) @@ (c, y, x)
- *)
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ ??' @ ??' @ pcst (#pattern.ident.Z_shiftl @ (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ')) @ #?ℤ')))
- (fun '((r1, r2)%core) rs s rc c rx x rshiftl rland ry y rmask mask roffset offset => cst2 (r1, r2)%core (#(ident.fancy_addc (Z.log2 s) offset) @ (cst rc c, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftl_good rshiftl rland offset && land_good rland ry mask && range_in_bitwidth rshiftl s && (mask =? Z.ones (Z.log2 s - offset)) && (0 <=? offset) && (offset <=? Z.log2 s) && lit_good s rs && lit_good mask rmask && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ ??' @ pcst (#pattern.ident.Z_shiftl @ (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ')) @ #?ℤ') @ ??'))
- (fun '((r1, r2)%core) rs s rc c rshiftl rland ry y rmask mask roffset offset rx x => cst2 (r1, r2)%core (#(ident.fancy_addc (Z.log2 s) offset) @ (cst rc c, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftl_good rshiftl rland offset && range_in_bitwidth rshiftl s && land_good rland ry mask && (mask =? Z.ones (Z.log2 s - offset)) && (0 <=? offset) && (offset <=? Z.log2 s) && lit_good s rs && lit_good mask rmask && lit_good offset roffset)
+ *)
+ ; (forall r rs s rc c rx x rshiftl rland ry y rmask mask roffset offset,
+ s ∈ rs -> mask ∈ rmask -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftl_good rshiftl rland offset -> land_good rland ry mask -> range_in_bitwidth rshiftl s -> (mask = Z.ones (Z.log2 s - offset)) -> (0 <= offset <= Z.log2 s)
+ -> cstZZ r (Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ rc c) (cstZ rx x) (cstZ rshiftl (Z.shiftl (cstZ rland (Z.land (cstZ ry y) (cstZ rmask ('mask)))) (cstZ roffset ('offset)))))
+ = cstZZ r (ident.interp (ident.fancy_addc (Z.log2 s) offset) (cstZ rc c, cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rc c rshiftl rland ry y rmask mask roffset offset rx x,
+ s ∈ rs -> mask ∈ rmask -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftl_good rshiftl rland offset -> range_in_bitwidth rshiftl s -> land_good rland ry mask -> (mask = Z.ones (Z.log2 s - offset)) -> (0 <= offset <= Z.log2 s)
+ -> cstZZ r (Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ rc c) (cstZ rshiftl (Z.shiftl (cstZ rland (Z.land (cstZ ry y) (cstZ rmask ('mask)))) (cstZ roffset ('offset)))) (cstZ rx x))
+ = cstZZ r (ident.interp (ident.fancy_addc (Z.log2 s) offset) (cstZ rc c, cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rc c rx x rshiftr ry y roffset offset,
+ s ∈ rs -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftr_good rshiftr ry offset -> range_in_bitwidth rshiftr s
+ -> cstZZ r (Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ rc c) (cstZ rx x) (cstZ rshiftr (Z.shiftr (cstZ ry y) (cstZ roffset ('offset)))))
+ = cstZZ r (ident.interp (ident.fancy_addc (Z.log2 s) (-offset)) (cstZ rc c, cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rc c rshiftr ry y roffset offset rx x,
+ s ∈ rs -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftr_good rshiftr ry offset -> range_in_bitwidth rshiftr s
+ -> cstZZ r (Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ rc c) (cstZ rshiftr (Z.shiftr (cstZ ry y) (cstZ roffset ('offset)))) (cstZ rx x))
+ = cstZZ r (ident.interp (ident.fancy_addc (Z.log2 s) (-offset)) (cstZ rc c, cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rc c rx x ry y,
+ s ∈ rs -> (s = 2^Z.log2 s) -> range_in_bitwidth ry s
+ -> cstZZ r (Z.add_with_get_carry_full (cstZ rs ('s)) (cstZ rc c) (cstZ rx x) (cstZ ry y))
+ = cstZZ r (ident.interp (ident.fancy_addc (Z.log2 s) 0) (cstZ rc c, cstZ rx x, cstZ ry y)))
+
+ (*
+(Z.sub_get_borrow_concrete 2^256) @@ (?x, ?y << 128) --> (sub 128) @@ (x, y)
+(Z.sub_get_borrow_concrete 2^256) @@ (?x, ?y >> 128) --> (sub (- 128)) @@ (x, y)
+(Z.sub_get_borrow_concrete 2^256) @@ (?x, ?y) --> (sub 0) @@ (y, x)
+ *)
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ ??' @ ??' @ pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ')))
- (fun '((r1, r2)%core) rs s rc c rx x rshiftr ry y roffset offset => cst2 (r1, r2)%core (#(ident.fancy_addc (Z.log2 s) (-offset)) @ (cst rc c, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftr_good rshiftr ry offset && range_in_bitwidth rshiftr s && lit_good s rs && lit_good offset roffset)
+ ; (forall r rs s rx x rshiftl rland ry y rmask mask roffset offset,
+ s ∈ rs -> mask ∈ rmask -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftl_good rshiftl rland offset -> range_in_bitwidth rshiftl s -> land_good rland ry mask -> (mask = Z.ones (Z.log2 s - offset)) -> (0 <= offset <= Z.log2 s)
+ -> cstZZ r (Z.sub_get_borrow_full (cstZ rs ('s)) (cstZ rx x) (cstZ rshiftl (Z.shiftl (cstZ rland (Z.land (cstZ ry y) (cstZ rmask ('mask)))) (cstZ roffset ('offset)))))
+ = cstZZ r (ident.interp (ident.fancy_sub (Z.log2 s) offset) (cstZ rx x, cstZ ry y)))
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ ??' @ pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ') @ ??'))
- (fun '((r1, r2)%core) rs s rc c rshiftr ry y roffset offset rx x => cst2 (r1, r2)%core (#(ident.fancy_addc (Z.log2 s) (-offset)) @ (cst rc c, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftr_good rshiftr ry offset && range_in_bitwidth rshiftr s && lit_good s rs && lit_good offset roffset)
+ ; (forall r rs s rx x rshiftr ry y roffset offset,
+ s ∈ rs -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftr_good rshiftr ry offset -> range_in_bitwidth rshiftr s
+ -> cstZZ r (Z.sub_get_borrow_full (cstZ rs ('s)) (cstZ rx x) (cstZ rshiftr (Z.shiftr (cstZ ry y) (cstZ roffset ('offset)))))
+ = cstZZ r (ident.interp (ident.fancy_sub (Z.log2 s) (-offset)) (cstZ rx x, cstZ ry y)))
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_add_with_get_carry @ #?ℤ' @ ??' @ ??' @ ??'))
- (fun '((r1, r2)%core) rs s rc c rx x ry y => cst2 (r1, r2)%core (#(ident.fancy_addc (Z.log2 s) 0) @ (cst rc c, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && range_in_bitwidth ry s && lit_good s rs)
+ ; (forall r rs s rx x ry y,
+ s ∈ rs -> (s = 2^Z.log2 s) -> range_in_bitwidth ry s
+ -> cstZZ r (Z.sub_get_borrow_full (cstZ rs ('s)) (cstZ rx x) (cstZ ry y))
+ = cstZZ r (ident.interp (ident.fancy_sub (Z.log2 s) 0) (cstZ rx x, cstZ ry y)))
-(*
-(Z.sub_get_borrow_concrete 2^256) @@ (?x, ?y << 128) --> (sub 128) @@ (x, y)
-(Z.sub_get_borrow_concrete 2^256) @@ (?x, ?y >> 128) --> (sub (- 128)) @@ (x, y)
-(Z.sub_get_borrow_concrete 2^256) @@ (?x, ?y) --> (sub 0) @@ (y, x)
- *)
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_sub_get_borrow @ #?ℤ' @ ??' @ pcst (#pattern.ident.Z_shiftl @ (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ')) @ #?ℤ')))
- (fun '((r1, r2)%core) rs s rx x rshiftl rland ry y rmask mask roffset offset => cst2 (r1, r2)%core (#(ident.fancy_sub (Z.log2 s) offset) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftl_good rshiftl rland offset && range_in_bitwidth rshiftl s && land_good rland ry mask && (mask =? Z.ones (Z.log2 s - offset)) && (0 <=? offset) && (offset <=? Z.log2 s) && lit_good s rs && lit_good mask rmask && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_sub_get_borrow @ #?ℤ' @ ??' @ pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ')))
- (fun '((r1, r2)%core) rs s rx x rshiftr ry y roffset offset => cst2 (r1, r2)%core (#(ident.fancy_sub (Z.log2 s) (-offset)) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftr_good rshiftr ry offset && range_in_bitwidth rshiftr s && lit_good s rs && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_sub_get_borrow @ #?ℤ' @ ??' @ ??'))
- (fun '((r1, r2)%core) rs s rx x ry y => cst2 (r1, r2)%core (#(ident.fancy_sub (Z.log2 s) 0) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && range_in_bitwidth ry s && lit_good s rs)
-(*
+ (*
(Z.sub_with_get_borrow_concrete 2^256) @@ (?c, ?x, ?y << 128) --> (subb 128) @@ (c, x, y)
(Z.sub_with_get_borrow_concrete 2^256) @@ (?c, ?x, ?y >> 128) --> (subb (- 128)) @@ (c, x, y)
(Z.sub_with_get_borrow_concrete 2^256) @@ (?c, ?x, ?y) --> (subb 0) @@ (c, y, x)
- *)
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_sub_with_get_borrow @ #?ℤ' @ ??' @ ??' @ pcst (#pattern.ident.Z_shiftl @ (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ')) @ #?ℤ')))
- (fun '((r1, r2)%core) rs s rb b rx x rshiftl rland ry y rmask mask roffset offset => cst2 (r1, r2)%core (#(ident.fancy_subb (Z.log2 s) offset) @ (cst rb b, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftl_good rshiftl rland offset && range_in_bitwidth rshiftl s && land_good rland ry mask && (mask =? Z.ones (Z.log2 s - offset)) && (0 <=? offset) && (offset <=? Z.log2 s) && lit_good s rs && lit_good mask rmask && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_sub_with_get_borrow @ #?ℤ' @ ??' @ ??' @ pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ')))
- (fun '((r1, r2)%core) rs s rb b rx x rshiftr ry y roffset offset => cst2 (r1, r2)%core (#(ident.fancy_subb (Z.log2 s) (-offset)) @ (cst rb b, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && shiftr_good rshiftr ry offset && range_in_bitwidth rshiftr s && lit_good s rs && lit_good offset roffset)
-
- ; make_rewriteo
- (pcst2 (#pattern.ident.Z_sub_with_get_borrow @ #?ℤ' @ ??' @ ??' @ ??'))
- (fun '((r1, r2)%core) rs s rb b rx x ry y => cst2 (r1, r2)%core (#(ident.fancy_subb (Z.log2 s) 0) @ (cst rb b, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && range_in_bitwidth ry s && lit_good s rs)
-
- (*(Z.rshi_concrete 2^256 ?n) @@ (?c, ?x, ?y) --> (rshi n) @@ (x, y)*)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_rshi @ #?ℤ' @ ??' @ ??' @ #?ℤ'))
- (fun r rs s rx x ry y rn n => cst r (#(ident.fancy_rshi (Z.log2 s) n) @ (cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && lit_good s rs && lit_good n rn)
-(*
+ *)
+
+ ; (forall r rs s rb b rx x rshiftl rland ry y rmask mask roffset offset,
+ s ∈ rs -> mask ∈ rmask -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftl_good rshiftl rland offset -> range_in_bitwidth rshiftl s -> land_good rland ry mask -> (mask = Z.ones (Z.log2 s - offset)) -> (0 <= offset <= Z.log2 s)
+ -> cstZZ r (Z.sub_with_get_borrow_full (cstZ rs ('s)) (cstZ rb b) (cstZ rx x) (cstZ rshiftl (Z.shiftl (cstZ rland (Z.land (cstZ ry y) (cstZ rmask ('mask)))) (cstZ roffset ('offset)))))
+ = cstZZ r (ident.interp (ident.fancy_subb (Z.log2 s) offset) (cstZ rb b, cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rb b rx x rshiftr ry y roffset offset,
+ s ∈ rs -> offset ∈ roffset -> (s = 2^Z.log2 s) -> shiftr_good rshiftr ry offset -> range_in_bitwidth rshiftr s
+ -> cstZZ r (Z.sub_with_get_borrow_full (cstZ rs ('s)) (cstZ rb b) (cstZ rx x) (cstZ rshiftr (Z.shiftr (cstZ ry y) (cstZ roffset ('offset)))))
+ = cstZZ r (ident.interp (ident.fancy_subb (Z.log2 s) (-offset)) (cstZ rb b, cstZ rx x, cstZ ry y)))
+
+ ; (forall r rs s rb b rx x ry y,
+ s ∈ rs -> (s = 2^Z.log2 s) -> range_in_bitwidth ry s
+ -> cstZZ r (Z.sub_with_get_borrow_full (cstZ rs ('s)) (cstZ rb b) (cstZ rx x) (cstZ ry y))
+ = cstZZ r (ident.interp (ident.fancy_subb (Z.log2 s) 0) (cstZ rb b, cstZ rx x, cstZ ry y)))
+
+ (*(Z.rshi_concrete 2^256 ?n) @@ (?c, ?x, ?y) --> (rshi n) @@ (x, y)*)
+
+ ; (forall r rs s rx x ry y rn n,
+ s ∈ rs -> n ∈ rn -> (s = 2^Z.log2 s)
+ -> cstZ r (Z.rshi (cstZ rs ('s)) (cstZ rx x) (cstZ ry y) (cstZ rn ('n)))
+ = cstZ r (ident.interp (ident.fancy_rshi (Z.log2 s) n) (cstZ rx x, cstZ ry y)))
+
+ (*
Z.zselect @@ (Z.cc_m_concrete 2^256 ?c, ?x, ?y) --> selm @@ (c, x, y)
Z.zselect @@ (?c &' 1, ?x, ?y) --> sell @@ (c, x, y)
Z.zselect @@ (?c, ?x, ?y) --> selc @@ (c, x, y)
- *)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_zselect @ pcst (#pattern.ident.Z_cc_m @ #?ℤ' @ ??') @ ??' @ ??'))
- (fun r rccm rs s rc c rx x ry y => cst r (#(ident.fancy_selm (Z.log2 s)) @ (cst rc c, cst rx x, cst ry y)) when (s =? 2^Z.log2 s) && cc_m_good rccm s rc && lit_good s rs)
-
- ; make_rewriteo
- (pcst (#pattern.ident.Z_zselect @ pcst (#pattern.ident.Z_land @ #?ℤ' @ ??') @ ??' @ ??'))
- (fun r rland rmask mask rc c rx x ry y => cst r (#ident.fancy_sell @ (cst rc c, cst rx x, cst ry y)) when (mask =? 1) && land_good rland mask rc && lit_good mask rmask)
-
- ; make_rewriteo
- (pcst (#pattern.ident.Z_zselect @ pcst (#pattern.ident.Z_land @ ??' @ #?ℤ') @ ??' @ ??'))
- (fun r rland rc c rmask mask rx x ry y => cst r (#ident.fancy_sell @ (cst rc c, cst rx x, cst ry y)) when (mask =? 1) && land_good rland rc mask && lit_good mask rmask)
-
- ; make_rewrite
- (pcst (#pattern.ident.Z_zselect @ ?? @ ?? @ ??))
- (fun r c x y => cst r (#ident.fancy_selc @ (c, x, y)))
-
-(*Z.add_modulo @@ (?x, ?y, ?m) --> addm @@ (x, y, m)*)
- ; make_rewrite
- (#pattern.ident.Z_add_modulo @ ?? @ ?? @ ??)
- (fun x y m => #ident.fancy_addm @ (x, y, m))
-(*
+ *)
+ ; (forall r rccm rs s rc c rx x ry y,
+ s ∈ rs -> (s = 2^Z.log2 s) -> cc_m_good rccm s rc
+ -> cstZ r (Z.zselect (cstZ rccm (Z.cc_m (cstZ rs ('s)) (cstZ rc c))) (cstZ rx x) (cstZ ry y))
+ = cstZ r (ident.interp (ident.fancy_selm (Z.log2 s)) (cstZ rc c, cstZ rx x, cstZ ry y)))
+
+ ; (forall r rland r1 rc c rx x ry y,
+ 1 ∈ r1 -> land_good rland 1 rc
+ -> cstZ r (Z.zselect (cstZ rland (cstZ r1 1 &' cstZ rc c)) (cstZ rx x) (cstZ ry y))
+ = cstZ r (ident.interp ident.fancy_sell (cstZ rc c, cstZ rx x, cstZ ry y)))
+
+ ; (forall r rland rc c r1 rx x ry y,
+ 1 ∈ r1 -> land_good rland rc 1
+ -> cstZ r (Z.zselect (cstZ rland (cstZ rc c &' cstZ r1 1)) (cstZ rx x) (cstZ ry y))
+ = cstZ r (ident.interp ident.fancy_sell (cstZ rc c, cstZ rx x, cstZ ry y)))
+
+ ; (forall r c x y,
+ cstZ r (Z.zselect c x y)
+ = cstZ r (ident.interp ident.fancy_selc (c, x, y)))
+
+ (*Z.add_modulo @@ (?x, ?y, ?m) --> addm @@ (x, y, m)*)
+ ; (forall x y m,
+ Z.add_modulo x y m
+ = ident.interp ident.fancy_addm (x, y, m))
+
+ (*
Z.mul @@ (?x &' (2^128-1), ?y &' (2^128-1)) --> mulll @@ (x, y)
Z.mul @@ (?x &' (2^128-1), ?y >> 128) --> mullh @@ (x, y)
Z.mul @@ (?x >> 128, ?y &' (2^128-1)) --> mulhl @@ (x, y)
Z.mul @@ (?x >> 128, ?y >> 128) --> mulhh @@ (x, y)
- *)
- (* literal on left *)
- ; make_rewriteo
- (#?ℤ' *' pcst (#pattern.ident.Z_land @ ??' @ #?ℤ'))
- (fun r rx x rland ry y rmask mask => let s := (2*Z.log2_up mask)%Z in x <- invert_low s x; cst r (#(ident.fancy_mulll s) @ (##x, cst ry y)) when (mask =? 2^(s/2)-1) && land_good rland ry mask && lit_good x rx && lit_good mask rmask)
- ; make_rewriteo
- (#?ℤ' *' pcst (#pattern.ident.Z_land @ #?ℤ' @ ??'))
- (fun r rx x rland rmask mask ry y => let s := (2*Z.log2_up mask)%Z in x <- invert_low s x; cst r (#(ident.fancy_mulll s) @ (##x, cst ry y)) when (mask =? 2^(s/2)-1) && land_good rland mask ry && lit_good x rx && lit_good mask rmask)
- ; make_rewriteo
- (#?ℤ' *' pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ'))
- (fun r rx x rshiftr ry y roffset offset => let s := (2*offset)%Z in x <- invert_low s x; cst r (#(ident.fancy_mullh s) @ (##x, cst ry y)) when shiftr_good rshiftr ry offset && lit_good x rx && lit_good offset roffset)
- ; make_rewriteo
- (#?ℤ' *' pcst (#pattern.ident.Z_land @ #?ℤ' @ ??'))
- (fun r rx x rland rmask mask ry y => let s := (2*Z.log2_up mask)%Z in x <- invert_high s x; cst r (#(ident.fancy_mulhl s) @ (##x, cst ry y)) when (mask =? 2^(s/2)-1) && land_good rland mask ry && lit_good x rx && lit_good mask rmask)
- ; make_rewriteo
- (#?ℤ' *' pcst (#pattern.ident.Z_land @ ??' @ #?ℤ'))
- (fun r rx x rland ry y rmask mask => let s := (2*Z.log2_up mask)%Z in x <- invert_high s x; cst r (#(ident.fancy_mulhl s) @ (##x, cst ry y)) when (mask =? 2^(s/2)-1) && land_good rland ry mask && lit_good x rx && lit_good mask rmask)
- ; make_rewriteo
- (#?ℤ' *' pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ'))
- (fun r rx x rshiftr ry y roffset offset => let s := (2*offset)%Z in x <- invert_high s x; cst r (#(ident.fancy_mulhh s) @ (##x, cst ry y)) when shiftr_good rshiftr ry offset && lit_good x rx && lit_good offset roffset)
- (* literal on right *)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ #?ℤ' @ ??') *' #?ℤ')
- (fun r rland rmask mask rx x ry y => let s := (2*Z.log2_up mask)%Z in y <- invert_low s y; cst r (#(ident.fancy_mulll s) @ (cst rx x, ##y)) when (mask =? 2^(s/2)-1) && land_good rland mask rx && lit_good y ry && lit_good mask rmask)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ') *' #?ℤ')
- (fun r rland rx x rmask mask ry y => let s := (2*Z.log2_up mask)%Z in y <- invert_low s y; cst r (#(ident.fancy_mulll s) @ (cst rx x, ##y)) when (mask =? 2^(s/2)-1) && land_good rland rx mask && lit_good y ry && lit_good mask rmask)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ #?ℤ' @ ??') *' #?ℤ')
- (fun r rland rmask mask rx x ry y => let s := (2*Z.log2_up mask)%Z in y <- invert_high s y; cst r (#(ident.fancy_mullh s) @ (cst rx x, ##y)) when (mask =? 2^(s/2)-1) && land_good rland mask rx && lit_good y ry && lit_good mask rmask)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ') *' #?ℤ')
- (fun r rland rx x rmask mask ry y => let s := (2*Z.log2_up mask)%Z in y <- invert_high s y; cst r (#(ident.fancy_mullh s) @ (cst rx x, ##y)) when (mask =? 2^(s/2)-1) && land_good rland rx mask && lit_good y ry && lit_good mask rmask)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ') *' #?ℤ')
- (fun r rshiftr rx x roffset offset ry y => let s := (2*offset)%Z in y <- invert_low s y; cst r (#(ident.fancy_mulhl s) @ (cst rx x, ##y)) when shiftr_good rshiftr rx offset && lit_good y ry && lit_good offset roffset)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ') *' #?ℤ')
- (fun r rshiftr rx x roffset offset ry y => let s := (2*offset)%Z in y <- invert_high s y; cst r (#(ident.fancy_mulhh s) @ (cst rx x, ##y)) when shiftr_good rshiftr rx offset && lit_good y ry && lit_good offset roffset)
- (* no literal *)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ #?ℤ' @ ??') *' pcst (#pattern.ident.Z_land @ #?ℤ' @ ??'))
- (fun r rland1 rmask1 mask1 rx x rland2 rmask2 mask2 ry y => let s := (2*Z.log2_up mask1)%Z in cst r (#(ident.fancy_mulll s) @ (cst rx x, cst ry y)) when (mask1 =? 2^(s/2)-1) && (mask2 =? 2^(s/2)-1) && land_good rland1 mask1 rx && land_good rland2 mask2 ry && lit_good mask1 rmask1 && lit_good mask2 rmask2)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ') *' pcst (#pattern.ident.Z_land @ #?ℤ' @ ??'))
- (fun r rland1 rx x rmask1 mask1 rland2 rmask2 mask2 ry y => let s := (2*Z.log2_up mask1)%Z in cst r (#(ident.fancy_mulll s) @ (cst rx x, cst ry y)) when (mask1 =? 2^(s/2)-1) && (mask2 =? 2^(s/2)-1) && land_good rland1 rx mask1 && land_good rland2 mask2 ry && lit_good mask1 rmask1 && lit_good mask2 rmask2)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ #?ℤ' @ ??') *' pcst (#pattern.ident.Z_land @ ??' @ #?ℤ'))
- (fun r rland1 rmask1 mask1 rx x rland2 ry y rmask2 mask2 => let s := (2*Z.log2_up mask1)%Z in cst r (#(ident.fancy_mulll s) @ (cst rx x, cst ry y)) when (mask1 =? 2^(s/2)-1) && (mask2 =? 2^(s/2)-1) && land_good rland1 mask1 rx && land_good rland2 ry mask2 && lit_good mask1 rmask1 && lit_good mask2 rmask2)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ') *' pcst (#pattern.ident.Z_land @ ??' @ #?ℤ'))
- (fun r rland1 rx x rmask1 mask1 rland2 ry y rmask2 mask2 => let s := (2*Z.log2_up mask1)%Z in cst r (#(ident.fancy_mulll s) @ (cst rx x, cst ry y)) when (mask1 =? 2^(s/2)-1) && (mask2 =? 2^(s/2)-1) && land_good rland1 rx mask1 && land_good rland2 ry mask2 && lit_good mask1 rmask1 && lit_good mask2 rmask2)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ #?ℤ' @ ??') *' pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ'))
- (fun r rland1 rmask mask rx x rshiftr2 ry y roffset offset => let s := (2*offset)%Z in cst r (#(ident.fancy_mullh s) @ (cst rx x, cst ry y)) when (mask =? 2^(s/2)-1) && land_good rland1 mask rx && shiftr_good rshiftr2 ry offset && lit_good mask rmask && lit_good offset roffset)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_land @ ??' @ #?ℤ') *' pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ'))
- (fun r rland1 rx x rmask mask rshiftr2 ry y roffset offset => let s := (2*offset)%Z in cst r (#(ident.fancy_mullh s) @ (cst rx x, cst ry y)) when (mask =? 2^(s/2)-1) && land_good rland1 rx mask && shiftr_good rshiftr2 ry offset && lit_good mask rmask && lit_good offset roffset)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ') *' pcst (#pattern.ident.Z_land @ #?ℤ' @ ??'))
- (fun r rshiftr1 rx x roffset offset rland2 rmask mask ry y => let s := (2*offset)%Z in cst r (#(ident.fancy_mulhl s) @ (cst rx x, cst ry y)) when (mask =? 2^(s/2)-1) && shiftr_good rshiftr1 rx offset && land_good rland2 mask ry && lit_good mask rmask && lit_good offset roffset)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ') *' pcst (#pattern.ident.Z_land @ ??' @ #?ℤ'))
- (fun r rshiftr1 rx x roffset offset rland2 ry y rmask mask => let s := (2*offset)%Z in cst r (#(ident.fancy_mulhl s) @ (cst rx x, cst ry y)) when (mask =? 2^(s/2)-1) && shiftr_good rshiftr1 rx offset && land_good rland2 ry mask && lit_good mask rmask && lit_good offset roffset)
- ; make_rewriteo
- (pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ') *' pcst (#pattern.ident.Z_shiftr @ ??' @ #?ℤ'))
- (fun r rshiftr1 rx x roffset1 offset1 rshiftr2 ry y roffset2 offset2 => let s := (2*offset1)%Z in cst r (#(ident.fancy_mulhh s) @ (cst rx x, cst ry y)) when (offset1 =? offset2) && shiftr_good rshiftr1 rx offset1 && shiftr_good rshiftr2 ry offset2 && lit_good offset1 roffset1 && lit_good offset2 roffset2)
-
-
-
- (** Dummy rule to make sure we use the two value ranges; this can be removed *)
- ; make_rewriteo
- (??')
- (fun rx x => cst rx x when is_tighter_than_bool rx value_range || is_tighter_than_bool rx flag_range)
-
- ].
+ *)
+ (* literal on left *)
+ ; (forall r rx x rland ry y rmask mask,
+ plet s := (2*Z.log2_up mask)%Z in
+ plet xo := invert_low s x in
+ plet xv := match xo with Some x => x | None => 0 end in
+ xo <> None -> x ∈ rx -> mask ∈ rmask -> (mask = 2^(s/2)-1) -> land_good rland ry mask
+ -> cstZ r (cstZ rx ('x) * cstZ rland (Z.land (cstZ ry y) (cstZ rmask ('mask))))
+ = cstZ r (ident.interp (ident.fancy_mulll s) ('xv, cstZ ry y)))
+
+ ; (forall r rx x rland rmask mask ry y,
+ plet s := (2*Z.log2_up mask)%Z in
+ plet xo := invert_low s x in
+ plet xv := match xo with Some x => x | None => 0 end in
+ xo <> None -> x ∈ rx -> mask ∈ rmask -> (mask = 2^(s/2)-1) -> land_good rland mask ry
+ -> cstZ r (cstZ rx ('x) * cstZ rland (Z.land (cstZ rmask ('mask)) (cstZ ry y)))
+ = cstZ r (ident.interp (ident.fancy_mulll s) ('xv, cstZ ry y)))
+
+ ; (forall r rx x rshiftr ry y roffset offset,
+ plet s := (2*offset)%Z in
+ plet xo := invert_low s x in
+ plet xv := match xo with Some x => x | None => 0 end in
+ xo <> None -> x ∈ rx -> offset ∈ roffset -> shiftr_good rshiftr ry offset
+ -> cstZ r (cstZ rx ('x) * cstZ rshiftr (Z.shiftr (cstZ ry y) (cstZ roffset ('offset))))
+ = cstZ r (ident.interp (ident.fancy_mullh s) ('xv, cstZ ry y)))
+
+ ; (forall r rx x rland rmask mask ry y,
+ plet s := (2*Z.log2_up mask)%Z in
+ plet xo := invert_high s x in
+ plet xv := match xo with Some x => x | None => 0 end in
+ xo <> None -> x ∈ rx -> mask ∈ rmask -> (mask = 2^(s/2)-1) -> land_good rland mask ry
+ -> cstZ r (cstZ rx ('x) * cstZ rland (Z.land (cstZ rmask ('mask)) (cstZ ry y)))
+ = cstZ r (ident.interp (ident.fancy_mulhl s) ('xv, cstZ ry y)))
+
+ ; (forall r rx x rland ry y rmask mask,
+ plet s := (2*Z.log2_up mask)%Z in
+ plet xo := invert_high s x in
+ plet xv := match xo with Some x => x | None => 0 end in
+ xo <> None -> x ∈ rx -> mask ∈ rmask -> (mask = 2^(s/2)-1) -> land_good rland ry mask
+ -> cstZ r (cstZ rx ('x) * cstZ rland (Z.land (cstZ ry y) (cstZ rmask ('mask))))
+ = cstZ r (ident.interp (ident.fancy_mulhl s) ('xv, cstZ ry y)))
+
+ ; (forall r rx x rshiftr ry y roffset offset,
+ plet s := (2*offset)%Z in
+ plet xo := invert_high s x in
+ plet xv := match xo with Some x => x | None => 0 end in
+ xo <> None -> x ∈ rx -> offset ∈ roffset -> shiftr_good rshiftr ry offset
+ -> cstZ r (cstZ rx ('x) * cstZ rshiftr (Z.shiftr (cstZ ry y) (cstZ roffset ('offset))))
+ = cstZ r (ident.interp (ident.fancy_mulhh s) ('xv, cstZ ry y)))
+
+ (* literal on right *)
+ ; (forall r rland rmask mask rx x ry y,
+ plet s := (2*Z.log2_up mask)%Z in
+ plet yo := invert_low s y in
+ plet yv := match yo with Some y => y | None => 0 end in
+ yo <> None -> y ∈ ry -> mask ∈ rmask -> (mask = 2^(s/2)-1) -> land_good rland mask rx
+ -> cstZ r (cstZ rland (Z.land (cstZ rmask ('mask)) (cstZ rx x)) * cstZ ry ('y))
+ = cstZ r (ident.interp (ident.fancy_mulll s) (cstZ rx x, 'yv)))
+
+ ; (forall r rland rx x rmask mask ry y,
+ plet s := (2*Z.log2_up mask)%Z in
+ plet yo := invert_low s y in
+ plet yv := match yo with Some y => y | None => 0 end in
+ yo <> None -> y ∈ ry -> mask ∈ rmask -> (mask = 2^(s/2)-1) -> land_good rland rx mask
+ -> cstZ r (cstZ rland (Z.land (cstZ rx x) (cstZ rmask ('mask))) * cstZ ry ('y))
+ = cstZ r (ident.interp (ident.fancy_mulll s) (cstZ rx x, 'yv)))
+
+ ; (forall r rland rmask mask rx x ry y,
+ plet s := (2*Z.log2_up mask)%Z in
+ plet yo := invert_high s y in
+ plet yv := match yo with Some y => y | None => 0 end in
+ yo <> None -> y ∈ ry -> mask ∈ rmask -> (mask = 2^(s/2)-1) -> land_good rland mask rx
+ -> cstZ r (cstZ rland (Z.land (cstZ rmask ('mask)) (cstZ rx x)) * cstZ ry ('y))
+ = cstZ r (ident.interp (ident.fancy_mullh s) (cstZ rx x, 'yv)))
+
+ ; (forall r rland rx x rmask mask ry y,
+ plet s := (2*Z.log2_up mask)%Z in
+ plet yo := invert_high s y in
+ plet yv := match yo with Some y => y | None => 0 end in
+ yo <> None -> y ∈ ry -> mask ∈ rmask -> (mask = 2^(s/2)-1) -> land_good rland rx mask
+ -> cstZ r (cstZ rland (Z.land (cstZ rx x) (cstZ rmask ('mask))) * cstZ ry ('y))
+ = cstZ r (ident.interp (ident.fancy_mullh s) (cstZ rx x, 'yv)))
+
+ ; (forall r rshiftr rx x roffset offset ry y,
+ plet s := (2*offset)%Z in
+ plet yo := invert_low s y in
+ plet yv := match yo with Some y => y | None => 0 end in
+ yo <> None -> y ∈ ry -> offset ∈ roffset -> shiftr_good rshiftr rx offset
+ -> cstZ r (cstZ rshiftr (Z.shiftr (cstZ rx x) (cstZ roffset ('offset))) * cstZ ry ('y))
+ = cstZ r (ident.interp (ident.fancy_mulhl s) (cstZ rx x, 'yv)))
+
+ ; (forall r rshiftr rx x roffset offset ry y,
+ plet s := (2*offset)%Z in
+ plet yo := invert_high s y in
+ plet yv := match yo with Some y => y | None => 0 end in
+ yo <> None -> y ∈ ry -> offset ∈ roffset -> shiftr_good rshiftr rx offset
+ -> cstZ r (cstZ rshiftr (Z.shiftr (cstZ rx x) (cstZ roffset ('offset))) * cstZ ry ('y))
+ = cstZ r (ident.interp (ident.fancy_mulhh s) (cstZ rx x, 'yv)))
+
+ (* no literal *)
+ ; (forall r rland1 rmask1 mask1 rx x rland2 rmask2 mask2 ry y,
+ plet s := (2*Z.log2_up mask1)%Z in
+ mask1 ∈ rmask1 -> mask2 ∈ rmask2 -> (mask1 = 2^(s/2)-1) -> (mask2 = 2^(s/2)-1) -> land_good rland1 mask1 rx -> land_good rland2 mask2 ry
+ -> cstZ r (cstZ rland1 (Z.land (cstZ rmask1 ('mask1)) (cstZ rx x)) * cstZ rland2 (Z.land (cstZ rmask2 ('mask2)) (cstZ ry y)))
+ = cstZ r (ident.interp (ident.fancy_mulll s) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rland1 rx x rmask1 mask1 rland2 rmask2 mask2 ry y,
+ plet s := (2*Z.log2_up mask1)%Z in
+ mask1 ∈ rmask1 -> mask2 ∈ rmask2 -> (mask1 = 2^(s/2)-1) -> (mask2 = 2^(s/2)-1) -> land_good rland1 rx mask1 -> land_good rland2 mask2 ry
+ -> cstZ r (cstZ rland1 (Z.land (cstZ rx x) (cstZ rmask1 ('mask1))) * cstZ rland2 (Z.land (cstZ rmask2 ('mask2)) (cstZ ry y)))
+ = cstZ r (ident.interp (ident.fancy_mulll s) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rland1 rmask1 mask1 rx x rland2 ry y rmask2 mask2,
+ plet s := (2*Z.log2_up mask1)%Z in
+ mask1 ∈ rmask1 -> mask2 ∈ rmask2 -> (mask1 = 2^(s/2)-1) -> (mask2 = 2^(s/2)-1) -> land_good rland1 mask1 rx -> land_good rland2 ry mask2
+ -> cstZ r (cstZ rland1 (Z.land (cstZ rmask1 ('mask1)) (cstZ rx x)) * cstZ rland2 (Z.land (cstZ ry y) (cstZ rmask2 ('mask2))))
+ = cstZ r (ident.interp (ident.fancy_mulll s) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rland1 rx x rmask1 mask1 rland2 ry y rmask2 mask2,
+ plet s := (2*Z.log2_up mask1)%Z in
+ mask1 ∈ rmask1 -> mask2 ∈ rmask2 -> (mask1 = 2^(s/2)-1) -> (mask2 = 2^(s/2)-1) -> land_good rland1 rx mask1 -> land_good rland2 ry mask2
+ -> cstZ r (cstZ rland1 (Z.land (cstZ rx x) (cstZ rmask1 ('mask1))) * cstZ rland2 (Z.land (cstZ ry y) (cstZ rmask2 ('mask2))))
+ = cstZ r (ident.interp (ident.fancy_mulll s) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rland1 rmask mask rx x rshiftr2 ry y roffset offset,
+ plet s := (2*offset)%Z in
+ mask ∈ rmask -> offset ∈ roffset -> (mask = 2^(s/2)-1) -> land_good rland1 mask rx -> shiftr_good rshiftr2 ry offset
+ -> cstZ r (cstZ rland1 (Z.land (cstZ rmask ('mask)) (cstZ rx x)) * cstZ rshiftr2 (Z.shiftr (cstZ ry y) (cstZ roffset ('offset))))
+ = cstZ r (ident.interp (ident.fancy_mullh s) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rland1 rx x rmask mask rshiftr2 ry y roffset offset,
+ plet s := (2*offset)%Z in
+ mask ∈ rmask -> offset ∈ roffset -> (mask = 2^(s/2)-1) -> land_good rland1 rx mask -> shiftr_good rshiftr2 ry offset
+ -> cstZ r (cstZ rland1 (Z.land (cstZ rx x) (cstZ rmask ('mask))) * cstZ rshiftr2 (Z.shiftr (cstZ ry y) (cstZ roffset ('offset))))
+ = cstZ r (ident.interp (ident.fancy_mullh s) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rshiftr1 rx x roffset offset rland2 rmask mask ry y,
+ plet s := (2*offset)%Z in
+ mask ∈ rmask -> offset ∈ roffset -> (mask = 2^(s/2)-1) -> shiftr_good rshiftr1 rx offset -> land_good rland2 mask ry
+ -> cstZ r (cstZ rshiftr1 (Z.shiftr (cstZ rx x) (cstZ roffset ('offset))) * cstZ rland2 (Z.land (cstZ rmask ('mask)) (cstZ ry y)))
+ = cstZ r (ident.interp (ident.fancy_mulhl s) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rshiftr1 rx x roffset offset rland2 ry y rmask mask,
+ plet s := (2*offset)%Z in
+ mask ∈ rmask -> offset ∈ roffset -> (mask = 2^(s/2)-1) -> shiftr_good rshiftr1 rx offset -> land_good rland2 ry mask
+ -> cstZ r (cstZ rshiftr1 (Z.shiftr (cstZ rx x) (cstZ roffset ('offset))) * cstZ rland2 (Z.land (cstZ ry y) (cstZ rmask ('mask))))
+ = cstZ r (ident.interp (ident.fancy_mulhl s) (cstZ rx x, cstZ ry y)))
+
+ ; (forall r rshiftr1 rx x roffset1 offset1 rshiftr2 ry y roffset2 offset2,
+ plet s := (2*offset1)%Z in
+ offset1 ∈ roffset1 -> offset2 ∈ roffset2 -> (offset1 = offset2) -> shiftr_good rshiftr1 rx offset1 -> shiftr_good rshiftr2 ry offset2
+ -> cstZ r (cstZ rshiftr1 (Z.shiftr (cstZ rx x) (cstZ roffset1 ('offset1))) * cstZ rshiftr2 (Z.shiftr (cstZ ry y) (cstZ roffset2 ('offset2))))
+ = cstZ r (ident.interp (ident.fancy_mulhh s) (cstZ rx x, cstZ ry y)))
+
+ (** Dummy rule to make sure we use the two value ranges; this can be removed *)
+ ; (forall rx x,
+ ((is_tighter_than_bool rx value_range = true)
+ \/ (is_tighter_than_bool rx flag_range = true))
+ -> cstZ rx x = cstZ rx x)
+ ]%Z%zrange
+ ].
Definition fancy_dtree'
:= Eval compute in @compile_rewrites ident var pattern.ident (@pattern.ident.arg_types) pattern.Raw.ident (@pattern.ident.strip_types) pattern.Raw.ident.ident_beq 100 fancy_rewrite_rules.
diff --git a/src/RewriterRulesInterpGood.v b/src/RewriterRulesInterpGood.v
index a2aa56a36..954340fa4 100644
--- a/src/RewriterRulesInterpGood.v
+++ b/src/RewriterRulesInterpGood.v
@@ -475,7 +475,10 @@ Module Compilers.
| [ |- ?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
@@ -689,6 +692,8 @@ Module Compilers.
|- 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
end.
Local Ltac unfold_cast_lemmas :=