mirror of
https://github.com/grin-compiler/grin.git
synced 2024-09-11 07:25:28 +03:00
Fixed bug in dead code elimination
Now producer name introduction introduces new variables for fetch-binding left-hand sides. This change fixes a bug in DVE and DDE where these transformations did not handle fetch-bindings correctly.
This commit is contained in:
parent
8639a9acc4
commit
adaefab92f
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,3 +23,4 @@ output/
|
||||
*.ibc
|
||||
*.agdai
|
||||
.output
|
||||
.grin-output/
|
||||
|
@ -48,11 +48,34 @@ Unspecified location:
|
||||
- refactor dead code elimination so that is uses unspec loc for the types of #undefined
|
||||
|
||||
Producer name introduction:
|
||||
- PNI introduces new variables at each producer site
|
||||
- after PNI, the created-by analysis can be run on the resulting code
|
||||
- PNI also introduces new variables for bindings with a fetch left-hand side
|
||||
- this makes DVE and DDE simpler to implement (*)
|
||||
|
||||
- applying PNI multiple times can result in a lot of redundant code
|
||||
- we can eliminate this redundancy by applying Copy Progagation & Simple Dead Variable Elimination
|
||||
- but, we hae to exclude these two transformation from the optimizing pipeline
|
||||
- and run them manually each time a transformation changes the AST
|
||||
|
||||
(* DDE and DVE simplification):
|
||||
- DDE needs to remove dead fields from node patterns
|
||||
- for this, it needs liveness and producer information
|
||||
- for bindings of form: (CInt n) <- fetch p
|
||||
- DDE would have to look through the pointer p
|
||||
- derefernce it, and collect the information for the variable pointed at by it
|
||||
- using this information, it could remove the dead fields of the pattern
|
||||
- instead, we make sure that all fetch-bindings can only have variable patterns, so that producer information can flow more easily
|
||||
|
||||
- DVE needs to remove dead bindings and replace all occurences of deleted variables with #undefineds
|
||||
- fetch accepts only names as its first parameter, so we cannot replace them with #undefined
|
||||
(since #undefined is a value)
|
||||
- this is not a problem, since DVE can remove such bindings altogether IF the pattern is only a variable
|
||||
- however, if have a binding of form: (CInt n) <- fetch p
|
||||
- DVE would have to collect all names in the node pattern
|
||||
- and replace all those as well
|
||||
- instead, we make sure that all fetch-bindings can only have variable patterns, so that replacing dead variables is simpler
|
||||
|
||||
Avoid looping optimization:
|
||||
- use taboo sets of previous ASTs
|
||||
- let e' be the resulting AST after running all possible optimizations
|
||||
|
@ -54,6 +54,11 @@ deadVariableElimination :: LVAResult -> TypeEnv -> Exp -> Either String Exp
|
||||
deadVariableElimination lvaResult tyEnv
|
||||
= runTrf . (deleteDeadBindings lvaResult tyEnv >=> replaceDeletedVars tyEnv)
|
||||
|
||||
{- NOTE: Fetches do not have to be handled separately,
|
||||
since producer name introduction guarantees
|
||||
that all bindings with a fetch LHS will have a Var PAT
|
||||
(handled by the last case in alg).
|
||||
-}
|
||||
deleteDeadBindings :: LVAResult -> TypeEnv -> Exp -> Trf Exp
|
||||
deleteDeadBindings lvaResult tyEnv = cataM alg where
|
||||
alg :: ExpF Exp -> Trf Exp
|
||||
|
@ -37,6 +37,8 @@ producerNameIntroduction e = evalNameM e . cata alg $ e where
|
||||
SReturnF x@VarTagNode{} -> bindVal SReturn x
|
||||
SReturnF x@ConstTagNode{} -> bindVal SReturn x
|
||||
SReturnF x@Undefined{} -> bindVal SReturn x
|
||||
-- This is not a producer, but helps in the propagation of producer info (makes DDE simpler)
|
||||
SFetchF p -> bindFetch p
|
||||
expf -> fmap embed . sequence $ expf
|
||||
|
||||
-- binds a Val (usually a node) to a name, then puts it into some context
|
||||
@ -44,3 +46,9 @@ producerNameIntroduction e = evalNameM e . cata alg $ e where
|
||||
bindVal context val = do
|
||||
nodeVar <- fmap Var newNodeName
|
||||
return $ SBlock $ EBind (SReturn val) nodeVar (context nodeVar)
|
||||
|
||||
-- bind the lhs of a fetch-binding to a variable
|
||||
bindFetch :: Name -> NameM Exp
|
||||
bindFetch p = do
|
||||
fetchResult <- fmap Var newNodeName
|
||||
return $ SBlock $ EBind (SFetch p) fetchResult (SReturn fetchResult)
|
@ -33,6 +33,20 @@ spec = do
|
||||
|]
|
||||
(pni before) `sameAs` after
|
||||
|
||||
it "fetch" $ do
|
||||
let before = [prog|
|
||||
grinMain p =
|
||||
(CInt n) <- fetch p
|
||||
pure n
|
||||
|]
|
||||
let after = [prog|
|
||||
grinMain p =
|
||||
v.0 <- fetch p
|
||||
(CInt n) <- pure v.0
|
||||
pure n
|
||||
|]
|
||||
(pni before) `sameAs` after
|
||||
|
||||
it "update" $ do
|
||||
let before = [prog|
|
||||
grinMain =
|
||||
|
Loading…
Reference in New Issue
Block a user