Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run dead code analysis with reanalyze #737

Merged
merged 17 commits into from
May 27, 2022
Merged

Run dead code analysis with reanalyze #737

merged 17 commits into from
May 27, 2022

Conversation

sim642
Copy link
Member

@sim642 sim642 commented May 16, 2022

This is the result of me trying out reanalyze on our codebase. Instead of a local unused check based on signatures (which we rarely have) that the OCaml compiler has, this attempts to perform a global dead code analysis.

I manually went through all of its warnings and did one of the following for each one:

  1. Removed the dead code.
  2. Added a TODO for potentially significant code, which should maybe be used. Feel free to voice your opinions.
  3. Ignored the warning for false positives, significant code to keep or ARINC/spec analysis (which I didn't want to unnecessarily touch).

TODO

@sim642 sim642 added the cleanup Refactoring, clean-up label May 16, 2022
@sim642 sim642 added this to the v2.0.0 milestone May 16, 2022
@sim642
Copy link
Member Author

sim642 commented May 16, 2022

Looks like I'll have to open a PR for Gobview as well. Will do that in a moment.

@sim642 sim642 mentioned this pull request May 17, 2022
14 tasks
@@ -119,6 +119,7 @@ struct
| _ -> false

(* kill predicate for must-equality kind of analyses*)
(* TODO: why unused? how different from below? *)
Copy link
Member

@michael-schwarz michael-schwarz May 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They seem to be virtually identical, except the one below being a fair bit more chaotic.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it might have been copied there, but without completely rewriting this all, I'd rather not touch this analysis more than necessary.

@@ -151,6 +152,7 @@ struct
let bt = unrollTypeDeep (Cilfacade.typeOf b) in
type_may_change_t a bt

(* TODO: why unused? how different from below? *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are very similar, but the code below handles more cases, but is also considerably more weird.

@@ -117,6 +115,7 @@ struct
| false, false -> join x y
*)

(* TODO: overrides is_top, but not top? *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is some kind of hack to avoid the creation of top addresses as this will fail from HoarePO. What is a bit strange is that is_top answers true as soon as the Addr.UnknownPtr is in the set, but top_ptr is defined as

  let top_ptr        = of_list Addr.([UnknownPtr; NullPtr])

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it's weird because there isn't just a single value that this is_top returns true for. Probably good to have a comment about it to avoid surprises until we somehow design a more consistent domain where this inconsistency isn't necessary.

Comment on lines +17 to +18
val lower_bound : t option (* TODO: unused *)
val upper_bound : t option (* TODO: unused *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those seem a bit strange here. IIRC, IntOpsBase is the module type we use for single values, not modules, ....
Maybe @jerhard knows what they are intended for?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose at some point (maybe pre-bigints) it was necessary to know the min_int and max_int for these different types.

@@ -42,7 +42,7 @@ sig
val compare : t -> t -> int
val equal : t -> t -> bool
val hash : t -> int
val top_range : t -> t -> bool
val top_range : t -> t -> bool (* TODO: unused *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, I am not so sure what the intended semantics is here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the implementations, it seems to be for checking if the two arguments are min_int and max_int respectively. Again I guess we might've used that pre-bigints to do some special treatment, but that seems specific to intervals anyway.

@@ -51,7 +51,7 @@ sig
val to_int : t -> int
val of_int64 : int64 -> t
val to_int64 : t -> int64
val of_string : string -> t
val of_string : string -> t (* TODO: unused *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can keep the of_string, it may be handy sometimes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly yes. I guess this was used when we still parsed the strings from CIL constants for big values.

changes: CompareCIL.change_info
}

let empty_increment_data ?(server=false) file = {
let empty_increment_data ?(server=false) () = {
server;
old_data = None;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's interesting that the file need not be saved here...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file isn't saved in the incremental data, but with a separate variant into a separate file using Serialize, so this field was never read from. Actually #357 would probably change this and put the file (along with everything else) into a single record and not have separate files. Depending on the choices taken for #357, it need not be this increment data record that everything goes into, but maybe some outer wrapping record.

@@ -132,6 +132,7 @@ struct
in
fold f xs (empty ())

(* TODO: unused *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we might want to keep this

@@ -31,7 +31,7 @@ sig
val for_all: (key -> value -> bool) -> t -> bool
val map2: (value -> value -> value) -> t -> t -> t
val long_map2: (value -> value -> value) -> t -> t -> t
val merge : (key -> value option -> value option -> value option) -> t -> t -> t
val merge : (key -> value option -> value option -> value option) -> t -> t -> t (* TODO: unused, remove? *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think merge may also be worth keeping

@@ -105,7 +104,7 @@ struct
(* Map.map (List.map f) m *)
(* since hashes might change we need to rebuild: *)
apply_list (List.map f) m
let filter f m = apply_list (List.filter f) m (* TODO do something better? *)
let filter f m = apply_list (List.filter f) m (* TODO do something better? unused *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth keeping

@@ -48,6 +48,7 @@ struct
let elements m = Map.values m |> List.of_enum |> List.flatten

(* merge elements in x and y by f *)
(* TODO: unused, remove? *)
let merge op f x y =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also worth keeping in my opinion

@sim642
Copy link
Member Author

sim642 commented May 22, 2022

Since goblint/gobview#13 is now merged into Gobview, which now depends on changes from this PR, it would be good to now delay this too much since it blocks any other PRs to Gobview as they would only work on this branch of Goblint.

Regarding all the "worth keeping" comments, I'd suggest not removing those things now, but leaving the comments so it's immediately apparent if some weird code is used for anything or not.

@michael-schwarz
Copy link
Member

I'd suggest not removing those things now, but leaving the comments so it's immediately apparent if some weird code is used for anything or not.

Ok, sounds good to me!

@sim642 sim642 merged commit 38a0cba into master May 27, 2022
@sim642 sim642 deleted the reanalyze-dce branch May 27, 2022 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cleanup Refactoring, clean-up
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants