Ltac intro_if_new :=
repeat match goal with
| |- ?A -> _ => ((assert A by auto; fail 1) || fail 1) || intros _
| |- (_ <-> _) -> _ =>
intro
| |- (?A /\ ?B) -> ?C =>
apply (@and_ind A B C)
| |- isptr (force_ptr ?P) -> ?Q =>
apply (isptr_force_ptr'' P Q)
| |- isptr (offset_val ?i ?P) -> ?Q =>
apply (isptr_offset_val'' i P Q)
| H: is_pointer_or_null ?P |- isptr ?P -> _ =>
clear H
| |- ?x = ?y -> _ =>
let H := fresh in intro H;
first [subst x | subst y
| is_var x; rewrite H
| is_var y; rewrite <- H
| solve [discriminate H]
| idtac]
| |- isptr ?x -> _ =>
let H := fresh "P" x in intro H
| |- is_pointer_or_null ?x =>
let H := fresh "PN" x in intro H
| |- typed_false _ (Val.of_bool _) -> _ =>
simple apply typed_false_of_bool'
| |- typed_true _ (Val.of_bool _) -> _ =>
simple apply typed_true_of_bool'
| |- ptr_eq _ _ -> _ =>
apply ptr_eq_e'
| |- _ -> _ =>
intro
end.

Lemma saturate_aux20:
forall (P Q: mpred) P' Q' ,
P |-- !! P' ->
Q |-- !! Q' ->
P * Q |-- !! (P' /\ Q').