-
Notifications
You must be signed in to change notification settings - Fork 274
Move instead of merge symex L2 renaming map when possible #4199
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
Changes from all commits
9304733
131373b
2baf020
e12ae53
939a169
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,13 +31,15 @@ static void get_l1_name(exprt &expr); | |
|
||
goto_symex_statet::goto_symex_statet( | ||
const symex_targett::sourcet &_source, | ||
guard_managert &manager) | ||
guard_managert &manager, | ||
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider) | ||
: goto_statet(manager), | ||
source(_source), | ||
guard_manager(manager), | ||
symex_target(nullptr), | ||
record_events(true), | ||
dirty() | ||
dirty(), | ||
fresh_l2_name_provider(fresh_l2_name_provider) | ||
{ | ||
threads.emplace_back(guard_manager); | ||
call_stack().new_frame(source); | ||
|
@@ -213,9 +215,7 @@ void goto_symex_statet::assignment( | |
#endif | ||
|
||
// do the l2 renaming | ||
const auto level2_it = | ||
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0)).first; | ||
symex_renaming_levelt::increase_counter(level2_it); | ||
increase_generation(l1_identifier, lhs); | ||
lhs = set_indices<L2>(std::move(lhs), ns).get(); | ||
|
||
// in case we happen to be multi-threaded, record the memory access | ||
|
@@ -440,10 +440,7 @@ bool goto_symex_statet::l2_thread_read_encoding( | |
|
||
if(a_s_read.second.empty()) | ||
{ | ||
auto level2_it = | ||
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0)) | ||
.first; | ||
symex_renaming_levelt::increase_counter(level2_it); | ||
increase_generation(l1_identifier, ssa_l1); | ||
a_s_read.first=level2.current_count(l1_identifier); | ||
} | ||
const renamedt<ssa_exprt, L2> l2_false_case = set_indices<L2>(ssa_l1, ns); | ||
|
@@ -477,10 +474,6 @@ bool goto_symex_statet::l2_thread_read_encoding( | |
return true; | ||
} | ||
|
||
const auto level2_it = | ||
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0)) | ||
.first; | ||
|
||
// No event and no fresh index, but avoid constant propagation | ||
if(!record_events) | ||
{ | ||
|
@@ -489,7 +482,7 @@ bool goto_symex_statet::l2_thread_read_encoding( | |
} | ||
|
||
// produce a fresh L2 name | ||
symex_renaming_levelt::increase_counter(level2_it); | ||
increase_generation(l1_identifier, ssa_l1); | ||
expr = set_indices<L2>(std::move(ssa_l1), ns).get(); | ||
|
||
// and record that | ||
|
@@ -500,6 +493,35 @@ bool goto_symex_statet::l2_thread_read_encoding( | |
return true; | ||
} | ||
|
||
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the | ||
/// latest generation on this path. | ||
/// \return the newly allocated generation number | ||
std::size_t goto_symex_statet::increase_generation( | ||
const irep_idt l1_identifier, | ||
const ssa_exprt &lhs) | ||
{ | ||
auto current_emplace_res = | ||
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like this method belongs to symex_level2t. :leaves: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was considered but not done because we didn't want |
||
|
||
current_emplace_res.first->second.second = | ||
fresh_l2_name_provider(l1_identifier); | ||
|
||
return current_emplace_res.first->second.second; | ||
} | ||
|
||
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the | ||
/// latest generation on this path. Does nothing if there isn't an expression | ||
/// keyed by the l1 identifier. | ||
void goto_symex_statet::increase_generation_if_exists(const irep_idt identifier) | ||
{ | ||
// If we can't find the name in the local scope, this is a no-op. | ||
auto current_names_iter = level2.current_names.find(identifier); | ||
if(current_names_iter == level2.current_names.end()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :leaves: |
||
return; | ||
|
||
current_names_iter->second.second = fresh_l2_name_provider(identifier); | ||
} | ||
|
||
/// thread encoding | ||
bool goto_symex_statet::l2_thread_write_encoding( | ||
const ssa_exprt &expr, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,7 +42,10 @@ Author: Daniel Kroening, [email protected] | |
class goto_symex_statet final : public goto_statet | ||
{ | ||
public: | ||
goto_symex_statet(const symex_targett::sourcet &, guard_managert &manager); | ||
goto_symex_statet( | ||
const symex_targett::sourcet &, | ||
guard_managert &manager, | ||
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider); | ||
~goto_symex_statet(); | ||
|
||
/// \brief Fake "copy constructor" that initializes the `symex_target` member | ||
|
@@ -202,7 +205,24 @@ class goto_symex_statet final : public goto_statet | |
unsigned total_vccs = 0; | ||
unsigned remaining_vccs = 0; | ||
|
||
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the | ||
// latest generation on this path. | ||
std::size_t | ||
increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs); | ||
|
||
/// Increases the generation of the L1 identifier. Does nothing if there | ||
/// isn't an expression keyed by it. | ||
void increase_generation_if_exists(const irep_idt identifier); | ||
|
||
/// Drops an L1 name from the local L2 map | ||
void drop_l1_name(symex_renaming_levelt::current_namest::const_iterator it) | ||
{ | ||
level2.current_names.erase(it); | ||
} | ||
|
||
private: | ||
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could maybe be part of |
||
|
||
/// \brief Dangerous, do not use | ||
/// | ||
/// Copying a state S1 to S2 risks S2 pointing to a deallocated | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -98,15 +98,16 @@ class path_storaget | |
/// error-handling paths. | ||
std::unordered_map<irep_idt, local_safe_pointerst> safe_pointers; | ||
|
||
/// Provide a unique index for a given \p id, starting from \p minimum_index. | ||
std::size_t get_unique_index(const irep_idt &id, std::size_t minimum_index) | ||
/// Provide a unique L1 index for a given \p id, starting from | ||
/// \p minimum_index. | ||
std::size_t get_unique_l1_index(const irep_idt &id, std::size_t minimum_index) | ||
{ | ||
auto entry = unique_index_map.emplace(id, minimum_index); | ||
|
||
if(!entry.second) | ||
entry.first->second = std::max(entry.first->second + 1, minimum_index); | ||
return get_unique_index(l1_indices, id, minimum_index); | ||
} | ||
|
||
return entry.first->second; | ||
std::size_t get_unique_l2_index(const irep_idt &id) | ||
{ | ||
return get_unique_index(l2_indices, id, 1); | ||
} | ||
|
||
private: | ||
|
@@ -115,8 +116,24 @@ class path_storaget | |
virtual patht &private_peek() = 0; | ||
virtual void private_pop() = 0; | ||
|
||
typedef std::unordered_map<irep_idt, std::size_t> name_index_mapt; | ||
|
||
std::size_t get_unique_index( | ||
name_index_mapt &unique_index_map, | ||
const irep_idt &id, | ||
std::size_t minimum_index) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. definition should go to the cpp file. Also I would suggest declaring a class for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems short and hot enough to be worth inlining to me |
||
auto entry = unique_index_map.emplace(id, minimum_index); | ||
|
||
if(!entry.second) | ||
entry.first->second = std::max(entry.first->second + 1, minimum_index); | ||
|
||
return entry.first->second; | ||
} | ||
|
||
/// Storage used by \ref get_unique_index. | ||
std::unordered_map<irep_idt, std::size_t> unique_index_map; | ||
name_index_mapt l1_indices; | ||
name_index_mapt l2_indices; | ||
}; | ||
|
||
/// \brief LIFO save queue: depth-first search, try to finish paths | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about making current_names private in symex levels instead? (or both)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both sounds reasonable to me, but suggest doing further refactoring elsewhere, this PR has already dragged on a fair while