Notation val_inject:= Val.inject.
(* A minimal preservation property we sometimes require. *)
(* Definition readonly {F V} (ge: Genv.t F V) m1 b m2 := forall gv, Genv.find_var_info ge b = Some gv -> gvar_readonly gv && negb (gvar_volatile gv) = true -> forall ch ofs, Mem.load ch m2 b ofs = Mem.load ch m1 b ofs. *)
Definition readonlyLD m1 b m2 :=
forall chunk ofs
(NWR: forall ofs', ofs <= ofs' < ofs + size_chunk chunk ->
~(Mem.perm m1 b ofs' Cur Writable)),
Mem.load chunk m2 b ofs = Mem.load chunk m1 b ofs /\
(forall ofs', ofs <= ofs' < ofs + size_chunk chunk ->
(forall k p, Mem.perm m1 b ofs' k p <-> Mem.perm m2 b ofs' k p)).
Definition readonly m1 b m2 :=
forall n ofs
(NWR: forall i, 0 <= i < n ->
~(Mem.perm m1 b (ofs + i) Cur Writable)),
Mem.loadbytes m2 b ofs n = Mem.loadbytes m1 b ofs n /\
(forall i, 0 <= i < n ->
(forall k p, Mem.perm m1 b (ofs+i) k p <-> Mem.perm m2 b (ofs+i) k p)).
Definition max_readonlyLD m1 b m2 :=
forall chunk ofs
(NWR: forall ofs', ofs <= ofs' < ofs + size_chunk chunk ->
~(Mem.perm m1 b ofs' Max Writable)),
Mem.load chunk m2 b ofs = Mem.load chunk m1 b ofs /\
(forall ofs', ofs <= ofs' < ofs + size_chunk chunk ->
(forall k p, Mem.perm m1 b ofs' k p <-> Mem.perm m2 b ofs' k p)).
Definition max_readonly m1 b m2 :=
forall n ofs
(NWR: forall i, 0 <= i < n ->
~(Mem.perm m1 b (ofs + i) Max Writable)),
Mem.loadbytes m2 b ofs n = Mem.loadbytes m1 b ofs n /\
(forall i, 0 <= i < n ->
(forall k p, Mem.perm m1 b (ofs+i) k p <-> Mem.perm m2 b (ofs+i) k p)).
Definition mem_forward (m1 m2:mem) :=
forall b, Mem.valid_block m1 b ->
(Mem.valid_block m2 b
/\ (forall ofs p, Mem.perm m2 b ofs Max p -> Mem.perm m1 b ofs Max p)
(* Lemma store_forward: forall m b ofs v ch m' (M:Mem.store ch m b ofs v = Some m'), mem_forward m m'.  Lemma storebytes_forward: forall m b ofs bytes m' (M: Mem.storebytes m b ofs bytes = Some m'), mem_forward m m'. *)
(* Lemma unchanged_on_sym P m m' b: Mem.unchanged_on P m m' -> Mem.valid_block m b -> Mem.unchanged_on (fun bb z => P bb z /\ bb=b) m' m. *)

Lemma loadbytes_unchanged_on (P : block -> Z -> Prop) m m' b ofs n:
Mem.unchanged_on P m m' -> Mem.valid_block m b ->
(forall i : Z, ofs <= i < ofs + n -> P b i) ->
Mem.loadbytes m b ofs n = Mem.loadbytes m' b ofs n.