5 #include "HsVersions.h"
14 -- Determine the proc points for a set of basic blocks.
16 -- A proc point is any basic block that must start a new function.
17 -- The entry block of the original function is a proc point.
18 -- The continuation of a function call is also a proc point.
19 -- The third kind of proc point arises when there is a joint point
20 -- in the control flow. Suppose we have code like the following:
22 -- if (...) { ...; call foo(); ...}
23 -- else { ...; call bar(); ...}
26 -- That last statement "x = y" must be a proc point because
27 -- it can be reached by blocks owned by different proc points
28 -- (the two branches of the conditional).
30 -- We calculate these proc points by starting with the minimal set
31 -- and finding blocks that are reachable from more proc points than
32 -- one of their parents. (This ensures we don't choose a block
33 -- simply beause it is reachable from another block that is reachable
34 -- from multiple proc points.) These new blocks are added to the
35 -- set of proc points and the process is repeated until there
36 -- are no more proc points to be found.
38 calculateProcPoints :: [BrokenBlock] -> UniqSet BlockId
39 calculateProcPoints blocks =
40 calculateProcPoints' init_proc_points blocks
42 init_proc_points = mkUniqSet $
44 filter always_proc_point blocks
45 always_proc_point BrokenBlock {
46 brokenBlockEntry = FunctionEntry _ _ _ } = True
47 always_proc_point BrokenBlock {
48 brokenBlockEntry = ContinuationEntry _ _ _ } = True
49 always_proc_point _ = False
51 calculateProcPoints' :: UniqSet BlockId -> [BrokenBlock] -> UniqSet BlockId
52 calculateProcPoints' old_proc_points blocks =
53 if sizeUniqSet old_proc_points == sizeUniqSet new_proc_points
55 else calculateProcPoints' new_proc_points blocks
57 blocks_ufm :: BlockEnv BrokenBlock
58 blocks_ufm = blocksToBlockEnv blocks
60 owners = calculateOwnership blocks_ufm old_proc_points blocks
64 map (calculateNewProcPoints owners) blocks)
66 calculateNewProcPoints :: BlockEnv (UniqSet BlockId)
69 calculateNewProcPoints owners block =
70 unionManyUniqSets (map (maybe_proc_point parent_id) child_ids)
72 parent_id = brokenBlockId block
73 child_ids = brokenBlockTargets block
74 maybe_proc_point parent_id child_id =
76 then unitUniqSet child_id
79 parent_owners = lookupWithDefaultBEnv owners emptyUniqSet parent_id
80 child_owners = lookupWithDefaultBEnv owners emptyUniqSet child_id
82 -- only if parent isn't dead
83 (not $ isEmptyUniqSet parent_owners) &&
84 -- and only if child has more owners than parent
85 (not $ isEmptyUniqSet $
86 child_owners `minusUniqSet` parent_owners)
88 calculateOwnership :: BlockEnv BrokenBlock
91 -> BlockEnv (UniqSet BlockId)
92 calculateOwnership blocks_ufm proc_points blocks =
93 fixedpoint dependants update (map brokenBlockId blocks) emptyBlockEnv
95 dependants :: BlockId -> [BlockId]
97 brokenBlockTargets $ lookupWithDefaultBEnv
98 blocks_ufm unknown_block ident
102 -> BlockEnv (UniqSet BlockId)
103 -> Maybe (BlockEnv (UniqSet BlockId))
104 update ident cause owners =
105 case (cause, ident `elementOfUniqSet` proc_points) of
107 Just $ extendBlockEnv owners ident (unitUniqSet ident)
108 (Nothing, False) -> Nothing
109 (Just _, True) -> Nothing
110 (Just cause', False) ->
111 if (sizeUniqSet old) == (sizeUniqSet new)
113 else Just $ extendBlockEnv owners ident new
115 old = lookupWithDefaultBEnv owners emptyUniqSet ident
116 new = old `unionUniqSets`
117 lookupWithDefaultBEnv owners emptyUniqSet cause'
119 unknown_block = panic "unknown BlockId in calculateOwnership"