Skip to content

Commit ce5e392

Browse files
jbertholdgithub-actions
andauthored
EXPERIMENTS: shorten cache lookup chains, invalidate cache on new ensures (#3998)
### Fixes #3982 To avoid situations where the cache contains successive mappings `e -> e1 -> e2 -> e3 ... -> e_n` (a "lookup chain"), the following modifications are made: 1. When inserting `e -> e1`, first check whether `e1 -> e2` is in the cache, and insert `e -> e2` instead in this case. 2. When looking up `e` and a binding `e -> e1` is found, check whether a binding `e1 -> e2` is also in the cache. In this case, update the binding for `e` to `e -> e2` and return `e2`. This will eventually lead to removing all lookup chains that may exist in a cache (for "interesting" cached values that are being looked up), without the risk of a loop. Assume the following: * the cache was initially empty; * insertions and lookups are performed as described above; * the cache contains a lookup chain `e -> e1 -> e2`. If `e1 -> e2` was inserted first, insertion of `e -> e1` would have resulted in storing `e -> e2`. Therefore, `e -> e1` must have been inserted first. A subsequent lookup of `e` will update the cache to contain `e -> e2`. Insertion of `e -> e1`, then `e1 -> e2`, then `e2 -> e3`, will create the lookup chain `e -> e1 -> e2 -> e3`. - A lookup of `e` would leave the cache containing two shorter chains `e -> e2 -> e3` and `e1 -> e2 -> e3`. - A lookup of `e1` would also leave the cache containing one shorter chain `e -> e1 -> e3`, and `e2 -> e3`. Every lookup potentially shortens a lookup chain, possibly to several chains. ### Fixes #3993 When a new path condition is added (from an `ensures` clause), the `Equations` cache is purged. While some entries may still be valid, * all entries `t -> t` (no simplification possible) may be invalid because new equations might be applicable with the new path condition * even entries `t -> t'` with `t /= t'` may be invalid because while they already memoise some applicable simplifications, they may store sub-terms that could now be evaluated or simplified further (new equations may apply) --------- Co-authored-by: github-actions <[email protected]>
1 parent e4bd3aa commit ce5e392

File tree

2 files changed

+56
-15
lines changed

2 files changed

+56
-15
lines changed

booster/library/Booster/Pattern/ApplyEquations.hs

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ module Booster.Pattern.ApplyEquations (
2222
handleSimplificationEquation,
2323
simplifyConstraint,
2424
simplifyConstraints,
25-
SimplifierCache,
25+
SimplifierCache (..),
26+
CacheTag (..),
2627
evaluateConstraints,
2728
) where
2829

@@ -234,19 +235,46 @@ popRecursion = do
234235
throw $ InternalError "Trying to pop an empty recursion stack"
235236
else eqState $ put s{recursionStack = tail s.recursionStack}
236237

237-
toCache :: Monad io => CacheTag -> Term -> Term -> EquationT io ()
238-
toCache tag orig result = eqState . modify $ \s -> s{cache = updateCache tag s.cache}
239-
where
240-
insertInto = Map.insert orig result
241-
updateCache LLVM cache = cache{llvm = insertInto cache.llvm}
242-
updateCache Equations cache = cache{equations = insertInto cache.equations}
243-
244-
fromCache :: Monad io => CacheTag -> Term -> EquationT io (Maybe Term)
245-
fromCache tag t = eqState $ Map.lookup t <$> gets (select tag . (.cache))
246-
where
247-
select :: CacheTag -> SimplifierCache -> Map Term Term
248-
select LLVM = (.llvm)
249-
select Equations = (.equations)
238+
toCache :: LoggerMIO io => CacheTag -> Term -> Term -> EquationT io ()
239+
toCache LLVM orig result = eqState . modify $
240+
\s -> s{cache = s.cache{llvm = Map.insert orig result s.cache.llvm}}
241+
toCache Equations orig result = eqState $ do
242+
s <- get
243+
-- Check before inserting a new result to avoid creating a
244+
-- lookup chain e -> result -> olderResult.
245+
newEqCache <- case Map.lookup result s.cache.equations of
246+
Nothing ->
247+
pure $ Map.insert orig result s.cache.equations
248+
Just furtherResult -> do
249+
when (result /= furtherResult) $ do
250+
withContextFor Equations . logMessage $
251+
"toCache shortening a chain "
252+
<> showHashHex (getAttributes orig).hash
253+
<> "->"
254+
<> showHashHex (getAttributes furtherResult).hash
255+
pure $ Map.insert orig furtherResult s.cache.equations
256+
put s{cache = s.cache{equations = newEqCache}}
257+
258+
fromCache :: LoggerMIO io => CacheTag -> Term -> EquationT io (Maybe Term)
259+
fromCache tag t = eqState $ do
260+
s <- get
261+
case tag of
262+
LLVM -> pure $ Map.lookup t s.cache.llvm
263+
Equations -> do
264+
case Map.lookup t s.cache.equations of
265+
Nothing -> pure Nothing
266+
Just t' -> case Map.lookup t' s.cache.equations of
267+
Nothing -> pure $ Just t'
268+
Just t'' -> do
269+
when (t'' /= t') $ do
270+
withContextFor Equations . logMessage $
271+
"fromCache shortening a chain "
272+
<> showHashHex (getAttributes t).hash
273+
<> "->"
274+
<> showHashHex (getAttributes t'').hash
275+
let newEqCache = Map.insert t t'' s.cache.equations
276+
put s{cache = s.cache{equations = newEqCache}}
277+
pure $ Just t''
250278

251279
logWarn :: LoggerMIO m => Text -> m ()
252280
logWarn msg =
@@ -899,6 +927,12 @@ applyEquation term rule =
899927
Left other ->
900928
liftIO $ Exception.throw other
901929
lift $ pushConstraints $ Set.fromList ensuredConditions
930+
-- when a new path condition is added, invalidate the equation cache
931+
unless (null ensuredConditions) $ do
932+
withContextFor Equations . logMessage $
933+
("New ensured condition from evaluation, invalidating cache" :: Text)
934+
lift . eqState . modify $
935+
\s -> s{cache = s.cache{equations = mempty}}
902936
pure $ substituteInTerm subst rule.rhs
903937
where
904938
filterOutKnownConstraints :: Set Predicate -> [Predicate] -> EquationT io [Predicate]

booster/library/Booster/Pattern/Rewrite.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ import Booster.Definition.Base
5050
import Booster.LLVM as LLVM (API)
5151
import Booster.Log
5252
import Booster.Pattern.ApplyEquations (
53+
CacheTag (Equations),
5354
EquationFailure (..),
54-
SimplifierCache,
55+
SimplifierCache (..),
5556
evaluatePattern,
5657
simplifyConstraint,
5758
)
@@ -401,6 +402,12 @@ applyRule pat@Pattern{ceilConditions} rule =
401402
Left other ->
402403
liftIO $ Exception.throw other
403404

405+
-- if a new constraint is going to be added, the equation cache is invalid
406+
unless (null newConstraints) $ do
407+
withContextFor Equations . logMessage $
408+
("New path condition ensured, invalidating cache" :: Text)
409+
lift . RewriteT . lift . modify $ \s -> s{equations = mempty}
410+
404411
-- existential variables may be present in rule.rhs and rule.ensures,
405412
-- need to strip prefixes and freshen their names with respect to variables already
406413
-- present in the input pattern and in the unification substitution

0 commit comments

Comments
 (0)