diff --git a/theories/algebra/big_op.v b/theories/algebra/big_op.v
index d7f86c27dffb69ce6d0468d45c3b8182c37a8d94..7bf52ebc2d90a1bb6b37f59afb9d85c6563752cd 100644
--- a/theories/algebra/big_op.v
+++ b/theories/algebra/big_op.v
@@ -101,23 +101,36 @@ Section list.
   Lemma big_opL_unit l : ([^o list] k↦y ∈ l, monoid_unit) ≡ (monoid_unit : M).
   Proof. induction l; rewrite /= ?left_id //. Qed.
 
-  Lemma big_opL_forall R f g l :
+  Lemma big_opL_gen_proper_2 (R : relation M) f g l1 l2 :
+    R monoid_unit monoid_unit →
+    Proper (R ==> R ==> R) o →
+    (∀ k,
+      match l1 !! k, l2 !! k with
+      | Some y1, Some y2 => R (f k y1) (g k y2)
+      | None, None => True
+      | _, _ => False
+      end) →
+    R ([^o list] k ↦ y ∈ l1, f k y) ([^o list] k ↦ y ∈ l2, g k y).
+  Proof.
+    intros ??. revert l2 f g. induction l1 as [|x1 l1 IH]=> -[|x2 l2] //= f g Hfg.
+    - by specialize (Hfg 0).
+    - by specialize (Hfg 0).
+    - f_equiv; [apply (Hfg 0)|]. apply IH. intros k. apply (Hfg (S k)).
+  Qed.
+  Lemma big_opL_gen_proper R f g l :
     Reflexive R →
     Proper (R ==> R ==> R) o →
     (∀ k y, l !! k = Some y → R (f k y) (g k y)) →
     R ([^o list] k ↦ y ∈ l, f k y) ([^o list] k ↦ y ∈ l, g k y).
   Proof.
-    intros ??. revert f g. induction l as [|x l IH]=> f g ? //=; f_equiv; eauto.
+    intros. apply big_opL_gen_proper_2; [done..|].
+    intros k. destruct (l !! k) eqn:?; auto.
   Qed.
 
   Lemma big_opL_ext f g l :
     (∀ k y, l !! k = Some y → f k y = g k y) →
     ([^o list] k ↦ y ∈ l, f k y) = [^o list] k ↦ y ∈ l, g k y.
-  Proof. apply big_opL_forall; apply _. Qed.
-  Lemma big_opL_proper f g l :
-    (∀ k y, l !! k = Some y → f k y ≡ g k y) →
-    ([^o list] k ↦ y ∈ l, f k y) ≡ ([^o list] k ↦ y ∈ l, g k y).
-  Proof. apply big_opL_forall; apply _. Qed.
+  Proof. apply big_opL_gen_proper; apply _. Qed.
 
   Lemma big_opL_permutation (f : A → M) l1 l2 :
     l1 ≡ₚ l2 → ([^o list] x ∈ l1, f x) ≡ ([^o list] x ∈ l2, f x).
@@ -131,14 +144,41 @@ Section list.
     Proper ((≡ₚ) ==> (≡)) (big_opL o (λ _, f)).
   Proof. intros xs1 xs2. apply big_opL_permutation. Qed.
 
-  Global Instance big_opL_ne n :
+  (** The lemmas [big_opL_ne] and [big_opL_proper] are more generic than the
+  instances as they also give [l !! k = Some y] in the premise. *)
+  Lemma big_opL_ne f g l n :
+    (∀ k y, l !! k = Some y → f k y ≡{n}≡ g k y) →
+    ([^o list] k ↦ y ∈ l, f k y) ≡{n}≡ ([^o list] k ↦ y ∈ l, g k y).
+  Proof. apply big_opL_gen_proper; apply _. Qed.
+  Lemma big_opL_proper f g l :
+    (∀ k y, l !! k = Some y → f k y ≡ g k y) →
+    ([^o list] k ↦ y ∈ l, f k y) ≡ ([^o list] k ↦ y ∈ l, g k y).
+  Proof. apply big_opL_gen_proper; apply _. Qed.
+
+  (** The version [big_opL_proper_2] with [≡] for the list arguments can only be
+  used if there is a setoid on [A]. The version for [dist n] can be found in
+  [algebra.list]. We do not define this lemma as a [Proper] instance, since
+  [f_equiv] will then use sometimes use this one, and other times
+  [big_opL_proper'], depending on whether a setoid on [A] exists. *)
+  Lemma big_opL_proper_2 `{!Equiv A} f g l1 l2 :
+    l1 ≡ l2 →
+    (∀ k y1 y2,
+      l1 !! k = Some y1 → l2 !! k = Some y2 → y1 ≡ y2 → f k y1 ≡ g k y2) →
+    ([^o list] k ↦ y ∈ l1, f k y) ≡ ([^o list] k ↦ y ∈ l2, g k y).
+  Proof.
+    intros Hl Hf. apply big_opL_gen_proper_2; try (apply _ || done).
+    intros k. assert (l1 !! k ≡ l2 !! k) as Hlk by (by f_equiv).
+    destruct (l1 !! k) eqn:?, (l2 !! k) eqn:?; inversion Hlk; naive_solver.
+  Qed.
+
+  Global Instance big_opL_ne' n :
     Proper (pointwise_relation _ (pointwise_relation _ (dist n)) ==> (=) ==> dist n)
            (big_opL o (A:=A)).
-  Proof. intros f f' Hf l ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f f' Hf l ? <-. apply big_opL_ne; intros; apply Hf. Qed.
   Global Instance big_opL_proper' :
     Proper (pointwise_relation _ (pointwise_relation _ (≡)) ==> (=) ==> (≡))
            (big_opL o (A:=A)).
-  Proof. intros f f' Hf l ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f f' Hf l ? <-. apply big_opL_proper; intros; apply Hf. Qed.
 
   Lemma big_opL_consZ_l (f : Z → A → M) x l :
     ([^o list] k↦y ∈ x :: l, f k y) = f 0 x `o` [^o list] k↦y ∈ l, f (1 + k)%Z y.
@@ -172,48 +212,96 @@ Section gmap.
   Implicit Types m : gmap K A.
   Implicit Types f g : K → A → M.
 
-  Lemma big_opM_forall R f g m :
-    Reflexive R → Proper (R ==> R ==> R) o →
+  Lemma big_opM_empty f : ([^o map] k↦x ∈ ∅, f k x) = monoid_unit.
+  Proof. by rewrite big_opM_eq /big_opM_def map_to_list_empty. Qed.
+
+  Lemma big_opM_insert f m i x :
+    m !! i = None →
+    ([^o map] k↦y ∈ <[i:=x]> m, f k y) ≡ f i x `o` [^o map] k↦y ∈ m, f k y.
+  Proof. intros ?. by rewrite big_opM_eq /big_opM_def map_to_list_insert. Qed.
+
+  Lemma big_opM_delete f m i x :
+    m !! i = Some x →
+    ([^o map] k↦y ∈ m, f k y) ≡ f i x `o` [^o map] k↦y ∈ delete i m, f k y.
+  Proof.
+    intros. rewrite -big_opM_insert ?lookup_delete //.
+    by rewrite insert_delete insert_id.
+  Qed.
+
+  Lemma big_opM_gen_proper_2 (R : relation M) f g m1 m2 :
+    subrelation (≡) R → Equivalence R →
+    Proper (R ==> R ==> R) o →
+    (∀ k,
+      match m1 !! k, m2 !! k with
+      | Some y1, Some y2 => R (f k y1) (g k y2)
+      | None, None => True
+      | _, _ => False
+      end) →
+    R ([^o map] k ↦ x ∈ m1, f k x) ([^o map] k ↦ x ∈ m2, g k x).
+  Proof.
+    intros HR ??. revert m2 f g.
+    induction m1 as [|k x1 m1 Hm1k IH] using map_ind=> m2 f g Hfg.
+    { destruct m2 as [|k x2 m2 _ _] using map_ind.
+      { rewrite !big_opM_empty. by apply HR. }
+      generalize (Hfg k). by rewrite lookup_empty lookup_insert. }
+    generalize (Hfg k). rewrite lookup_insert.
+    destruct (m2 !! k) as [x2|] eqn:Hm2k; [intros Hk|done].
+    etrans; [by apply HR, big_opM_insert|].
+    etrans; [|by symmetry; apply HR, big_opM_delete].
+    f_equiv; [done|]. apply IH=> k'. destruct (decide (k = k')) as [->|?].
+    - by rewrite lookup_delete Hm1k.
+    - generalize (Hfg k'). rewrite lookup_insert_ne // lookup_delete_ne //.
+  Qed.
+
+  Lemma big_opM_gen_proper R f g m :
+    Reflexive R →
+    Proper (R ==> R ==> R) o →
     (∀ k x, m !! k = Some x → R (f k x) (g k x)) →
     R ([^o map] k ↦ x ∈ m, f k x) ([^o map] k ↦ x ∈ m, g k x).
   Proof.
-    intros ?? Hf. rewrite big_opM_eq. apply (big_opL_forall R); auto.
+    intros ?? Hf. rewrite big_opM_eq. apply (big_opL_gen_proper R); auto.
     intros k [i x] ?%elem_of_list_lookup_2. by apply Hf, elem_of_map_to_list.
   Qed.
 
   Lemma big_opM_ext f g m :
     (∀ k x, m !! k = Some x → f k x = g k x) →
     ([^o map] k ↦ x ∈ m, f k x) = ([^o map] k ↦ x ∈ m, g k x).
-  Proof. apply big_opM_forall; apply _. Qed.
+  Proof. apply big_opM_gen_proper; apply _. Qed.
+
+  (** The lemmas [big_opM_ne] and [big_opM_proper] are more generic than the
+  instances as they also give [m !! k = Some y] in the premise. *)
+  Lemma big_opM_ne f g m n :
+    (∀ k x, m !! k = Some x → f k x ≡{n}≡ g k x) →
+    ([^o map] k ↦ x ∈ m, f k x) ≡{n}≡ ([^o map] k ↦ x ∈ m, g k x).
+  Proof. apply big_opM_gen_proper; apply _. Qed.
   Lemma big_opM_proper f g m :
     (∀ k x, m !! k = Some x → f k x ≡ g k x) →
     ([^o map] k ↦ x ∈ m, f k x) ≡ ([^o map] k ↦ x ∈ m, g k x).
-  Proof. apply big_opM_forall; apply _. Qed.
+  Proof. apply big_opM_gen_proper; apply _. Qed.
+  (** The version [big_opL_proper_2] with [≡] for the map arguments can only be
+  used if there is a setoid on [A]. The version for [dist n] can be found in
+  [algebra.gmap]. We do not define this lemma as a [Proper] instance, since
+  [f_equiv] will then use sometimes use this one, and other times
+  [big_opM_proper'], depending on whether a setoid on [A] exists. *)
+  Lemma big_opM_proper_2 `{!Equiv A} f g m1 m2 :
+    m1 ≡ m2 →
+    (∀ k y1 y2,
+      m1 !! k = Some y1 → m2 !! k = Some y2 → y1 ≡ y2 → f k y1 ≡ g k y2) →
+    ([^o map] k ↦ y ∈ m1, f k y) ≡ ([^o map] k ↦ y ∈ m2, g k y).
+  Proof.
+    intros Hl Hf. apply big_opM_gen_proper_2; try (apply _ || done).
+    intros k. assert (m1 !! k ≡ m2 !! k) as Hlk by (by f_equiv).
+    destruct (m1 !! k) eqn:?, (m2 !! k) eqn:?; inversion Hlk; naive_solver.
+  Qed.
 
-  Global Instance big_opM_ne n :
+  Global Instance big_opM_ne' n :
     Proper (pointwise_relation _ (pointwise_relation _ (dist n)) ==> (=) ==> dist n)
            (big_opM o (K:=K) (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opM_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_opM_ne; intros; apply Hf. Qed.
   Global Instance big_opM_proper' :
     Proper (pointwise_relation _ (pointwise_relation _ (≡)) ==> (=) ==> (≡))
            (big_opM o (K:=K) (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opM_forall; apply _ || intros; apply Hf. Qed.
-
-  Lemma big_opM_empty f : ([^o map] k↦x ∈ ∅, f k x) = monoid_unit.
-  Proof. by rewrite big_opM_eq /big_opM_def map_to_list_empty. Qed.
-
-  Lemma big_opM_insert f m i x :
-    m !! i = None →
-    ([^o map] k↦y ∈ <[i:=x]> m, f k y) ≡ f i x `o` [^o map] k↦y ∈ m, f k y.
-  Proof. intros ?. by rewrite big_opM_eq /big_opM_def map_to_list_insert. Qed.
-
-  Lemma big_opM_delete f m i x :
-    m !! i = Some x →
-    ([^o map] k↦y ∈ m, f k y) ≡ f i x `o` [^o map] k↦y ∈ delete i m, f k y.
-  Proof.
-    intros. rewrite -big_opM_insert ?lookup_delete //.
-    by rewrite insert_delete insert_id.
-  Qed.
+  Proof. intros f g Hf m ? <-. apply big_opM_proper; intros; apply Hf. Qed.
 
   Lemma big_opM_singleton f i x : ([^o map] k↦y ∈ {[i:=x]}, f k y) ≡ f i x.
   Proof.
@@ -278,30 +366,37 @@ Section gset.
   Implicit Types X : gset A.
   Implicit Types f : A → M.
 
-  Lemma big_opS_forall R f g X :
+  Lemma big_opS_gen_proper R f g X :
     Reflexive R → Proper (R ==> R ==> R) o →
     (∀ x, x ∈ X → R (f x) (g x)) →
     R ([^o set] x ∈ X, f x) ([^o set] x ∈ X, g x).
   Proof.
-    rewrite big_opS_eq. intros ?? Hf. apply (big_opL_forall R); auto.
+    rewrite big_opS_eq. intros ?? Hf. apply (big_opL_gen_proper R); auto.
     intros k x ?%elem_of_list_lookup_2. by apply Hf, elem_of_elements.
   Qed.
 
   Lemma big_opS_ext f g X :
     (∀ x, x ∈ X → f x = g x) →
     ([^o set] x ∈ X, f x) = ([^o set] x ∈ X, g x).
-  Proof. apply big_opS_forall; apply _. Qed.
+  Proof. apply big_opS_gen_proper; apply _. Qed.
+
+  (** The lemmas [big_opS_ne] and [big_opS_proper] are more generic than the
+  instances as they also give [x ∈ X] in the premise. *)
+  Lemma big_opS_ne f g X n :
+    (∀ x, x ∈ X → f x ≡{n}≡ g x) →
+    ([^o set] x ∈ X, f x) ≡{n}≡ ([^o set] x ∈ X, g x).
+  Proof. apply big_opS_gen_proper; apply _. Qed.
   Lemma big_opS_proper f g X :
     (∀ x, x ∈ X → f x ≡ g x) →
     ([^o set] x ∈ X, f x) ≡ ([^o set] x ∈ X, g x).
-  Proof. apply big_opS_forall; apply _. Qed.
+  Proof. apply big_opS_gen_proper; apply _. Qed.
 
-  Global Instance big_opS_ne n :
+  Global Instance big_opS_ne' n :
     Proper (pointwise_relation _ (dist n) ==> (=) ==> dist n) (big_opS o (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opS_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_opS_ne; intros; apply Hf. Qed.
   Global Instance big_opS_proper' :
     Proper (pointwise_relation _ (≡) ==> (=) ==> (≡)) (big_opS o (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opS_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_opS_proper; intros; apply Hf. Qed.
 
   Lemma big_opS_empty f : ([^o set] x ∈ ∅, f x) = monoid_unit.
   Proof. by rewrite big_opS_eq /big_opS_def elements_empty. Qed.
@@ -365,30 +460,37 @@ Section gmultiset.
   Implicit Types X : gmultiset A.
   Implicit Types f : A → M.
 
-  Lemma big_opMS_forall R f g X :
+  Lemma big_opMS_gen_proper R f g X :
     Reflexive R → Proper (R ==> R ==> R) o →
     (∀ x, x ∈ X → R (f x) (g x)) →
     R ([^o mset] x ∈ X, f x) ([^o mset] x ∈ X, g x).
   Proof.
-    rewrite big_opMS_eq. intros ?? Hf. apply (big_opL_forall R); auto.
+    rewrite big_opMS_eq. intros ?? Hf. apply (big_opL_gen_proper R); auto.
     intros k x ?%elem_of_list_lookup_2. by apply Hf, gmultiset_elem_of_elements.
   Qed.
 
   Lemma big_opMS_ext f g X :
     (∀ x, x ∈ X → f x = g x) →
     ([^o mset] x ∈ X, f x) = ([^o mset] x ∈ X, g x).
-  Proof. apply big_opMS_forall; apply _. Qed.
+  Proof. apply big_opMS_gen_proper; apply _. Qed.
+
+  (** The lemmas [big_opMS_ne] and [big_opMS_proper] are more generic than the
+  instances as they also give [x ∈ X] in the premise. *)
+  Lemma big_opMS_ne f g X n :
+    (∀ x, x ∈ X → f x ≡{n}≡ g x) →
+    ([^o mset] x ∈ X, f x) ≡{n}≡ ([^o mset] x ∈ X, g x).
+  Proof. apply big_opMS_gen_proper; apply _. Qed.
   Lemma big_opMS_proper f g X :
     (∀ x, x ∈ X → f x ≡ g x) →
     ([^o mset] x ∈ X, f x) ≡ ([^o mset] x ∈ X, g x).
-  Proof. apply big_opMS_forall; apply _. Qed.
+  Proof. apply big_opMS_gen_proper; apply _. Qed.
 
-  Global Instance big_opMS_ne n :
+  Global Instance big_opMS_ne' n :
     Proper (pointwise_relation _ (dist n) ==> (=) ==> dist n) (big_opMS o (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opMS_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_opMS_ne; intros; apply Hf. Qed.
   Global Instance big_opMS_proper' :
     Proper (pointwise_relation _ (≡) ==> (=) ==> (≡)) (big_opMS o (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opMS_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_opMS_proper; intros; apply Hf. Qed.
 
   Lemma big_opMS_empty f : ([^o mset] x ∈ ∅, f x) = monoid_unit.
   Proof. by rewrite big_opMS_eq /big_opMS_def gmultiset_elements_empty. Qed.
diff --git a/theories/algebra/gmap.v b/theories/algebra/gmap.v
index 25bc95c5b11171ea68209a004f7a8a9fa8cab7d2..d499dfa7db0c15fe543000009094b351e4ecf2fb 100644
--- a/theories/algebra/gmap.v
+++ b/theories/algebra/gmap.v
@@ -44,32 +44,28 @@ Proof. intros ? m m' ? i. by apply (discrete _). Qed.
 Global Instance gmapO_leibniz: LeibnizEquiv A → LeibnizEquiv gmapO.
 Proof. intros; change (LeibnizEquiv (gmap K A)); apply _. Qed.
 
-Global Instance lookup_ne k :
-  NonExpansive (lookup k : gmap K A → option A).
+Global Instance lookup_ne k : NonExpansive (lookup k : gmap K A → option A).
 Proof. by intros m1 m2. Qed.
-Global Instance lookup_proper k :
-  Proper ((≡) ==> (≡)) (lookup k : gmap K A → option A) := _.
-Global Instance alter_ne (f : A → A) (k : K) n :
-  Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (alter f k).
+Global Instance partial_alter_ne n :
+  Proper ((dist n ==> dist n) ==> (=) ==> dist n ==> dist n)
+         (partial_alter (M:=gmap K A)).
 Proof.
-  intros ? m m' Hm k'.
-  by destruct (decide (k = k')); simplify_map_eq; rewrite (Hm k').
-Qed.
-Global Instance insert_ne i :
-  NonExpansive2 (insert (M:=gmap K A) i).
-Proof.
-  intros n x y ? m m' ? j; destruct (decide (i = j)); simplify_map_eq;
-    [by constructor|by apply lookup_ne].
+  by intros f1 f2 Hf i ? <- m1 m2 Hm j; destruct (decide (i = j)) as [->|];
+    rewrite ?lookup_partial_alter ?lookup_partial_alter_ne //;
+    try apply Hf; apply lookup_ne.
 Qed.
-Global Instance singleton_ne i :
-  NonExpansive (singletonM i : A → gmap K A).
+Global Instance insert_ne i : NonExpansive2 (insert (M:=gmap K A) i).
+Proof. intros n x y ? m m' ? j; apply partial_alter_ne; by try constructor. Qed.
+Global Instance singleton_ne i : NonExpansive (singletonM i : A → gmap K A).
 Proof. by intros ????; apply insert_ne. Qed.
-Global Instance delete_ne i :
-  NonExpansive (delete (M:=gmap K A) i).
+Global Instance delete_ne i : NonExpansive (delete (M:=gmap K A) i).
 Proof.
   intros n m m' ? j; destruct (decide (i = j)); simplify_map_eq;
     [by constructor|by apply lookup_ne].
 Qed.
+Global Instance alter_ne (f : A → A) (k : K) n :
+  Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (alter f k).
+Proof. intros ? m m' Hm k'. by apply partial_alter_ne; [solve_proper|..]. Qed.
 
 Global Instance gmap_empty_discrete : Discrete (∅ : gmap K A).
 Proof.
@@ -99,6 +95,63 @@ End cofe.
 
 Arguments gmapO _ {_ _} _.
 
+(** Non-expansiveness of higher-order map functions and big-ops *)
+Lemma merge_ne `{Countable K} {A B C : ofeT} (f g : option A → option B → option C)
+    `{!DiagNone f, !DiagNone g} n :
+  ((dist n) ==> (dist n) ==> (dist n))%signature f g →
+  ((dist n) ==> (dist n) ==> (dist n))%signature (merge (M:=gmap K) f) (merge g).
+Proof. by intros Hf ?? Hm1 ?? Hm2 i; rewrite !lookup_merge //; apply Hf. Qed.
+Instance union_with_proper `{Countable K} {A : ofeT} n :
+  Proper (((dist n) ==> (dist n) ==> (dist n)) ==>
+          (dist n) ==> (dist n) ==>(dist n)) (union_with (M:=gmap K A)).
+Proof.
+  intros ?? Hf ?? Hm1 ?? Hm2 i; apply (merge_ne _ _); auto.
+  by do 2 destruct 1; first [apply Hf | constructor].
+Qed.
+Instance map_fmap_proper `{Countable K} {A B : ofeT} (f : A → B) n :
+  Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (fmap (M:=gmap K) f).
+Proof. intros ? m m' ? k; rewrite !lookup_fmap. by repeat f_equiv. Qed.
+Instance map_zip_with_proper `{Countable K} {A B C : ofeT} (f : A → B → C) n :
+  Proper (dist n ==> dist n ==> dist n) f →
+  Proper (dist n ==> dist n ==> dist n) (map_zip_with (M:=gmap K) f).
+Proof.
+  intros Hf m1 m1' Hm1 m2 m2' Hm2. apply merge_ne; try done.
+  destruct 1; destruct 1; repeat f_equiv; constructor || done.
+Qed.
+
+Lemma big_opM_ne_2 `{Monoid M o} `{Countable K} {A : ofeT} (f g : K → A → M) m1 m2 n :
+  m1 ≡{n}≡ m2 →
+  (∀ k y1 y2,
+    m1 !! k = Some y1 → m2 !! k = Some y2 → y1 ≡{n}≡ y2 → f k y1 ≡{n}≡ g k y2) →
+  ([^o map] k ↦ y ∈ m1, f k y) ≡{n}≡ ([^o map] k ↦ y ∈ m2, g k y).
+Proof.
+  intros Hl Hf. apply big_opM_gen_proper_2; try (apply _ || done).
+  { by intros ?? ->. }
+  { apply monoid_ne. }
+  intros k. assert (m1 !! k ≡{n}≡ m2 !! k) as Hlk by (by f_equiv).
+  destruct (m1 !! k) eqn:?, (m2 !! k) eqn:?; inversion Hlk; naive_solver.
+Qed.
+
+Lemma big_sepM2_ne_2 {PROP : bi} `{Countable K} (A B : ofeT)
+    (Φ Ψ : K → A → B → PROP) m1 m2 m1' m2' n :
+  m1 ≡{n}≡ m1' → m2 ≡{n}≡ m2' →
+  (∀ k y1 y1' y2 y2',
+    m1 !! k = Some y1 → m1' !! k = Some y1' → y1 ≡{n}≡ y1' →
+    m2 !! k = Some y2 → m2' !! k = Some y2' → y2 ≡{n}≡ y2' →
+    Φ k y1 y2 ≡{n}≡ Ψ k y1' y2') →
+  ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2)%I ≡{n}≡ ([∗ map] k ↦ y1;y2 ∈ m1';m2', Ψ k y1 y2)%I.
+Proof.
+  intros Hm1 Hm2 Hf. rewrite big_sepM2_eq /big_sepM2_def. f_equiv.
+  { f_equiv; split; intros Hm k.
+    - trans (is_Some (m1 !! k)); [symmetry; apply: is_Some_ne; by f_equiv|].
+      rewrite Hm. apply: is_Some_ne; by f_equiv.
+    - trans (is_Some (m1' !! k)); [apply: is_Some_ne; by f_equiv|].
+      rewrite Hm. symmetry. apply: is_Some_ne; by f_equiv. }
+  apply big_opM_ne_2; [by f_equiv|].
+  intros k [x1 y1] [x2 y2] (?&?&[=<- <-]&?&?)%map_lookup_zip_with_Some
+    (?&?&[=<- <-]&?&?)%map_lookup_zip_with_Some [??]; naive_solver.
+Qed.
+
 (* CMRA *)
 Section cmra.
 Context `{Countable K} {A : cmraT}.
diff --git a/theories/algebra/list.v b/theories/algebra/list.v
index 6325e1716d5040c61c7c9c4adca7fc6c32adea7b..669500516482021e9b5cff81e849443ebc3900b2 100644
--- a/theories/algebra/list.v
+++ b/theories/algebra/list.v
@@ -94,13 +94,64 @@ End cofe.
 
 Arguments listO : clear implicits.
 
+(** Non-expansiveness of higher-order list functions and big-ops *)
+Instance list_fmap_ne {A B : ofeT} (f : A → B) n :
+  Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (fmap (M:=list) f).
+Proof. intros Hf l k ?; by eapply Forall2_fmap, Forall2_impl; eauto. Qed.
+Instance list_omap_ne {A B : ofeT} (f : A → option B) n :
+  Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (omap (M:=list) f).
+Proof.
+  intros Hf. induction 1 as [|x1 x2 l1 l2 Hx Hl]; csimpl; [constructor|].
+  destruct (Hf _ _ Hx); [f_equiv|]; auto.
+Qed.
+Instance imap_ne {A B : ofeT} (f : nat → A → B) n :
+  (∀ i, Proper (dist n ==> dist n) (f i)) → Proper (dist n ==> dist n) (imap f).
+Proof.
+  intros Hf l1 l2 Hl. revert f Hf.
+  induction Hl; intros f Hf; simpl; [constructor|f_equiv; naive_solver].
+Qed.
+Instance list_bind_ne {A B : ofeT} (f : A → list A) n :
+  Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (mbind f).
+Proof. induction 2; simpl; [constructor|solve_proper]. Qed.
+Instance list_join_ne {A : ofeT} : NonExpansive (mjoin (M:=list) (A:=A)).
+Proof. induction 1; simpl; [constructor|solve_proper]. Qed.
+Instance zip_with_ne {A B C : ofeT} (f : A → B → C) :
+  Proper (dist n ==> dist n ==> dist n) f →
+  Proper (dist n ==> dist n ==> dist n) (zip_with f).
+Proof. induction 2; destruct 1; simpl; [constructor..|f_equiv; [f_equiv|]; auto]. Qed.
+
+Lemma big_opL_ne_2 `{Monoid M o} {A : ofeT} (f g : nat → A → M) l1 l2 n :
+  l1 ≡{n}≡ l2 →
+  (∀ k y1 y2,
+    l1 !! k = Some y1 → l2 !! k = Some y2 → y1 ≡{n}≡ y2 → f k y1 ≡{n}≡ g k y2) →
+  ([^o list] k ↦ y ∈ l1, f k y) ≡{n}≡ ([^o list] k ↦ y ∈ l2, g k y).
+Proof.
+  intros Hl Hf. apply big_opL_gen_proper_2; try (apply _ || done).
+  { apply monoid_ne. }
+  intros k. assert (l1 !! k ≡{n}≡ l2 !! k) as Hlk by (by f_equiv).
+  destruct (l1 !! k) eqn:?, (l2 !! k) eqn:?; inversion Hlk; naive_solver.
+Qed.
+
+Lemma big_sepL2_ne_2 {PROP : bi} {A B : ofeT}
+    (Φ Ψ : nat → A → B → PROP) l1 l2 l1' l2' n :
+  l1 ≡{n}≡ l1' → l2 ≡{n}≡ l2' →
+  (∀ k y1 y1' y2 y2',
+    l1 !! k = Some y1 → l1' !! k = Some y1' → y1 ≡{n}≡ y1' →
+    l2 !! k = Some y2 → l2' !! k = Some y2' → y2 ≡{n}≡ y2' →
+    Φ k y1 y2 ≡{n}≡ Ψ k y1' y2') →
+  ([∗ list] k ↦ y1;y2 ∈ l1;l2, Φ k y1 y2)%I ≡{n}≡ ([∗ list] k ↦ y1;y2 ∈ l1';l2', Ψ k y1 y2)%I.
+Proof.
+  intros Hl1 Hl2 Hf. rewrite !big_sepL2_alt. f_equiv.
+  { do 2 f_equiv; by apply: length_ne. }
+  apply big_opL_ne_2; [by f_equiv|].
+  intros k [x1 y1] [x2 y2] (?&?&[=<- <-]&?&?)%lookup_zip_with_Some
+    (?&?&[=<- <-]&?&?)%lookup_zip_with_Some [??]; naive_solver.
+Qed.
+
 (** Functor *)
 Lemma list_fmap_ext_ne {A} {B : ofeT} (f g : A → B) (l : list A) n :
   (∀ x, f x ≡{n}≡ g x) → f <$> l ≡{n}≡ g <$> l.
 Proof. intros Hf. by apply Forall2_fmap, Forall_Forall2, Forall_true. Qed.
-Instance list_fmap_ne {A B : ofeT} (f : A → B) n:
-  Proper (dist n ==> dist n) f → Proper (dist n ==> dist n) (fmap (M:=list) f).
-Proof. intros Hf l k ?; by eapply Forall2_fmap, Forall2_impl; eauto. Qed.
 Definition listO_map {A B} (f : A -n> B) : listO A -n> listO B :=
   OfeMor (fmap f : listO A → listO B).
 Instance listO_map_ne A B : NonExpansive (@listO_map A B).
diff --git a/theories/bi/big_op.v b/theories/bi/big_op.v
index 491596e320a6569b84e2462980ec712c5b9a915c..6f57d7fc50db7e479f63ad89efe94a99ccbd6606 100644
--- a/theories/bi/big_op.v
+++ b/theories/bi/big_op.v
@@ -91,24 +91,33 @@ Section sep_list.
     ⊣⊢ ([∗ list] k↦y ∈ l1, Φ k y) ∗ ([∗ list] k↦y ∈ l2, Φ (length l1 + k) y).
   Proof. by rewrite big_opL_app. Qed.
 
+  Lemma big_sepL_submseteq `{BiAffine PROP} (Φ : A → PROP) l1 l2 :
+    l1 ⊆+ l2 → ([∗ list] y ∈ l2, Φ y) ⊢ [∗ list] y ∈ l1, Φ y.
+  Proof.
+    intros [l ->]%submseteq_Permutation. by rewrite big_sepL_app sep_elim_l.
+  Qed.
+
+  (** The lemmas [big_sepL_mono], [big_sepL_ne] and [big_sepL_proper] are more
+  generic than the instances as they also give [l !! k = Some y] in the premise. *)
   Lemma big_sepL_mono Φ Ψ l :
     (∀ k y, l !! k = Some y → Φ k y ⊢ Ψ k y) →
     ([∗ list] k ↦ y ∈ l, Φ k y) ⊢ [∗ list] k ↦ y ∈ l, Ψ k y.
-  Proof. apply big_opL_forall; apply _. Qed.
+  Proof. apply big_opL_gen_proper; apply _. Qed.
+  Lemma big_sepL_ne Φ Ψ l n :
+    (∀ k y, l !! k = Some y → Φ k y ≡{n}≡ Ψ k y) →
+    ([∗ list] k ↦ y ∈ l, Φ k y)%I ≡{n}≡ ([∗ list] k ↦ y ∈ l, Ψ k y)%I.
+  Proof. apply big_opL_ne. Qed.
   Lemma big_sepL_proper Φ Ψ l :
     (∀ k y, l !! k = Some y → Φ k y ⊣⊢ Ψ k y) →
     ([∗ list] k ↦ y ∈ l, Φ k y) ⊣⊢ ([∗ list] k ↦ y ∈ l, Ψ k y).
   Proof. apply big_opL_proper. Qed.
-  Lemma big_sepL_submseteq `{BiAffine PROP} (Φ : A → PROP) l1 l2 :
-    l1 ⊆+ l2 → ([∗ list] y ∈ l2, Φ y) ⊢ [∗ list] y ∈ l1, Φ y.
-  Proof.
-    intros [l ->]%submseteq_Permutation. by rewrite big_sepL_app sep_elim_l.
-  Qed.
 
+  (** No need to declare instances for non-expansiveness and properness, we
+  get both from the generic [big_opL] instances. *)
   Global Instance big_sepL_mono' :
     Proper (pointwise_relation _ (pointwise_relation _ (⊢)) ==> (=) ==> (⊢))
            (big_opL (@bi_sep PROP) (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_sepL_mono; intros; apply Hf. Qed.
   Global Instance big_sepL_id_mono' :
     Proper (Forall2 (⊢) ==> (⊢)) (big_opL (@bi_sep PROP) (λ _ P, P)).
   Proof. by induction 1 as [|P Q Ps Qs HPQ ? IH]; rewrite /= ?HPQ ?IH. Qed.
@@ -349,6 +358,8 @@ Section sep_list2.
     - by rewrite -assoc IH.
   Qed.
 
+  (** The lemmas [big_sepL2_mono], [big_sepL2_ne] and [big_sepL2_proper] are more
+  generic than the instances as they also give [li !! k = Some yi] in the premise. *)
   Lemma big_sepL2_mono Φ Ψ l1 l2 :
     (∀ k y1 y2, l1 !! k = Some y1 → l2 !! k = Some y2 → Φ k y1 y2 ⊢ Ψ k y1 y2) →
     ([∗ list] k ↦ y1;y2 ∈ l1;l2, Φ k y1 y2) ⊢ [∗ list] k ↦ y1;y2 ∈ l1;l2, Ψ k y1 y2.
@@ -356,6 +367,13 @@ Section sep_list2.
     intros H. rewrite !big_sepL2_alt. f_equiv. apply big_sepL_mono=> k [y1 y2].
     rewrite lookup_zip_with=> ?; simplify_option_eq; auto.
   Qed.
+  Lemma big_sepL2_ne Φ Ψ l1 l2 n :
+    (∀ k y1 y2, l1 !! k = Some y1 → l2 !! k = Some y2 → Φ k y1 y2 ≡{n}≡ Ψ k y1 y2) →
+    ([∗ list] k ↦ y1;y2 ∈ l1;l2, Φ k y1 y2)%I ≡{n}≡ ([∗ list] k ↦ y1;y2 ∈ l1;l2, Ψ k y1 y2)%I.
+  Proof.
+    intros H. rewrite !big_sepL2_alt. f_equiv. apply big_sepL_ne=> k [y1 y2].
+    rewrite lookup_zip_with=> ?; simplify_option_eq; auto.
+  Qed.
   Lemma big_sepL2_proper Φ Ψ l1 l2 :
     (∀ k y1 y2, l1 !! k = Some y1 → l2 !! k = Some y2 → Φ k y1 y2 ⊣⊢ Ψ k y1 y2) →
     ([∗ list] k ↦ y1;y2 ∈ l1;l2, Φ k y1 y2) ⊣⊢ [∗ list] k ↦ y1;y2 ∈ l1;l2, Ψ k y1 y2.
@@ -363,15 +381,26 @@ Section sep_list2.
     intros; apply (anti_symm _);
       apply big_sepL2_mono; auto using equiv_entails, equiv_entails_sym.
   Qed.
+  Lemma big_sepL2_proper_2 `{!Equiv A, !Equiv B} Φ Ψ l1 l2 l1' l2' :
+    l1 ≡ l1' → l2 ≡ l2' →
+    (∀ k y1 y1' y2 y2',
+      l1 !! k = Some y1 → l1' !! k = Some y1' → y1 ≡ y1' →
+      l2 !! k = Some y2 → l2' !! k = Some y2' → y2 ≡ y2' →
+      Φ k y1 y2 ⊣⊢ Ψ k y1' y2') →
+    ([∗ list] k ↦ y1;y2 ∈ l1;l2, Φ k y1 y2) ⊣⊢ [∗ list] k ↦ y1;y2 ∈ l1';l2', Ψ k y1 y2.
+  Proof.
+    intros Hl1 Hl2 Hf. rewrite !big_sepL2_alt. f_equiv.
+    { do 2 f_equiv; by apply length_proper. }
+    apply big_opL_proper_2; [by f_equiv|].
+    intros k [x1 y1] [x2 y2] (?&?&[=<- <-]&?&?)%lookup_zip_with_Some
+      (?&?&[=<- <-]&?&?)%lookup_zip_with_Some [??]; naive_solver.
+  Qed.
 
-  Global Instance big_sepL2_ne n :
+  Global Instance big_sepL2_ne' n :
     Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (dist n)))
       ==> (=) ==> (=) ==> (dist n))
            (big_sepL2 (PROP:=PROP) (A:=A) (B:=B)).
-  Proof.
-    intros Φ1 Φ2 HΦ x1 ? <- x2 ? <-. rewrite !big_sepL2_alt. f_equiv.
-    f_equiv=> k [y1 y2]. apply HΦ.
-  Qed.
+  Proof. intros f g Hf l1 ? <- l2 ? <-. apply big_sepL2_ne; intros; apply Hf. Qed.
   Global Instance big_sepL2_mono' :
     Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (⊢)))
       ==> (=) ==> (=) ==> (⊢))
@@ -499,24 +528,33 @@ Section and_list.
     ⊣⊢ ([∧ list] k↦y ∈ l1, Φ k y) ∧ ([∧ list] k↦y ∈ l2, Φ (length l1 + k) y).
   Proof. by rewrite big_opL_app. Qed.
 
+  Lemma big_andL_submseteq (Φ : A → PROP) l1 l2 :
+    l1 ⊆+ l2 → ([∧ list] y ∈ l2, Φ y) ⊢ [∧ list] y ∈ l1, Φ y.
+  Proof.
+    intros [l ->]%submseteq_Permutation. by rewrite big_andL_app and_elim_l.
+  Qed.
+
+  (** The lemmas [big_andL_mono], [big_andL_ne] and [big_andL_proper] are more
+  generic than the instances as they also give [l !! k = Some y] in the premise. *)
   Lemma big_andL_mono Φ Ψ l :
     (∀ k y, l !! k = Some y → Φ k y ⊢ Ψ k y) →
     ([∧ list] k ↦ y ∈ l, Φ k y) ⊢ [∧ list] k ↦ y ∈ l, Ψ k y.
-  Proof. apply big_opL_forall; apply _. Qed.
+  Proof. apply big_opL_gen_proper; apply _. Qed.
+  Lemma big_andL_ne Φ Ψ l n :
+    (∀ k y, l !! k = Some y → Φ k y ≡{n}≡ Ψ k y) →
+    ([∧ list] k ↦ y ∈ l, Φ k y)%I ≡{n}≡ ([∧ list] k ↦ y ∈ l, Ψ k y)%I.
+  Proof. apply big_opL_ne. Qed.
   Lemma big_andL_proper Φ Ψ l :
     (∀ k y, l !! k = Some y → Φ k y ⊣⊢ Ψ k y) →
     ([∧ list] k ↦ y ∈ l, Φ k y) ⊣⊢ ([∧ list] k ↦ y ∈ l, Ψ k y).
   Proof. apply big_opL_proper. Qed.
-  Lemma big_andL_submseteq (Φ : A → PROP) l1 l2 :
-    l1 ⊆+ l2 → ([∧ list] y ∈ l2, Φ y) ⊢ [∧ list] y ∈ l1, Φ y.
-  Proof.
-    intros [l ->]%submseteq_Permutation. by rewrite big_andL_app and_elim_l.
-  Qed.
 
+  (** No need to declare instances for non-expansiveness and properness, we
+  get both from the generic [big_opL] instances. *)
   Global Instance big_andL_mono' :
     Proper (pointwise_relation _ (pointwise_relation _ (⊢)) ==> (=) ==> (⊢))
            (big_opL (@bi_and PROP) (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_andL_mono; intros; apply Hf. Qed.
   Global Instance big_andL_id_mono' :
     Proper (Forall2 (⊢) ==> (⊢)) (big_opL (@bi_and PROP) (λ _ P, P)).
   Proof. by induction 1 as [|P Q Ps Qs HPQ ? IH]; rewrite /= ?HPQ ?IH. Qed.
@@ -589,24 +627,33 @@ Section or_list.
     ⊣⊢ ([∨ list] k↦y ∈ l1, Φ k y) ∨ ([∨ list] k↦y ∈ l2, Φ (length l1 + k) y).
   Proof. by rewrite big_opL_app. Qed.
 
+  Lemma big_orL_submseteq (Φ : A → PROP) l1 l2 :
+    l1 ⊆+ l2 → ([∨ list] y ∈ l1, Φ y) ⊢ [∨ list] y ∈ l2, Φ y.
+  Proof.
+    intros [l ->]%submseteq_Permutation. by rewrite big_orL_app -or_intro_l.
+  Qed.
+
+  (** The lemmas [big_orL_mono], [big_orL_ne] and [big_orL_proper] are more
+  generic than the instances as they also give [l !! k = Some y] in the premise. *)
   Lemma big_orL_mono Φ Ψ l :
     (∀ k y, l !! k = Some y → Φ k y ⊢ Ψ k y) →
     ([∨ list] k ↦ y ∈ l, Φ k y) ⊢ [∨ list] k ↦ y ∈ l, Ψ k y.
-  Proof. apply big_opL_forall; apply _. Qed.
+  Proof. apply big_opL_gen_proper; apply _. Qed.
+  Lemma big_orL_ne Φ Ψ l n :
+    (∀ k y, l !! k = Some y → Φ k y ≡{n}≡ Ψ k y) →
+    ([∨ list] k ↦ y ∈ l, Φ k y)%I ≡{n}≡ ([∨ list] k ↦ y ∈ l, Ψ k y)%I.
+  Proof. apply big_opL_ne. Qed.
   Lemma big_orL_proper Φ Ψ l :
     (∀ k y, l !! k = Some y → Φ k y ⊣⊢ Ψ k y) →
     ([∨ list] k ↦ y ∈ l, Φ k y) ⊣⊢ ([∨ list] k ↦ y ∈ l, Ψ k y).
   Proof. apply big_opL_proper. Qed.
-  Lemma big_orL_submseteq (Φ : A → PROP) l1 l2 :
-    l1 ⊆+ l2 → ([∨ list] y ∈ l1, Φ y) ⊢ [∨ list] y ∈ l2, Φ y.
-  Proof.
-    intros [l ->]%submseteq_Permutation. by rewrite big_orL_app -or_intro_l.
-  Qed.
 
+  (** No need to declare instances for non-expansiveness and properness, we
+  get both from the generic [big_opL] instances. *)
   Global Instance big_orL_mono' :
     Proper (pointwise_relation _ (pointwise_relation _ (⊢)) ==> (=) ==> (⊢))
            (big_opL (@bi_or PROP) (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_opL_forall; apply _ || intros; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_orL_mono; intros; apply Hf. Qed.
   Global Instance big_orL_id_mono' :
     Proper (Forall2 (⊢) ==> (⊢)) (big_opL (@bi_or PROP) (λ _ P, P)).
   Proof. by induction 1 as [|P Q Ps Qs HPQ ? IH]; rewrite /= ?HPQ ?IH. Qed.
@@ -680,22 +727,31 @@ Section map.
   Implicit Types m : gmap K A.
   Implicit Types Φ Ψ : K → A → PROP.
 
+  Lemma big_sepM_subseteq `{BiAffine PROP} Φ m1 m2 :
+    m2 ⊆ m1 → ([∗ map] k ↦ x ∈ m1, Φ k x) ⊢ [∗ map] k ↦ x ∈ m2, Φ k x.
+  Proof. rewrite big_opM_eq. intros. by apply big_sepL_submseteq, map_to_list_submseteq. Qed.
+
+  (** The lemmas [big_sepM_mono], [big_sepM_ne] and [big_sepM_proper] are more
+  generic than the instances as they also give [l !! k = Some y] in the premise. *)
   Lemma big_sepM_mono Φ Ψ m :
     (∀ k x, m !! k = Some x → Φ k x ⊢ Ψ k x) →
     ([∗ map] k ↦ x ∈ m, Φ k x) ⊢ [∗ map] k ↦ x ∈ m, Ψ k x.
-  Proof. apply big_opM_forall; apply _ || auto. Qed.
+  Proof. apply big_opM_gen_proper; apply _ || auto. Qed.
+  Lemma big_sepM_ne Φ Ψ m n :
+    (∀ k x, m !! k = Some x → Φ k x ≡{n}≡ Ψ k x) →
+    ([∗ map] k ↦ x ∈ m, Φ k x)%I ≡{n}≡ ([∗ map] k ↦ x ∈ m, Ψ k x)%I.
+  Proof. apply big_opM_ne. Qed.
   Lemma big_sepM_proper Φ Ψ m :
     (∀ k x, m !! k = Some x → Φ k x ⊣⊢ Ψ k x) →
     ([∗ map] k ↦ x ∈ m, Φ k x) ⊣⊢ ([∗ map] k ↦ x ∈ m, Ψ k x).
   Proof. apply big_opM_proper. Qed.
-  Lemma big_sepM_subseteq `{BiAffine PROP} Φ m1 m2 :
-    m2 ⊆ m1 → ([∗ map] k ↦ x ∈ m1, Φ k x) ⊢ [∗ map] k ↦ x ∈ m2, Φ k x.
-  Proof. rewrite big_opM_eq. intros. by apply big_sepL_submseteq, map_to_list_submseteq. Qed.
 
+  (** No need to declare instances for non-expansiveness and properness, we
+  get both from the generic [big_opM] instances. *)
   Global Instance big_sepM_mono' :
     Proper (pointwise_relation _ (pointwise_relation _ (⊢)) ==> (=) ==> (⊢))
            (big_opM (@bi_sep PROP) (K:=K) (A:=A)).
-  Proof. intros f g Hf m ? <-. apply big_sepM_mono=> ???; apply Hf. Qed.
+  Proof. intros f g Hf m ? <-. apply big_sepM_mono; intros; apply Hf. Qed.
 
   Lemma big_sepM_empty Φ : ([∗ map] k↦x ∈ ∅, Φ k x) ⊣⊢ emp.
   Proof. by rewrite big_opM_empty. Qed.
@@ -876,6 +932,8 @@ Section map2.
     set_unfold=>k. by rewrite !elem_of_dom.
   Qed.
 
+  (** The lemmas [big_sepM2_mono], [big_sepM2_ne] and [big_sepM2_proper] are more
+  generic than the instances as they also give [mi !! k = Some yi] in the premise. *)
   Lemma big_sepM2_mono Φ Ψ m1 m2 :
     (∀ k y1 y2, m1 !! k = Some y1 → m2 !! k = Some y2 → Φ k y1 y2 ⊢ Ψ k y1 y2) →
     ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2) ⊢ [∗ map] k ↦ y1;y2 ∈ m1;m2, Ψ k y1 y2.
@@ -888,6 +946,17 @@ Section map2.
     destruct (m2 !! k) as [y2|]; simpl; last done.
     intros ?; simplify_eq. by apply Hm1m2.
   Qed.
+  Lemma big_sepM2_ne Φ Ψ m1 m2 n :
+    (∀ k y1 y2, m1 !! k = Some y1 → m2 !! k = Some y2 → Φ k y1 y2 ≡{n}≡ Ψ k y1 y2) →
+    ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2)%I ≡{n}≡ ([∗ map] k ↦ y1;y2 ∈ m1;m2, Ψ k y1 y2)%I.
+  Proof.
+    intros Hm1m2. rewrite big_sepM2_eq /big_sepM2_def.
+    f_equiv. apply big_sepM_ne=> k [x1 x2]. rewrite map_lookup_zip_with.
+    specialize (Hm1m2 k x1 x2).
+    destruct (m1 !! k) as [y1|]; last done.
+    destruct (m2 !! k) as [y2|]; simpl; last done.
+    intros ?; simplify_eq. by apply Hm1m2.
+  Qed.
   Lemma big_sepM2_proper Φ Ψ m1 m2 :
     (∀ k y1 y2, m1 !! k = Some y1 → m2 !! k = Some y2 → Φ k y1 y2 ⊣⊢ Ψ k y1 y2) →
     ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2) ⊣⊢ [∗ map] k ↦ y1;y2 ∈ m1;m2, Ψ k y1 y2.
@@ -895,15 +964,30 @@ Section map2.
     intros; apply (anti_symm _);
       apply big_sepM2_mono; auto using equiv_entails, equiv_entails_sym.
   Qed.
-
-  Global Instance big_sepM2_ne n :
+  Lemma big_sepM2_proper_2 `{!Equiv A, !Equiv B} Φ Ψ m1 m2 m1' m2' :
+    m1 ≡ m1' → m2 ≡ m2' →
+    (∀ k y1 y1' y2 y2',
+      m1 !! k = Some y1 → m1' !! k = Some y1' → y1 ≡ y1' →
+      m2 !! k = Some y2 → m2' !! k = Some y2' → y2 ≡ y2' →
+      Φ k y1 y2 ⊣⊢ Ψ k y1' y2') →
+    ([∗ map] k ↦ y1;y2 ∈ m1;m2, Φ k y1 y2) ⊣⊢ [∗ map] k ↦ y1;y2 ∈ m1';m2', Ψ k y1 y2.
+  Proof.
+    intros Hm1 Hm2 Hf. rewrite big_sepM2_eq /big_sepM2_def. f_equiv.
+    { f_equiv; split; intros Hm k.
+      - trans (is_Some (m1 !! k)); [symmetry; apply is_Some_proper; by f_equiv|].
+        rewrite Hm. apply is_Some_proper; by f_equiv.
+      - trans (is_Some (m1' !! k)); [apply is_Some_proper; by f_equiv|].
+        rewrite Hm. symmetry. apply is_Some_proper; by f_equiv. }
+    apply big_opM_proper_2; [by f_equiv|].
+    intros k [x1 y1] [x2 y2] (?&?&[=<- <-]&?&?)%map_lookup_zip_with_Some
+      (?&?&[=<- <-]&?&?)%map_lookup_zip_with_Some [??]; naive_solver.
+  Qed.
+
+  Global Instance big_sepM2_ne' n :
     Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (dist n)))
       ==> (=) ==> (=) ==> (dist n))
            (big_sepM2 (PROP:=PROP) (K:=K) (A:=A) (B:=B)).
-  Proof.
-    intros Φ1 Φ2 HΦ x1 ? <- x2 ? <-. rewrite big_sepM2_eq /big_sepM2_def.
-    f_equiv. f_equiv=> k [y1 y2]. apply HΦ.
-  Qed.
+  Proof. intros f g Hf m1 ? <- m2 ? <-. apply big_sepM2_ne; intros; apply Hf. Qed.
   Global Instance big_sepM2_mono' :
     Proper (pointwise_relation _ (pointwise_relation _ (pointwise_relation _ (⊢)))
       ==> (=) ==> (=) ==> (⊢)) (big_sepM2 (PROP:=PROP) (K:=K) (A:=A) (B:=B)).
@@ -1182,18 +1266,27 @@ Section gset.
   Implicit Types X : gset A.
   Implicit Types Φ : A → PROP.
 
+  Lemma big_sepS_subseteq `{BiAffine PROP} Φ X Y :
+    Y ⊆ X → ([∗ set] x ∈ X, Φ x) ⊢ [∗ set] x ∈ Y, Φ x.
+  Proof. rewrite big_opS_eq. intros. by apply big_sepL_submseteq, elements_submseteq. Qed.
+
+  (** The lemmas [big_sepS_mono], [big_sepS_ne] and [big_sepS_proper] are more
+  generic than the instances as they also give [x ∈ X] in the premise. *)
   Lemma big_sepS_mono Φ Ψ X :
     (∀ x, x ∈ X → Φ x ⊢ Ψ x) →
     ([∗ set] x ∈ X, Φ x) ⊢ [∗ set] x ∈ X, Ψ x.
-  Proof. intros. apply big_opS_forall; apply _ || auto. Qed.
+  Proof. intros. apply big_opS_gen_proper; apply _ || auto. Qed.
+  Lemma big_sepS_ne Φ Ψ X n :
+    (∀ x, x ∈ X → Φ x ≡{n}≡ Ψ x) →
+    ([∗ set] x ∈ X, Φ x)%I ≡{n}≡ ([∗ set] x ∈ X, Ψ x)%I.
+  Proof. apply big_opS_ne. Qed.
   Lemma big_sepS_proper Φ Ψ X :
     (∀ x, x ∈ X → Φ x ⊣⊢ Ψ x) →
     ([∗ set] x ∈ X, Φ x) ⊣⊢ ([∗ set] x ∈ X, Ψ x).
   Proof. apply big_opS_proper. Qed.
-  Lemma big_sepS_subseteq `{BiAffine PROP} Φ X Y :
-    Y ⊆ X → ([∗ set] x ∈ X, Φ x) ⊢ [∗ set] x ∈ Y, Φ x.
-  Proof. rewrite big_opS_eq. intros. by apply big_sepL_submseteq, elements_submseteq. Qed.
 
+  (** No need to declare instances for non-expansiveness and properness, we
+  get both from the generic [big_opS] instances. *)
   Global Instance big_sepS_mono' :
      Proper (pointwise_relation _ (⊢) ==> (=) ==> (⊢)) (big_opS (@bi_sep PROP) (A:=A)).
   Proof. intros f g Hf m ? <-. by apply big_sepS_mono. Qed.
@@ -1344,18 +1437,27 @@ Section gmultiset.
   Implicit Types X : gmultiset A.
   Implicit Types Φ : A → PROP.
 
+  Lemma big_sepMS_subseteq `{BiAffine PROP} Φ X Y :
+    Y ⊆ X → ([∗ mset] x ∈ X, Φ x) ⊢ [∗ mset] x ∈ Y, Φ x.
+  Proof. rewrite big_opMS_eq. intros. by apply big_sepL_submseteq, gmultiset_elements_submseteq. Qed.
+
+  (** The lemmas [big_sepMS_mono], [big_sepMS_ne] and [big_sepMS_proper] are more
+  generic than the instances as they also give [l !! k = Some y] in the premise. *)
   Lemma big_sepMS_mono Φ Ψ X :
     (∀ x, x ∈ X → Φ x ⊢ Ψ x) →
     ([∗ mset] x ∈ X, Φ x) ⊢ [∗ mset] x ∈ X, Ψ x.
-  Proof. intros. apply big_opMS_forall; apply _ || auto. Qed.
+  Proof. intros. apply big_opMS_gen_proper; apply _ || auto. Qed.
+  Lemma big_sepMS_ne Φ Ψ X n :
+    (∀ x, x ∈ X → Φ x ≡{n}≡ Ψ x) →
+    ([∗ mset] x ∈ X, Φ x)%I ≡{n}≡ ([∗ mset] x ∈ X, Ψ x)%I.
+  Proof. apply big_opMS_ne. Qed.
   Lemma big_sepMS_proper Φ Ψ X :
     (∀ x, x ∈ X → Φ x ⊣⊢ Ψ x) →
     ([∗ mset] x ∈ X, Φ x) ⊣⊢ ([∗ mset] x ∈ X, Ψ x).
   Proof. apply big_opMS_proper. Qed.
-  Lemma big_sepMS_subseteq `{BiAffine PROP} Φ X Y :
-    Y ⊆ X → ([∗ mset] x ∈ X, Φ x) ⊢ [∗ mset] x ∈ Y, Φ x.
-  Proof. rewrite big_opMS_eq. intros. by apply big_sepL_submseteq, gmultiset_elements_submseteq. Qed.
 
+  (** No need to declare instances for non-expansiveness and properness, we
+  get both from the generic [big_opMS] instances. *)
   Global Instance big_sepMS_mono' :
      Proper (pointwise_relation _ (⊢) ==> (=) ==> (⊢)) (big_opMS (@bi_sep PROP) (A:=A)).
   Proof. intros f g Hf m ? <-. by apply big_sepMS_mono. Qed.