diff --git a/src/plugins/wp/Cint.ml b/src/plugins/wp/Cint.ml index 7866b2d1414f6e61c4e9bfdb736e4146ba851655..866b9aa56bbde81fed16fd1205f11967c5c18991 100644 --- a/src/plugins/wp/Cint.ml +++ b/src/plugins/wp/Cint.ml @@ -590,6 +590,10 @@ let smp_shift zf = (* f(e1,0)~>e1, c2>0==>f(c1,c2)~>zf(c1,c2), c2>0==>f(0,c2)~>0 end | _ -> raise Not_found +(* -------------------------------------------------------------------------- *) +(* --- Comparision with L-AND / L-OR / L-NOT --- *) +(* -------------------------------------------------------------------------- *) + let smp_leq_with_land a b = let es = match_fun f_land a in let a1,_ = match_list_head match_positive_or_null_integer es in @@ -649,6 +653,10 @@ let smp_eq_with_lnot a b = (* b1==~e <==> ~b1==e *) let k1 = Integer.lognot b1 in e_eq (e_zint k1) e +(* -------------------------------------------------------------------------- *) +(* --- Comparision with LSL / LSR --- *) +(* -------------------------------------------------------------------------- *) + let two_power_k_minus1 k = try Integer.pred (Integer.two_power k) with Z.Overflow -> raise Not_found @@ -715,28 +723,25 @@ let smp_eq_with_lsl a b = let smp_leq_with_lsl a0 b0 = smp_cmp_with_lsl e_leq a0 b0 -let mk_cmp_with_lsr_cst cmp e x2 x1 = - (* build (e&~((2**x2)-1)) cmp (x1<<x2) *) - cmp - (e_zint (Integer.shift_left x1 x2)) - (e_fun f_land [e_zint (Integer.lognot (two_power_k_minus1 x2));e]) - -let smp_cmp_with_lsr cmp a0 b0 = +let smp_eq_with_lsr a0 b0 = try let b1 = match_integer b0 in let e,a2 = match_fun f_lsr a0 |> match_positive_or_null_integer_arg2 in - (* (e>>a2) cmp b1 <==> (e&~((2**a2)-1)) cmp (b1<<a2) + (* (e>>a2) == b1 <==> (e&~((2**a2)-1)) == (b1<<a2) That rule is similar to - e/A2 cmp b2 <==> (e/A2)*A2 cmp b2*A2) with A2==2**a2 + e/A2 == b2 <==> (e/A2)*A2 == b2*A2) with A2==2**a2 So, A2>0 and (e/A2)*A2 == e&~((2**a2)-1) *) - mk_cmp_with_lsr_cst cmp e a2 b1 + (* build (e&~((2**a2)-1)) == (b1<<a2) *) + e_eq + (e_zint (Integer.shift_left b1 a2)) + (e_fun f_land [e_zint (Integer.lognot (two_power_k_minus1 a2));e]) with Not_found -> (* This rule takes into acount several cases. One of them is - (a>>p) cmp (b>>(n+p)) <==> (a&~((2**p)-1)) cmp (b>>n)&~((2**p)-1) + (a>>p) == (b>>(n+p)) <==> (a&~((2**p)-1)) == (b>>n)&~((2**p)-1) That rule is similar to - (a/P)cmp(b/(N*P)) <==> (a/P)*P cmp ((b/N)/P)*P + (a/P) == (b/(N*P)) <==> (a/P)*P == ((b/N)/P)*P with P==2**p, N=2**n, q=p+n. So, (a/P)*P==a&~((2**p)-1), b/N==b>>n, ((b/N)/P)*P==(b>>n)&~((2**p)-1) *) let a,p = match_fun f_lsr a0 |> match_positive_or_null_integer_arg2 in @@ -745,10 +750,7 @@ let smp_cmp_with_lsr cmp a0 b0 = let a = if Integer.lt n p then e_fun f_lsr [a;e_zint (Z.sub p n)] else a in let b = if Integer.lt n q then e_fun f_lsr [b;e_zint (Z.sub q n)] else b in let m = F.e_zint (Integer.lognot (two_power_k_minus1 n)) in - cmp (e_fun f_land [a;m]) (e_fun f_land [b;m]) - -let smp_eq_with_lsr a0 b0 = - smp_cmp_with_lsr e_eq a0 b0 + e_eq (e_fun f_land [a;m]) (e_fun f_land [b;m]) let smp_leq_with_lsr a0 b0 = try @@ -758,17 +760,32 @@ let smp_leq_with_lsr a0 b0 = (* b2>= 0 ==> (0<=(e>>b2) <==> 0<=e) (note: invalid for `e_eq`) *) e_leq e_zero e else - let a1 = match_integer a0 in let e,b2 = match_positive_or_null_integer_arg2 bs in - (* a1 <= (e>>b2) <==> (e&~((2**b2)-1)) >= (a1<<b2) *) - mk_cmp_with_lsr_cst (fun a b -> e_leq b a) e b2 a1 + let k = Integer.two_power b2 in + let m = e_times k a0 in + if is_positive_or_null e then + (* e >= 0 ==> a0 <= (e / 2^b2) <==> (a0 * 2^b2) <= e *) + e_leq m e + else + let r = e_zint (Z.sub k Z.one) in + (* a1 <= (e / 2^b2) <==> a0 * 2^b2 - 2^b2 + 1) <= e *) + e_leq (e_sub m r) e with Not_found -> if b0 == e_zero then let e,_ = match_fun f_lsr a0 |> match_positive_or_null_arg2 in (* a2>= 0 ==> ((e>>a2)<=0 <==> e<=0) (note: invalid for `e_eq`) *) e_leq e e_zero else - smp_cmp_with_lsr e_leq a0 b0 + let e,a1 = match_fun f_lsr a0 |> match_positive_or_null_integer_arg2 in + let k = Integer.two_power a1 in + let m = e_times k b0 in + if is_negative e then + (* e <= 0 ==> (e / 2^a1) <= b0 <==> e <= (b0 * 2^a1) *) + e_leq e m + else + let r = e_zint (Z.sub k Z.one) in + (* (e / 2^b1) <= a1 <==> e <= (a1 * 2^b1 + 2^b1 - 1) *) + e_leq e (e_add m r) (* Rewritting at export *) let bitk_export k e = F.e_fun ~result:Logic.Bool f_bit_export [e;k]