let ok_to_replace_with_incdec curiosh defiosh f id vi r =
let num_uses () =
let _ = useList := [] in
let ulc = new useListerClass id vi in
let _ = visitCilFunction (ulc :> cilVisitor) f in
List.length (!useList)
in
let inc_or_dec e vi =
match e.enode with
BinOp((PlusA|PlusPI|IndexPI),
{enode = Lval(Var vi', NoOffset)},
{enode = Const(CInt64(one,_,_))},_) ->
if vi.vid = vi'.vid && one = Int64.one
then Some(PlusA)
else if vi.vid = vi'.vid && one = Int64.minus_one
then Some(MinusA)
else None
| BinOp((MinusA|MinusPI),
{enode = Lval(Var vi', NoOffset)},
{enode = Const(CInt64(one,_,_))},_) ->
if vi.vid = vi'.vid && one = Int64.one
then Some(MinusA)
else None
| _ -> None
in
match r with
RD.RDExp({enode = Lval(Var rhsvi, NoOffset)}) ->
let curido = RD.iosh_singleton_lookup curiosh rhsvi in
let defido = RD.iosh_singleton_lookup defiosh rhsvi in
(match curido, defido with
Some(curid), _ ->
let defios = try IH.find defiosh rhsvi.vid
with Not_found -> RD.IOS.empty in
let redefrhso = getDefRhs curid in
(match redefrhso with
None -> (if !debug then (Cilmsg.debug "ok_to_replace: couldn't get rhs for redef: %d" curid);
None)
| Some(redefrhs, _, redefiosh) ->
let tmprdido = RD.iosh_singleton_lookup redefiosh vi in
match tmprdido with
None -> (if !debug then (Cilmsg.debug "ok_to_replace: conflicting defs of %s reach redef of %s" vi.vname rhsvi.vname);
None)
| Some tmprdid ->
if not (tmprdid = id) then
(if !debug then (Cilmsg.debug "ok_to_replace: initial def of %s doesn't reach redef of %s" vi.vname rhsvi.vname);
None)
else let redefios = try IH.find redefiosh rhsvi.vid
with Not_found -> RD.IOS.empty in
let curdef_stmt =
try IH.find RD.ReachingDef.defIdStmtHash curid
with Not_found ->
Cilmsg.fatal "ok_to_replace: couldn't find statement defining %d" curid in
if not (RD.IOS.compare defios redefios = 0) then
(if !debug then
(Cilmsg.debug
"ok_to_replace: different sets of definitions of %s reach the def of %s and the redef of %s"
rhsvi.vname
vi.vname
rhsvi.vname);
None)
else
(match redefrhs with
RD.RDExp(e) -> (match inc_or_dec e rhsvi with
Some(PlusA) ->
if num_uses () = 1 then
Some(curdef_stmt.sid, curid, rhsvi, PlusA)
else (if !debug then (Cilmsg.debug "ok_to_replace: tmp used more than once");
None)
| Some(MinusA) ->
if num_uses () = 1 then
Some(curdef_stmt.sid, curid, rhsvi, MinusA)
else (if !debug then (Cilmsg.debug "ok_to_replace: tmp used more than once");
None)
| None ->
(if !debug then (Cilmsg.debug "ok_to_replace: redef isn't adding or subtracting one from itself");
None)
| _ -> (Cilmsg.fatal "ok_to_replace: unexpected op in inc/dec info."))
| _ -> (if !debug then (Cilmsg.debug "ok_to_replace: redef a call");
None)))
| _ -> (if !debug then (Cilmsg.debug "ok_to_replace: %s has conflicting definitions" rhsvi.vname);
None))
| _ -> (if !debug then (Cilmsg.debug "ok_to_replace: rhs not of correct form");
None)