diff --git a/src/kernel_services/abstract_interp/ival.ml b/src/kernel_services/abstract_interp/ival.ml
index dbce56a8b6d129c48d49a071ee2c803af3179859..c6aed4e7b02d279a199745b85bc87a71f96c9905 100644
--- a/src/kernel_services/abstract_interp/ival.ml
+++ b/src/kernel_services/abstract_interp/ival.ml
@@ -268,8 +268,6 @@ let float_zeros = Float Fval.zeros
 let positive_integers = Top(Some Int.zero, None, Int.zero, Int.one)
 let negative_integers =
   Top(None, Some Int.zero, Int.zero, Int.one)
-let strictly_negative_integers =
-  Top(None, Some Int.minus_one, Int.zero, Int.one)
 
 let is_zero x = x == zero
 
@@ -793,6 +791,31 @@ let array_truncate r i =
       Set r
     end
 
+let array_filter (f : Int.t -> bool) (a : Int.t array) : t =
+  let l = Array.length a in
+  let r = Array.make l Int.zero in
+  let j = ref 0 in
+  for i = 0 to Array.length a  - 1 do
+    let x = a.(i) in
+    if f x then begin
+      r.(!j) <- x;
+      incr j;
+    end
+  done;
+  array_truncate r !j
+
+exception Empty
+
+let array_map_reduce (f : 'a -> 'b) (g : 'b -> 'b -> 'b) (set : 'a array) : 'b =
+  if Array.length set <= 0 then
+    raise Empty
+  else
+    let acc = ref (f set.(0)) in
+    for i = 1 to Array.length set - 1 do
+      acc := g !acc (f set.(i))
+    done;
+    !acc
+
 let array_inter a1 a2 =
   let l1 = Array.length a1 in
   let l2 = Array.length a2 in
@@ -1259,13 +1282,6 @@ let apply2_n f (s1 : Integer.t array) (s2 : Integer.t array) =
   done;
   inject_ps !ps
 
-let apply2_v f s1 s2 =
-  match s1, s2 with
-    [| x1 |], [| x2 |] -> 
-      inject_singleton (f x1 x2)
-  | _ -> apply2_n f s1 s2
-
-
 let apply_set f v1 v2 =
   match v1,v2 with
   | Set s1, Set s2 -> apply2_n f s1 s2
@@ -1516,156 +1532,6 @@ let max_int s =
   | Float _ -> None
 
 
-exception No_such_element
-
-let smallest_above min x = (* TODO: improve for Set *)
-  match x with
-  | Set s ->
-      let r = ref None in
-      Array.iter
-        (fun e ->
-          if Int.ge e min
-          then match !r with
-          | Some rr when Int.lt e rr -> r := Some e
-          | None -> r := Some e
-          | _ -> ())
-        s;
-      begin match !r with
-        None -> raise No_such_element
-      | Some r -> r
-      end
-  | Top(mn,mx,r,modu) ->
-      let some_min = Some min in
-      if not (max_is_greater mx some_min)
-      then raise No_such_element;
-      if min_is_lower some_min mn
-      then Extlib.the mn
-      else Int.round_up_to_r ~min ~r ~modu
-  | Float _ -> raise No_such_element
-
-let largest_below max x = (* TODO: improve for Set *)
-  match x with
-  | Float _ -> raise No_such_element
-  | Set s ->
-      let r = ref None in
-      Array.iter
-        (fun e ->
-          if Int.le e max
-          then match !r with
-          | Some rr when Int.gt e rr -> r := Some e
-          | None -> r := Some e
-          | _ -> ())
-        s;
-      begin match !r with
-        None -> raise No_such_element
-      | Some r -> r
-      end
-  | Top(mn,mx,r,modu) ->
-      let some_max = Some max in
-      if not (min_is_lower mn some_max)
-      then raise No_such_element;
-      if max_is_greater some_max mx
-      then Extlib.the mx
-      else Int.round_down_to_r ~max ~r ~modu
-
-(* Rounds up (x+1) to the next power of two, then subtracts one; optimized. *)
-let next_pred_power_of_two x =
-  (* Unroll the first iterations, and skip the tests. *)
-  let x = Int.logor x (Int.shift_right x Int.one) in
-  let x = Int.logor x (Int.shift_right x Int.two) in
-  let x = Int.logor x (Int.shift_right x Int.four) in
-  let x = Int.logor x (Int.shift_right x Int.eight) in
-  let x = Int.logor x (Int.shift_right x Int.sixteen) in
-  let shift = Int.thirtytwo in
-  let rec loop old shift =
-    let x = Int.logor old (Int.shift_right old shift) in
-    if Int.equal old x then x
-    else loop x (Int.shift_left shift Int.one) in
-  loop x shift
-
-(* [different_bits min max] returns an overapproximation of the mask
-   of the bits that can be different for different numbers
-   in the interval [min]..[max] *)
-let different_bits min max =
-  let x = Int.logxor min max in
-  next_pred_power_of_two x
-
-(* [pos_max_land min1 max1 min2 max2] computes an upper bound for
-   [x1 land x2] where [x1] is in [min1]..[max1] and [x2] is in [min2]..[max2].
-   Precondition : [min1], [max1], [min2], [max2] must all have the
-   same sign.
-   Note: the algorithm below is optimal for the problem as stated.
-   It is possible to compute this optimal solution faster but it does not
-   seem worth the time necessary to think about it as long as integers
-   are at most 64-bit. *)
-let pos_max_land min1 max1 min2 max2 =
-  let x1 = different_bits min1 max1 in
-  let x2 = different_bits min2 max2 in
-(*      Format.printf "pos_max_land %a %a -> %a |  %a %a -> %a@."
-        Int.pretty min1 Int.pretty max1 Int.pretty x1
-        Int.pretty min2 Int.pretty max2 Int.pretty x2; *)
-  let fold_maxs max1 p f acc =
-    let rec aux p acc =
-      let p = Int.shift_right p Int.one in
-      if Int.is_zero p
-      then f max1 acc
-      else if Int.is_zero (Int.logand p max1) 
-      then aux p acc
-      else 
-	let c = Int.logor (Int.sub max1 p) (Int.pred p) in
-	aux p (f c acc)
-    in aux p acc
-  in
-  let sx1 = Int.succ x1 in
-  let n1 = fold_maxs max1 sx1 (fun _ y -> succ y) 0 in
-  let maxs1 = Array.make n1 sx1 in
-  let _ = fold_maxs max1 sx1 (fun x i -> Array.set maxs1 i x; succ i) 0 in
-  fold_maxs max2 (Int.succ x2)
-    (fun max2 acc -> 
-      Array.fold_left
-	(fun acc max1 -> Int.max (Int.logand max1 max2) acc)
-	acc
-	maxs1)
-    (Int.logand max1 max2)
-
-let bitwise_or v1 v2 =
-  if is_bottom v1 || is_bottom v2
-  then bottom
-  else
-    match v1, v2 with
-      | Float _, _ | _, Float _ -> top
-      | Set s1, Set s2 -> apply2_v Int.logor s1 s2
-      | Set [|s|],(Top _ as v) | (Top _ as v),Set [|s|] when Int.is_zero s -> v
-      | Top _, _ | _, Top _ ->
-        ( match min_and_max v1 with
-           Some mn1, Some mx1 when Int.ge mn1 Int.zero ->
-             ( match min_and_max v2 with
-               Some mn2, Some mx2 when Int.ge mn2 Int.zero ->
-                 let new_max = next_pred_power_of_two (Int.logor mx1 mx2) in
-		 let new_min = Int.max mn1 mn2 in (* Or can only add bits *)
-                 inject_range (Some new_min) (Some new_max)
-             | _ -> top )
-         | _ -> top )
-
-
-let bitwise_xor v1 v2 =
-  if is_bottom v1 || is_bottom v2
-  then bottom
-  else
-    match v1, v2 with
-     | Float _, _ | _, Float _ -> top
-     | Set s1, Set s2 -> apply2_v Int.logxor s1 s2
-     | Top _, _ | _, Top _ ->
-       (match min_and_max v1 with
-         | Some mn1, Some mx1 when Int.ge mn1 Int.zero ->
-           (match min_and_max v2 with
-             | Some mn2, Some mx2 when Int.ge mn2 Int.zero ->
-               let new_max = next_pred_power_of_two (Int.logor mx1 mx2) in
-	       let new_min = Int.zero in
-               inject_range (Some new_min) (Some new_max)
-             | _ -> top )
-         | _ -> top )
-
 (* TODO: rename this function to scale_int *)
 let scale f v =
   if Int.is_zero f
@@ -2658,218 +2524,498 @@ let reinterpret_as_float kind i =
       (* currently always imprecise *)
       top_float
 
-let set_bits mn mx =
-  match mn, mx with
-    Some mn, Some mx ->
-      Int.logand (Int.lognot (different_bits mn mx)) mn
-  | _ -> Int.zero
-
-let sub_bits x = (* TODO: can be improved *)
-  let popcnt = Int.popcount x in
-  let rec aux cursor acc =
-    if Int.gt cursor x 
-    then acc
-    else 
-      let acc = 
-	if Int.is_zero (Int.logand cursor x)
-	then acc
-	else O.fold (fun e acc -> O.add (Int.logor cursor e) acc) acc acc
-      in
-      aux (Int.shift_left cursor Int.one) acc
+let overlaps ~partial ~size t1 t2 =
+  let diff = sub_int t1 t2 in
+  match diff with
+  | Set array ->
+    not (array_for_all
+           (fun i -> Int.ge (Int.abs i) size || (partial && Int.is_zero i))
+           array)
+  | Top (min, max, _r, _modu) ->
+    let pred_size = Int.pred size in
+    min_le_elt min pred_size && max_ge_elt max (Int.neg pred_size)
+  | Float _ -> assert false
+
+
+
+(* ------------------------------------------------------------------------ *)
+(* --- Bitwise operators                                                --- *)
+(* ------------------------------------------------------------------------ *)
+
+(* --- Bit lattice --- *)
+
+type bit_value = On | Off | Both
+
+module Bit =
+struct
+  type t = bit_value
+
+  let to_string = function
+    | Off -> "0"
+    | On -> "1"
+    | Both -> "T"
+
+  let _pretty (fmt : Format.formatter) (b :t) =
+    Format.pp_print_string fmt (to_string b)
+
+  let union (b1 : t) (b2 : t) : t =
+    if b1 = b2 then b1 else Both
+
+  let not : t -> t = function
+    | On -> Off
+    | Off -> On
+    | Both -> Both
+end
+
+
+(* --- Bit operators --- *)
+
+exception NoBackward
+
+module type BitOperator =
+sig
+  (** Printable version of the operator *)
+  val representation : string
+  (* forward is given here as the lifted function of some bit operator op
+     where op
+     1. is assumed to be commutative (backward functions do not assume the
+        position of the arguments)
+     2. must ensure  0 op 0 = 0  as otherwise applying op on a sign bit may
+        produce a negative result from two positive operands; but we don't
+        want to produce a negative result when the operation is unsigned which
+        we don't know unless one of the operands is negative;
+     3. is not constant, otherwise nothing of all of this makes sense.
+     forward is defined as
+     forward b1 b2 = { x1 op x2 | x1 \in b1, x2 \in b2 }
+  *)
+  val forward : bit_value -> bit_value -> bit_value
+  (** backward_off b = { x | \exist y \in b . x op y = y op x = 1 } *)
+  val backward_off : bit_value -> bit_value
+  (** backward_on b = { x | \exist y \in b . x op y = y op x = 0 } *)
+  val backward_on : bit_value -> bit_value
+end
+
+module And : BitOperator =
+struct
+  let representation = "&"
+
+  let forward v1 v2 =
+    match v1 with
+    | Off -> Off
+    | On -> v2
+    | Both -> if v2 = Off then Off else Both
+
+  let backward_off = function
+    | (Off | Both) -> Both
+    | On -> Off
+
+  let backward_on = function
+    | Off -> raise NoBackward
+    | (On | Both) -> On
+end
+
+module Or : BitOperator =
+struct
+  let representation = "|"
+
+  let forward v1 v2 =
+    match v1 with
+    | On -> On
+    | Off -> v2
+    | Both -> if v2 = On then On else Both
+
+  let backward_off = function
+    | On -> raise NoBackward
+    | (Off | Both) -> Off
+
+  let backward_on = function
+    | (On | Both) -> Both
+    | Off -> On
+end
+
+module Xor : BitOperator =
+struct
+  let representation = "^"
+
+  let forward v1 v2 =
+    match v1 with
+    | Both -> Both
+    | Off -> v2
+    | On -> Bit.not v2
+
+  let backward_on v = Bit.not v
+
+  let backward_off v = v
+end
+
+
+(* --- Bit extraction and mutation --- *)
+
+module Int =
+struct
+  include Integer
+
+  let significant_bits (i : t) : int =
+    (* shift right until nothing changes *)
+    let rec count i acc =
+      let new_i = shift_right i one in
+      if equal i new_i
+      then acc
+      else count new_i (acc + 1)
+    in
+    count i 0
+
+  let biggest_power_of_two_divider (i : t) : int =
+    let rec aux p acc =
+      if equal (logand i p) zero
+      then aux (shift_left p one) (acc + 1)
+      else acc
+    in
+    aux Int.one 0
+end
+
+let significant_bits (v : t) : int option =
+  match min_and_max v with
+  | None, _ | _, None -> None
+  | Some l, Some u ->
+    Some (max (Int.significant_bits l) (Int.significant_bits u))
+
+let extract_sign (v : t) : bit_value =
+  match min_and_max v with
+  | _, Some u when Int.(lt u zero) -> On
+  | Some l, _ when Int.(ge l zero) -> Off
+  | _, _ -> Both
+
+let extract_bit (v : t) (i : int) : bit_value =
+  let power = Int.(two_power_of_int i) in
+  let bit_value x =
+    if Int.(is_zero (logand power x)) then Off else On
   in
-  let o = aux Int.one o_zero in
-  let s = 1 lsl popcnt in
-  (* assert (O.cardinal o = s); *)
-  inject_ps (Pre_set (o, s))
-
-let bitwise_and_intervals ~size ~signed v1 v2 =
-  let max_int_v1, max_int_v2 as max_int_v1_v2 = max_int v1, max_int v2 in
-  let min_int_v1, min_int_v2 as min_int_v1_v2 = min_int v1, min_int v2 in
-  let half_range = Int.two_power_of_int (pred size) in
-  let minint = Int.neg half_range in
-  let vmax =
-    match max_int_v1_v2 with
-    | Some maxv1, Some maxv2 ->
-      if Int.lt maxv1 Int.zero && Int.lt maxv2 Int.zero
-      then begin
-        Some (match min_int_v1_v2 with
-          Some minv1, Some minv2 ->
-            pos_max_land minv1 maxv1 minv2 maxv2
-        | _ -> assert false)
-      end
-      else
-        let max1 = (* improved min of maxv1 and maxv2*)
-          try
-            let bi1 = smallest_above Int.zero v1 in
-            let bi2 = smallest_above Int.zero v2 in
-            pos_max_land bi1 maxv1 bi2 maxv2
-          with No_such_element -> minint
-        in
-        let max2 = (* improved min of maxv1 and altmax2*)
-          try
-            let altmax2 =
-              Int.add half_range (largest_below Int.minus_one v2)
-            in
-            let bi1 = smallest_above Int.zero v1 in
-            let bi2 =
-              Int.add half_range (smallest_above minint v2)
-            in
-            pos_max_land bi1 maxv1 bi2 altmax2
-          with No_such_element -> minint
-        in
-        let max3 = (* improved min of maxv2 and altmax1*)
-          try
-            let altmax1 =
-              Int.add half_range (largest_below Int.minus_one v1)
-            in
-            let bi2 = smallest_above Int.zero v2 in
-            let bi1 =
-              Int.add half_range (smallest_above minint v1)
-            in
-            pos_max_land bi2 maxv2 bi1 altmax1
-          with No_such_element -> minint
-        in
-          (* Format.printf "bitwise_and v1 %a v2 %a maxv1 %a maxv2 %a \
-             max1 max2 max3 %a %a %a@."
-             pretty v1 pretty v2
-             Int.pretty maxv1 Int.pretty maxv2
-             Int.pretty max1 Int.pretty max2 Int.pretty max3; *)
-        Some (Int.max max1 (Int.max max2 max3))
-    | _ -> None
+  match v with
+  | Float _ -> Both
+  | Set s ->
+    array_map_reduce bit_value Bit.union s
+  | Top (None, _, _r, _m) | Top (_, None, _r, _m) -> Both
+  | Top (Some l, Some u, _r, _m) ->
+    (* It does not take modulo into account *)
+    if Int.(ge (sub u power)) l (* u - l >= mask *)
+    then Both
+    else Bit.union (bit_value l) (bit_value u)
+
+let reduce_sign (v : t) (b : bit_value) : t =
+  match b with
+  | Both -> v
+  | On ->
+    begin match v with
+      | Float _ -> v
+      | Set s -> array_filter Int.(gt zero) s
+      | Top (_l, Some u, _r, _modu) when Int.(lt u zero) -> v
+      | Top (l, _u, r, modu) ->
+        let u = Some Int.(round_down_to_r ~max:minus_one ~r ~modu) in
+        inject_top l u r modu
+    end
+  | Off ->
+    begin match v with
+      | Float _ -> v
+      | Set s -> array_filter Int.(le zero) s
+      | Top (Some l, _u, _r, _modu) when Int.(ge l zero) -> v
+      | Top (_l, u, r, modu) ->
+        let l = Some Int.(round_up_to_r ~min:zero ~r ~modu) in
+        inject_top l u r modu
+    end
+
+let reduce_bit (v : t) (i : int) (b : bit_value) : t =
+  let power = Int.(two_power_of_int i) in (* 001000 *)
+  let mask = Int.(pred (two_power_of_int (i+1))) in (* 001111 *)
+  let bit_value (x : Int.t) =
+    if Int.(is_zero (logand power x)) then Off else On
   in
-  let somenegativev1 = intersects v1 strictly_negative_integers in
-  let somenegativev2 = intersects v2 strictly_negative_integers in
-  let vmin =
-    if somenegativev1 && somenegativev2
-    then Some minint
-    else if somenegativev1 || somenegativev2
-    then some_zero
-    else begin
-      let bits1 = set_bits min_int_v1 max_int_v1 in
-      let bits2 = set_bits min_int_v2 max_int_v2 in
-      let min_a = Int.logand bits1 bits2 in
-      let min_a =
-        if not signed
-        then
-          let rec find_mask x bit acc =
-            if Int.is_zero (Int.logand x bit)
-            then acc
-            else
-              find_mask
-                x
-                (Int.shift_right bit Int.one)
-                (Int.logor bit acc)
+  if b = Both
+  then v
+  else match v with
+    | Float _ -> v
+    | Set s ->
+      array_filter (fun x -> bit_value x = b) s
+    | Top (l, u, r, modu) ->
+      (* Reduce bounds to the nearest satisfying bound *)
+      let l' = match l with
+        | Some l when bit_value l <> b ->
+          let min = match b with
+            | On ->  Int.(logor (logand l (lognot mask)) power) (* ll1000 *)
+            | Off -> Int.(succ (logor l mask)) (* ll0000 *)
+            | Both -> assert false
           in
-          match min_int_v1_v2 with
-            Some m1, Some m2 ->
-              let mask1 = find_mask bits1 half_range Int.zero in
-              let min_b = Int.logand mask1 m2 in
-              let mask2 = find_mask bits2 half_range Int.zero in
-              let min_c = Int.logand mask2 m1 in
-                      (* Format.printf
-                         "bitwise_and v1 %a v2 %a min_b %a min_c %a@."
-                         pretty v1 pretty v2
-                         Int.pretty min_b Int.pretty min_c; *)
-              Int.max (Int.max min_a min_b) min_c
-          | _ -> assert false
-        else min_a
+          Some (Int.round_up_to_r ~min ~r ~modu)
+        | _ -> l
+      and u' = match u with
+        | Some u when bit_value u <> b ->
+          let max = match b with
+            | On ->  Int.(pred (logand u (lognot mask))) (* ll1111 *)
+            | Off -> Int.(logand (logor u mask) (lognot power)) (* ll0111 *)
+            | Both -> assert false
+          in
+          Some (Int.round_down_to_r ~max ~r ~modu)
+        | _ -> u
       in
-              (* Format.printf "bitwise_and v1 %a v2 %a bits1 %a bits2 %a@."
-                 pretty v1 pretty v2
-                 Int.pretty bits1 Int.pretty bits2; *)
-      Some min_a
-    end
-  in
-  vmin, vmax
-
-(* [common_low_bits v] returns the common pattern between the 
-   least-significant bits of all the elements of the Ival [v]. 
-   The pattern is in the form [lower_bits, mask] where [mask]
-   indicates the consecutive least significant bits that are
-   common between all elements, and
-   [lower_bits] indicates their values. *)
-let common_low_bits v =
+      inject_top l' u' r modu
+
+
+(* --- Bit masks --- *)
+
+(** bit masks are composed of an array of significant bit values where index 0
+    represents the lowest bit, and a single bit_value to represent the possible
+    leading bits. *)
+type bit_mask = bit_value array * bit_value
+
+let int_to_bit_array n (x : Int.t) =
+  let a = Array.make n On in
+  let p = ref Int.one in
+  for i = 0 to n-1 do
+    if Int.(equal (logand x !p) zero) then
+      a.(i) <- Off;
+    p := Int.(shift_left !p one)
+  done;
+  a
+
+(** Compute a mask only precise for low bits, overapproximating the high ones.
+    More precisely, bit values are computed until an uncertainty appears
+    in the mask *)
+let low_bit_mask (v : t) =
   match v with
-  | Float _ -> assert false
-  | Top(_,_,r,m) -> 
-    if Int.is_zero (Int.logand m (Int.pred m))
-    then (* m is a power of two *)
-      r, Int.pred m
-    else Int.zero, Int.zero (* TODO *)
-  | Set [| v |] ->
-    v, next_pred_power_of_two v
-  | Set _ -> Int.zero, Int.zero (* TODO *)
-
-let bitwise_and ~size ~signed v1 v2 =
-  if is_bottom v1 || is_bottom v2
-  then bottom
-  else
-    match v1, v2 with
-    | Float _, _ | _, Float _ -> assert false
-    | Set s1, Set s2 ->
-      apply2_v Int.logand s1 s2
-    | Top _, other | other, Top _ ->
-      let min, max = bitwise_and_intervals ~signed ~size v1 v2 in
-      let lower_bits1, mask1 = common_low_bits v1 in
-      let lower_bits2, mask2 = common_low_bits v2 in
-      let mask = Int.logand mask1 mask2 in
-      let modu = Int.succ mask in
-      let r = Int.logand lower_bits1 (Int.logand lower_bits2 mask) in
-      let min = match min with
-        | Some min -> Some (Int.round_up_to_r ~min ~r ~modu)
-        | _ -> min 
+  | Set [| |] -> raise Error_Bottom
+  | Set [| x |] -> (* singleton : build a full mask  *)
+    let n = Int.significant_bits x in
+    int_to_bit_array n x, if Int.(ge x zero) then Off else On
+  | _ ->
+    let _,_,r,modu = min_max_r_mod v in (* requires cardinal > 1 *)
+    (* Find how much modu can be divided by two *)
+    let n = Int.biggest_power_of_two_divider modu in
+    (* Recompute rest *)
+    let r = Int.(logand (sub (two_power_of_int n) one) r) in
+    int_to_bit_array n r, Both
+
+let combine_masks (op : bit_value -> bit_value -> bit_value)
+    (b1,s1 : bit_mask) (b2,s2 : bit_mask) : bit_mask =
+  let n = max (Array.length b1) (Array.length b2) in
+  let r = Array.make n Both in
+  for i = 0 to n-1 do
+    let b1 = try b1.(i) with _ -> s1
+    and b2 = try b2.(i) with _ -> s2
+    in
+    r.(i) <- op b1 b2
+  done;
+  r, op s1 s2
+
+let mask_to_r_modu (b,_s : bit_mask) : Int.t * Int.t =
+  let n = Array.length b in
+  let r = ref Int.zero (* current rest *)
+  and p = ref Int.one (* current bit *) in
+  begin try
+      for i = 0 to n-1 do
+        begin match b.(i) with
+        | On -> r := Int.(logor !r !p)
+        | Off -> ()
+        | Both -> raise Exit
+        end;
+        p := Int.(shift_left !p one)
+      done;
+    with Exit -> ()
+  end;
+  !r, !p
+
+
+(* --- Bitwise binary operators --- *)
+
+module BitwiseOperator (Op : BitOperator) =
+struct
+  include Op
+
+  exception Result_does_not_fit_small_sets
+
+
+  let backward (b : bit_value) = function
+    | On -> backward_on b
+    | Off -> backward_off b
+    | Both -> assert false
+
+  (* The number of bits on which the result should be significant *)
+  let result_size (v1 : t) (v2 : t)
+      ?(s1 : bit_value = extract_sign v1)
+      ?(s2 : bit_value = extract_sign v2)
+      ()
+    : int option =
+    let n1 = significant_bits v1 and n2 = significant_bits v2 in
+    let n1_greater = 
+      match n1, n2 with
+      | _, None -> false
+      | Some n1, Some n2 when n1 <= n2 -> false
+      | _ -> true
+    in
+    (* whether n1 or n2 is greater, look if the sign bit oped with anything is
+       not constant. If it is constant, then the highest bits are irrelevant. *)
+    if n1_greater then
+      if forward Both s2 = Both then n1 else n2
+    else
+      if forward s1 Both = Both then n2 else n1
+
+
+  (* Try to build a small set.
+     It is basically enumerating the possible results, by choosing the possible
+     bits from left to right. This function aborts if we ever exceed the small
+     set size. The algorithm is probably not complete, as it is not always
+     possible to reduce the operands leading to a result (without an
+     exponential cost)  meaning that sometimes small sets can be obtained but
+     the algorithm will fail to find them.
+  *)
+  let compute_small_set (v1 : t) (v2 : t) (r : Int.t) (modu : Int.t) =
+    let s1 = extract_sign v1 and s2 = extract_sign v2 in
+    match result_size v1 v2 ~s1 ~s2 () with
+    | None -> raise Result_does_not_fit_small_sets
+    | Some n ->
+      let acc = [] in (* List of possible results, with the operands leading
+                         to these results *)
+      let s = forward s1 s2 in
+      (* Either the result is positive *)
+      let acc =
+        if s <> On then
+          let v1 = reduce_sign v1 (backward_off s2)
+          and v2 = reduce_sign v2 (backward_off s1) in
+          (r, v1, v2) :: acc
+        else acc
       in
-      let max = match max with
-        | Some max -> Some (Int.round_down_to_r ~max ~r ~modu)
-        | _ -> max 
+      (* Or negative *)
+      let acc =
+        if s <> Off then
+          let v1 = reduce_sign v1 (backward_on s2)
+          and v2 = reduce_sign v2 (backward_on s1) in
+          (Int.(logor r (neg (two_power_of_int n))), v1, v2) :: acc
+        else
+          acc
       in
-      let result = inject_top min max r modu in
-      ( match other with
-	Top _ | Float _ -> result
-      | Set s ->
-	if 
-	  array_for_all
-	    (fun elt -> 
-	      Int.ge elt Int.zero && 
-		Int.popcount elt <= !small_cardinal_log) 
-	    s 
-	then
-	  let result2 = 
-	    Array.fold_left
-	      (fun acc elt ->
-		join 
-		  (sub_bits elt)
-		  acc)
-	      bottom
-	      s
-	  in
-	  narrow result result2
-	else result)
-
-let bitwise_not v =
-  (* the result is [-v - 1] *)
+      let rec step acc i =
+        if List.length acc > !small_cardinal then
+          raise Result_does_not_fit_small_sets;
+        if i < 0 then acc
+        else
+          let mask = Int.(two_power_of_int i) in
+          let set_one_bit acc (r,v1,v2) =
+            let b1 = extract_bit v1 i and b2 = extract_bit v2 i in
+            let b = forward b1 b2 in
+            (* Either the bit is on  *)
+            let acc =
+              if b <> Off then
+                let v1 = reduce_bit v1 i (backward_on b2)
+                and v2 = reduce_bit v2 i (backward_on b1) in
+                (Int.logor mask r, v1, v2) :: acc
+              else acc
+            in
+            (* Or off *)
+            let acc =
+              if b <> On then
+                let v1 = reduce_bit v1 i (backward_off b2)
+                and v2 = reduce_bit v2 i (backward_off b1) in
+                (r, v1, v2) :: acc
+              else acc
+            in
+            acc
+          in
+          if mask < modu
+          then acc
+          else step (List.fold_left set_one_bit [] acc) (i-1)
+      in
+      let acc = step acc (n-1) in
+      let o = List.fold_left (fun o (r,_,_) -> O.add r o) O.empty acc in
+      share_set o (O.cardinal o)
+
+  (* If lower is true (resp. false), compute the lower (resp. upper) bound of
+     the result interval when applying op to v1 and v2.
+     We iterate from left to right. We keep track of an ival for each operand
+     such that, by applying the operator on the two ivals, we can find the
+     actual bound of the operation.
+     This function should be exact  when the operands are small sets or tops
+     with modulo 1. Otherwise, it is an overapproximation of the bound. *)
+  let compute_bound (v1 : t) (v2 : t) (lower : bool) =
+    (* What is the sign of the result *)
+    let s1 = extract_sign v1 and s2 = extract_sign v2 in
+    let s,s1,v1,s2,v2 =
+      match forward s1 s2 with 
+      | (On | Off) as s -> s,s1,v1,s2,v2 (* constant sign *)
+      | Both -> (* choose the best sign *)
+        let s = if lower then On else Off in
+        let s1 = backward s2 s and s2 = backward s1 s in
+        let v1 = reduce_sign v1 s1 and v2 = reduce_sign v2 s2 in
+        s,s1,v1,s2,v2
+    in
+    (* Is the result bounded ? *)
+    match result_size v1 v2 ~s1 ~s2 () with
+    | None ->
+      (* Unbounded result *)
+      None
+    | Some n ->
+      (* The result is bounded: iterate from the rightmost significant bit *)
+      let rec step r v1 v2 i =
+        if i < 0 then r
+        else
+          let mask = Int.(two_power_of_int i) in
+          let b1 = extract_bit v1 i and b2 = extract_bit v2 i in
+          let b, v1, v2 = match forward b1 b2 with
+          | (On | Off) as b -> b,v1,v2 (* constant bit *)
+          | Both -> (* choose the best bit *)
+            let b = if lower then Off else On in
+            let b1 = backward b2 b and b2 = backward b1 b in
+            let v1 = reduce_bit v1 i b1 and v2 = reduce_bit v2 i b2 in
+             b, v1, v2
+          in
+          let r = match b with
+            | On -> Int.logor mask r
+            | Off -> r
+            | Both -> assert false
+          in
+          step r v1 v2 (i-1)
+      in
+      let r = match s with
+        | On -> Int.(neg (two_power_of_int n))
+        | Off -> Int.zero
+        | Both -> assert false
+      in
+      Some (step r v1 v2 (n - 1))
+
+  let bitwise_forward (v1 : t) (v2 : t) : t =
+    try
+      let mask1 = low_bit_mask v1
+      and mask2 = low_bit_mask v2 in
+      let r, modu = mask_to_r_modu (combine_masks forward mask1 mask2) in
+      try
+        compute_small_set v1 v2 r modu
+      with Result_does_not_fit_small_sets ->
+        let min = compute_bound v1 v2 true
+        and max = compute_bound v1 v2 false in
+        inject_interval min max r modu
+    with Error_Bottom -> bottom
+end
+
+let bitwise_or = let module M = BitwiseOperator (Or) in M.bitwise_forward
+let bitwise_and = let module M = BitwiseOperator (And) in M.bitwise_forward
+let bitwise_xor = let module M = BitwiseOperator (Xor) in M.bitwise_forward
+
+
+(* --- Bitwise not --- *)
+
+let bitwise_signed_not v =
   match v with
   | Float _ -> assert false
-  | Top _ -> add_int (neg_int v) minus_one
+  | Top _ -> add_int (neg_int v) minus_one (* [-v - 1] *)
   | Set s -> map_set_strict_decr Int.lognot s
 
-let bitwise_not_size ~size ~signed v =
-  let nv = bitwise_not v in
-  if not signed then
-    cast_int_to_int ~size:(Integer.of_int size) ~signed nv
-  else nv (* always fits in the type if the argument fitted. *)
+let bitwise_unsigned_not ~size v =
+  let size = Int.of_int size in
+  cast_int_to_int ~size ~signed:false (bitwise_signed_not v)
 
-let overlaps ~partial ~size t1 t2 =
-  let diff = sub_int t1 t2 in
-  match diff with
-  | Set array ->
-    not (array_for_all
-           (fun i -> Int.ge (Int.abs i) size || (partial && Int.is_zero i))
-           array)
-  | Top (min, max, _r, _modu) ->
-    let pred_size = Int.pred size in
-    min_le_elt min pred_size && max_ge_elt max (Int.neg pred_size)
-  | Float _ -> assert false
+let bitwise_not ~size ~signed v =
+  if signed then
+    bitwise_signed_not v
+  else
+    bitwise_unsigned_not ~size v
 
 let pretty_debug = pretty
 let name = "ival"
diff --git a/src/kernel_services/abstract_interp/ival.mli b/src/kernel_services/abstract_interp/ival.mli
index 5ef75814d9a3c42f41104f622531998d82fd1204..4f2438bc90fbd3a1a2faf0e4d639ab41c7564917 100644
--- a/src/kernel_services/abstract_interp/ival.mli
+++ b/src/kernel_services/abstract_interp/ival.mli
@@ -101,14 +101,15 @@ val min_and_max_float : t -> (Fval.F.t * Fval.F.t) option * bool
     may be NaN. *)
 
 
-val bitwise_and : size:int -> signed:bool -> t -> t -> t
+val bitwise_and : t -> t -> t
 val bitwise_or : t -> t -> t
 val bitwise_xor : t -> t -> t
-val bitwise_not: t -> t
+val bitwise_signed_not: t -> t
+(* For the two following functions, the argument is assumed to fit within the
+   given size. *)
+val bitwise_unsigned_not: size:int -> t -> t
+val bitwise_not: size:int -> signed:bool -> t -> t
 
-val bitwise_not_size: size:int -> signed:bool -> t -> t
-(** bitwise negation on a finite integer type. The argument is assumed to
-    fit within the type. *)
 
 val zero : t
 (** The lattice element that contains only the integer 0. *)
diff --git a/src/plugins/value/values/cvalue_backward.ml b/src/plugins/value/values/cvalue_backward.ml
index 06fd996ee2fbf8609a11a106cb3cbcb818d12612..a4296ad5a415dd4e0efec7790319fa65e5537576 100644
--- a/src/plugins/value/values/cvalue_backward.ml
+++ b/src/plugins/value/values/cvalue_backward.ml
@@ -200,7 +200,6 @@ let _backward_mult typ v1 v2 res_value =
 let backward_band ~v1 ~v2 ~res typ =
   let size = Cil.bitsSizeOf typ in
   let signed = Bit_utils.is_signed_int_enum_pointer typ in
-  let bitwise_and = V.bitwise_and ~size ~signed in
   (* Reduction of a when a & b = res. *)
   let backward_band_aux a b =
     (* For each bit, if a & _ = 1 then a = 1. [a1] is [a] with all such bits at 1
@@ -210,21 +209,18 @@ let backward_band ~v1 ~v2 ~res typ =
        (for the others, not (xor res b) = 1 and this bitwise_and has no effect
        on a). *)
     let a2 =
-      bitwise_and a (V.bitwise_not_size ~size ~signed (V.bitwise_xor res b))
+      V.bitwise_and a (V.bitwise_not ~size ~signed (V.bitwise_xor res b))
     in
     V.narrow a1 a2
   in
   backward_band_aux v1 v2, backward_band_aux v2 v1
 
-let backward_bor ~v1 ~v2 ~res typ =
-  let size = Cil.bitsSizeOf typ in
-  let signed = Bit_utils.is_signed_int_enum_pointer typ in
-  let bitwise_and = V.bitwise_and ~size ~signed in
+let backward_bor ~v1 ~v2 ~res =
   (* Reduction of a when a | b = res. *)
   let backward_bor_aux a b =
     (* For each bit, if a | _ = 0 then a = 0. [a1] is [a] with all such bits at 0
        (for the others, res = 1 and this bitwise_and has no effect on a). *)
-    let a1 = bitwise_and res a in
+    let a1 = V.bitwise_and res a in
     (* For each bit, if a | 0 = 1 then a = 1. [a2] is [a] with all such bits at 1
        (for the others, xor res b = 0 and this bitwise_or has no effect on a). *)
     let a2 = V.bitwise_or (V.bitwise_xor res b) a in
@@ -305,7 +301,7 @@ let backward_binop ~typ_res ~res_value ~typ_e1 v1 binop v2 =
 
   | BAnd, TInt _ -> Some (backward_band ~v1 ~v2 ~res:res_value typ)
 
-  | BOr, TInt _ -> Some (backward_bor ~v1 ~v2 ~res:res_value typ)
+  | BOr, TInt _ -> Some (backward_bor ~v1 ~v2 ~res:res_value)
 
   | _, _ -> None
 
diff --git a/src/plugins/value/values/cvalue_forward.ml b/src/plugins/value/values/cvalue_forward.ml
index dfa37387807a03fdf09fbde858a8578df40e937c..d417304af105379bcdf6c584f2aa2c9b1d84e4dd 100644
--- a/src/plugins/value/values/cvalue_forward.ml
+++ b/src/plugins/value/values/cvalue_forward.ml
@@ -338,10 +338,7 @@ let forward_binop_int ~typ ev1 op ev2 =
   | Shiftlt -> V.shift_left ev1 ev2
   | BXor    -> V.bitwise_xor ev1 ev2
   | BOr     -> V.bitwise_or ev1 ev2
-  | BAnd    ->
-    let size = Cil.bitsSizeOf typ in
-    let signed = Bit_utils.is_signed_int_enum_pointer typ in
-    V.bitwise_and ~size ~signed ev1 ev2
+  | BAnd    -> V.bitwise_and ev1 ev2
   (* Strict evaluation. The caller of this function is supposed to take
      into account the laziness of those operators itself *)
   | LOr  ->
@@ -384,7 +381,7 @@ let forward_binop_float fkind ev1 op ev2 =
    This is left to the caller *)
 let forward_uneg v t =
   try
-    match Cil.unrollType t with
+    match Cil. unrollType t with
     | TFloat _ ->
       let v = V.project_float v in
       V.inject_ival (Ival.inject_float (Fval.neg v))
@@ -404,7 +401,7 @@ let forward_unop typ op value =
       | TInt (ik, _) | TEnum ({ekind=ik}, _) ->
         let size = Cil.bitsSizeOfInt ik in
         let signed = Cil.isSigned ik in
-        V.bitwise_not_size ~signed ~size value
+        V.bitwise_not ~signed ~size value
       | _ -> assert false
     end
   | LNot ->
diff --git a/src/plugins/value/values/offsm_value.ml b/src/plugins/value/values/offsm_value.ml
index faccc93f4dae5d61bef5df6cd25ae4beb357e9b1..5f5b29937cdefea143768bf1d91254bb5975d2e6 100644
--- a/src/plugins/value/values/offsm_value.ml
+++ b/src/plugins/value/values/offsm_value.ml
@@ -244,8 +244,7 @@ let aux_and (b, e) (vv1: offsm_range) (vv2: offsm_range) =
       of inverse sign. extract_bits generate always positive integers, which
       is good. The good solution would be have V.bitwise_and to accept both
       signs simultaneously. *)
-    let f = V.bitwise_and ~signed:false  ~size:(Integer.to_int size) in
-    lift f size vv1 vv2
+    lift V.bitwise_and size vv1 vv2
 
 (* O is neutral for xor, and  v ^ v = 0 *)
 let aux_xor (b, e) (vv1: offsm_range) (vv2: offsm_range) =
@@ -346,7 +345,7 @@ let cast ~old_size ~new_size ~signed o =
 
 let bnot o =
   let aux itv (v, s, rel) o =
-    let v' = V_Or_Uninitialized.map V.bitwise_not v in
+    let v' = V_Or_Uninitialized.map V.bitwise_signed_not v in
     V_Offsetmap.add ~exact:true itv (v', s, rel) o
   in
   V_Offsetmap.fold aux o o
diff --git a/src/plugins/value_types/cvalue.ml b/src/plugins/value_types/cvalue.ml
index 3774848d76af67fef09c41c73da4d4e624609d5b..2ad0734894a1d9793eb398e9cc0d26a29a3ddb94 100644
--- a/src/plugins/value_types/cvalue.ml
+++ b/src/plugins/value_types/cvalue.ml
@@ -586,27 +586,27 @@ module V = struct
     else
       import_function ~topify:Origin.K_Arith Ival.bitwise_or v1 v2
 
-  let bitwise_and ~signed ~size v1 v2 =
+  let bitwise_and v1 v2 =
     if equal v1 v2 && cardinal_zero_or_one v1 then v1
     else
-      let f i1 i2 = Ival.bitwise_and ~size ~signed i1 i2 in
+      let f i1 i2 = Ival.bitwise_and i1 i2 in
       import_function ~topify:Origin.K_Arith f v1 v2
 
   let shift_right e1 e2 =
     arithmetic_function Ival.shift_right e1 e2
 
-  let bitwise_not v =
+  let bitwise_signed_not v =
     try
       let i = project_ival v in
-      inject_ival (Ival.bitwise_not i)
+      inject_ival (Ival.bitwise_signed_not i)
     with Not_based_on_null -> topify_arith_origin v
 
-  let bitwise_not_size ~signed ~size v =
+  let bitwise_not ~size ~signed v =
     try
       let i = project_ival v in
-      inject_ival (Ival.bitwise_not_size ~size ~signed i)
+      inject_ival (Ival.bitwise_not ~size ~signed i)
     with Not_based_on_null -> topify_arith_origin v
-  
+
   let extract_bits ~topify ~start ~stop ~size v =
     try
       let i = project_ival_bottom v in
diff --git a/src/plugins/value_types/cvalue.mli b/src/plugins/value_types/cvalue.mli
index cfb06aadf7cdc90eb736c61d137c5e05bac721ec..bff937fb16374a54aa67ea81a7dc50c85959502f 100644
--- a/src/plugins/value_types/cvalue.mli
+++ b/src/plugins/value_types/cvalue.mli
@@ -135,11 +135,11 @@ module V : sig
   val c_rem: t -> t -> t
   val shift_right: t -> t -> t
   val shift_left: t -> t -> t
-  val bitwise_and: signed:bool -> size:int -> t -> t -> t
+  val bitwise_and: t -> t -> t
   val bitwise_xor: t -> t -> t
   val bitwise_or : t -> t -> t
-  val bitwise_not: t -> t
-  val bitwise_not_size: signed:bool -> size:int -> t -> t
+  val bitwise_signed_not: t -> t
+  val bitwise_not: size:int -> signed:bool -> t -> t
 
   (** [all_values ~size v] returns true iff v contains all integer values
       representable in [size] bits. *)
diff --git a/tests/builtins/oracle/strnlen.res.oracle b/tests/builtins/oracle/strnlen.res.oracle
index 22a88e13e197f18907637349bb50b79f4965ee19..9cacd457242f401eae1bff00691a9f9965a1881f 100644
--- a/tests/builtins/oracle/strnlen.res.oracle
+++ b/tests/builtins/oracle/strnlen.res.oracle
@@ -58,7 +58,7 @@
     [3] ∈ {100}
     [4] ∈ {101}
     [5] ∈ {0}
-  c ∈ [-2147483648..2147483646]
+  c ∈ [-2147483648..2147483646],0%2
   r1a ∈ {3}
   r1b ∈ {5}
   r1c ∈ UNINITIALIZED
diff --git a/tests/idct/oracle/ieee_1180_1990.res.oracle b/tests/idct/oracle/ieee_1180_1990.res.oracle
index 8e96d4acb601c55097c9f49a4039a07fcd16fa68..90343756005917a5aded940e75b0e60e55de5dc5 100644
--- a/tests/idct/oracle/ieee_1180_1990.res.oracle
+++ b/tests/idct/oracle/ieee_1180_1990.res.oracle
@@ -917,7 +917,7 @@
 [scope:rm_asserts] removing 16 assertion(s)
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function IEEE_1180_1990_rand:
-  i ∈ [0..2147483646]
+  i ∈ [0..2147483646],0%2
   j ∈ [0..600]
   x ∈ [0.0000000000000000 .. 600.9999997201375663]
   IEEE_1180_1990_rand_randx ∈ [--..--]
diff --git a/tests/value/bitwise_or.c b/tests/value/bitwise_or.c
index 4f10b3da2a75fad66d640ffe9be29d7ae0524834..2eddbadb24d3d8359a6e2bb7638d8185b87befb9 100644
--- a/tests/value/bitwise_or.c
+++ b/tests/value/bitwise_or.c
@@ -3,13 +3,14 @@
 */
 #include "__fc_builtin.h"
 
-int or1, or2, or3, or4, or5;
-int and1, and2, and3, and4, xor1, xor2;
-unsigned int uand1, uand2, uand3, uand4, uand5;
-int a,b,c,d,e;
 extern unsigned short s;
 
-int main(){
+void f1(void) {
+  int or1, or2, or3, or4, or5;
+  int and1, and2, and3, and4, xor1, xor2;
+  unsigned int uand1, uand2, uand3, uand4, uand5;
+  int a,b,c,d,e;
+
   a = Frama_C_interval(3,17);
   b = Frama_C_interval(-3,17);
   c = Frama_C_interval(13,27);
@@ -34,6 +35,22 @@ int main(){
   unsigned mask07 = (16 * s + 13) & 0x7;
   unsigned mask0f = (16 * s + 13) & 0xF;
   unsigned mask1f = (16 * s + 13) & 0x1F;
+}
+
+void f2(void) {
+  int x = Frama_C_interval(62,110) & ~(7);
+}
 
-  return 0;
+volatile unsigned char t[3];
+
+void f3(void) {
+  int x = (t[0] & 0x10 ? -1^255 : 0) | t[1];
+  int y = (t[0] & 0x20 ? -1^255 : 0) | t[2];
+}
+
+void main(void) {
+  f1();
+  f2();
+  f3();
 }
+
diff --git a/tests/value/oracle/addition.res.oracle b/tests/value/oracle/addition.res.oracle
index 3bb9c9026b6be3734f2a9754ad38c818df083dd8..f601e53058bff5ba8712b59c7b0ce069bfa7a1b4 100644
--- a/tests/value/oracle/addition.res.oracle
+++ b/tests/value/oracle/addition.res.oracle
@@ -166,7 +166,7 @@
   p10 ∈
      {{ garbled mix of &{p1}
       (origin: Arithmetic {tests/value/addition.i:52}) }}
-  p11 ∈ [-2147483648..0]
+  p11 ∈ [-2147483648..0],0%4
   p12 ∈
      {{ garbled mix of &{p1; p2}
       (origin: Arithmetic {tests/value/addition.i:56}) }}
@@ -397,7 +397,7 @@
   p10 ∈
      {{ garbled mix of &{p1}
       (origin: Arithmetic {tests/value/addition.i:52}) }}
-  p11 ∈ [-2147483648..0]
+  p11 ∈ [-2147483648..0],0%4
   p12 ∈
      {{ garbled mix of &{p1; p2}
       (origin: Arithmetic {tests/value/addition.i:56}) }}
diff --git a/tests/value/oracle/bitwise_or.res.oracle b/tests/value/oracle/bitwise_or.res.oracle
index 21b618d85c0e46f824607a068f5210d5ea9e0d44..3a0e350f43ac2c40d13e7c3c4f296c3c3fc84fc4 100644
--- a/tests/value/oracle/bitwise_or.res.oracle
+++ b/tests/value/oracle/bitwise_or.res.oracle
@@ -3,66 +3,70 @@
 [eva] Computing initial state
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
-  or1 ∈ {0}
-  or2 ∈ {0}
-  or3 ∈ {0}
-  or4 ∈ {0}
-  or5 ∈ {0}
-  and1 ∈ {0}
-  and2 ∈ {0}
-  and3 ∈ {0}
-  and4 ∈ {0}
-  xor1 ∈ {0}
-  xor2 ∈ {0}
-  uand1 ∈ {0}
-  uand2 ∈ {0}
-  uand3 ∈ {0}
-  uand4 ∈ {0}
-  uand5 ∈ {0}
-  a ∈ {0}
-  b ∈ {0}
-  c ∈ {0}
-  d ∈ {0}
-  e ∈ {0}
   s ∈ [--..--]
-[eva] computing for function Frama_C_interval <- main.
-  Called from tests/value/bitwise_or.c:13.
-[eva] using specification for function Frama_C_interval
-[eva] tests/value/bitwise_or.c:13: 
-  function Frama_C_interval: precondition 'order' got status valid.
-[eva] Done for function Frama_C_interval
-[eva] computing for function Frama_C_interval <- main.
+  t[0..2] ∈ [--..--]
+[eva] computing for function f1 <- main.
+  Called from tests/value/bitwise_or.c:52.
+[eva] computing for function Frama_C_interval <- f1 <- main.
   Called from tests/value/bitwise_or.c:14.
+[eva] using specification for function Frama_C_interval
 [eva] tests/value/bitwise_or.c:14: 
   function Frama_C_interval: precondition 'order' got status valid.
 [eva] Done for function Frama_C_interval
-[eva] computing for function Frama_C_interval <- main.
+[eva] computing for function Frama_C_interval <- f1 <- main.
   Called from tests/value/bitwise_or.c:15.
 [eva] tests/value/bitwise_or.c:15: 
   function Frama_C_interval: precondition 'order' got status valid.
 [eva] Done for function Frama_C_interval
+[eva] computing for function Frama_C_interval <- f1 <- main.
+  Called from tests/value/bitwise_or.c:16.
+[eva] tests/value/bitwise_or.c:16: 
+  function Frama_C_interval: precondition 'order' got status valid.
+[eva] Done for function Frama_C_interval
+[eva] Recording results for f1
+[eva] Done for function f1
+[eva] computing for function f2 <- main.
+  Called from tests/value/bitwise_or.c:53.
+[eva] computing for function Frama_C_interval <- f2 <- main.
+  Called from tests/value/bitwise_or.c:41.
+[eva] tests/value/bitwise_or.c:41: 
+  function Frama_C_interval: precondition 'order' got status valid.
+[eva] Done for function Frama_C_interval
+[eva] Recording results for f2
+[eva] Done for function f2
+[eva] computing for function f3 <- main.
+  Called from tests/value/bitwise_or.c:54.
+[eva] Recording results for f3
+[eva] Done for function f3
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
-[eva:final-states] Values at end of function main:
+[eva:final-states] Values at end of function f1:
   Frama_C_entropy_source ∈ [--..--]
-  or1 ∈ [--..--]
+  or1 ∈ [-3..31]
   or2 ∈ [13..31]
-  or3 ∈ [--..--]
+  or3 ∈ [-3..31]
   and1 ∈ [0..17]
   and2 ∈ [0..17]
   and3 ∈ [0..27]
   xor1 ∈ [0..31]
-  xor2 ∈ [--..--]
-  uand4 ∈ [8..24]
+  xor2 ∈ [-20..31]
+  uand4 ∈ {8; 16; 24}
   a ∈ [3..17]
   b ∈ [-3..17]
   c ∈ [13..27]
   i1 ∈ [0..0x1FFFE],0%2
   i2 ∈ [0..0x3FFFC],0%4
-  v1 ∈ [0..0x1FFFE],0%2
-  v2 ∈ [0..0x3FFFF]
+  v1 ∈ [0..0x1FFFC],0%4
+  v2 ∈ [0..0x3FFFE],0%2
   mask07 ∈ {5}
   mask0f ∈ {13}
   mask1f ∈ {13; 29}
-  __retres ∈ {0}
+[eva:final-states] Values at end of function f2:
+  Frama_C_entropy_source ∈ [--..--]
+  x ∈ {56; 64; 72; 80; 88; 96; 104}
+[eva:final-states] Values at end of function f3:
+  x ∈ [-256..255]
+  y ∈ [-256..255]
+[eva:final-states] Values at end of function main:
+  Frama_C_entropy_source ∈ [--..--]
diff --git a/tests/value/oracle/cast.res.oracle b/tests/value/oracle/cast.res.oracle
index f5f0b310db631ce8aff871c321a0d8f708d0386b..12e82f34a53f045237c470c50cb70486d3bcecee 100644
--- a/tests/value/oracle/cast.res.oracle
+++ b/tests/value/oracle/cast.res.oracle
@@ -68,7 +68,7 @@
   i_0 ∈ [--..--]
   __retres ∈ [-536870912..536870911]
 [eva:final-states] Values at end of function main1:
-  G ∈ [0..12]
+  G ∈ [2..12]
   H ∈ [-536870912..536870911]
   K ∈ [-10..20]
   L ∈ [-4000..2],0%2
@@ -86,7 +86,7 @@
   G_0 ∈ {-126; -125; -124; -123; -122; -121} or UNINITIALIZED
   S___fc_stdout[0..1] ∈ [--..--]
 [eva:final-states] Values at end of function main:
-  G ∈ [0..12]
+  G ∈ [2..12]
   H ∈ [-536870912..536870911]
   K ∈ [-10..20]
   L ∈ [-4000..2],0%2
diff --git a/tests/value/oracle/postcond_leaf.res.oracle b/tests/value/oracle/postcond_leaf.res.oracle
index 0888126aadf7fd6d719a0908ceea109b3b2d48ee..bd9241c82545abbc272006a05012b229ae4f4830 100644
--- a/tests/value/oracle/postcond_leaf.res.oracle
+++ b/tests/value/oracle/postcond_leaf.res.oracle
@@ -4,7 +4,8 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   i ∈ [--..--]
-[kernel] tests/value/postcond_leaf.c:108: Warning: 
+  j ∈ [--..--]
+[kernel] tests/value/postcond_leaf.c:109: Warning: 
   No code nor implicit assigns clause for function f1, generating default assigns from the prototype
 [eva] using specification for function f1
 [eva] tests/value/postcond_leaf.c:21: Warning: 
diff --git a/tests/value/oracle/shift.0.res.oracle b/tests/value/oracle/shift.0.res.oracle
index 6544f7ef1f4f67469baf5489ebfc83980eed75bf..aa83c00acb6fec860002e54317aee5ec41e97e39 100644
--- a/tests/value/oracle/shift.0.res.oracle
+++ b/tests/value/oracle/shift.0.res.oracle
@@ -77,7 +77,7 @@
   ua ∈ {1401}
   ub ∈ {1073741074}
   c ∈ [--..--]
-  z ∈ [-2147483648..2147483631]
+  z ∈ [-2147483648..2147483630],0%2
   zz ∈ {0}
   shl ∈ {1}
 [from] Computing for function main
diff --git a/tests/value/oracle/shift.1.res.oracle b/tests/value/oracle/shift.1.res.oracle
index 0332ad41be63d8ea469071b1ff3be8a6d533bafd..076532ff7124c6875536b00e1051863ad9d4aa3c 100644
--- a/tests/value/oracle/shift.1.res.oracle
+++ b/tests/value/oracle/shift.1.res.oracle
@@ -65,7 +65,7 @@
   ua ∈ {1401}
   ub ∈ {1073741074}
   c ∈ [--..--]
-  z ∈ [-2147483648..2147483631]
+  z ∈ [-2147483648..2147483630],0%2
   zz ∈ {0}
   shl ∈ {0; 1}
 [from] Computing for function main
diff --git a/tests/value/postcond_leaf.c b/tests/value/postcond_leaf.c
index 1afa96fd61f72825e88db72e9b8f1a9bf1e33ef5..6f7282285f0a26c50ac10ffd08d16d935cc5c571 100644
--- a/tests/value/postcond_leaf.c
+++ b/tests/value/postcond_leaf.c
@@ -103,35 +103,36 @@ void h4() {
 int* k(int *p);
 
 
-void main(j) {
-  if (j & 1) {
+volatile int j;
+void main() {
+  if (j) {
     f1();
   }
-  if (j & 2) {
+  if (j) {
     f2();
   }
-  if (j & 3) {
+  if (j) {
     f3();
   }
-  if (j & 4) {
+  if (j) {
     f4();
   }
-  if (j & 5) {
+  if (j) {
     g1();
   }
-  if (j & 6) {
+  if (j) {
     g2();
   }
-  if (j & 7) {
+  if (j) {
     g3();
   }
-  if (j & 8) {
+  if (j) {
     h1();
   }
-  if (j & 9) {
+  if (j) {
     h2();
   }
-  if (j & 10) {
+  if (j) {
     h3();
   }
   if (j & 11) {
@@ -143,3 +144,4 @@ void main(j) {
   }
 
 }
+