Ltac repeat_extract_exists_pre :=
   first [(apply extract_exists_pre;
             let x := fresh "x" in intro x; normalize;
                repeat_extract_exists_pre;
                revert x)
           | autorewrite with canon
          ].Ltac extract_exists_in_SEP :=
 match goal with |- @semax _ _ _ (PROPx _ (LOCALx _ (SEPx ?R))) _ _ =>
   match R with context [ exp ?z :: _] =>
        let n := find_in_list (exp z) R
         in rewrite (grab_nth_SEP n); unfold nth, delete_nth; rewrite extract_exists_in_SEP;
             repeat_extract_exists_pre
  end
end.

(* Specifications: *)
Lemma flatten_sepcon_in_SEP: forall P Q R1 R2 R, PROPx P (LOCALx Q (SEPx ((R1*R2) :: R))) = PROPx P (LOCALx Q (SEPx (R1 :: R2 :: R))).
Lemma flatten_sepcon_in_SEP'': forall n P Q (R1 R2: mpred) (R: list mpred) R', nth_error R n = Some ((R1 * R2)) -> R' = firstn n R ++ R1 :: R2 :: skipn (S n) R -> PROPx P (LOCALx Q (SEPx R)) = PROPx P (LOCALx Q (SEPx R')).