Skip to content

Commit 6747532

Browse files
authored
More inlining (#59)
* Fix scope of inlining * Prune self-referencing unreferenced bindings too * Remove unnecessary repeated inlining
1 parent 8c189e5 commit 6747532

File tree

5 files changed

+50
-19
lines changed

5 files changed

+50
-19
lines changed

src/Eucalypt/Core/Eliminate.hs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,15 @@ import Data.Maybe (fromMaybe)
1414
import Eucalypt.Core.Syn
1515
import qualified Data.Set as Set
1616

17+
1718
-- | Eliminate unused bindings from let expressions.
18-
--
19-
-- TODO: this but efficiently... at present this is just to cut down
20-
-- on noise while debugging and tidying up after inlining.
2119
prune :: CoreExp a -> CoreExp a
2220
prune (CoreLet smid bs b) =
2321
let prunedB = pruneScope b
2422
usedInB = foldMapBound Set.singleton prunedB
2523
prunedBs = map (second pruneScope) bs
26-
usedInBs = mconcat $ map (foldMapBound Set.singleton . snd) prunedBs
24+
setsBoundByBs = map (foldMapBound Set.singleton . snd) prunedBs
25+
usedInBs = mconcat $ removeSelfReferences setsBoundByBs
2726
used = usedInB <> usedInBs
2827
in CoreLet smid (blankUnused used prunedBs) prunedB
2928
where
@@ -44,6 +43,18 @@ prune e = e
4443

4544

4645

46+
-- | When considering bound variables in each let binding, we need to
47+
-- discard self-references (for instance in recursive functions) or we
48+
-- will never prune them
49+
removeSelfReferences :: [Set.Set Int] -> [Set.Set Int]
50+
removeSelfReferences boundSets = zipWith f boundSets [0..]
51+
where
52+
f s i = s Set.\\ Set.singleton i
53+
54+
55+
56+
-- | Remove let bindings that have been overwritten by CoreEliminated
57+
-- in the 'prune' step
4758
compress :: CoreExp a -> CoreExp a
4859
compress (CoreLet smid bs b) =
4960
let compressedB = compressScope b
@@ -52,7 +63,12 @@ compress (CoreLet smid bs b) =
5263
editedBindings =
5364
map (second $ remapBindings indexRemapping) $
5465
filter bindingIsNotEliminated compressedBs
55-
in CoreLet smid editedBindings $ remapBindings indexRemapping compressedB
66+
in
67+
if null editedBindings
68+
then
69+
instantiate (const CoreEliminated) compressedB
70+
else
71+
CoreLet smid editedBindings $ remapBindings indexRemapping compressedB
5672
where
5773
compressScope = toScope . compress . fromScope
5874
bindingIsNotEliminated = not . isEliminated . unscope . snd

src/Eucalypt/Core/Inliner.hs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,29 @@ tagInlinables e = e
115115

116116

117117

118+
transScope ::
119+
(Monad f1, Monad f2)
120+
=> (f2 (Var b1 a1) -> f1 (Var b2 a2))
121+
-> Scope b1 f2 a1
122+
-> Scope b2 f1 a2
123+
transScope f = toScope . f . fromScope
124+
125+
126+
118127
betaReduce :: CoreExp a -> CoreExp a
119-
betaReduce e@(CoreApply _ (CoreLambda _ True ns body) xs) =
120-
if length xs == length ns
121-
then
122-
instantiate (xs !!) body
123-
else
124-
e
128+
betaReduce (CoreApply smid l@(CoreLambda _ inlineFlag ns body) xs) =
129+
if inlineFlag && length xs == length ns
130+
then betaReduce $ instantiate (map betaReduce xs !!) body
131+
else CoreApply smid (betaReduce l) (map betaReduce xs)
132+
betaReduce (CoreApply smid f xs) =
133+
CoreApply smid (betaReduce f) (map betaReduce xs)
125134
betaReduce (CoreLambda smid i ns body) =
126-
CoreLambda smid i ns $ (Scope . betaReduce . unscope) body
127-
betaReduce (CoreLet smid bs b) =
128-
CoreLet smid bs' b'
135+
CoreLambda smid i ns $ transScope betaReduce body
136+
betaReduce (CoreLet smid bs b) = CoreLet smid bs' b'
129137
where
130138
b' = betaReduceScope b
131139
bs' = map (second betaReduceScope) bs
132-
betaReduceScope = Scope . betaReduce . unscope
140+
betaReduceScope = transScope betaReduce
133141
betaReduce (CoreMeta smid m e) = CoreMeta smid (betaReduce m) $ betaReduce e
134142
betaReduce (CoreLookup smid b e) = CoreLookup smid (betaReduce b) e
135143
betaReduce (CoreList smid xs) = CoreList smid (map betaReduce xs)

src/Eucalypt/Driver/Evaluator.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ evaluate opts = do
166166
(putStrLn (pprint prunedEvaluand) >> exitSuccess)
167167

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

172172
let finalEvaluand = compressedEvaluand

test/Eucalypt/Core/EliminateSpec.hs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ t4equiv =
6464
] $
6565
corelist [var "b0", var "b2"]
6666

67+
t5 :: CoreExpr
68+
t5 = letexp [("circle", lam ["x"] (app (var "circle") [var "x"]))] $ int 1
69+
70+
t5equiv :: CoreExpr
71+
t5equiv = int 1
6772

6873
spec :: Spec
6974
spec = do
@@ -76,6 +81,8 @@ spec = do
7681
it "renumbers correctly" $
7782
newBindIndexes [True, False, False, True, True, False] `shouldBe`
7883
[Just 0, Nothing, Nothing, Just 1, Just 2, Nothing]
79-
describe "compresses bindings once eliminated" $
84+
describe "compresses bindings once eliminated" $ do
8085
it "compresses correctly" $
81-
compress t4 `shouldBe` t4equiv
86+
compress t4 `shouldBe` t4equiv
87+
it "prunes self referential bindings with no further references" $
88+
(compress . prune) t5 `shouldBe` t5equiv

test/Eucalypt/Core/InlinerSpec.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,4 @@ spec =
8787
it "inlines transpositions" $
8888
inline singleTranspositionApplied `shouldBe` singleTransposedResult
8989
it "inlines sample B" $
90-
inline sampleB `shouldBe` sampleBEquiv
90+
inline sampleB `shouldBe` sampleBEquiv

0 commit comments

Comments
 (0)