Skip to content

replace recursion in letify_rec by loop [blocks: #4395] #4406

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

Merged
merged 3 commits into from
Mar 24, 2019

Conversation

kroening
Copy link
Member

@kroening kroening commented Mar 19, 2019

This avoids stack overflow in the case of expressions with many unique subexpressions. PR #4395 is an exemplar.

  • Each commit message has a non-empty body, explaining why the change was made.
  • n/a Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • n/a The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

This avoids stack overflow in the case of expressions with many unique
subexpressions.  PR #4395 is an exemplar.
if(map.find(current)->second.count < LET_COUNT)
return letify_rec(expr, let_order, map, i + 1);
auto m_it = map.find(current);
INVARIANT(m_it != map.end(), "expression should have been seen already");
Copy link
Contributor

Choose a reason for hiding this comment

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

This invariant should be documented. It looks like a precondition of letify.

@@ -46,11 +46,10 @@ class letifyt
seen_expressionst &map,
std::vector<exprt> &let_order);

static exprt letify_rec(
static exprt letify(
Copy link
Contributor

Choose a reason for hiding this comment

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

It's maybe a good occasion to document the function

Copy link
Collaborator

@tautschnig tautschnig left a comment

Choose a reason for hiding this comment

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

A request for documentation/aiding understanding below, but my bigger concern is the absence of newly viable tests. I believe we have a number of tests that are marked broken-smt-backend because of this stack overflow. If this fix does what it promises, then presumably it should be possible to enable those tests? I could be wrong, because there may be further problems down the line, but I'd at least like to see this discussed.

auto m_it = map.find(current);
INVARIANT(m_it != map.end(), "expression should have been seen already");

if(m_it->second.count >= LET_COUNT)
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be nice to document this magic number. At least I have absolutely no idea why "2" is the right value, or indeed what it even is good 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.

Two is really the only viable choice, and the symbolic name could well be replaced by 2.
"2" means that the expression is used more than once.
"3" (or higher) implies that the procedure becomes worst-case exponential.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe using "1" instead of "2" would make things a lot clearer? That would make clear we are talking about something we have seen more than once. The named constant here really obfuscates this code, because 1) the name does not convey useful information and 2) one has to look elsewhere to find the value.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Adding to my comment moments ago: I think this one should be if(m_it->second.count != 1).

Copy link
Collaborator

Choose a reason for hiding this comment

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

... and the other one in substitute_let is likely also best written as != 1, mirroring this one.

@kroening
Copy link
Member Author

@tautschnig The tests are in #4406!

@tautschnig
Copy link
Collaborator

@tautschnig The tests are in #4406!

(I suppose #4395, which solves that part of my request-for-changes. Will comment on the other one above.)

@tautschnig tautschnig changed the title replace recursion in letify_rec by loop replace recursion in letify_rec by loop [blocks: #4395] Mar 21, 2019
Copy link
Collaborator

@martin-cs martin-cs left a comment

Choose a reason for hiding this comment

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

Approve subject to other's comments. This is something we do need though.

@kroening kroening assigned tautschnig and unassigned kroening Mar 24, 2019
@kroening
Copy link
Member Author

Now with improved documentation

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: 7ed433f).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/105593807

@tautschnig tautschnig merged commit d5cf916 into develop Mar 24, 2019
@tautschnig tautschnig deleted the non-rec-letify branch March 24, 2019 22:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants