Skip to content

Commit 9de88be

Browse files
committed
Binding a list of CminorSel expressions to let-variables
This can be useful to avoid duplicating computations.
1 parent de545d7 commit 9de88be

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

backend/CminorSel.v

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
(** The Cminor language after instruction selection. *)
1414

15+
Require Import Recdef.
1516
Require Import Coqlib.
1617
Require Import Maps.
1718
Require Import AST.
@@ -504,6 +505,8 @@ with lift_condexpr (p: nat) (a: condexpr) {struct a}: condexpr :=
504505

505506
Definition lift (a: expr): expr := lift_expr O a.
506507

508+
Definition lift_list (al: exprlist): exprlist := lift_exprlist O al.
509+
507510
(** We now relate the evaluation of a lifted expression with that
508511
of the original expression. *)
509512

@@ -582,4 +585,92 @@ Proof.
582585
eexact H. apply insert_lenv_0.
583586
Qed.
584587

585-
Global Hint Resolve eval_lift: evalexpr.
588+
Lemma eval_lift_list:
589+
forall ge sp e m le w al vl,
590+
eval_exprlist ge sp e m le al vl ->
591+
eval_exprlist ge sp e m (w::le) (lift_list al) vl.
592+
Proof.
593+
induction 1; simpl; eauto using eval_lift, eval_exprlist.
594+
Qed.
595+
596+
Global Hint Resolve eval_lift eval_lift_list: evalexpr.
597+
598+
(** Some operations over [exprlist]. *)
599+
600+
Fixpoint length_exprlist (al: exprlist) : nat :=
601+
match al with Enil => O | Econs a al => S (length_exprlist al) end.
602+
603+
Fixpoint app_exprlist (al bl: exprlist) : exprlist :=
604+
match al with Enil => bl | Econs a al => Econs a (app_exprlist al bl) end.
605+
606+
Lemma eval_app_exprlist: forall ge sp e m le al1 al2 vl1 vl2,
607+
eval_exprlist ge sp e m le al1 vl1 ->
608+
eval_exprlist ge sp e m le al2 vl2 ->
609+
eval_exprlist ge sp e m le (app_exprlist al1 al2) (vl1 ++ vl2).
610+
Proof.
611+
intros. revert al1 vl1 H. induction 1; simpl; eauto using eval_exprlist.
612+
Qed.
613+
614+
(** Binding a list of expressions *)
615+
616+
Function bind_exprs_rec (al: exprlist) (args: exprlist) (f: exprlist -> expr)
617+
{measure length_exprlist al} : expr :=
618+
match al with
619+
| Enil => f args
620+
| Econs a al =>
621+
Elet a (bind_exprs_rec (lift_list al)
622+
(app_exprlist (lift_list args) (Econs (Eletvar O) Enil))
623+
f)
624+
end.
625+
Proof.
626+
intros. replace (length_exprlist (lift_list al0)) with (length_exprlist al0).
627+
- simpl; lia.
628+
- generalize al0. induction al1; simpl; f_equal; auto.
629+
Qed.
630+
631+
Definition bind_exprs (al: exprlist) (f: exprlist -> expr) : expr :=
632+
bind_exprs_rec al Enil f.
633+
634+
Lemma eval_bind_exprs_gen: forall (P: val -> Prop) ge sp e m le al vl f,
635+
eval_exprlist ge sp e m le al vl ->
636+
(forall args,
637+
eval_exprlist ge sp e m (rev vl ++ le) args vl ->
638+
exists v, eval_expr ge sp e m (rev vl ++ le) (f args) v /\ P v) ->
639+
exists v, eval_expr ge sp e m le (bind_exprs al f) v /\ P v.
640+
Proof.
641+
intros until m.
642+
assert (REC: forall al args f le vl1 vl2,
643+
(forall args',
644+
eval_exprlist ge sp e m (rev vl2 ++ le) args' (vl1 ++ vl2) ->
645+
exists v, eval_expr ge sp e m (rev vl2 ++ le) (f args') v /\ P v) ->
646+
eval_exprlist ge sp e m le args vl1 ->
647+
eval_exprlist ge sp e m le al vl2 ->
648+
exists v, eval_expr ge sp e m le (bind_exprs_rec al args f) v /\ P v).
649+
{ intros until f. functional induction (bind_exprs_rec al args f); intros until vl2; intros F A B.
650+
- inv B. apply F. rewrite app_nil_r. auto.
651+
- inv B.
652+
destruct (IHe0 (v1 :: le) (vl1 ++ v1 :: nil) vl) as (v & X & Y).
653+
+ intros.
654+
assert (EQ: rev vl ++ v1 :: le = rev (v1 :: vl) ++ le).
655+
{ simpl. rewrite app_ass. auto. }
656+
rewrite EQ. apply F. rewrite <- EQ. rewrite app_ass in H. auto.
657+
+ apply eval_app_exprlist.
658+
* apply eval_lift_list; auto.
659+
* repeat constructor.
660+
+ apply eval_lift_list; auto.
661+
+ exists v; split; eauto using eval_expr.
662+
}
663+
intros. eapply REC with (args := Enil); eauto using eval_exprlist.
664+
assumption.
665+
Qed.
666+
667+
Lemma eval_bind_exprs: forall ge sp e m le al vl f v,
668+
eval_exprlist ge sp e m le al vl ->
669+
(forall args,
670+
eval_exprlist ge sp e m (rev vl ++ le) args vl ->
671+
eval_expr ge sp e m (rev vl ++ le) (f args) v) ->
672+
eval_expr ge sp e m le (bind_exprs al f) v.
673+
Proof.
674+
intros. exploit (eval_bind_exprs_gen (fun v' => v' = v)); eauto.
675+
intros (v' & A & B). subst v'; auto.
676+
Qed.

0 commit comments

Comments
 (0)