PageRenderTime 58ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/nativeGen/RegAlloc/Liveness.hs

http://github.com/ilyasergey/GHC-XAppFix
Haskell | 950 lines | 614 code | 213 blank | 123 comment | 6 complexity | f8097f7cdebacd3bd814109d08738e4d MD5 | raw file
  1. -----------------------------------------------------------------------------
  2. --
  3. -- The register liveness determinator
  4. --
  5. -- (c) The University of Glasgow 2004
  6. --
  7. -----------------------------------------------------------------------------
  8. {-# OPTIONS -Wall -fno-warn-name-shadowing #-}
  9. module RegAlloc.Liveness (
  10. RegSet,
  11. RegMap, emptyRegMap,
  12. BlockMap, emptyBlockMap,
  13. LiveCmmDecl,
  14. InstrSR (..),
  15. LiveInstr (..),
  16. Liveness (..),
  17. LiveInfo (..),
  18. LiveBasicBlock,
  19. mapBlockTop, mapBlockTopM, mapSCCM,
  20. mapGenBlockTop, mapGenBlockTopM,
  21. stripLive,
  22. stripLiveBlock,
  23. slurpConflicts,
  24. slurpReloadCoalesce,
  25. eraseDeltasLive,
  26. patchEraseLive,
  27. patchRegsLiveInstr,
  28. reverseBlocksInTops,
  29. regLiveness,
  30. natCmmTopToLive
  31. ) where
  32. import Reg
  33. import Instruction
  34. import BlockId
  35. import OldCmm hiding (RegSet)
  36. import OldPprCmm()
  37. import Digraph
  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 i
  75. = case i of
  76. Instr instr -> regUsageOfInstr 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. -- | An instruction with liveness information.
  114. data LiveInstr instr
  115. = LiveInstr (InstrSR instr) (Maybe Liveness)
  116. -- | Liveness information.
  117. -- The regs which die are ones which are no longer live in the *next* instruction
  118. -- in this sequence.
  119. -- (NB. if the instruction is a jump, these registers might still be live
  120. -- at the jump target(s) - you have to check the liveness at the destination
  121. -- block to find out).
  122. data Liveness
  123. = Liveness
  124. { liveBorn :: RegSet -- ^ registers born in this instruction (written to for first time).
  125. , liveDieRead :: RegSet -- ^ registers that died because they were read for the last time.
  126. , liveDieWrite :: RegSet } -- ^ registers that died because they were clobbered by something.
  127. -- | Stash regs live on entry to each basic block in the info part of the cmm code.
  128. data LiveInfo
  129. = LiveInfo
  130. (Maybe CmmStatics) -- cmm info table static stuff
  131. (Maybe BlockId) -- id of the first block
  132. (Maybe (BlockMap RegSet)) -- argument locals live on entry to this block
  133. (Map BlockId (Set Int)) -- stack slots live on entry to this block
  134. -- | A basic block with liveness information.
  135. type LiveBasicBlock instr
  136. = GenBasicBlock (LiveInstr instr)
  137. instance PlatformOutputable instr
  138. => PlatformOutputable (InstrSR instr) where
  139. pprPlatform platform (Instr realInstr)
  140. = pprPlatform platform realInstr
  141. pprPlatform _ (SPILL reg slot)
  142. = hcat [
  143. ptext (sLit "\tSPILL"),
  144. char ' ',
  145. ppr reg,
  146. comma,
  147. ptext (sLit "SLOT") <> parens (int slot)]
  148. pprPlatform _ (RELOAD slot reg)
  149. = hcat [
  150. ptext (sLit "\tRELOAD"),
  151. char ' ',
  152. ptext (sLit "SLOT") <> parens (int slot),
  153. comma,
  154. ppr reg]
  155. instance PlatformOutputable instr
  156. => PlatformOutputable (LiveInstr instr) where
  157. pprPlatform platform (LiveInstr instr Nothing)
  158. = pprPlatform platform instr
  159. pprPlatform platform (LiveInstr instr (Just live))
  160. = pprPlatform platform instr
  161. $$ (nest 8
  162. $ vcat
  163. [ pprRegs (ptext (sLit "# born: ")) (liveBorn live)
  164. , pprRegs (ptext (sLit "# r_dying: ")) (liveDieRead live)
  165. , pprRegs (ptext (sLit "# w_dying: ")) (liveDieWrite live) ]
  166. $+$ space)
  167. where pprRegs :: SDoc -> RegSet -> SDoc
  168. pprRegs name regs
  169. | isEmptyUniqSet regs = empty
  170. | otherwise = name <> (hcat $ punctuate space $ map ppr $ uniqSetToList regs)
  171. instance PlatformOutputable LiveInfo where
  172. pprPlatform platform (LiveInfo mb_static firstId liveVRegsOnEntry liveSlotsOnEntry)
  173. = (maybe empty (pprPlatform platform) mb_static)
  174. $$ text "# firstId = " <> ppr firstId
  175. $$ text "# liveVRegsOnEntry = " <> ppr liveVRegsOnEntry
  176. $$ text "# liveSlotsOnEntry = " <> text (show liveSlotsOnEntry)
  177. -- | map a function across all the basic blocks in this code
  178. --
  179. mapBlockTop
  180. :: (LiveBasicBlock instr -> LiveBasicBlock instr)
  181. -> LiveCmmDecl statics instr -> LiveCmmDecl statics instr
  182. mapBlockTop f cmm
  183. = evalState (mapBlockTopM (\x -> return $ f x) cmm) ()
  184. -- | map a function across all the basic blocks in this code (monadic version)
  185. --
  186. mapBlockTopM
  187. :: Monad m
  188. => (LiveBasicBlock instr -> m (LiveBasicBlock instr))
  189. -> LiveCmmDecl statics instr -> m (LiveCmmDecl statics instr)
  190. mapBlockTopM _ cmm@(CmmData{})
  191. = return cmm
  192. mapBlockTopM f (CmmProc header label sccs)
  193. = do sccs' <- mapM (mapSCCM f) sccs
  194. return $ CmmProc header label sccs'
  195. mapSCCM :: Monad m => (a -> m b) -> SCC a -> m (SCC b)
  196. mapSCCM f (AcyclicSCC x)
  197. = do x' <- f x
  198. return $ AcyclicSCC x'
  199. mapSCCM f (CyclicSCC xs)
  200. = do xs' <- mapM f xs
  201. return $ CyclicSCC xs'
  202. -- map a function across all the basic blocks in this code
  203. mapGenBlockTop
  204. :: (GenBasicBlock i -> GenBasicBlock i)
  205. -> (GenCmmDecl d h (ListGraph i) -> GenCmmDecl d h (ListGraph i))
  206. mapGenBlockTop f cmm
  207. = evalState (mapGenBlockTopM (\x -> return $ f x) cmm) ()
  208. -- | map a function across all the basic blocks in this code (monadic version)
  209. mapGenBlockTopM
  210. :: Monad m
  211. => (GenBasicBlock i -> m (GenBasicBlock i))
  212. -> (GenCmmDecl d h (ListGraph i) -> m (GenCmmDecl d h (ListGraph i)))
  213. mapGenBlockTopM _ cmm@(CmmData{})
  214. = return cmm
  215. mapGenBlockTopM f (CmmProc header label (ListGraph blocks))
  216. = do blocks' <- mapM f blocks
  217. return $ CmmProc header label (ListGraph blocks')
  218. -- | Slurp out the list of register conflicts and reg-reg moves from this top level thing.
  219. -- Slurping of conflicts and moves is wrapped up together so we don't have
  220. -- to make two passes over the same code when we want to build the graph.
  221. --
  222. slurpConflicts
  223. :: Instruction instr
  224. => LiveCmmDecl statics instr
  225. -> (Bag (UniqSet Reg), Bag (Reg, Reg))
  226. slurpConflicts live
  227. = slurpCmm (emptyBag, emptyBag) live
  228. where slurpCmm rs CmmData{} = rs
  229. slurpCmm rs (CmmProc info _ sccs)
  230. = foldl' (slurpSCC info) rs sccs
  231. slurpSCC info rs (AcyclicSCC b)
  232. = slurpBlock info rs b
  233. slurpSCC info rs (CyclicSCC bs)
  234. = foldl' (slurpBlock info) rs bs
  235. slurpBlock info rs (BasicBlock blockId instrs)
  236. | LiveInfo _ _ (Just blockLive) _ <- info
  237. , Just rsLiveEntry <- mapLookup blockId blockLive
  238. , (conflicts, moves) <- slurpLIs rsLiveEntry rs instrs
  239. = (consBag rsLiveEntry conflicts, moves)
  240. | otherwise
  241. = panic "Liveness.slurpConflicts: bad block"
  242. slurpLIs rsLive (conflicts, moves) []
  243. = (consBag rsLive conflicts, moves)
  244. slurpLIs rsLive rs (LiveInstr _ Nothing : lis)
  245. = slurpLIs rsLive rs lis
  246. slurpLIs rsLiveEntry (conflicts, moves) (LiveInstr instr (Just live) : lis)
  247. = let
  248. -- regs that die because they are read for the last time at the start of an instruction
  249. -- are not live across it.
  250. rsLiveAcross = rsLiveEntry `minusUniqSet` (liveDieRead live)
  251. -- regs live on entry to the next instruction.
  252. -- be careful of orphans, make sure to delete dying regs _after_ unioning
  253. -- in the ones that are born here.
  254. rsLiveNext = (rsLiveAcross `unionUniqSets` (liveBorn live))
  255. `minusUniqSet` (liveDieWrite live)
  256. -- orphan vregs are the ones that die in the same instruction they are born in.
  257. -- these are likely to be results that are never used, but we still
  258. -- need to assign a hreg to them..
  259. rsOrphans = intersectUniqSets
  260. (liveBorn live)
  261. (unionUniqSets (liveDieWrite live) (liveDieRead live))
  262. --
  263. rsConflicts = unionUniqSets rsLiveNext rsOrphans
  264. in case takeRegRegMoveInstr instr of
  265. Just rr -> slurpLIs rsLiveNext
  266. ( consBag rsConflicts conflicts
  267. , consBag rr moves) lis
  268. Nothing -> slurpLIs rsLiveNext
  269. ( consBag rsConflicts conflicts
  270. , moves) lis
  271. -- | For spill\/reloads
  272. --
  273. -- SPILL v1, slot1
  274. -- ...
  275. -- RELOAD slot1, v2
  276. --
  277. -- If we can arrange that v1 and v2 are allocated to the same hreg it's more likely
  278. -- the spill\/reload instrs can be cleaned and replaced by a nop reg-reg move.
  279. --
  280. --
  281. slurpReloadCoalesce
  282. :: forall statics instr. Instruction instr
  283. => LiveCmmDecl statics instr
  284. -> Bag (Reg, Reg)
  285. slurpReloadCoalesce live
  286. = slurpCmm emptyBag live
  287. where
  288. slurpCmm :: Bag (Reg, Reg)
  289. -> GenCmmDecl t t1 [SCC (LiveBasicBlock instr)]
  290. -> Bag (Reg, Reg)
  291. slurpCmm cs CmmData{} = cs
  292. slurpCmm cs (CmmProc _ _ sccs)
  293. = slurpComp cs (flattenSCCs sccs)
  294. slurpComp :: Bag (Reg, Reg)
  295. -> [LiveBasicBlock instr]
  296. -> Bag (Reg, Reg)
  297. slurpComp cs blocks
  298. = let (moveBags, _) = runState (slurpCompM blocks) emptyUFM
  299. in unionManyBags (cs : moveBags)
  300. slurpCompM :: [LiveBasicBlock instr]
  301. -> State (UniqFM [UniqFM Reg]) [Bag (Reg, Reg)]
  302. slurpCompM blocks
  303. = do -- run the analysis once to record the mapping across jumps.
  304. mapM_ (slurpBlock False) blocks
  305. -- run it a second time while using the information from the last pass.
  306. -- We /could/ run this many more times to deal with graphical control
  307. -- flow and propagating info across multiple jumps, but it's probably
  308. -- not worth the trouble.
  309. mapM (slurpBlock True) blocks
  310. slurpBlock :: Bool -> LiveBasicBlock instr
  311. -> State (UniqFM [UniqFM Reg]) (Bag (Reg, Reg))
  312. slurpBlock propagate (BasicBlock blockId instrs)
  313. = do -- grab the slot map for entry to this block
  314. slotMap <- if propagate
  315. then getSlotMap blockId
  316. else return emptyUFM
  317. (_, mMoves) <- mapAccumLM slurpLI slotMap instrs
  318. return $ listToBag $ catMaybes mMoves
  319. slurpLI :: UniqFM Reg -- current slotMap
  320. -> LiveInstr instr
  321. -> State (UniqFM [UniqFM Reg]) -- blockId -> [slot -> reg]
  322. -- for tracking slotMaps across jumps
  323. ( UniqFM Reg -- new slotMap
  324. , Maybe (Reg, Reg)) -- maybe a new coalesce edge
  325. slurpLI slotMap li
  326. -- remember what reg was stored into the slot
  327. | LiveInstr (SPILL reg slot) _ <- li
  328. , slotMap' <- addToUFM slotMap slot reg
  329. = return (slotMap', Nothing)
  330. -- add an edge betwen the this reg and the last one stored into the slot
  331. | LiveInstr (RELOAD slot reg) _ <- li
  332. = case lookupUFM slotMap slot of
  333. Just reg2
  334. | reg /= reg2 -> return (slotMap, Just (reg, reg2))
  335. | otherwise -> return (slotMap, Nothing)
  336. Nothing -> return (slotMap, Nothing)
  337. -- if we hit a jump, remember the current slotMap
  338. | LiveInstr (Instr instr) _ <- li
  339. , targets <- jumpDestsOfInstr instr
  340. , not $ null targets
  341. = do mapM_ (accSlotMap slotMap) targets
  342. return (slotMap, Nothing)
  343. | otherwise
  344. = return (slotMap, Nothing)
  345. -- record a slotmap for an in edge to this block
  346. accSlotMap slotMap blockId
  347. = modify (\s -> addToUFM_C (++) s blockId [slotMap])
  348. -- work out the slot map on entry to this block
  349. -- if we have slot maps for multiple in-edges then we need to merge them.
  350. getSlotMap blockId
  351. = do map <- get
  352. let slotMaps = fromMaybe [] (lookupUFM map blockId)
  353. return $ foldr mergeSlotMaps emptyUFM slotMaps
  354. mergeSlotMaps :: UniqFM Reg -> UniqFM Reg -> UniqFM Reg
  355. mergeSlotMaps map1 map2
  356. = listToUFM
  357. $ [ (k, r1) | (k, r1) <- ufmToList map1
  358. , case lookupUFM map2 k of
  359. Nothing -> False
  360. Just r2 -> r1 == r2 ]
  361. -- | Strip away liveness information, yielding NatCmmDecl
  362. stripLive
  363. :: (PlatformOutputable statics,
  364. PlatformOutputable instr,
  365. Instruction instr)
  366. => Platform
  367. -> LiveCmmDecl statics instr
  368. -> NatCmmDecl statics instr
  369. stripLive platform live
  370. = stripCmm live
  371. where stripCmm :: (PlatformOutputable statics,
  372. PlatformOutputable instr,
  373. 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 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
  384. (ListGraph $ map (stripLiveBlock platform) $ 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 [])
  387. = CmmProc info label (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" (pprPlatform platform 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. => Platform
  396. -> LiveBasicBlock instr
  397. -> NatBasicBlock instr
  398. stripLiveBlock platform (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 platform reg delta slot : acc) instrs
  407. spillNat acc (LiveInstr (RELOAD slot reg) _ : instrs)
  408. = do delta <- get
  409. spillNat (mkLoadInstr platform 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 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 $ 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 (ListGraph []))
  496. = CmmProc (LiveInfo info Nothing Nothing Map.empty) lbl []
  497. natCmmTopToLive (CmmProc info lbl (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 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. :: (PlatformOutputable instr, Instruction instr)
  519. => Platform
  520. -> LiveCmmDecl statics instr
  521. -> UniqSM (LiveCmmDecl statics instr)
  522. regLiveness _ (CmmData i d)
  523. = returnUs $ CmmData i d
  524. regLiveness _ (CmmProc info lbl [])
  525. | LiveInfo static mFirst _ _ <- info
  526. = returnUs $ CmmProc
  527. (LiveInfo static mFirst (Just mapEmpty) Map.empty)
  528. lbl []
  529. regLiveness platform (CmmProc info lbl sccs)
  530. | LiveInfo static mFirst _ liveSlotsOnEntry <- info
  531. = let (ann_sccs, block_live) = computeLiveness platform sccs
  532. in returnUs $ CmmProc (LiveInfo static mFirst (Just block_live) liveSlotsOnEntry)
  533. lbl ann_sccs
  534. -- -----------------------------------------------------------------------------
  535. -- | Check ordering of Blocks
  536. -- The computeLiveness function requires SCCs to be in reverse dependent order.
  537. -- If they're not the liveness information will be wrong, and we'll get a bad allocation.
  538. -- Better to check for this precondition explicitly or some other poor sucker will
  539. -- waste a day staring at bad assembly code..
  540. --
  541. checkIsReverseDependent
  542. :: Instruction instr
  543. => [SCC (LiveBasicBlock instr)] -- ^ SCCs of blocks that we're about to run the liveness determinator on.
  544. -> Maybe BlockId -- ^ BlockIds that fail the test (if any)
  545. checkIsReverseDependent sccs'
  546. = go emptyUniqSet sccs'
  547. where go _ []
  548. = Nothing
  549. go blocksSeen (AcyclicSCC block : sccs)
  550. = let dests = slurpJumpDestsOfBlock block
  551. blocksSeen' = unionUniqSets blocksSeen $ mkUniqSet [blockId block]
  552. badDests = dests `minusUniqSet` blocksSeen'
  553. in case uniqSetToList badDests of
  554. [] -> go blocksSeen' sccs
  555. bad : _ -> Just bad
  556. go blocksSeen (CyclicSCC blocks : sccs)
  557. = let dests = unionManyUniqSets $ map slurpJumpDestsOfBlock blocks
  558. blocksSeen' = unionUniqSets blocksSeen $ mkUniqSet $ map blockId blocks
  559. badDests = dests `minusUniqSet` blocksSeen'
  560. in case uniqSetToList badDests of
  561. [] -> go blocksSeen' sccs
  562. bad : _ -> Just bad
  563. slurpJumpDestsOfBlock (BasicBlock _ instrs)
  564. = unionManyUniqSets
  565. $ map (mkUniqSet . jumpDestsOfInstr)
  566. [ i | LiveInstr i _ <- instrs]
  567. -- | If we've compute liveness info for this code already we have to reverse
  568. -- the SCCs in each top to get them back to the right order so we can do it again.
  569. reverseBlocksInTops :: LiveCmmDecl statics instr -> LiveCmmDecl statics instr
  570. reverseBlocksInTops top
  571. = case top of
  572. CmmData{} -> top
  573. CmmProc info lbl sccs -> CmmProc info lbl (reverse sccs)
  574. -- | Computing liveness
  575. --
  576. -- On entry, the SCCs must be in "reverse" order: later blocks may transfer
  577. -- control to earlier ones only, else `panic`.
  578. --
  579. -- The SCCs returned are in the *opposite* order, which is exactly what we
  580. -- want for the next pass.
  581. --
  582. computeLiveness
  583. :: (PlatformOutputable instr, Instruction instr)
  584. => Platform
  585. -> [SCC (LiveBasicBlock instr)]
  586. -> ([SCC (LiveBasicBlock instr)], -- instructions annotated with list of registers
  587. -- which are "dead after this instruction".
  588. BlockMap RegSet) -- blocks annontated with set of live registers
  589. -- on entry to the block.
  590. computeLiveness platform sccs
  591. = case checkIsReverseDependent sccs of
  592. Nothing -> livenessSCCs emptyBlockMap [] sccs
  593. Just bad -> pprPanic "RegAlloc.Liveness.computeLivenss"
  594. (vcat [ text "SCCs aren't in reverse dependent order"
  595. , text "bad blockId" <+> ppr bad
  596. , pprPlatform platform sccs])
  597. livenessSCCs
  598. :: Instruction instr
  599. => BlockMap RegSet
  600. -> [SCC (LiveBasicBlock instr)] -- accum
  601. -> [SCC (LiveBasicBlock instr)]
  602. -> ( [SCC (LiveBasicBlock instr)]
  603. , BlockMap RegSet)
  604. livenessSCCs blockmap done []
  605. = (done, blockmap)
  606. livenessSCCs blockmap done (AcyclicSCC block : sccs)
  607. = let (blockmap', block') = livenessBlock blockmap block
  608. in livenessSCCs blockmap' (AcyclicSCC block' : done) sccs
  609. livenessSCCs blockmap done
  610. (CyclicSCC blocks : sccs) =
  611. livenessSCCs blockmap' (CyclicSCC blocks':done) sccs
  612. where (blockmap', blocks')
  613. = iterateUntilUnchanged linearLiveness equalBlockMaps
  614. blockmap blocks
  615. iterateUntilUnchanged
  616. :: (a -> b -> (a,c)) -> (a -> a -> Bool)
  617. -> a -> b
  618. -> (a,c)
  619. iterateUntilUnchanged f eq a b
  620. = head $
  621. concatMap tail $
  622. groupBy (\(a1, _) (a2, _) -> eq a1 a2) $
  623. iterate (\(a, _) -> f a b) $
  624. (a, panic "RegLiveness.livenessSCCs")
  625. linearLiveness
  626. :: Instruction instr
  627. => BlockMap RegSet -> [LiveBasicBlock instr]
  628. -> (BlockMap RegSet, [LiveBasicBlock instr])
  629. linearLiveness = mapAccumL livenessBlock
  630. -- probably the least efficient way to compare two
  631. -- BlockMaps for equality.
  632. equalBlockMaps a b
  633. = a' == b'
  634. where a' = map f $ mapToList a
  635. b' = map f $ mapToList b
  636. f (key,elt) = (key, uniqSetToList elt)
  637. -- | Annotate a basic block with register liveness information.
  638. --
  639. livenessBlock
  640. :: Instruction instr
  641. => BlockMap RegSet
  642. -> LiveBasicBlock instr
  643. -> (BlockMap RegSet, LiveBasicBlock instr)
  644. livenessBlock blockmap (BasicBlock block_id instrs)
  645. = let
  646. (regsLiveOnEntry, instrs1)
  647. = livenessBack emptyUniqSet blockmap [] (reverse instrs)
  648. blockmap' = mapInsert block_id regsLiveOnEntry blockmap
  649. instrs2 = livenessForward regsLiveOnEntry instrs1
  650. output = BasicBlock block_id instrs2
  651. in ( blockmap', output)
  652. -- | Calculate liveness going forwards,
  653. -- filling in when regs are born
  654. livenessForward
  655. :: Instruction instr
  656. => RegSet -- regs live on this instr
  657. -> [LiveInstr instr] -> [LiveInstr instr]
  658. livenessForward _ [] = []
  659. livenessForward rsLiveEntry (li@(LiveInstr instr mLive) : lis)
  660. | Nothing <- mLive
  661. = li : livenessForward rsLiveEntry lis
  662. | Just live <- mLive
  663. , RU _ written <- regUsageOfInstr instr
  664. = let
  665. -- Regs that are written to but weren't live on entry to this instruction
  666. -- are recorded as being born here.
  667. rsBorn = mkUniqSet
  668. $ filter (\r -> not $ elementOfUniqSet r rsLiveEntry) written
  669. rsLiveNext = (rsLiveEntry `unionUniqSets` rsBorn)
  670. `minusUniqSet` (liveDieRead live)
  671. `minusUniqSet` (liveDieWrite live)
  672. in LiveInstr instr (Just live { liveBorn = rsBorn })
  673. : livenessForward rsLiveNext lis
  674. livenessForward _ _ = panic "RegLiveness.livenessForward: no match"
  675. -- | Calculate liveness going backwards,
  676. -- filling in when regs die, and what regs are live across each instruction
  677. livenessBack
  678. :: Instruction instr
  679. => RegSet -- regs live on this instr
  680. -> BlockMap RegSet -- regs live on entry to other BBs
  681. -> [LiveInstr instr] -- instructions (accum)
  682. -> [LiveInstr instr] -- instructions
  683. -> (RegSet, [LiveInstr instr])
  684. livenessBack liveregs _ done [] = (liveregs, done)
  685. livenessBack liveregs blockmap acc (instr : instrs)
  686. = let (liveregs', instr') = liveness1 liveregs blockmap instr
  687. in livenessBack liveregs' blockmap (instr' : acc) instrs
  688. -- don't bother tagging comments or deltas with liveness
  689. liveness1
  690. :: Instruction instr
  691. => RegSet
  692. -> BlockMap RegSet
  693. -> LiveInstr instr
  694. -> (RegSet, LiveInstr instr)
  695. liveness1 liveregs _ (LiveInstr instr _)
  696. | isMetaInstr instr
  697. = (liveregs, LiveInstr instr Nothing)
  698. liveness1 liveregs blockmap (LiveInstr instr _)
  699. | not_a_branch
  700. = (liveregs1, LiveInstr instr
  701. (Just $ Liveness
  702. { liveBorn = emptyUniqSet
  703. , liveDieRead = mkUniqSet r_dying
  704. , liveDieWrite = mkUniqSet w_dying }))
  705. | otherwise
  706. = (liveregs_br, LiveInstr instr
  707. (Just $ Liveness
  708. { liveBorn = emptyUniqSet
  709. , liveDieRead = mkUniqSet r_dying_br
  710. , liveDieWrite = mkUniqSet w_dying }))
  711. where
  712. RU read written = regUsageOfInstr instr
  713. -- registers that were written here are dead going backwards.
  714. -- registers that were read here are live going backwards.
  715. liveregs1 = (liveregs `delListFromUniqSet` written)
  716. `addListToUniqSet` read
  717. -- registers that are not live beyond this point, are recorded
  718. -- as dying here.
  719. r_dying = [ reg | reg <- read, reg `notElem` written,
  720. not (elementOfUniqSet reg liveregs) ]
  721. w_dying = [ reg | reg <- written,
  722. not (elementOfUniqSet reg liveregs) ]
  723. -- union in the live regs from all the jump destinations of this
  724. -- instruction.
  725. targets = jumpDestsOfInstr instr -- where we go from here
  726. not_a_branch = null targets
  727. targetLiveRegs target
  728. = case mapLookup target blockmap of
  729. Just ra -> ra
  730. Nothing -> emptyRegMap
  731. live_from_branch = unionManyUniqSets (map targetLiveRegs targets)
  732. liveregs_br = liveregs1 `unionUniqSets` live_from_branch
  733. -- registers that are live only in the branch targets should
  734. -- be listed as dying here.
  735. live_branch_only = live_from_branch `minusUniqSet` liveregs
  736. r_dying_br = uniqSetToList (mkUniqSet r_dying `unionUniqSets`
  737. live_branch_only)