[commit: ghc] master: Implement dead basic block elimination. (50f5c84)
Edward Z. Yang
ezyang at MIT.EDU
Fri May 6 03:11:39 CEST 2011
Fixed up in 246183c669a1e851ccc4
Edward
Excerpts from Simon Marlow's message of Thu May 05 08:57:10 -0400 2011:
> On 30/04/2011 15:18, Edward Z. Yang wrote:
> > Repository : ssh://darcs.haskell.org//srv/darcs/ghc
> >
> > On branch : master
> >
> > http://hackage.haskell.org/trac/ghc/changeset/50f5c8491bfcb6b891f772e2915443dbb5078e97
> >
> >> ---------------------------------------------------------------
> >
> > commit 50f5c8491bfcb6b891f772e2915443dbb5078e97
> > Author: Edward Z. Yang<ezyang at mit.edu>
> > Date: Tue Apr 5 17:38:15 2011 +0100
> >
> > Implement dead basic block elimination.
> >
> > Signed-off-by: Edward Z. Yang<ezyang at mit.edu>
> >
> >> ---------------------------------------------------------------
> >
> > compiler/cmm/CmmOpt.hs | 61 +++++++++++++++++++++++++++++++++++++
> > compiler/nativeGen/AsmCodeGen.lhs | 7 ++--
> > 2 files changed, 64 insertions(+), 4 deletions(-)
> >
> > diff --git a/compiler/cmm/CmmOpt.hs b/compiler/cmm/CmmOpt.hs
> > index c71f188..1c7e7e5 100644
> > --- a/compiler/cmm/CmmOpt.hs
> > +++ b/compiler/cmm/CmmOpt.hs
> > @@ -14,6 +14,7 @@
> > -----------------------------------------------------------------------------
> >
> > module CmmOpt (
> > + cmmEliminateDeadBlocks,
> > cmmMiniInline,
> > cmmMachOpFold,
> > cmmLoopifyForC,
> > @@ -30,10 +31,70 @@ import UniqFM
> > import Unique
> > import FastTypes
> > import Outputable
> > +import BlockId
> >
> > import Data.Bits
> > import Data.Word
> > import Data.Int
> > +import Data.Maybe
> > +
> > +import Compiler.Hoopl hiding (Unique)
> > +
> > +-- -----------------------------------------------------------------------------
> > +-- Eliminates dead blocks
> > +
> > +{-
> > +We repeatedly expand the set of reachable blocks until we hit a
> > +fixpoint, and then prune any blocks that were not in this set. This is
> > +actually a required optimization, as dead blocks can cause problems
> > +for invariants in the linear register allocator (and possibly other
> > +places.)
> > +-}
> > +
> > +-- Deep fold over statements could probably be abstracted out, but it
> > +-- might not be worth the effort since OldCmm is moribund
> > +cmmEliminateDeadBlocks :: [CmmBasicBlock] -> [CmmBasicBlock]
> > +cmmEliminateDeadBlocks [] = []
> > +cmmEliminateDeadBlocks blocks@(BasicBlock base_id _:_) =
> > + let -- Calculate what's reachable from what block
> > + -- We have to do a deep fold into CmmExpr because
> > + -- there may be a BlockId in the CmmBlock literal.
> > + reachableMap = foldl f emptyBlockMap blocks
> > + where f m (BasicBlock block_id stmts) = mapInsert block_id (reachableFrom stmts) m
> > + reachableFrom stmts = foldl stmt emptyBlockSet stmts
> > + where
> > + stmt m CmmNop = m
> > + stmt m (CmmComment _) = m
> > + stmt m (CmmAssign _ e) = expr m e
> > + stmt m (CmmStore e1 e2) = expr (expr m e1) e2
> > + stmt m (CmmCall c _ as _ _) = f (actuals m as) c
> > + where f m (CmmCallee e _) = expr m e
> > + f m (CmmPrim _) = m
> > + stmt m (CmmBranch b) = setInsert b m
> > + stmt m (CmmCondBranch e b) = setInsert b (expr m e)
> > + stmt m (CmmSwitch e bs) = foldl (flip setInsert) (expr m e) (catMaybes bs)
> > + stmt m (CmmJump e as) = expr (actuals m as) e
> > + stmt m (CmmReturn as) = actuals m as
> > + actuals m as = foldl (\m h -> expr m (hintlessCmm h)) m as
> > + expr m (CmmLit l) = lit m l
> > + expr m (CmmLoad e _) = expr m e
> > + expr m (CmmReg _) = m
> > + expr m (CmmMachOp _ es) = foldl expr m es
> > + expr m (CmmStackSlot _ _) = m
> > + expr m (CmmRegOff _ _) = m
> > + lit m (CmmBlock b) = setInsert b m
> > + lit m _ = m
> > + -- Expand reachable set until you hit fixpoint
> > + initReachable = setSingleton base_id :: BlockSet
> > + expandReachable old_set new_set =
> > + if setSize new_set> setSize old_set
> > + then expandReachable new_set $ setFold
> > + (\x s -> maybe setEmpty id (mapLookup x reachableMap) `setUnion` s)
> > + new_set
> > + (setDifference new_set old_set)
> > + else new_set -- fixpoint achieved
> > + reachable = expandReachable setEmpty initReachable
> > + in filter (\(BasicBlock block_id _) -> setMember block_id reachable) blocks
>
> I think a better way to do a closure operation like this is with two
> sets: a set of objects "Done" that you have already processed, and a set
> of objects "ToDo" still to be processed. For each block B in ToDo: add
> the block to Done, and add any new references from B to ToDo (if they
> aren't already in Done). When ToDo is empty, you're done. ToDo can be
> a list even, it doesn't need to be a set.
>
> This way you don't look at references from the same block multiple
> times, you don't need to precalculate reachableMap, and you don't
> repeatedly compute the size of sets.
>
> Cheers,
> Simon
More information about the Cvs-ghc
mailing list