let get_read_addr with_direct p =
      let add d acc =
        if logic_data d then
          (debug3 "[get_read_addr] ignore access to logic data %a" F.pp_data d;
           acc)
        else
          if with_direct || not (direct_lval d) then add_unique F.eq_data d acc
          else
            (debug3 "[get_read_addr] ignore direct access to %a" F.pp_data d; acc)
      in
      let do_var acc (v_opt, fv) = match v_opt with
        | Some (vi, _l) ->
            (* TODO: maybe we should take only the variables at Here ? *)
            add (F.addr vi (F.tau_of_var fv)) acc
        | None -> debug3 "get_read_addr : ignore logic variable %a" F.pp_var fv;
            acc
      in

      let rec do_path do_exp acc ch = match ch with
        | F.Pfield _ -> acc
        | F.Pidx i -> do_exp acc i
            
      and do_data do_exp acc d =
        let frec =  do_data do_exp in
        match d with
          | F.D1null | F.D1addr _ -> acc
          | F.D1base p -> frec acc p
          | F.D1var (v, fv) -> do_var acc (v, fv)
          | F.D1proj (s, ch) ->
              let acc =
                try
                  let p = F.addr_of_data d in
                  let acc = add p acc in
                  frec acc p
                with Not_found -> do_path do_exp (frec acc s) ch
              in acc
          | F.D1depl (ps, F.Pfield _) -> frec acc ps
          | F.D1depl (p, F.Pidx i) | F.D1shift (p, i)  ->
              let acc = do_exp acc i in frec acc p
          | F.D1indir p  ->
              let acc = match frec [] p with
                | [] -> acc (* no modifiable var in p *)
                    (* TODO : check indir cannot be lowered *)
                | accp -> List.fold_left (fun acc d -> add d acc) acc accp
              in add p acc
          | F.D1mu (s, F.Pfield _f, x)  ->
              let acc = match x with Some x -> do_exp acc x | None -> acc in
              frec acc s (* TODO what about f ? *)
          | F.D1mu (t, F.Pidx i, x)  ->
              let acc = match x with Some x -> do_exp acc x | None -> acc in
              let acc = do_exp acc i in
              frec acc t (* TODO what about idx ? *)
          | F.D1muRange (t, x)  ->
              let acc = do_exp acc x in
              frec acc t (* TODO what about idx ? *)
          | F.D1muI _  | F.D1muIrange _ ->
              unsupported "[get_read_addr] of %a" F.pp_data d
    in
    let ptrs = F.visit_data_in_pred ~all:false do_data [] p in
    ptrs