-- -fglagow-exts for kind signatures
module ZipDataflow
- ( zdfSolveFrom, zdfRewriteFrom
+ ( DebugNodes(), RewritingDepth(..), LastOutFacts(..)
+ , zdfSolveFrom, zdfRewriteFrom
, ForwardTransfers(..), BackwardTransfers(..)
, ForwardRewrites(..), BackwardRewrites(..)
, ForwardFixedPoint, BackwardFixedPoint
import CmmTx
import DFMonad
import MkZipCfg
+import StackSlot
import ZipCfg
import qualified ZipCfg as G
import Outputable
import Panic
import UniqFM
-import UniqSupply
import Control.Monad
import Maybe
-> transfers m l a -- Dataflow transfer functions
-> a -- Fact flowing in (at entry or exit)
-> Graph m l -- Graph to be analyzed
- -> fixedpt m l a () -- Answers
+ -> FuelMonad (fixedpt m l a ()) -- Answers
-- There are exactly two instances: forward and backward
instance DataflowSolverDirection ForwardTransfers ForwardFixedPoint
-> rewrites m l a graph
-> a -- fact flowing in (at entry or exit)
-> Graph m l
- -> UniqSupply
-> FuelMonad (fixedpt m l a (Graph m l))
data RewritingDepth = RewriteShallow | RewriteDeep
-> ForwardTransfers m l a -- dataflow transfer functions
-> a
-> Graph m l -- graph to be analyzed
- -> ForwardFixedPoint m l a () -- answers
+ -> FuelMonad (ForwardFixedPoint m l a ()) -- answers
solve_f env name lattice transfers in_fact g =
- runWithInfiniteFuel $ runDFM panic_us lattice $
- fwd_pure_anal name env transfers in_fact g
- where panic_us = panic "pure analysis pulled on a UniqSupply"
+ runDFM lattice $ fwd_pure_anal name env transfers in_fact g
rewrite_f_graph :: (DebugNodes m l, Outputable a)
=> RewritingDepth
-> ForwardRewrites m l a Graph
-> a -- fact flowing in (at entry or exit)
-> Graph m l
- -> UniqSupply
-> FuelMonad (ForwardFixedPoint m l a (Graph m l))
-rewrite_f_graph depth start_facts name lattice transfers rewrites in_fact g u =
- runDFM u lattice $
+rewrite_f_graph depth start_facts name lattice transfers rewrites in_fact g =
+ runDFM lattice $
do fuel <- fuelRemaining
(fp, fuel') <- forward_rew maybeRewriteWithFuel return depth start_facts name
transfers rewrites in_fact g fuel
-> ForwardRewrites m l a AGraph
-> a -- fact flowing in (at entry or exit)
-> Graph m l
- -> UniqSupply
-> FuelMonad (ForwardFixedPoint m l a (Graph m l))
-rewrite_f_agraph depth start_facts name lattice transfers rewrites in_fact g u =
- runDFM u lattice $
+rewrite_f_agraph depth start_facts name lattice transfers rewrites in_fact g =
+ runDFM lattice $
do fuel <- fuelRemaining
(fp, fuel') <- forward_rew maybeRewriteWithFuel areturn depth start_facts name
transfers rewrites in_fact g fuel
return fp
areturn :: AGraph m l -> DFM a (Graph m l)
-areturn g = liftUSM $ graphOfAGraph g
+areturn g = liftToDFM $ liftUniq $ graphOfAGraph g
{-
do { idfact <- getFact id
; (last_outs, fuel) <-
case check_maybe fuel $ fr_first rewrites idfact id of
- Nothing -> solve_tail idfact tail fuel
+ Nothing -> solve_tail (ft_first_out transfers idfact id) tail fuel
Just g ->
do g <- return_graph g
(a, fuel) <- subAnalysis' $
; a <- finish
; return (a, lgraphToGraph (LGraph eid rewritten), fuel)
}
- don't_rewrite finish in_fact g fuel =
- do { solve depth name emptyBlockEnv transfers rewrites in_fact g fuel
+ don't_rewrite facts finish in_fact g fuel =
+ do { solve depth name facts transfers rewrites in_fact g fuel
; a <- finish
; return (a, g, fuel)
}
- inner_rew :: DFM a b
- -> a -> Graph m l -> Fuel
- -> DFM a (b, Graph m l, Fuel)
- inner_rew = case depth of RewriteShallow -> don't_rewrite
- RewriteDeep -> rewrite emptyBlockEnv
+ inner_rew :: DFM a f -> a -> Graph m l -> Fuel -> DFM a (f, Graph m l, Fuel)
+ inner_rew f i g fu = getAllFacts >>= \facts -> inner_rew' facts f i g fu
+ where inner_rew' = case depth of RewriteShallow -> don't_rewrite
+ RewriteDeep -> rewrite
fixed_pt_and_fuel =
do { (a, g, fuel) <- rewrite xstart_facts getExitFact in_factx gx fuelx
; facts <- getAllFacts
do let h = ZFirst id
a <- getFact id
case check_maybe fuel $ fr_first rewrites a id of
- Nothing -> do { (rewritten, fuel) <- rew_tail h a t rewritten fuel
+ Nothing -> do { (rewritten, fuel) <-
+ rew_tail h (ft_first_out transfers a id)
+ t rewritten fuel
; rewrite_blocks bs rewritten fuel }
Just g -> do { markGraphRewritten
; g <- return_graph g
rew_tail h in' (G.ZLast l) rewritten fuel =
my_trace "Rewriting last node" (ppr l) $
case check_maybe fuel $ either_last rewrites in' l of
- Nothing -> -- can throw away facts because this is the rewriting phase
- return (insertBlock (zipht h (G.ZLast l)) rewritten, fuel)
+ Nothing -> do check_facts in' l
+ return (insertBlock (zipht h (G.ZLast l)) rewritten, fuel)
Just g -> do { markGraphRewritten
; g <- return_graph g
; ((), g, fuel) <- inner_rew (return ()) in' g fuel
}
either_last rewrites in' (LastExit) = fr_exit rewrites in'
either_last rewrites in' (LastOther l) = fr_last rewrites in' l
+ check_facts in' (LastOther l) =
+ let LastOutFacts last_outs = ft_last_outs transfers in' l
+ in mapM (uncurry checkFactMatch) last_outs
+ check_facts _ LastExit = return []
in fixed_pt_and_fuel
--lastOutFacts :: (DataflowAnalysis m, Monad (m f)) => m f (LastOutFacts f)
-> BackwardTransfers m l a -- dataflow transfer functions
-> a -- exit fact
-> Graph m l -- graph to be analyzed
- -> BackwardFixedPoint m l a () -- answers
+ -> FuelMonad (BackwardFixedPoint m l a ()) -- answers
solve_b env name lattice transfers exit_fact g =
- runWithInfiniteFuel $ runDFM panic_us lattice $
- bwd_pure_anal name env transfers g exit_fact
- where panic_us = panic "pure analysis pulled on a UniqSupply"
+ runDFM lattice $ bwd_pure_anal name env transfers g exit_fact
rewrite_b_graph :: (DebugNodes m l, Outputable a)
-> BackwardRewrites m l a Graph
-> a -- fact flowing in at exit
-> Graph m l
- -> UniqSupply
-> FuelMonad (BackwardFixedPoint m l a (Graph m l))
-rewrite_b_graph depth start_facts name lattice transfers rewrites exit_fact g u =
- runDFM u lattice $
+rewrite_b_graph depth start_facts name lattice transfers rewrites exit_fact g =
+ runDFM lattice $
do fuel <- fuelRemaining
(fp, fuel') <- backward_rew maybeRewriteWithFuel return depth start_facts name
transfers rewrites g exit_fact fuel
-> BackwardRewrites m l a AGraph
-> a -- fact flowing in at exit
-> Graph m l
- -> UniqSupply
-> FuelMonad (BackwardFixedPoint m l a (Graph m l))
-rewrite_b_agraph depth start_facts name lattice transfers rewrites exit_fact g u =
- runDFM u lattice $
+rewrite_b_agraph depth start_facts name lattice transfers rewrites exit_fact g =
+ runDFM lattice $
do fuel <- fuelRemaining
(fp, fuel') <- backward_rew maybeRewriteWithFuel areturn depth start_facts name
transfers rewrites g exit_fact fuel
set_head_fact (G.ZFirst id) a fuel =
case check_maybe fuel $ br_first rewrites a id of
- Nothing -> do { setFact id a; return fuel }
+ Nothing -> do { my_trace "set_head_fact" (ppr id) $
+ setFact id $ bt_first_in transfers a id
+ ; return fuel }
Just g -> do { (a, fuel) <- subsolve g a fuel
; setFact id a
; return fuel
let Graph entry blockenv = g
blocks = reverse $ G.postorder_dfs_from blockenv entry
in do { solve depth name start transfers rewrites g exit_fact fuel
+ ; env <- getAllFacts
+ ; my_trace "facts after solving" (ppr env) $ return ()
; eid <- freshBlockId "temporary entry id"
- ; (rewritten, fuel) <- rewrite_blocks blocks emptyBlockEnv fuel
- ; (rewritten, fuel) <- rewrite_blocks [Block eid entry] rewritten fuel
+ ; (rewritten, fuel) <- rewrite_blocks True blocks emptyBlockEnv fuel
+ -- We can't have the fact check fail on the bogus entry, which _may_ change
+ ; (rewritten, fuel) <- rewrite_blocks False [Block eid entry] rewritten fuel
; a <- getFact eid
; return (a, lgraphToGraph (LGraph eid rewritten), fuel)
}
- don't_rewrite g exit_fact fuel =
+ don't_rewrite facts g exit_fact fuel =
do { (fp, _) <-
- solve depth name emptyBlockEnv transfers rewrites g exit_fact fuel
+ solve depth name facts transfers rewrites g exit_fact fuel
; return (zdfFpOutputFact fp, g, fuel) }
- inner_rew = case depth of RewriteShallow -> don't_rewrite
- RewriteDeep -> rewrite emptyBlockEnv
inner_rew :: Graph m l -> a -> Fuel -> DFM a (a, Graph m l, Fuel)
+ inner_rew g a f = getAllFacts >>= \facts -> inner_rew' facts g a f
+ where inner_rew' = case depth of RewriteShallow -> don't_rewrite
+ RewriteDeep -> rewrite
fixed_pt_and_fuel =
do { (a, g, fuel) <- rewrite xstart_facts gx exit_fact fuelx
; facts <- getAllFacts
; let fp = FP facts a changed (panic "no decoration?!") g
; return (fp, fuel)
}
- rewrite_blocks :: [Block m l] -> (BlockEnv (Block m l))
+ rewrite_blocks :: Bool -> [Block m l] -> (BlockEnv (Block m l))
-> Fuel -> DFM a (BlockEnv (Block m l), Fuel)
- rewrite_blocks bs rewritten fuel =
+ rewrite_blocks check bs rewritten fuel =
do { env <- factsEnv
; let rew [] r f = return (r, f)
rew (b : bs) r f =
- do { (r, f) <- rewrite_block env b r f; rew bs r f }
+ do { (r, f) <- rewrite_block check env b r f; rew bs r f }
; rew bs rewritten fuel }
- rewrite_block env b rewritten fuel =
+ rewrite_block check env b rewritten fuel =
let (h, l) = G.goto_end (G.unzip b) in
case maybeRewriteWithFuel fuel $ either_last env l of
- Nothing -> propagate fuel h (last_in env l) (ZLast l) rewritten
+ Nothing -> propagate check fuel h (last_in env l) (ZLast l) rewritten
Just g ->
do { markGraphRewritten
; g <- return_graph g
; (a, g, fuel) <- inner_rew g exit_fact fuel
; let G.Graph t new_blocks = g
; let rewritten' = new_blocks `plusUFM` rewritten
- ; propagate fuel h a t rewritten' -- continue at entry of g
+ ; propagate check fuel h a t rewritten' -- continue at entry of g
}
either_last _env (LastExit) = br_exit rewrites
either_last env (LastOther l) = br_last rewrites env l
last_in _env (LastExit) = exit_fact
last_in env (LastOther l) = bt_last_in transfers env l
- propagate fuel (ZHead h m) a tail rewritten =
+ propagate check fuel (ZHead h m) a tail rewritten =
case maybeRewriteWithFuel fuel $ br_middle rewrites a m of
Nothing ->
- propagate fuel h (bt_middle_in transfers a m) (ZTail m tail) rewritten
+ propagate check fuel h (bt_middle_in transfers a m) (ZTail m tail) rewritten
Just g ->
do { markGraphRewritten
; g <- return_graph g
- ; my_trace "Rewrote middle node"
+ ; my_trace "With Facts" (ppr a) $ return ()
+ ; my_trace " Rewrote middle node"
(f4sep [ppr m, text "to", pprGraph g]) $
return ()
; (a, g, fuel) <- inner_rew g a fuel
; let Graph t newblocks = G.splice_tail g tail
- ; propagate fuel h a t (newblocks `plusUFM` rewritten) }
- propagate fuel (ZFirst id) a tail rewritten =
+ ; propagate check fuel h a t (newblocks `plusUFM` rewritten) }
+ propagate check fuel (ZFirst id) a tail rewritten =
case maybeRewriteWithFuel fuel $ br_first rewrites a id of
- Nothing -> do { checkFactMatch id a
+ Nothing -> do { if check then checkFactMatch id $ bt_first_in transfers a id
+ else return ()
; return (insertBlock (Block id tail) rewritten, fuel) }
Just g ->
do { markGraphRewritten
; my_trace "Rewrote first node"
(f4sep [ppr id <> colon, text "to", pprGraph g]) $ return ()
; (a, g, fuel) <- inner_rew g a fuel
- ; checkFactMatch id a
+ ; if check then checkFactMatch id a else return ()
; let Graph t newblocks = G.splice_tail g tail
; let r = insertBlock (Block id t) (newblocks `plusUFM` rewritten)
; return (r, fuel) }
my_nest depth sdoc = my_trace "" $ nest (3*depth) sdoc
ppIter depth n = my_nest depth (empty $$ text "*************** iteration" <+> pp_i n)
pp_i n = int n <+> text "of" <+> text name <+> text "on" <+> graphId
- unchanged depth = my_nest depth (text "facts are unchanged")
+ unchanged depth =
+ my_nest depth (text "facts for" <+> graphId <+> text "are unchanged")
+ graphId = case blocks of { Block id _ : _ -> ppr id ; [] -> text "<empty>" }
+ show_blocks = my_trace "Blocks:" (vcat (map pprBlock blocks))
+ pprBlock (Block id t) = nest 2 (pprFact (id, t))
pprFacts depth n env =
my_nest depth (text "facts for iteration" <+> pp_i n <+> text "are:" $$
(nest 2 $ vcat $ map pprFact $ ufmToList env))
pprFact (id, a) = hang (ppr id <> colon) 4 (ppr a)
- graphId = case blocks of { Block id _ : _ -> ppr id ; [] -> text "<empty>" }
- show_blocks = my_trace "Blocks:" (vcat (map pprBlock blocks))
- pprBlock (Block id t) = nest 2 (pprFact (id, t))
f4sep :: [SDoc] -> SDoc