-
Notifications
You must be signed in to change notification settings - Fork 44
Consider known predicates in Booster's simplifier API #3953
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
Conversation
KEVM performance:
|
evaluatePattern' pat@Pattern{term, constraints, ceilConditions} = withPatternContext pat $ do | ||
pushConstraints constraints | ||
evaluatePattern' pat@Pattern{term, ceilConditions} = withPatternContext pat $ do | ||
newTerm <- withTermContext term $ evaluateTerm' BottomUp term | ||
-- after evaluating the term, evaluate all (existing and | ||
-- newly-acquired) constraints, once |
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.
Maybe we should still start empty and push the path condition as the first step.
The code here returns all stored predicates
as constraints of the pattern (in line 424) which may or may not be correct depending on how the function was called. This is correct for the current use of the function but might not be correct in all future use cases.
Alternatively, how about we inline all of evaluatedPattern'
into evaluatePattern
(so no mistakes are possible).
@@ -331,7 +331,7 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu | |||
"Known true side conditions (won't check):" <+> pretty knownTrue | |||
|
|||
unclearRequires <- | |||
catMaybes <$> mapM (checkConstraint id notAppliedIfBottom) toCheck | |||
catMaybes <$> mapM (checkConstraint id notAppliedIfBottom (Set.fromList knownTrue)) toCheck |
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.
knownTrue
are just the requires clauses from the rule that syntactically occur in the path condition after substituting.
I think we want the entire path condition (pat.constraints
) instead here, and it comes from the subject, so no substitutions are required.
catMaybes <$> mapM (checkConstraint id notAppliedIfBottom (Set.fromList knownTrue)) toCheck | |
catMaybes <$> mapM (checkConstraint id notAppliedIfBottom prior) toCheck |
This means the argument can actually be fixed in the local checkConstraint
definition but we can also keep them as an argument for clarity.
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.
🤦
@@ -376,7 +376,7 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu | |||
Set.toList rule.ensures | |||
trivialIfBottom = RewriteRuleAppT $ pure Trivial | |||
newConstraints <- | |||
catMaybes <$> mapM (checkConstraint id trivialIfBottom) ruleEnsures | |||
catMaybes <$> mapM (checkConstraint id trivialIfBottom (Set.fromList knownTrue)) ruleEnsures |
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.
catMaybes <$> mapM (checkConstraint id trivialIfBottom (Set.fromList knownTrue)) ruleEnsures | |
catMaybes <$> mapM (checkConstraint id trivialIfBottom prior) ruleEnsures |
RewriteConfig{definition, llvmApi, smtSolver} <- lift $ RewriteT ask | ||
oldCache <- lift . RewriteT . lift $ get | ||
(simplified, cache) <- | ||
withContext CtxConstraint $ | ||
simplifyConstraint definition llvmApi smtSolver oldCache p | ||
simplifyConstraint definition llvmApi smtSolver oldCache knownPredicates p |
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.
As mentioned, one could just use pat.constraints
here...
simplifyConstraint definition llvmApi smtSolver oldCache knownPredicates p | |
simplifyConstraint definition llvmApi smtSolver oldCache pat.constraints p |
-- update cache | ||
lift . RewriteT . lift . modify $ const cache | ||
-- TODO should we keep the traces? Or only on success? |
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.
🚮
Maybe this did not have much impact because only the |
To my disappointment, there's still no difference:
|
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.
LGTM
Would be good to craft a simple integration test that demonstrates the utility...
I was trying something related (but not quite sufficient) recently, using code like this:
I tested that we are able to rewrite |
@jberthold I've added two integration tests that make sure we use the path condition when trying simplifications:
|
The change in #3953 introduced additional arguments to evaluation functions which allow callers to supply some "known true" predicates for the simplification and evaluation. However, doing so means that the cache will get populated with associations that might only be true if this known truth does not change. The case in point was a predicate being cached as "true" because of an earlier evaluation, and then _removed_ from the path condition. This change removes returning the cache from any inteface functions that take known truth arguments, and runs internal computations that modify the predicates with a fresh empty cache.
…ite (#4103) The change in #3953 introduced additional arguments to evaluation functions which allow callers to supply some "known true" predicates for the simplification and evaluation. However, doing so means that the cache will get populated with associations that might only be true if this known truth does not change. The case in point was a predicate being cached as "true" because of an earlier evaluation, and then _removed_ from the path condition (see added integration test). This change * refactors `checkConstraint` functions to fix the pattern constraints * skips the cache update if any additional "known truth" arguments were supplied to `checkConstraint`, and * runs internal computations that manipulate the predicates with a fresh empty cache. Furthermore, to avoid a significant performance penalty, we * simplify the pattern constraints once before starting to rewrite * only simplify the pattern _term_ during rewriting - the pattern constraints are already evaluated and stay the same - if a new constraint is added (by way of an `ensures`), this constraint is evaluated before adding it * At the end of the rewrite, we still simplify everything again (including the entire path condition). We are not using the SMT solver to detect a vacuous state at the start, though, could add that separately if desired. At the moment, the behaviour is largely the same as before (integration test expectations identical except for some evaluation in vacuous states). --------- Co-authored-by: github-actions <[email protected]>
The
runEquationT
function now takes aSet Predicate
, which are the "predicates known to be true" and are populated into the initialEquationState
. Their origin is intended to be the rewriting path condition.There's now a possibility to supply prior knowledge to the following API functions in
Booster.Pattern.Rewrite
:evaluateTerm
simplifyConstraint
There's also a light change in
evaluatePattern
, which is now passes the pattern's constraints as an argument torunEuationT
rather then usingpushConstraint
.