aboutsummaryrefslogtreecommitdiff
path: root/src/Compilers/Z/RewriteAddToAdc.v
blob: 838c92b7538b6c4e6f1909c4cdfae3af47c4d888 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Require Import Coq.ZArith.ZArith.
Require Import Crypto.Compilers.Named.Context.
Require Import Crypto.Compilers.Named.Syntax.
Require Import Crypto.Compilers.Named.InterpretToPHOAS.
Require Import Crypto.Compilers.Named.Compile.
Require Import Crypto.Compilers.Named.Wf.
Require Import Crypto.Compilers.Named.CountLets.
Require Import Crypto.Compilers.Named.PositiveContext.
Require Import Crypto.Compilers.Named.PositiveContext.Defaults.
Require Import Crypto.Compilers.Syntax.
Require Import Crypto.Compilers.ExprInversion.
Require Import Crypto.Compilers.Z.Syntax.
Require Import Crypto.Compilers.Z.Named.DeadCodeElimination.
Require Import Crypto.Compilers.Z.Named.RewriteAddToAdc.
Require Import Crypto.Util.PointedProp.
Require Import Crypto.Util.Decidable.

(** N.B. This procedure only works when there are no nested lets,
    i.e., nothing like [let x := let y := z in w] in the PHOAS syntax
    tree.  This is a limitation of [compile]. *)

Local Open Scope bool_scope.

Section language.
  Local Notation PContext var := (PositiveContext _ var _ internal_base_type_dec_bl).

  Definition RewriteAdc {t} (e : Expr t)
    : Expr t
    := let is_good e' := match option_map (wf_unit (Context:=PContext _) empty) e' with
                         | Some (Some trivial) => true
                         | _ => false
                         end in
       let interp_to_phoas := InterpToPHOAS (Context:=fun var => PContext var)
                                            (fun _ t => Op (OpConst 0%Z) TT) in
       let e' := compile (e _) (DefaultNamesFor e) in
       let e' := option_map (rewrite_expr Pos.eqb) e' in
       let good := is_good e' in
       let e' := match e' with
                 | Some e'
                   => let ls := Named.default_names_for e' in
                      match EliminateDeadCode (Context:=PContext _) e' ls with
                      | Some e'' => Some e''
                      | None => Some e'
                      end
                 | None => None
                 end in
       let good := good && is_good e' in
       if good
       then let e' := option_map interp_to_phoas e' in
            match e' with
            | Some e'
              => match t return Expr (Arrow (domain t) (codomain t)) -> Expr t with
                 | Arrow _ _ => fun x => x
                 end e'
            | None => e
            end
       else e.
End language.