Skip to content

Commit c6904b9

Browse files
committed
Merge remote-tracking branch 'origin/master' into release
2 parents e623881 + 08f0cbd commit c6904b9

17 files changed

+194759
-218
lines changed

booster/library/Booster/Pattern/ApplyEquations.hs

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ runEquationT definition llvmApi smtSolver sCache known (EquationT m) = do
333333
, logger
334334
, prettyModifiers
335335
}
336+
-- NB the returned cache assumes the known predicates
336337
pure (res, endState.cache)
337338

338339
iterateEquations ::
@@ -423,19 +424,24 @@ llvmSimplify term = do
423424
----------------------------------------
424425
-- Interface functions
425426

426-
-- | Evaluate and simplify a term.
427+
{- | Evaluate and simplify a term.
428+
429+
The returned cache should only be reused with the same known predicates.
430+
-}
427431
evaluateTerm ::
428432
LoggerMIO io =>
429433
Direction ->
430434
KoreDefinition ->
431435
Maybe LLVM.API ->
432436
SMT.SMTContext ->
437+
SimplifierCache ->
433438
Set Predicate ->
434439
Term ->
435440
io (Either EquationFailure Term, SimplifierCache)
436-
evaluateTerm direction def llvmApi smtSolver knownPredicates =
437-
runEquationT def llvmApi smtSolver mempty knownPredicates
438-
. evaluateTerm' direction
441+
evaluateTerm direction def llvmApi smtSolver cache knownPredicates term =
442+
runEquationT def llvmApi smtSolver cache knownPredicates $
443+
withTermContext term $
444+
evaluateTerm' direction term
439445

440446
-- version for internal nested evaluation
441447
evaluateTerm' ::
@@ -447,6 +453,9 @@ evaluateTerm' direction = iterateEquations direction PreferFunctions
447453

448454
{- | Simplify a Pattern, processing its constraints independently.
449455
Returns either the first failure or the new pattern if no failure was encountered
456+
457+
The returned cache may only be reused if pat.constraints are known
458+
to remain true in the next usage context.
450459
-}
451460
evaluatePattern ::
452461
LoggerMIO io =>
@@ -510,35 +519,28 @@ evaluatePattern' pat@Pattern{term, ceilConditions} = withPatternContext pat $ do
510519
err -> throw err
511520

512521
-- evaluate the given predicate assuming all others
522+
-- This manipulates the known predicates so it should run without cache
513523
simplifyAssumedPredicate :: LoggerMIO io => Predicate -> EquationT io ()
514524
simplifyAssumedPredicate p = do
515-
allPs <- predicates <$> getState
516-
let otherPs = Set.delete p allPs
517-
eqState $ modify $ \s -> s{predicates = otherPs}
525+
prior <- getState
526+
let otherPs = Set.delete p (prior.predicates)
527+
eqState $ modify $ \s -> s{predicates = otherPs, cache = mempty}
518528
newP <- simplifyConstraint' True $ coerce p
519-
pushConstraints $ Set.singleton $ coerce newP
529+
eqState $ modify $ \s -> s{cache = prior.cache, predicates = otherPs <> Set.singleton (coerce newP)}
520530

521531
evaluateConstraints ::
522532
LoggerMIO io =>
523533
KoreDefinition ->
524534
Maybe LLVM.API ->
525535
SMT.SMTContext ->
526-
SimplifierCache ->
527536
Set Predicate ->
528-
io (Either EquationFailure (Set Predicate), SimplifierCache)
529-
evaluateConstraints def mLlvmLibrary smtSolver cache =
530-
runEquationT def mLlvmLibrary smtSolver cache mempty . evaluateConstraints'
531-
532-
evaluateConstraints' ::
533-
LoggerMIO io =>
534-
Set Predicate ->
535-
EquationT io (Set Predicate)
536-
evaluateConstraints' constraints = do
537-
pushConstraints constraints
538-
-- evaluate all existing constraints, once
539-
traverse_ simplifyAssumedPredicate . predicates =<< getState
540-
-- this may yield additional new constraints, left unevaluated
541-
predicates <$> getState
537+
io (Either EquationFailure (Set Predicate))
538+
evaluateConstraints def mLlvmLibrary smtSolver constraints =
539+
fmap fst $ runEquationT def mLlvmLibrary smtSolver mempty constraints $ do
540+
-- evaluate all existing constraints, once
541+
traverse_ simplifyAssumedPredicate . predicates =<< getState
542+
-- this may yield additional new constraints, left unevaluated
543+
predicates <$> getState
542544

543545
----------------------------------------
544546

@@ -1075,9 +1077,8 @@ applyEquation term rule =
10751077
(to decide whether or not a rule can apply, not to retain the
10761078
ensured conditions).
10771079
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.
1080+
Consistency of the returned SimplifierCache must be tracked by the
1081+
caller, the cache incorporates the given knownPredicates.
10811082
-}
10821083
simplifyConstraint ::
10831084
LoggerMIO io =>
@@ -1088,8 +1089,11 @@ simplifyConstraint ::
10881089
Set Predicate ->
10891090
Predicate ->
10901091
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
1092+
simplifyConstraint def mbApi smt cache knownPredicates =
1093+
runEquationT def mbApi smt cache knownPredicates
1094+
. (coerce <$>)
1095+
. simplifyConstraint' True
1096+
. coerce
10931097

10941098
simplifyConstraints ::
10951099
LoggerMIO io =>

booster/library/Booster/Pattern/Implies.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ runImplies def mLlvmLibrary mSMTOptions antecedent consequent =
150150
subst
151151
else -- FIXME This is incomplete because patL.constraints are not assumed in the check.
152152

153-
ApplyEquations.evaluateConstraints def mLlvmLibrary solver mempty filteredConsequentPreds >>= \case
154-
(Right newPreds, _) ->
153+
ApplyEquations.evaluateConstraints def mLlvmLibrary solver filteredConsequentPreds >>= \case
154+
Right newPreds ->
155155
if all (== Predicate TrueBool) newPreds
156156
then
157157
implies
@@ -161,7 +161,7 @@ runImplies def mLlvmLibrary mSMTOptions antecedent consequent =
161161
subst
162162
else -- here we conservatively abort (incomplete)
163163
pure . Left . RpcError.backendError $ RpcError.Aborted "unknown constraints"
164-
(Left other, _) ->
164+
Left other ->
165165
pure . Left . RpcError.backendError $ RpcError.Aborted (Text.pack . constructorName $ other)
166166

167167
case (internalised antecedent.term, internalised consequent.term) of

booster/library/Booster/Pattern/Rewrite.hs

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import Data.List.NonEmpty (NonEmpty (..), toList)
3838
import Data.List.NonEmpty qualified as NE
3939
import Data.Map qualified as Map
4040
import Data.Maybe (catMaybes, fromMaybe)
41-
import Data.Sequence (Seq, (|>))
41+
import Data.Sequence as Seq (Seq, fromList, (|>))
4242
import Data.Set qualified as Set
4343
import Data.Text as Text (Text, pack)
4444
import Numeric.Natural
@@ -55,9 +55,12 @@ import Booster.LLVM as LLVM (API)
5555
import Booster.Log
5656
import Booster.Pattern.ApplyEquations (
5757
CacheTag (Equations),
58+
Direction (..),
5859
EquationFailure (..),
5960
SimplifierCache (..),
61+
evaluateConstraints,
6062
evaluatePattern,
63+
evaluateTerm,
6164
simplifyConstraint,
6265
)
6366
import Booster.Pattern.Base
@@ -516,9 +519,16 @@ applyRule pat@Pattern{ceilConditions} rule =
516519
, rulePredicate = Just rulePredicate
517520
}
518521
where
519-
filterOutKnownConstraints :: Set.Set Predicate -> [Predicate] -> RewriteT io [Predicate]
520-
filterOutKnownConstraints priorKnowledge constraitns = do
521-
let (knownTrue, toCheck) = partition (`Set.member` priorKnowledge) constraitns
522+
-- These predicates are known (and do not change) during the
523+
-- entire rewrite step. The simplifier cache cannot be retained
524+
-- when additional predicates are used (see 'checkConstraint').
525+
knownPatternPredicates =
526+
pat.constraints <> (Set.fromList . asEquations $ pat.substitution)
527+
528+
filterOutKnownConstraints :: [Predicate] -> RewriteT io [Predicate]
529+
filterOutKnownConstraints constraints = do
530+
let (knownTrue, toCheck) =
531+
partition (`Set.member` knownPatternPredicates) constraints
522532
unless (null knownTrue) $
523533
getPrettyModifiers >>= \case
524534
ModifiersRep (_ :: FromModifiersT mods => Proxy mods) ->
@@ -537,14 +547,16 @@ applyRule pat@Pattern{ceilConditions} rule =
537547
Set.Set Predicate ->
538548
Predicate ->
539549
RewriteRuleAppT (RewriteT io) (Maybe a)
540-
checkConstraint onUnclear onBottom knownPredicates p = do
550+
checkConstraint onUnclear onBottom extraPredicates p = do
541551
RewriteConfig{definition, llvmApi, smtSolver} <- lift $ RewriteT ask
542-
RewriteState{cache = oldCache} <- lift . RewriteT . lift $ get
543-
(simplified, cache) <-
552+
RewriteState{cache} <- lift . RewriteT . lift $ get
553+
let knownPredicates = knownPatternPredicates <> extraPredicates
554+
(simplified, newCache) <-
544555
withContext CtxConstraint $
545-
simplifyConstraint definition llvmApi smtSolver oldCache knownPredicates p
546-
-- update cache
547-
lift $ updateRewriterCache cache
556+
simplifyConstraint definition llvmApi smtSolver cache knownPredicates p
557+
-- Important: only retain new cache if no extraPredicates were supplied!
558+
when (Set.null extraPredicates) $
559+
lift (updateRewriterCache newCache)
548560
case simplified of
549561
Right (Predicate FalseBool) -> onBottom
550562
Right (Predicate TrueBool) -> pure Nothing
@@ -559,14 +571,9 @@ applyRule pat@Pattern{ceilConditions} rule =
559571
-- apply substitution to rule requires
560572
let ruleRequires =
561573
concatMap (splitBoolPredicates . substituteInPredicate matchingSubst) rule.requires
562-
knownConstraints = pat.constraints <> (Set.fromList . asEquations $ pat.substitution)
563574

564575
-- filter out any predicates known to be _syntactically_ present in the known prior
565-
toCheck <-
566-
lift $
567-
filterOutKnownConstraints
568-
knownConstraints
569-
ruleRequires
576+
toCheck <- lift $ filterOutKnownConstraints ruleRequires
570577

571578
-- simplify the constraints (one by one in isolation). Stop if false, abort rewrite if indeterminate.
572579
unclearRequires <-
@@ -575,17 +582,13 @@ applyRule pat@Pattern{ceilConditions} rule =
575582
( checkConstraint
576583
id
577584
returnNotApplied
578-
knownConstraints
585+
mempty -- checkConstraint already considers knownConstraints
579586
)
580587
toCheck
581588

582589
-- unclear conditions may have been simplified and
583590
-- could now be syntactically present in the path constraints, filter again
584-
stillUnclear <-
585-
lift $
586-
filterOutKnownConstraints
587-
knownConstraints
588-
unclearRequires
591+
stillUnclear <- lift $ filterOutKnownConstraints unclearRequires
589592

590593
-- check unclear requires-clauses in the context of known constraints (priorKnowledge)
591594
solver <- lift $ RewriteT $ (.smtSolver) <$> ask
@@ -614,17 +617,14 @@ applyRule pat@Pattern{ceilConditions} rule =
614617
-- apply substitution to rule ensures
615618
let ruleEnsures =
616619
concatMap (splitBoolPredicates . coerce . substituteInTerm matchingSubst . coerce) rule.ensures
617-
knownConstraints =
618-
pat.constraints
619-
<> (Set.fromList . asEquations $ pat.substitution)
620-
<> Set.fromList unclearRequiresAfterSmt
621620
newConstraints <-
622621
catMaybes
623622
<$> mapM
624623
( checkConstraint
625624
id
626625
returnTrivial
627-
knownConstraints
626+
-- supply required path conditions as extra constraints
627+
(Set.fromList unclearRequiresAfterSmt)
628628
)
629629
ruleEnsures
630630

@@ -672,7 +672,7 @@ applyRule pat@Pattern{ceilConditions} rule =
672672
let ruleRequires =
673673
concatMap (splitBoolPredicates . coerce . substituteInTerm matchingSubst . coerce) rule.requires
674674
collapseAndBools . catMaybes
675-
<$> mapM (checkConstraint id returnNotApplied pat.constraints) ruleRequires
675+
<$> mapM (checkConstraint id returnNotApplied mempty) ruleRequires
676676

677677
ruleGroupPriority :: [RewriteRule a] -> Maybe Priority
678678
ruleGroupPriority = \case
@@ -1001,9 +1001,16 @@ performRewrite ::
10011001
Pattern ->
10021002
io (Natural, Seq (RewriteTrace ()), RewriteResult Pattern)
10031003
performRewrite rewriteConfig pat = do
1004-
(rr, RewriteStepsState{counter, traces}) <-
1005-
flip runStateT rewriteStart $ doSteps False pat
1006-
pure (counter, traces, rr)
1004+
simplifiedConstraints <-
1005+
withContext CtxSimplify $ evaluateConstraints definition llvmApi smtSolver pat.constraints
1006+
case simplifiedConstraints of
1007+
Right constraints ->
1008+
(flip runStateT rewriteStart $ doSteps False pat{constraints})
1009+
>>= \(rr, RewriteStepsState{counter, traces}) -> pure (counter, traces, rr)
1010+
Left r@(SideConditionFalse{}) ->
1011+
pure (0, fromList [RewriteSimplified (Just r)], error "Just return #Bottom here")
1012+
Left err ->
1013+
error (show err)
10071014
where
10081015
RewriteConfig
10091016
{ definition
@@ -1034,6 +1041,27 @@ performRewrite rewriteConfig pat = do
10341041

10351042
updateCache simplifierCache = modify $ \rss -> (rss :: RewriteStepsState){simplifierCache}
10361043

1044+
-- only simplifies the _term_ of the pattern
1045+
simplifyT :: Pattern -> StateT RewriteStepsState io (Maybe Pattern)
1046+
simplifyT p = withContext CtxSimplify $ do
1047+
cache <- simplifierCache <$> get
1048+
evaluateTerm BottomUp definition llvmApi smtSolver cache p.constraints p.term >>= \(res, newCache) -> do
1049+
updateCache newCache
1050+
case res of
1051+
Right newTerm -> do
1052+
emitRewriteTrace $ RewriteSimplified Nothing
1053+
pure $ Just p{term = newTerm}
1054+
Left r@SideConditionFalse{} -> do
1055+
emitRewriteTrace $ RewriteSimplified (Just r)
1056+
pure Nothing
1057+
Left r@UndefinedTerm{} -> do
1058+
emitRewriteTrace $ RewriteSimplified (Just r)
1059+
pure Nothing
1060+
Left other -> do
1061+
emitRewriteTrace $ RewriteSimplified (Just other)
1062+
pure $ Just p
1063+
1064+
-- simplifies term and constraints of the pattern
10371065
simplifyP :: Pattern -> StateT RewriteStepsState io (Maybe Pattern)
10381066
simplifyP p = withContext CtxSimplify $ do
10391067
st <- get
@@ -1228,7 +1256,7 @@ performRewrite rewriteConfig pat = do
12281256
else withSimplified pat' msg (pure . RewriteAborted failure)
12291257
where
12301258
withSimplified p msg cont = do
1231-
(withPatternContext p $ simplifyP p) >>= \case
1259+
(withPatternContext p $ simplifyT p) >>= \case
12321260
Nothing -> do
12331261
logMessage ("Rewrite stuck after simplification." :: Text)
12341262
pure $ RewriteStuck p

booster/test/rpc-integration/resources/3934-smt.kompile

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
kompile-from-double-definition.sh

0 commit comments

Comments
 (0)