(*Lemma eval_binop_lessdef:
  forall op v1 v1' v2 v2' v m m',
  eval_binop op v1 v2 m = Some v ->
  Val.lessdef v1 v1' -> Val.lessdef v2 v2' -> Mem.extends m m' ->
  exists v', eval_binop op v1' v2' m' = Some v' /\ Val.lessdef v v'.
Proof.
  intros until m'; intros EV LD1 LD2 ME.
  assert (exists v', eval_binop op v1' v2' m = Some v' /\ Val.lessdef v v').
  inv LD1. inv LD2. exists v; auto.
  destruct op; destruct v1'; simpl in *; inv EV; TrivialExists.
  destruct op; simpl in *; inv EV; TrivialExists.
  destruct op; try (exact H).
  simpl in *. TrivialExists. inv EV. apply Val.of_optbool_lessdef.
  intros. apply Val.cmpu_bool_lessdef with (Mem.valid_pointer m) v1 v2; auto.
  intros; eapply Mem.valid_pointer_extends; eauto.
Qed.
*)
(** Lenb: same for binops
    Compatibility of [eval_binop] with respect to [val_inject]. *)

(*Lenb: fom Cminorgenproof: *)
Remark val_inject_val_of_bool:
  forall f b, val_inject f (Val.of_bool b) (Val.of_bool b).(*Lenb: fom Cminorgenproof: *)
Remark val_inject_val_of_optbool:
  forall f ob, val_inject f (Val.of_optbool ob) (Val.of_optbool ob).(*Lenb: fom Cminorgenproof: *)
Ltac TrivialExistsCMINORGEN :=
  match goal with
  | [ |- exists y, Some ?x = Some y /\ val_inject _ _ _ ] =>
      exists x; split; [auto | try(econstructor; eauto)]
  | [ |- exists y, _ /\ val_inject _ (Vint ?x) _ ] =>
      exists (Vint x); split; [eauto with evalexpr | constructor]
  | [ |- exists y, _ /\ val_inject _ (Vfloat ?x) _ ] =>
      exists (Vfloat x); split; [eauto with evalexpr | constructor]
  | [ |- exists y, _ /\ val_inject _ (Vlong ?x) _ ] =>
      exists (Vlong x); split; [eauto with evalexpr | constructor]
  | _ => idtac
  end.

(* Specifications: *)
Lemma eval_binop_compat: forall f op v1 tv1 v2 tv2 v m tm, eval_binop op v1 v2 m = Some v -> val_inject f v1 tv1 -> val_inject f v2 tv2 -> Mem.inject f m tm -> exists tv, eval_binop op tv1 tv2 tm = Some tv /\ val_inject f v tv.
Lemma set_var_inject: forall j e1 e2 id v1 v2, env_inject j e1 e2 -> val_inject j v1 v2 -> env_inject j (PTree.set id v1 e1) (PTree.set id v2 e2).
Lemma set_params_inject: forall j il vl1 vl2, val_list_inject j vl1 vl2 -> env_inject j (set_params vl1 il) (set_params vl2 il).
Lemma set_locals_inject: forall j e1 e2, env_inject j e1 e2 -> forall il, env_inject j (set_locals il e1) (set_locals il e2).
Lemma lessdef_inject: forall v j (Hv: forall b1, getBlocks (v::nil) b1 = true -> j b1 = Some(b1,0)) v' (LD: Val.lessdef v v'), val_inject j v v'.