PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/compiler/nativeGen/RegAlloc/Liveness.hs

https://github.com/dorchard/ghc
Haskell | 956 lines | 620 code | 213 blank | 123 comment | 6 complexity | f0252e8b8b03eb2e46e2f5c7c99b556c MD5 | raw file
  1. -----------------------------------------------------------------------------
  2. --
  3. -- The register liveness determinator
  4. --
  5. -- (c) The University of Glasgow 2004
  6. --
  7. -----------------------------------------------------------------------------
  8. module RegAlloc.Liveness (
  9. RegSet,
  10. RegMap, emptyRegMap,
  11. BlockMap, emptyBlockMap,
  12. LiveCmmDecl,
  13. InstrSR (..),
  14. LiveInstr (..),
  15. Liveness (..),
  16. LiveInfo (..),
  17. LiveBasicBlock,
  18. mapBlockTop, mapBlockTopM, mapSCCM,
  19. mapGenBlockTop, mapGenBlockTopM,
  20. stripLive,
  21. stripLiveBlock,
  22. slurpConflicts,
  23. slurpReloadCoalesce,
  24. eraseDeltasLive,
  25. patchEraseLive,
  26. patchRegsLiveInstr,
  27. reverseBlocksInTops,
  28. regLiveness,
  29. natCmmTopToLive
  30. ) where
  31. import Reg
  32. import Instruction
  33. import BlockId
  34. import Cmm hiding (RegSet)
  35. import PprCmm()
  36. import Digraph
  37. import DynFlags
  38. import Outputable
  39. import Platform
  40. import Unique
  41. import UniqSet
  42. import UniqFM
  43. import UniqSupply
  44. import Bag
  45. import State
  46. import FastString
  47. import Data.List
  48. import Data.Maybe
  49. import Data.Map (Map)
  50. import Data.Set (Set)
  51. import qualified Data.Map as Map
  52. -----------------------------------------------------------------------------
  53. type RegSet = UniqSet Reg
  54. type RegMap a = UniqFM a
  55. emptyRegMap :: UniqFM a
  56. emptyRegMap = emptyUFM
  57. type BlockMap a = BlockEnv a
  58. -- | A top level thing which carries liveness information.
  59. type LiveCmmDecl statics instr
  60. = GenCmmDecl
  61. statics
  62. LiveInfo
  63. [SCC (LiveBasicBlock instr)]
  64. -- | The register allocator also wants to use SPILL/RELOAD meta instructions,
  65. -- so we'll keep those here.
  66. data InstrSR instr
  67. -- | A real machine instruction
  68. = Instr instr
  69. -- | spill this reg to a stack slot
  70. | SPILL Reg Int
  71. -- | reload this reg from a stack slot
  72. | RELOAD Int Reg
  73. instance Instruction instr => Instruction (InstrSR instr) where
  74. regUsageOfInstr platform i
  75. = case i of
  76. Instr instr -> regUsageOfInstr platform instr
  77. SPILL reg _ -> RU [reg] []
  78. RELOAD _ reg -> RU [] [reg]
  79. patchRegsOfInstr i f
  80. = case i of
  81. Instr instr -> Instr (patchRegsOfInstr instr f)
  82. SPILL reg slot -> SPILL (f reg) slot
  83. RELOAD slot reg -> RELOAD slot (f reg)
  84. isJumpishInstr i
  85. = case i of
  86. Instr instr -> isJumpishInstr instr
  87. _ -> False
  88. jumpDestsOfInstr i
  89. = case i of
  90. Instr instr -> jumpDestsOfInstr instr
  91. _ -> []
  92. patchJumpInstr i f
  93. = case i of
  94. Instr instr -> Instr (patchJumpInstr instr f)
  95. _ -> i
  96. mkSpillInstr = error "mkSpillInstr[InstrSR]: Not making SPILL meta-instr"
  97. mkLoadInstr = error "mkLoadInstr[InstrSR]: Not making LOAD meta-instr"
  98. takeDeltaInstr i
  99. = case i of
  100. Instr instr -> takeDeltaInstr instr
  101. _ -> Nothing
  102. isMetaInstr i
  103. = case i of
  104. Instr instr -> isMetaInstr instr
  105. _ -> False
  106. mkRegRegMoveInstr platform r1 r2
  107. = Instr (mkRegRegMoveInstr platform r1 r2)
  108. takeRegRegMoveInstr i
  109. = case i of
  110. Instr instr -> takeRegRegMoveInstr instr
  111. _ -> Nothing
  112. mkJumpInstr target = map Instr (mkJumpInstr target)
  113. mkStackAllocInstr platform amount =
  114. Instr (mkStackAllocInstr platform amount)
  115. mkStackDeallocInstr platform amount =
  116. Instr (mkStackDeallocInstr platform amount)
  117. -- | An instruction with liveness information.
  118. data LiveInstr instr
  119. = LiveInstr (InstrSR instr) (Maybe Liveness)
  120. -- | Liveness information.
  121. -- The regs which die are ones which are no longer live in the *next* instruction
  122. -- in this sequence.
  123. -- (NB. if the instruction is a jump, these registers might still be live
  124. -- at the jump target(s) - you have to check the liveness at the destination
  125. -- block to find out).
  126. data Liveness
  127. = Liveness
  128. { liveBorn :: RegSet -- ^ registers born in this instruction (written to for first time).
  129. , liveDieRead :: RegSet -- ^ registers that died because they were read for the last time.
  130. , liveDieWrite :: RegSet } -- ^ registers that died because they were clobbered by something.
  131. -- | Stash regs live on entry to each basic block in the info part of the cmm code.
  132. data LiveInfo
  133. = LiveInfo
  134. (BlockEnv CmmStatics) -- cmm info table static stuff
  135. (Maybe BlockId) -- id of the first block
  136. (Maybe (BlockMap RegSet)) -- argument locals live on entry to this block
  137. (Map BlockId (Set Int)) -- stack slots live on entry to this block
  138. -- | A basic block with liveness information.
  139. type LiveBasicBlock instr
  140. = GenBasicBlock (LiveInstr instr)
  141. instance Outputable instr
  142. => Outputable (InstrSR instr) where
  143. ppr (Instr realInstr)
  144. = ppr realInstr
  145. ppr (SPILL reg slot)
  146. = hcat [
  147. ptext (sLit "\tSPILL"),
  148. char ' ',
  149. ppr reg,
  150. comma,
  151. ptext (sLit "SLOT") <> parens (int slot)]
  152. ppr (RELOAD slot reg)
  153. = hcat [
  154. ptext (sLit "\tRELOAD"),
  155. char ' ',
  156. ptext (sLit "SLOT") <> parens (int slot),
  157. comma,
  158. ppr reg]
  159. instance Outputable instr
  160. => Outputable (LiveInstr instr) where
  161. ppr (LiveInstr instr Nothing)
  162. = ppr instr
  163. ppr (LiveInstr instr (Just live))
  164. = ppr instr
  165. $$ (nest 8
  166. $ vcat
  167. [ pprRegs (ptext (sLit "# born: ")) (liveBorn live)
  168. , pprRegs (ptext (sLit "# r_dying: ")) (liveDieRead live)
  169. , pprRegs (ptext (sLit "# w_dying: ")) (liveDieWrite live) ]
  170. $+$ space)
  171. where pprRegs :: SDoc -> RegSet -> SDoc
  172. pprRegs name regs
  173. | isEmptyUniqSet regs = empty
  174. | otherwise = name <> (hcat $ punctuate space $ map ppr $ uniqSetToList regs)
  175. instance Outputable LiveInfo where
  176. ppr (LiveInfo mb_static firstId liveVRegsOnEntry liveSlotsOnEntry)
  177. = (ppr mb_static)
  178. $$ text "# firstId = " <> ppr firstId
  179. $$ text "# liveVRegsOnEntry = " <> ppr liveVRegsOnEntry
  180. $$ text "# liveSlotsOnEntry = " <> text (show liveSlotsOnEntry)
  181. -- | map a function across all the basic blocks in this code
  182. --
  183. mapBlockTop
  184. :: (LiveBasicBlock instr -> LiveBasicBlock instr)
  185. -> LiveCmmDecl statics instr -> LiveCmmDecl statics instr
  186. mapBlockTop f cmm
  187. = evalState (mapBlockTopM (\x -> return $ f x) cmm) ()
  188. -- | map a function across all the basic blocks in this code (monadic version)
  189. --
  190. mapBlockTopM
  191. :: Monad m
  192. => (LiveBasicBlock instr -> m (LiveBasicBlock instr))
  193. -> LiveCmmDecl statics instr -> m (LiveCmmDecl statics instr)
  194. mapBlockTopM _ cmm@(CmmData{})
  195. = return cmm
  196. mapBlockTopM f (CmmProc header label live sccs)
  197. = do sccs' <- mapM (mapSCCM f) sccs
  198. return $ CmmProc header label live sccs'
  199. mapSCCM :: Monad m => (a -> m b) -> SCC a -> m (SCC b)
  200. mapSCCM f (AcyclicSCC x)
  201. = do x' <- f x
  202. return $ AcyclicSCC x'
  203. mapSCCM f (CyclicSCC xs)
  204. = do xs' <- mapM f xs
  205. return $ CyclicSCC xs'
  206. -- map a function across all the basic blocks in this code
  207. mapGenBlockTop
  208. :: (GenBasicBlock i -> GenBasicBlock i)
  209. -> (GenCmmDecl d h (ListGraph i) -> GenCmmDecl d h (ListGraph i))
  210. mapGenBlockTop f cmm
  211. = evalState (mapGenBlockTopM (\x -> return $ f x) cmm) ()
  212. -- | map a function across all the basic blocks in this code (monadic version)
  213. mapGenBlockTopM
  214. :: Monad m
  215. => (GenBasicBlock i -> m (GenBasicBlock i))
  216. -> (GenCmmDecl d h (ListGraph i) -> m (GenCmmDecl d h (ListGraph i)))
  217. mapGenBlockTopM _ cmm@(CmmData{})
  218. = return cmm
  219. mapGenBlockTopM f (CmmProc header label live (ListGraph blocks))
  220. = do blocks' <- mapM f blocks
  221. return $ CmmProc header label live (ListGraph blocks')
  222. -- | Slurp out the list of register conflicts and reg-reg moves from this top level thing.
  223. -- Slurping of conflicts and moves is wrapped up together so we don't have
  224. -- to make two passes over the same code when we want to build the graph.
  225. --
  226. slurpConflicts
  227. :: Instruction instr
  228. => LiveCmmDecl statics instr
  229. -> (Bag (UniqSet Reg), Bag (Reg, Reg))
  230. slurpConflicts live
  231. = slurpCmm (emptyBag, emptyBag) live
  232. where slurpCmm rs CmmData{} = rs
  233. slurpCmm rs (CmmProc info _ _ sccs)
  234. = foldl' (slurpSCC info) rs sccs
  235. slurpSCC info rs (AcyclicSCC b)
  236. = slurpBlock info rs b
  237. slurpSCC info rs (CyclicSCC bs)
  238. = foldl' (slurpBlock info) rs bs
  239. slurpBlock info rs (BasicBlock blockId instrs)
  240. | LiveInfo _ _ (Just blockLive) _ <- info
  241. , Just rsLiveEntry <- mapLookup blockId blockLive
  242. , (conflicts, moves) <- slurpLIs rsLiveEntry rs instrs
  243. = (consBag rsLiveEntry conflicts, moves)
  244. | otherwise
  245. = panic "Liveness.slurpConflicts: bad block"
  246. slurpLIs rsLive (conflicts, moves) []
  247. = (consBag rsLive conflicts, moves)
  248. slurpLIs rsLive rs (LiveInstr _ Nothing : lis)
  249. = slurpLIs rsLive rs lis
  250. slurpLIs rsLiveEntry (conflicts, moves) (LiveInstr instr (Just live) : lis)
  251. = let
  252. -- regs that die because they are read for the last time at the start of an instruction
  253. -- are not live across it.
  254. rsLiveAcross = rsLiveEntry `minusUniqSet` (liveDieRead live)
  255. -- regs live on entry to the next instruction.
  256. -- be careful of orphans, make sure to delete dying regs _after_ unioning
  257. -- in the ones that are born here.
  258. rsLiveNext = (rsLiveAcross `unionUniqSets` (liveBorn live))
  259. `minusUniqSet` (liveDieWrite live)
  260. -- orphan vregs are the ones that die in the same instruction they are born in.
  261. -- these are likely to be results that are never used, but we still
  262. -- need to assign a hreg to them..
  263. rsOrphans = intersectUniqSets
  264. (liveBorn live)
  265. (unionUniqSets (liveDieWrite live) (liveDieRead live))
  266. --
  267. rsConflicts = unionUniqSets rsLiveNext rsOrphans
  268. in case takeRegRegMoveInstr instr of
  269. Just rr -> slurpLIs rsLiveNext
  270. ( consBag rsConflicts conflicts
  271. , consBag rr moves) lis
  272. Nothing -> slurpLIs rsLiveNext
  273. ( consBag rsConflicts conflicts
  274. , moves) lis
  275. -- | For spill\/reloads
  276. --
  277. -- SPILL v1, slot1
  278. -- ...
  279. -- RELOAD slot1, v2
  280. --
  281. -- If we can arrange that v1 and v2 are allocated to the same hreg it's more likely
  282. -- the spill\/reload instrs can be cleaned and replaced by a nop reg-reg move.
  283. --
  284. --
  285. slurpReloadCoalesce
  286. :: forall statics instr. Instruction instr
  287. => LiveCmmDecl statics instr
  288. -> Bag (Reg, Reg)
  289. slurpReloadCoalesce live
  290. = slurpCmm emptyBag live
  291. where
  292. slurpCmm :: Bag (Reg, Reg)
  293. -> GenCmmDecl t t1 [SCC (LiveBasicBlock instr)]
  294. -> Bag (Reg, Reg)
  295. slurpCmm cs CmmData{} = cs
  296. slurpCmm cs (CmmProc _ _ _ sccs)
  297. = slurpComp cs (flattenSCCs sccs)
  298. slurpComp :: Bag (Reg, Reg)
  299. -> [LiveBasicBlock instr]
  300. -> Bag (Reg, Reg)
  301. slurpComp cs blocks
  302. = let (moveBags, _) = runState (slurpCompM blocks) emptyUFM
  303. in unionManyBags (cs : moveBags)
  304. slurpCompM :: [LiveBasicBlock instr]
  305. -> State (UniqFM [UniqFM Reg]) [Bag (Reg, Reg)]
  306. slurpCompM blocks
  307. = do -- run the analysis once to record the mapping across jumps.
  308. mapM_ (slurpBlock False) blocks
  309. -- run it a second time while using the information from the last pass.
  310. -- We /could/ run this many more times to deal with graphical control
  311. -- flow and propagating info across multiple jumps, but it's probably
  312. -- not worth the trouble.
  313. mapM (slurpBlock True) blocks
  314. slurpBlock :: Bool -> LiveBasicBlock instr
  315. -> State (UniqFM [UniqFM Reg]) (Bag (Reg, Reg))
  316. slurpBlock propagate (BasicBlock blockId instrs)
  317. = do -- grab the slot map for entry to this block
  318. slotMap <- if propagate
  319. then getSlotMap blockId
  320. else return emptyUFM
  321. (_, mMoves) <- mapAccumLM slurpLI slotMap instrs
  322. return $ listToBag $ catMaybes mMoves
  323. slurpLI :: UniqFM Reg -- current slotMap
  324. -> LiveInstr instr
  325. -> State (UniqFM [UniqFM Reg]) -- blockId -> [slot -> reg]
  326. -- for tracking slotMaps across jumps
  327. ( UniqFM Reg -- new slotMap
  328. , Maybe (Reg, Reg)) -- maybe a new coalesce edge
  329. slurpLI slotMap li
  330. -- remember what reg was stored into the slot
  331. | LiveInstr (SPILL reg slot) _ <- li
  332. , slotMap' <- addToUFM slotMap slot reg
  333. = return (slotMap', Nothing)
  334. -- add an edge betwen the this reg and the last one stored into the slot
  335. | LiveInstr (RELOAD slot reg) _ <- li
  336. = case lookupUFM slotMap slot of
  337. Just reg2
  338. | reg /= reg2 -> return (slotMap, Just (reg, reg2))
  339. | otherwise -> return (slotMap, Nothing)
  340. Nothing -> return (slotMap, Nothing)
  341. -- if we hit a jump, remember the current slotMap
  342. | LiveInstr (Instr instr) _ <- li
  343. , targets <- jumpDestsOfInstr instr
  344. , not $ null targets
  345. = do mapM_ (accSlotMap slotMap) targets
  346. return (slotMap, Nothing)
  347. | otherwise
  348. = return (slotMap, Nothing)
  349. -- record a slotmap for an in edge to this block
  350. accSlotMap slotMap blockId
  351. = modify (\s -> addToUFM_C (++) s blockId [slotMap])
  352. -- work out the slot map on entry to this block
  353. -- if we have slot maps for multiple in-edges then we need to merge them.
  354. getSlotMap blockId
  355. = do map <- get
  356. let slotMaps = fromMaybe [] (lookupUFM map blockId)
  357. return $ foldr mergeSlotMaps emptyUFM slotMaps
  358. mergeSlotMaps :: UniqFM Reg -> UniqFM Reg -> UniqFM Reg
  359. mergeSlotMaps map1 map2
  360. = listToUFM
  361. $ [ (k, r1) | (k, r1) <- ufmToList map1
  362. , case lookupUFM map2 k of
  363. Nothing -> False
  364. Just r2 -> r1 == r2 ]
  365. -- | Strip away liveness information, yielding NatCmmDecl
  366. stripLive
  367. :: (Outputable statics, Outputable instr, Instruction instr)
  368. => DynFlags
  369. -> LiveCmmDecl statics instr
  370. -> NatCmmDecl statics instr
  371. stripLive dflags live
  372. = stripCmm live
  373. where stripCmm :: (Outputable statics, Outputable instr, Instruction instr)
  374. => LiveCmmDecl statics instr -> NatCmmDecl statics instr
  375. stripCmm (CmmData sec ds) = CmmData sec ds
  376. stripCmm (CmmProc (LiveInfo info (Just first_id) _ _) label live sccs)
  377. = let final_blocks = flattenSCCs sccs
  378. -- make sure the block that was first in the input list
  379. -- stays at the front of the output. This is the entry point
  380. -- of the proc, and it needs to come first.
  381. ((first':_), rest')
  382. = partition ((== first_id) . blockId) final_blocks
  383. in CmmProc info label live
  384. (ListGraph $ map (stripLiveBlock dflags) $ first' : rest')
  385. -- procs used for stg_split_markers don't contain any blocks, and have no first_id.
  386. stripCmm (CmmProc (LiveInfo info Nothing _ _) label live [])
  387. = CmmProc info label live (ListGraph [])
  388. -- If the proc has blocks but we don't know what the first one was, then we're dead.
  389. stripCmm proc
  390. = pprPanic "RegAlloc.Liveness.stripLive: no first_id on proc" (ppr proc)
  391. -- | Strip away liveness information from a basic block,
  392. -- and make real spill instructions out of SPILL, RELOAD pseudos along the way.
  393. stripLiveBlock
  394. :: Instruction instr
  395. => DynFlags
  396. -> LiveBasicBlock instr
  397. -> NatBasicBlock instr
  398. stripLiveBlock dflags (BasicBlock i lis)
  399. = BasicBlock i instrs'
  400. where (instrs', _)
  401. = runState (spillNat [] lis) 0
  402. spillNat acc []
  403. = return (reverse acc)
  404. spillNat acc (LiveInstr (SPILL reg slot) _ : instrs)
  405. = do delta <- get
  406. spillNat (mkSpillInstr dflags reg delta slot : acc) instrs
  407. spillNat acc (LiveInstr (RELOAD slot reg) _ : instrs)
  408. = do delta <- get
  409. spillNat (mkLoadInstr dflags reg delta slot : acc) instrs
  410. spillNat acc (LiveInstr (Instr instr) _ : instrs)
  411. | Just i <- takeDeltaInstr instr
  412. = do put i
  413. spillNat acc instrs
  414. spillNat acc (LiveInstr (Instr instr) _ : instrs)
  415. = spillNat (instr : acc) instrs
  416. -- | Erase Delta instructions.
  417. eraseDeltasLive
  418. :: Instruction instr
  419. => LiveCmmDecl statics instr
  420. -> LiveCmmDecl statics instr
  421. eraseDeltasLive cmm
  422. = mapBlockTop eraseBlock cmm
  423. where
  424. eraseBlock (BasicBlock id lis)
  425. = BasicBlock id
  426. $ filter (\(LiveInstr i _) -> not $ isJust $ takeDeltaInstr i)
  427. $ lis
  428. -- | Patch the registers in this code according to this register mapping.
  429. -- also erase reg -> reg moves when the reg is the same.
  430. -- also erase reg -> reg moves when the destination dies in this instr.
  431. patchEraseLive
  432. :: Instruction instr
  433. => (Reg -> Reg)
  434. -> LiveCmmDecl statics instr -> LiveCmmDecl statics instr
  435. patchEraseLive patchF cmm
  436. = patchCmm cmm
  437. where
  438. patchCmm cmm@CmmData{} = cmm
  439. patchCmm (CmmProc info label live sccs)
  440. | LiveInfo static id (Just blockMap) mLiveSlots <- info
  441. = let
  442. patchRegSet set = mkUniqSet $ map patchF $ uniqSetToList set
  443. blockMap' = mapMap patchRegSet blockMap
  444. info' = LiveInfo static id (Just blockMap') mLiveSlots
  445. in CmmProc info' label live $ map patchSCC sccs
  446. | otherwise
  447. = panic "RegAlloc.Liveness.patchEraseLive: no blockMap"
  448. patchSCC (AcyclicSCC b) = AcyclicSCC (patchBlock b)
  449. patchSCC (CyclicSCC bs) = CyclicSCC (map patchBlock bs)
  450. patchBlock (BasicBlock id lis)
  451. = BasicBlock id $ patchInstrs lis
  452. patchInstrs [] = []
  453. patchInstrs (li : lis)
  454. | LiveInstr i (Just live) <- li'
  455. , Just (r1, r2) <- takeRegRegMoveInstr i
  456. , eatMe r1 r2 live
  457. = patchInstrs lis
  458. | otherwise
  459. = li' : patchInstrs lis
  460. where li' = patchRegsLiveInstr patchF li
  461. eatMe r1 r2 live
  462. -- source and destination regs are the same
  463. | r1 == r2 = True
  464. -- desination reg is never used
  465. | elementOfUniqSet r2 (liveBorn live)
  466. , elementOfUniqSet r2 (liveDieRead live) || elementOfUniqSet r2 (liveDieWrite live)
  467. = True
  468. | otherwise = False
  469. -- | Patch registers in this LiveInstr, including the liveness information.
  470. --
  471. patchRegsLiveInstr
  472. :: Instruction instr
  473. => (Reg -> Reg)
  474. -> LiveInstr instr -> LiveInstr instr
  475. patchRegsLiveInstr patchF li
  476. = case li of
  477. LiveInstr instr Nothing
  478. -> LiveInstr (patchRegsOfInstr instr patchF) Nothing
  479. LiveInstr instr (Just live)
  480. -> LiveInstr
  481. (patchRegsOfInstr instr patchF)
  482. (Just live
  483. { -- WARNING: have to go via lists here because patchF changes the uniq in the Reg
  484. liveBorn = mkUniqSet $ map patchF $ uniqSetToList $ liveBorn live
  485. , liveDieRead = mkUniqSet $ map patchF $ uniqSetToList $ liveDieRead live
  486. , liveDieWrite = mkUniqSet $ map patchF $ uniqSetToList $ liveDieWrite live })
  487. --------------------------------------------------------------------------------
  488. -- | Convert a NatCmmDecl to a LiveCmmDecl, with empty liveness information
  489. natCmmTopToLive
  490. :: Instruction instr
  491. => NatCmmDecl statics instr
  492. -> LiveCmmDecl statics instr
  493. natCmmTopToLive (CmmData i d)
  494. = CmmData i d
  495. natCmmTopToLive (CmmProc info lbl live (ListGraph []))
  496. = CmmProc (LiveInfo info Nothing Nothing Map.empty) lbl live []
  497. natCmmTopToLive (CmmProc info lbl live (ListGraph blocks@(first : _)))
  498. = let first_id = blockId first
  499. sccs = sccBlocks blocks
  500. sccsLive = map (fmap (\(BasicBlock l instrs) ->
  501. BasicBlock l (map (\i -> LiveInstr (Instr i) Nothing) instrs)))
  502. $ sccs
  503. in CmmProc (LiveInfo info (Just first_id) Nothing Map.empty) lbl live sccsLive
  504. sccBlocks
  505. :: Instruction instr
  506. => [NatBasicBlock instr]
  507. -> [SCC (NatBasicBlock instr)]
  508. sccBlocks blocks = stronglyConnCompFromEdgedVertices graph
  509. where
  510. getOutEdges :: Instruction instr => [instr] -> [BlockId]
  511. getOutEdges instrs = concat $ map jumpDestsOfInstr instrs
  512. graph = [ (block, getUnique id, map getUnique (getOutEdges instrs))
  513. | block@(BasicBlock id instrs) <- blocks ]
  514. ---------------------------------------------------------------------------------
  515. -- Annotate code with register liveness information
  516. --
  517. regLiveness
  518. :: (Outputable instr, Instruction instr)
  519. => Platform
  520. -> LiveCmmDecl statics instr
  521. -> UniqSM (LiveCmmDecl statics instr)
  522. regLiveness _ (CmmData i d)
  523. = return $ CmmData i d
  524. regLiveness _ (CmmProc info lbl live [])
  525. | LiveInfo static mFirst _ _ <- info
  526. = return $ CmmProc
  527. (LiveInfo static mFirst (Just mapEmpty) Map.empty)
  528. lbl live []
  529. regLiveness platform (CmmProc info lbl live sccs)
  530. | LiveInfo static mFirst _ liveSlotsOnEntry <- info
  531. = let (ann_sccs, block_live) = computeLiveness platform sccs
  532. in return $ CmmProc (LiveInfo static mFirst (Just block_live) liveSlotsOnEntry)
  533. lbl live ann_sccs
  534. -- -----------------------------------------------------------------------------
  535. -- | Check ordering of Blocks
  536. -- The computeLiveness function requires SCCs to be in reverse
  537. -- dependent order. If they're not the liveness information will be
  538. -- wrong, and we'll get a bad allocation. Better to check for this
  539. -- precondition explicitly or some other poor sucker will waste a
  540. -- day staring at bad assembly code..
  541. --
  542. checkIsReverseDependent
  543. :: Instruction instr
  544. => [SCC (LiveBasicBlock instr)] -- ^ SCCs of blocks that we're about to run the liveness determinator on.
  545. -> Maybe BlockId -- ^ BlockIds that fail the test (if any)
  546. checkIsReverseDependent sccs'
  547. = go emptyUniqSet sccs'
  548. where go _ []
  549. = Nothing
  550. go blocksSeen (AcyclicSCC block : sccs)
  551. = let dests = slurpJumpDestsOfBlock block
  552. blocksSeen' = unionUniqSets blocksSeen $ mkUniqSet [blockId block]
  553. badDests = dests `minusUniqSet` blocksSeen'
  554. in case uniqSetToList badDests of
  555. [] -> go blocksSeen' sccs
  556. bad : _ -> Just bad
  557. go blocksSeen (CyclicSCC blocks : sccs)
  558. = let dests = unionManyUniqSets $ map slurpJumpDestsOfBlock blocks
  559. blocksSeen' = unionUniqSets blocksSeen $ mkUniqSet $ map blockId blocks
  560. badDests = dests `minusUniqSet` blocksSeen'
  561. in case uniqSetToList badDests of
  562. [] -> go blocksSeen' sccs
  563. bad : _ -> Just bad
  564. slurpJumpDestsOfBlock (BasicBlock _ instrs)
  565. = unionManyUniqSets
  566. $ map (mkUniqSet . jumpDestsOfInstr)
  567. [ i | LiveInstr i _ <- instrs]
  568. -- | If we've compute liveness info for this code already we have to reverse
  569. -- the SCCs in each top to get them back to the right order so we can do it again.
  570. reverseBlocksInTops :: LiveCmmDecl statics instr -> LiveCmmDecl statics instr
  571. reverseBlocksInTops top
  572. = case top of
  573. CmmData{} -> top
  574. CmmProc info lbl live sccs -> CmmProc info lbl live (reverse sccs)
  575. -- | Computing liveness
  576. --
  577. -- On entry, the SCCs must be in "reverse" order: later blocks may transfer
  578. -- control to earlier ones only, else `panic`.
  579. --
  580. -- The SCCs returned are in the *opposite* order, which is exactly what we
  581. -- want for the next pass.
  582. --
  583. computeLiveness
  584. :: (Outputable instr, Instruction instr)
  585. => Platform
  586. -> [SCC (LiveBasicBlock instr)]
  587. -> ([SCC (LiveBasicBlock instr)], -- instructions annotated with list of registers
  588. -- which are "dead after this instruction".
  589. BlockMap RegSet) -- blocks annontated with set of live registers
  590. -- on entry to the block.
  591. computeLiveness platform sccs
  592. = case checkIsReverseDependent sccs of
  593. Nothing -> livenessSCCs platform emptyBlockMap [] sccs
  594. Just bad -> pprPanic "RegAlloc.Liveness.computeLivenss"
  595. (vcat [ text "SCCs aren't in reverse dependent order"
  596. , text "bad blockId" <+> ppr bad
  597. , ppr sccs])
  598. livenessSCCs
  599. :: Instruction instr
  600. => Platform
  601. -> BlockMap RegSet
  602. -> [SCC (LiveBasicBlock instr)] -- accum
  603. -> [SCC (LiveBasicBlock instr)]
  604. -> ( [SCC (LiveBasicBlock instr)]
  605. , BlockMap RegSet)
  606. livenessSCCs _ blockmap done []
  607. = (done, blockmap)
  608. livenessSCCs platform blockmap done (AcyclicSCC block : sccs)
  609. = let (blockmap', block') = livenessBlock platform blockmap block
  610. in livenessSCCs platform blockmap' (AcyclicSCC block' : done) sccs
  611. livenessSCCs platform blockmap done
  612. (CyclicSCC blocks : sccs) =
  613. livenessSCCs platform blockmap' (CyclicSCC blocks':done) sccs
  614. where (blockmap', blocks')
  615. = iterateUntilUnchanged linearLiveness equalBlockMaps
  616. blockmap blocks
  617. iterateUntilUnchanged
  618. :: (a -> b -> (a,c)) -> (a -> a -> Bool)
  619. -> a -> b
  620. -> (a,c)
  621. iterateUntilUnchanged f eq a b
  622. = head $
  623. concatMap tail $
  624. groupBy (\(a1, _) (a2, _) -> eq a1 a2) $
  625. iterate (\(a, _) -> f a b) $
  626. (a, panic "RegLiveness.livenessSCCs")
  627. linearLiveness
  628. :: Instruction instr
  629. => BlockMap RegSet -> [LiveBasicBlock instr]
  630. -> (BlockMap RegSet, [LiveBasicBlock instr])
  631. linearLiveness = mapAccumL (livenessBlock platform)
  632. -- probably the least efficient way to compare two
  633. -- BlockMaps for equality.
  634. equalBlockMaps a b
  635. = a' == b'
  636. where a' = map f $ mapToList a
  637. b' = map f $ mapToList b
  638. f (key,elt) = (key, uniqSetToList elt)
  639. -- | Annotate a basic block with register liveness information.
  640. --
  641. livenessBlock
  642. :: Instruction instr
  643. => Platform
  644. -> BlockMap RegSet
  645. -> LiveBasicBlock instr
  646. -> (BlockMap RegSet, LiveBasicBlock instr)
  647. livenessBlock platform blockmap (BasicBlock block_id instrs)
  648. = let
  649. (regsLiveOnEntry, instrs1)
  650. = livenessBack platform emptyUniqSet blockmap [] (reverse instrs)
  651. blockmap' = mapInsert block_id regsLiveOnEntry blockmap
  652. instrs2 = livenessForward platform regsLiveOnEntry instrs1
  653. output = BasicBlock block_id instrs2
  654. in ( blockmap', output)
  655. -- | Calculate liveness going forwards,
  656. -- filling in when regs are born
  657. livenessForward
  658. :: Instruction instr
  659. => Platform
  660. -> RegSet -- regs live on this instr
  661. -> [LiveInstr instr] -> [LiveInstr instr]
  662. livenessForward _ _ [] = []
  663. livenessForward platform rsLiveEntry (li@(LiveInstr instr mLive) : lis)
  664. | Nothing <- mLive
  665. = li : livenessForward platform rsLiveEntry lis
  666. | Just live <- mLive
  667. , RU _ written <- regUsageOfInstr platform instr
  668. = let
  669. -- Regs that are written to but weren't live on entry to this instruction
  670. -- are recorded as being born here.
  671. rsBorn = mkUniqSet
  672. $ filter (\r -> not $ elementOfUniqSet r rsLiveEntry) written
  673. rsLiveNext = (rsLiveEntry `unionUniqSets` rsBorn)
  674. `minusUniqSet` (liveDieRead live)
  675. `minusUniqSet` (liveDieWrite live)
  676. in LiveInstr instr (Just live { liveBorn = rsBorn })
  677. : livenessForward platform rsLiveNext lis
  678. livenessForward _ _ _ = panic "RegLiveness.livenessForward: no match"
  679. -- | Calculate liveness going backwards,
  680. -- filling in when regs die, and what regs are live across each instruction
  681. livenessBack
  682. :: Instruction instr
  683. => Platform
  684. -> RegSet -- regs live on this instr
  685. -> BlockMap RegSet -- regs live on entry to other BBs
  686. -> [LiveInstr instr] -- instructions (accum)
  687. -> [LiveInstr instr] -- instructions
  688. -> (RegSet, [LiveInstr instr])
  689. livenessBack _ liveregs _ done [] = (liveregs, done)
  690. livenessBack platform liveregs blockmap acc (instr : instrs)
  691. = let (liveregs', instr') = liveness1 platform liveregs blockmap instr
  692. in livenessBack platform liveregs' blockmap (instr' : acc) instrs
  693. -- don't bother tagging comments or deltas with liveness
  694. liveness1
  695. :: Instruction instr
  696. => Platform
  697. -> RegSet
  698. -> BlockMap RegSet
  699. -> LiveInstr instr
  700. -> (RegSet, LiveInstr instr)
  701. liveness1 _ liveregs _ (LiveInstr instr _)
  702. | isMetaInstr instr
  703. = (liveregs, LiveInstr instr Nothing)
  704. liveness1 platform liveregs blockmap (LiveInstr instr _)
  705. | not_a_branch
  706. = (liveregs1, LiveInstr instr
  707. (Just $ Liveness
  708. { liveBorn = emptyUniqSet
  709. , liveDieRead = mkUniqSet r_dying
  710. , liveDieWrite = mkUniqSet w_dying }))
  711. | otherwise
  712. = (liveregs_br, LiveInstr instr
  713. (Just $ Liveness
  714. { liveBorn = emptyUniqSet
  715. , liveDieRead = mkUniqSet r_dying_br
  716. , liveDieWrite = mkUniqSet w_dying }))
  717. where
  718. !(RU read written) = regUsageOfInstr platform instr
  719. -- registers that were written here are dead going backwards.
  720. -- registers that were read here are live going backwards.
  721. liveregs1 = (liveregs `delListFromUniqSet` written)
  722. `addListToUniqSet` read
  723. -- registers that are not live beyond this point, are recorded
  724. -- as dying here.
  725. r_dying = [ reg | reg <- read, reg `notElem` written,
  726. not (elementOfUniqSet reg liveregs) ]
  727. w_dying = [ reg | reg <- written,
  728. not (elementOfUniqSet reg liveregs) ]
  729. -- union in the live regs from all the jump destinations of this
  730. -- instruction.
  731. targets = jumpDestsOfInstr instr -- where we go from here
  732. not_a_branch = null targets
  733. targetLiveRegs target
  734. = case mapLookup target blockmap of
  735. Just ra -> ra
  736. Nothing -> emptyRegMap
  737. live_from_branch = unionManyUniqSets (map targetLiveRegs targets)
  738. liveregs_br = liveregs1 `unionUniqSets` live_from_branch
  739. -- registers that are live only in the branch targets should
  740. -- be listed as dying here.
  741. live_branch_only = live_from_branch `minusUniqSet` liveregs
  742. r_dying_br = uniqSetToList (mkUniqSet r_dying `unionUniqSets`
  743. live_branch_only)