@@ -210,8 +210,18 @@ countSteps = length . (.termStack) <$> getState
210
210
pushTerm :: Monad io => Term -> EquationT io ()
211
211
pushTerm t = eqState . modify $ \ s -> s{termStack = t :<| s. termStack}
212
212
213
+ -- pushing new constraints means the cache is stale
213
214
pushConstraints :: Monad io => Set Predicate -> EquationT io ()
214
- pushConstraints ps = eqState . modify $ \ s -> s{predicates = s. predicates <> ps}
215
+ pushConstraints ps = eqState . modify $ \ s -> s{predicates = s. predicates <> ps, cache = mempty }
216
+
217
+ -- run an evaluation with a local empty cache (discarded afterwards)
218
+ withoutCache :: Monad io => EquationT io a -> EquationT io a
219
+ withoutCache action = do
220
+ prior <- getState
221
+ eqState $ put prior{cache = mempty }
222
+ a <- action
223
+ eqState $ modify $ \ s -> s{cache = prior. cache}
224
+ pure a
215
225
216
226
setChanged , resetChanged :: Monad io => EquationT io ()
217
227
setChanged = eqState . modify $ \ s -> s{changed = True }
@@ -333,6 +343,7 @@ runEquationT definition llvmApi smtSolver sCache known (EquationT m) = do
333
343
, logger
334
344
, prettyModifiers
335
345
}
346
+ -- NB the returned cache assumes the known predicates
336
347
pure (res, endState. cache)
337
348
338
349
iterateEquations ::
@@ -432,9 +443,10 @@ evaluateTerm ::
432
443
SMT. SMTContext ->
433
444
Set Predicate ->
434
445
Term ->
435
- io (Either EquationFailure Term , SimplifierCache )
446
+ io (Either EquationFailure Term )
436
447
evaluateTerm direction def llvmApi smtSolver knownPredicates =
437
- runEquationT def llvmApi smtSolver mempty knownPredicates
448
+ fmap fst
449
+ . runEquationT def llvmApi smtSolver mempty knownPredicates
438
450
. evaluateTerm' direction
439
451
440
452
-- version for internal nested evaluation
@@ -447,6 +459,9 @@ evaluateTerm' direction = iterateEquations direction PreferFunctions
447
459
448
460
{- | Simplify a Pattern, processing its constraints independently.
449
461
Returns either the first failure or the new pattern if no failure was encountered
462
+
463
+ The returned cache may only be reused if pat.constraints are known
464
+ to remain true in the next usage context.
450
465
-}
451
466
evaluatePattern ::
452
467
LoggerMIO io =>
@@ -476,7 +491,8 @@ evaluatePattern' pat@Pattern{term, ceilConditions} = withPatternContext pat $ do
476
491
newTerm <- withTermContext term $ evaluateTerm' BottomUp term `catch_` keepTopLevelResults
477
492
-- after evaluating the term, evaluate all (existing and
478
493
-- newly-acquired) constraints, once
479
- traverse_ simplifyAssumedPredicate . predicates =<< getState
494
+ -- this runs with a local empty cache because it manipulates the known constraints
495
+ withoutCache (traverse_ simplifyAssumedPredicate . predicates =<< getState)
480
496
-- this may yield additional new constraints, left unevaluated
481
497
evaluatedConstraints <- predicates <$> getState
482
498
-- break-up introduced symbolic _andBool_, filter-out trivial truth, de-duplicate
@@ -510,11 +526,12 @@ evaluatePattern' pat@Pattern{term, ceilConditions} = withPatternContext pat $ do
510
526
err -> throw err
511
527
512
528
-- evaluate the given predicate assuming all others
529
+ -- this manipulates the known predicates so it also resets the simplifier cache
513
530
simplifyAssumedPredicate :: LoggerMIO io => Predicate -> EquationT io ()
514
531
simplifyAssumedPredicate p = do
515
532
allPs <- predicates <$> getState
516
533
let otherPs = Set. delete p allPs
517
- eqState $ modify $ \ s -> s{predicates = otherPs}
534
+ eqState $ modify $ \ s -> s{predicates = otherPs, cache = mempty }
518
535
newP <- simplifyConstraint' True $ coerce p
519
536
pushConstraints $ Set. singleton $ coerce newP
520
537
@@ -525,16 +542,16 @@ evaluateConstraints ::
525
542
SMT. SMTContext ->
526
543
SimplifierCache ->
527
544
Set Predicate ->
528
- io (Either EquationFailure (Set Predicate ), SimplifierCache )
545
+ io (Either EquationFailure (Set Predicate ))
529
546
evaluateConstraints def mLlvmLibrary smtSolver cache =
530
- runEquationT def mLlvmLibrary smtSolver cache mempty . evaluateConstraints'
547
+ fmap fst . runEquationT def mLlvmLibrary smtSolver cache mempty . evaluateConstraints'
531
548
532
549
evaluateConstraints' ::
533
550
LoggerMIO io =>
534
551
Set Predicate ->
535
552
EquationT io (Set Predicate )
536
- evaluateConstraints' constraints = do
537
- pushConstraints constraints
553
+ evaluateConstraints' constraints = withoutCache $ do
554
+ pushConstraints constraints -- invalidates the cache
538
555
-- evaluate all existing constraints, once
539
556
traverse_ simplifyAssumedPredicate . predicates =<< getState
540
557
-- this may yield additional new constraints, left unevaluated
@@ -1074,10 +1091,6 @@ applyEquation term rule =
1074
1091
This is used during rewriting to simplify side conditions of rules
1075
1092
(to decide whether or not a rule can apply, not to retain the
1076
1093
ensured conditions).
1077
-
1078
- If and as soon as this function is used inside equation
1079
- application, it needs to run within the same 'EquationT' context
1080
- so we can detect simplification loops and avoid monad nesting.
1081
1094
-}
1082
1095
simplifyConstraint ::
1083
1096
LoggerMIO io =>
@@ -1087,9 +1100,13 @@ simplifyConstraint ::
1087
1100
SimplifierCache ->
1088
1101
Set Predicate ->
1089
1102
Predicate ->
1090
- io (Either EquationFailure Predicate , SimplifierCache )
1091
- simplifyConstraint def mbApi smt cache knownPredicates (Predicate p) = do
1092
- runEquationT def mbApi smt cache knownPredicates $ (coerce <$> ) . simplifyConstraint' True $ p
1103
+ io (Either EquationFailure Predicate )
1104
+ simplifyConstraint def mbApi smt cache knownPredicates =
1105
+ fmap fst
1106
+ . runEquationT def mbApi smt cache knownPredicates
1107
+ . (coerce <$> )
1108
+ . simplifyConstraint' True
1109
+ . coerce
1093
1110
1094
1111
simplifyConstraints ::
1095
1112
LoggerMIO io =>
0 commit comments