Skip to content

More inlining #59

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
Oct 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/Eucalypt/Core/Eliminate.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ import Data.Maybe (fromMaybe)
import Eucalypt.Core.Syn
import qualified Data.Set as Set


-- | Eliminate unused bindings from let expressions.
--
-- TODO: this but efficiently... at present this is just to cut down
-- on noise while debugging and tidying up after inlining.
prune :: CoreExp a -> CoreExp a
prune (CoreLet smid bs b) =
let prunedB = pruneScope b
usedInB = foldMapBound Set.singleton prunedB
prunedBs = map (second pruneScope) bs
usedInBs = mconcat $ map (foldMapBound Set.singleton . snd) prunedBs
setsBoundByBs = map (foldMapBound Set.singleton . snd) prunedBs
usedInBs = mconcat $ removeSelfReferences setsBoundByBs
used = usedInB <> usedInBs
in CoreLet smid (blankUnused used prunedBs) prunedB
where
Expand All @@ -44,6 +43,18 @@ prune e = e



-- | When considering bound variables in each let binding, we need to
-- discard self-references (for instance in recursive functions) or we
-- will never prune them
removeSelfReferences :: [Set.Set Int] -> [Set.Set Int]
removeSelfReferences boundSets = zipWith f boundSets [0..]
where
f s i = s Set.\\ Set.singleton i



-- | Remove let bindings that have been overwritten by CoreEliminated
-- in the 'prune' step
compress :: CoreExp a -> CoreExp a
compress (CoreLet smid bs b) =
let compressedB = compressScope b
Expand All @@ -52,7 +63,12 @@ compress (CoreLet smid bs b) =
editedBindings =
map (second $ remapBindings indexRemapping) $
filter bindingIsNotEliminated compressedBs
in CoreLet smid editedBindings $ remapBindings indexRemapping compressedB
in
if null editedBindings
then
instantiate (const CoreEliminated) compressedB
else
CoreLet smid editedBindings $ remapBindings indexRemapping compressedB
where
compressScope = toScope . compress . fromScope
bindingIsNotEliminated = not . isEliminated . unscope . snd
Expand Down
28 changes: 18 additions & 10 deletions src/Eucalypt/Core/Inliner.hs
Original file line number Diff line number Diff line change
Expand Up @@ -115,21 +115,29 @@ tagInlinables e = e



transScope ::
(Monad f1, Monad f2)
=> (f2 (Var b1 a1) -> f1 (Var b2 a2))
-> Scope b1 f2 a1
-> Scope b2 f1 a2
transScope f = toScope . f . fromScope



betaReduce :: CoreExp a -> CoreExp a
betaReduce e@(CoreApply _ (CoreLambda _ True ns body) xs) =
if length xs == length ns
then
instantiate (xs !!) body
else
e
betaReduce (CoreApply smid l@(CoreLambda _ inlineFlag ns body) xs) =
if inlineFlag && length xs == length ns
then betaReduce $ instantiate (map betaReduce xs !!) body
else CoreApply smid (betaReduce l) (map betaReduce xs)
betaReduce (CoreApply smid f xs) =
CoreApply smid (betaReduce f) (map betaReduce xs)
betaReduce (CoreLambda smid i ns body) =
CoreLambda smid i ns $ (Scope . betaReduce . unscope) body
betaReduce (CoreLet smid bs b) =
CoreLet smid bs' b'
CoreLambda smid i ns $ transScope betaReduce body
betaReduce (CoreLet smid bs b) = CoreLet smid bs' b'
where
b' = betaReduceScope b
bs' = map (second betaReduceScope) bs
betaReduceScope = Scope . betaReduce . unscope
betaReduceScope = transScope betaReduce
betaReduce (CoreMeta smid m e) = CoreMeta smid (betaReduce m) $ betaReduce e
betaReduce (CoreLookup smid b e) = CoreLookup smid (betaReduce b) e
betaReduce (CoreList smid xs) = CoreList smid (map betaReduce xs)
Expand Down
2 changes: 1 addition & 1 deletion src/Eucalypt/Driver/Evaluator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ evaluate opts = do
(putStrLn (pprint prunedEvaluand) >> exitSuccess)

-- Now some inlining
let inlinedEvaluand = {-# SCC "Inlining" #-} prune $ inline $ inline $ inline $ inline $ inline prunedEvaluand
let inlinedEvaluand = {-# SCC "Inlining" #-} prune $ prune $ inline prunedEvaluand
let compressedEvaluand = {-# SCC "Compression" #-} compress inlinedEvaluand

let finalEvaluand = compressedEvaluand
Expand Down
11 changes: 9 additions & 2 deletions test/Eucalypt/Core/EliminateSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ t4equiv =
] $
corelist [var "b0", var "b2"]

t5 :: CoreExpr
t5 = letexp [("circle", lam ["x"] (app (var "circle") [var "x"]))] $ int 1

t5equiv :: CoreExpr
t5equiv = int 1

spec :: Spec
spec = do
Expand All @@ -76,6 +81,8 @@ spec = do
it "renumbers correctly" $
newBindIndexes [True, False, False, True, True, False] `shouldBe`
[Just 0, Nothing, Nothing, Just 1, Just 2, Nothing]
describe "compresses bindings once eliminated" $
describe "compresses bindings once eliminated" $ do
it "compresses correctly" $
compress t4 `shouldBe` t4equiv
compress t4 `shouldBe` t4equiv
it "prunes self referential bindings with no further references" $
(compress . prune) t5 `shouldBe` t5equiv
2 changes: 1 addition & 1 deletion test/Eucalypt/Core/InlinerSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,4 @@ spec =
it "inlines transpositions" $
inline singleTranspositionApplied `shouldBe` singleTransposedResult
it "inlines sample B" $
inline sampleB `shouldBe` sampleBEquiv
inline sampleB `shouldBe` sampleBEquiv