method vstmt stm =

    (* give a set of varinfos and an iosh and get
     * the set of definition ids definining the vars *)

    let viSetToDefIdSet iosh vis =
      UD.VS.fold (fun vi s ->
        if IH.mem iosh vi.vid then
          let ios = IH.find iosh vi.vid in
          RD.IOS.fold (fun io s ->
            match io with None -> s
            | Some i -> IS.add i s) ios s
        else s) vis IS.empty
    in

    (* false when U(defid)\subeq instruses and SU(d) = empty *)
    let check_defid i instruses iosh defid =
      IS.mem defid (!usedDefsSet) &&
      try
        let defuses = IH.find defUseSetHash defid in
        (*let siduses = IH.find sidUseSetHash defid in*)
        if IH.mem sidUseSetHash defid then begin
          if !debug then Kernel.debug "siduses not empty: %a\n" d_instr i;
          true
        end else begin
          (* true if there is something in defuses not in instruses or when
           * something from defuses is in instruses and is also used somewhere else *)

          let instruses = viSetToDefIdSet iosh instruses in
          IS.fold (fun i' b ->
            if not(IS.mem i' instruses) then begin
              if !debug then Kernel.debug "i not in instruses: %a\n" d_instr i;
              true
            end else
              (* can only use the definition i' at the definition defid *)
              let i'_uses = IH.find defUseSetHash i' in
              IH.mem sidUseSetHash i' ||
              if not(IS.equal i'_uses (IS.singleton defid)) then begin
                IS.iter (fun iu -> match RD.getSimpRhs iu with
                | Some(RD.RDExp e) ->
                    if !debug then Kernel.debug "i' had other than one use: %d: %a\n"
                      (IS.cardinal i'_uses) d_exp e
                | Some(RD.RDCall i) ->
                    if !debug then Kernel.debug "i' had other than one use: %d: %a\n"
                             (IS.cardinal i'_uses) d_instr i
                | None -> ()) i'_uses;
                true
              end else b) defuses false
        end
      with Not_found -> true
    in

    let test (i,(_,s,iosh)) =
      match i with
      | Call(Some(Var vi,NoOffset),{enode = Lval(Var _vf,NoOffset)},el,_l) ->
          if not(!callHasNoSideEffects i) then begin
            if !debug then Kernel.debug "found call w/ side effects: %a\n" d_instr i;
            true
          end else begin
            if !debug then Kernel.debug "found call w/o side effects: %a\n" d_instr i;
            (vi.vglob || (Ciltools.is_volatile_vi vi) || (el_has_volatile el) ||
            let uses, defd = UD.computeUseDefInstr i in
            let rec loop n =
              n >= 0 &&
              (check_defid i uses iosh (n+s) || loop (n-1))
            in
            loop (UD.VS.cardinal defd - 1) || (incr removedCount; false))
          end
      |        Call _ -> true
      | Set(lh,e,_) when compareExpStripCasts (dummy_exp (Lval lh)) e ->
          false (* filter x = x *)
      | Set((Var vi,NoOffset),e,_) ->
          vi.vglob || (Ciltools.is_volatile_vi vi) || (exp_has_volatile e) ||
          let uses, defd = UD.computeUseDefInstr i in
          let rec loop n =
            n >= 0 &&
            (check_defid i uses iosh (n+s) || loop (n-1))
          in
          loop (UD.VS.cardinal defd - 1) || (incr removedCount; false)
      | _ -> true
    in

    let filter il stmdat =
      match
        let rd_dat_lst = RD.instrRDs il stm.sid stmdat false in
        let ildatlst = List.combine [il] rd_dat_lst in
        let ildatlst' = List.filter test ildatlst in
        let (newil,_) = List.split ildatlst' in
        newil
      with
      | [] -> Skip Cil_datatype.Location.unknown
      | [ x ] -> x
      | _ :: _ :: _ -> assert false
    in

    match RD.getRDs stm with
      None -> DoChildren
    | Some(_,s,iosh) ->
        match stm.skind with
          Instr il ->
            stm.skind <- Instr(filter il ((),s,iosh));
            SkipChildren
        | _ -> DoChildren