[sledge] Revise solver existential instantiation

Summary:
In case the starting locations of two heap segments are
related (provably equal up to some offset), add equations between
their enclosing block to the goal. In these cases, the enclosing
blocks must be the same, so no completeness is lost. This has the
effect of instantiating existentials in the enclosing block prior to
others, which can avoid incomplete instantiation guesses.

Reviewed By: mbouaziz

Differential Revision: D14323550

fbshipit-source-id: 89a34a2c8
master
Josh Berdine 6 years ago committed by Facebook Github Bot
parent 29f7f30b1a
commit 0578064a7f

@ -486,74 +486,82 @@ let excise_seg_sub_skew ({us; com; min; xs; sub; zs} as goal) msg ssg k_l
(* C k-[b;m)->⟨o,α⟩ * M ⊢ ∃xs. l-[b';m')->⟨n,α'⟩ * S R *)
let excise_seg ({sub} as goal) msg ssg =
[%Trace.info "@[<2>excise_seg@ %a@ |- %a@]" Sh.pp_seg msg Sh.pp_seg ssg] ;
let {Sh.loc= k; siz= o} = msg in
let {Sh.loc= l; siz= n} = ssg in
let {Sh.loc= k; bas= b; len= m; siz= o} = msg in
let {Sh.loc= l; bas= b'; len= m'; siz= n} = ssg in
Equality.difference sub.cong k l
>>= fun k_l ->
match[@warning "-p"] Z.sign k_l with
(* k-l < 0 so k < l *)
| -1 -> (
let ko = Exp.add Typ.ptr k o in
let ln = Exp.add Typ.ptr l n in
Equality.difference sub.cong ko ln
>>= fun ko_ln ->
match[@warning "-p"] Z.sign ko_ln with
(* k+o-(l+n) < 0 so k+o < l+n *)
| -1 -> (
Equality.difference sub.cong l ko
>>= fun l_ko ->
match[@warning "-p"] Z.sign l_ko with
(* l-(k+o) < 0 [k; o)
* so l < k+o [l; n) *)
| -1 ->
Some
(excise_seg_min_skew goal msg ssg (Z.neg k_l) (Z.neg l_ko)
(Z.neg ko_ln))
| _ -> None )
(* k+o-(l+n) = 0 [k; o)
* so k+o = l+n [l; n) *)
| 0 -> Some (excise_seg_sub_suffix goal msg ssg (Z.neg k_l))
(* k+o-(l+n) > 0 [k; o)
* so k+o > l+n [l; n) *)
| 1 -> Some (excise_seg_sub_infix goal msg ssg (Z.neg k_l) ko_ln) )
(* k-l = 0 so k = l *)
| 0 -> (
match Equality.difference sub.cong o n with
| None -> Some {goal with sub= Sh.and_ (Exp.eq o n) goal.sub}
| Some o_n -> (
match[@warning "-p"] Z.sign o_n with
(* o-n < 0 [k; o)
* so o < n [l; n) *)
| -1 -> Some (excise_seg_min_prefix goal msg ssg (Z.neg o_n))
(* o-n = 0 [k; o)
* so o = n [l; n) *)
| 0 -> Some (excise_seg_same goal msg ssg)
(* o-n > 0 [k; o)
* so o > n [l; n) *)
| 1 -> Some (excise_seg_sub_prefix goal msg ssg o_n) ) )
(* k-l > 0 so k > l *)
| 1 -> (
let ko = Exp.add Typ.ptr k o in
let ln = Exp.add Typ.ptr l n in
Equality.difference sub.cong ko ln
>>= fun ko_ln ->
match[@warning "-p"] Z.sign ko_ln with
(* k+o-(l+n) < 0 [k; o)
* so k+o < l+n [l; n) *)
| -1 -> Some (excise_seg_min_infix goal msg ssg k_l (Z.neg ko_ln))
(* k+o-(l+n) = 0 [k; o)
* so k+o = l+n [l; n) *)
| 0 -> Some (excise_seg_min_suffix goal msg ssg k_l)
(* k+o-(l+n) > 0 so k+o > l+n *)
| 1 -> (
Equality.difference sub.cong k ln
>>= fun k_ln ->
match[@warning "-p"] Z.sign k_ln with
(* k-(l+n) < 0 [k; o)
* so k < l+n [l; n) *)
| -1 ->
Some (excise_seg_sub_skew goal msg ssg k_l (Z.neg k_ln) ko_ln)
| _ -> None ) )
if
(not (Equality.entails_eq sub.cong b b'))
|| not (Equality.entails_eq sub.cong m m')
then
Some
{goal with sub= Sh.and_ (Exp.eq b b') (Sh.and_ (Exp.eq m m') goal.sub)}
else
match[@warning "-p"] Z.sign k_l with
(* k-l < 0 so k < l *)
| -1 -> (
let ko = Exp.add Typ.ptr k o in
let ln = Exp.add Typ.ptr l n in
Equality.difference sub.cong ko ln
>>= fun ko_ln ->
match[@warning "-p"] Z.sign ko_ln with
(* k+o-(l+n) < 0 so k+o < l+n *)
| -1 -> (
Equality.difference sub.cong l ko
>>= fun l_ko ->
match[@warning "-p"] Z.sign l_ko with
(* l-(k+o) < 0 [k; o)
* so l < k+o [l; n) *)
| -1 ->
Some
(excise_seg_min_skew goal msg ssg (Z.neg k_l) (Z.neg l_ko)
(Z.neg ko_ln))
| _ -> None )
(* k+o-(l+n) = 0 [k; o)
* so k+o = l+n [l; n) *)
| 0 -> Some (excise_seg_sub_suffix goal msg ssg (Z.neg k_l))
(* k+o-(l+n) > 0 [k; o)
* so k+o > l+n [l; n) *)
| 1 -> Some (excise_seg_sub_infix goal msg ssg (Z.neg k_l) ko_ln) )
(* k-l = 0 so k = l *)
| 0 -> (
match Equality.difference sub.cong o n with
| None -> Some {goal with sub= Sh.and_ (Exp.eq o n) goal.sub}
| Some o_n -> (
match[@warning "-p"] Z.sign o_n with
(* o-n < 0 [k; o)
* so o < n [l; n) *)
| -1 -> Some (excise_seg_min_prefix goal msg ssg (Z.neg o_n))
(* o-n = 0 [k; o)
* so o = n [l; n) *)
| 0 -> Some (excise_seg_same goal msg ssg)
(* o-n > 0 [k; o)
* so o > n [l; n) *)
| 1 -> Some (excise_seg_sub_prefix goal msg ssg o_n) ) )
(* k-l > 0 so k > l *)
| 1 -> (
let ko = Exp.add Typ.ptr k o in
let ln = Exp.add Typ.ptr l n in
Equality.difference sub.cong ko ln
>>= fun ko_ln ->
match[@warning "-p"] Z.sign ko_ln with
(* k+o-(l+n) < 0 [k; o)
* so k+o < l+n [l; n) *)
| -1 -> Some (excise_seg_min_infix goal msg ssg k_l (Z.neg ko_ln))
(* k+o-(l+n) = 0 [k; o)
* so k+o = l+n [l; n) *)
| 0 -> Some (excise_seg_min_suffix goal msg ssg k_l)
(* k+o-(l+n) > 0 so k+o > l+n *)
| 1 -> (
Equality.difference sub.cong k ln
>>= fun k_ln ->
match[@warning "-p"] Z.sign k_ln with
(* k-(l+n) < 0 [k; o)
* so k < l+n [l; n) *)
| -1 ->
Some
(excise_seg_sub_skew goal msg ssg k_l (Z.neg k_ln) ko_ln)
| _ -> None ) )
let excise_heap ({min; sub} as goal) =
[%Trace.info "@[<2>excise_heap@ %a@]" pp goal] ;

@ -130,4 +130,26 @@ let%test_module _ =
%a_2 = %a1_8
16 = %m_7
emp |}]
let%expect_test _ =
check_frame
(Sh.star
(Sh.seg {loc= l; bas= l; len= !16; siz= !8; arr= a})
(Sh.seg {loc= l + !8; bas= l; len= !16; siz= !8; arr= a2}))
[a3_; m_]
(Sh.seg {loc= l; bas= l; len= m; siz= m; arr= a3}) ;
[%expect
{|
( infer_frame:
(%l_5 + 8) -[ %l_5, 16 )-> 8,%a_2
* %l_5 -[ %l_5, 16 )-> 8,%a_1
\- %a_3, %m_7 .
%l_5 -[)-> %m_7,%a_3
) infer_frame:
.
%a1_8 .
%m_7,%a_3 = 8,%a_1^8,%a1_8
%a_2 = %a1_8
16 = %m_7
emp |}]
end )

Loading…
Cancel
Save