PageRenderTime 66ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

/compiler/nativeGen/RegAlloc/Liveness.hs

https://bitbucket.org/carter/ghc
Haskell | 955 lines | 620 code | 213 blank | 122 comment | 6 complexity | 6c422c56fe10b290defcf6be39dcefd3 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 OldCmm hiding (RegSet)
  35. import OldPprCmm()
  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 sccs)
  197. = do sccs' <- mapM (mapSCCM f) sccs
  198. return $ CmmProc header label 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 (ListGraph blocks))
  220. = do blocks' <- mapM f blocks
  221. return $ CmmProc header label (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 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 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 [])
  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" (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 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. :: (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 [])
  525. | LiveInfo static mFirst _ _ <- info
  526. = return $ 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 return $ 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. :: (Outputable 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 platform 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. , ppr sccs])
  597. livenessSCCs
  598. :: Instruction instr
  599. => Platform
  600. -> BlockMap RegSet
  601. -> [SCC (LiveBasicBlock instr)] -- accum
  602. -> [SCC (LiveBasicBlock instr)]
  603. -> ( [SCC (LiveBasicBlock instr)]
  604. , BlockMap RegSet)
  605. livenessSCCs _ blockmap done []
  606. = (done, blockmap)
  607. livenessSCCs platform blockmap done (AcyclicSCC block : sccs)
  608. = let (blockmap', block') = livenessBlock platform blockmap block
  609. in livenessSCCs platform blockmap' (AcyclicSCC block' : done) sccs
  610. livenessSCCs platform blockmap done
  611. (CyclicSCC blocks : sccs) =
  612. livenessSCCs platform blockmap' (CyclicSCC blocks':done) sccs
  613. where (blockmap', blocks')
  614. = iterateUntilUnchanged linearLiveness equalBlockMaps
  615. blockmap blocks
  616. iterateUntilUnchanged
  617. :: (a -> b -> (a,c)) -> (a -> a -> Bool)
  618. -> a -> b
  619. -> (a,c)
  620. iterateUntilUnchanged f eq a b
  621. = head $
  622. concatMap tail $
  623. groupBy (\(a1, _) (a2, _) -> eq a1 a2) $
  624. iterate (\(a, _) -> f a b) $
  625. (a, panic "RegLiveness.livenessSCCs")
  626. linearLiveness
  627. :: Instruction instr
  628. => BlockMap RegSet -> [LiveBasicBlock instr]
  629. -> (BlockMap RegSet, [LiveBasicBlock instr])
  630. linearLiveness = mapAccumL (livenessBlock platform)
  631. -- probably the least efficient way to compare two
  632. -- BlockMaps for equality.
  633. equalBlockMaps a b
  634. = a' == b'
  635. where a' = map f $ mapToList a
  636. b' = map f $ mapToList b
  637. f (key,elt) = (key, uniqSetToList elt)
  638. -- | Annotate a basic block with register liveness information.
  639. --
  640. livenessBlock
  641. :: Instruction instr
  642. => Platform
  643. -> BlockMap RegSet
  644. -> LiveBasicBlock instr
  645. -> (BlockMap RegSet, LiveBasicBlock instr)
  646. livenessBlock platform blockmap (BasicBlock block_id instrs)
  647. = let
  648. (regsLiveOnEntry, instrs1)
  649. = livenessBack platform emptyUniqSet blockmap [] (reverse instrs)
  650. blockmap' = mapInsert block_id regsLiveOnEntry blockmap
  651. instrs2 = livenessForward platform regsLiveOnEntry instrs1
  652. output = BasicBlock block_id instrs2
  653. in ( blockmap', output)
  654. -- | Calculate liveness going forwards,
  655. -- filling in when regs are born
  656. livenessForward
  657. :: Instruction instr
  658. => Platform
  659. -> RegSet -- regs live on this instr
  660. -> [LiveInstr instr] -> [LiveInstr instr]
  661. livenessForward _ _ [] = []
  662. livenessForward platform rsLiveEntry (li@(LiveInstr instr mLive) : lis)
  663. | Nothing <- mLive
  664. = li : livenessForward platform rsLiveEntry lis
  665. | Just live <- mLive
  666. , RU _ written <- regUsageOfInstr platform instr
  667. = let
  668. -- Regs that are written to but weren't live on entry to this instruction
  669. -- are recorded as being born here.
  670. rsBorn = mkUniqSet
  671. $ filter (\r -> not $ elementOfUniqSet r rsLiveEntry) written
  672. rsLiveNext = (rsLiveEntry `unionUniqSets` rsBorn)
  673. `minusUniqSet` (liveDieRead live)
  674. `minusUniqSet` (liveDieWrite live)
  675. in LiveInstr instr (Just live { liveBorn = rsBorn })
  676. : livenessForward platform rsLiveNext lis
  677. livenessForward _ _ _ = panic "RegLiveness.livenessForward: no match"
  678. -- | Calculate liveness going backwards,
  679. -- filling in when regs die, and what regs are live across each instruction
  680. livenessBack
  681. :: Instruction instr
  682. => Platform
  683. -> RegSet -- regs live on this instr
  684. -> BlockMap RegSet -- regs live on entry to other BBs
  685. -> [LiveInstr instr] -- instructions (accum)
  686. -> [LiveInstr instr] -- instructions
  687. -> (RegSet, [LiveInstr instr])
  688. livenessBack _ liveregs _ done [] = (liveregs, done)
  689. livenessBack platform liveregs blockmap acc (instr : instrs)
  690. = let (liveregs', instr') = liveness1 platform liveregs blockmap instr
  691. in livenessBack platform liveregs' blockmap (instr' : acc) instrs
  692. -- don't bother tagging comments or deltas with liveness
  693. liveness1
  694. :: Instruction instr
  695. => Platform
  696. -> RegSet
  697. -> BlockMap RegSet
  698. -> LiveInstr instr
  699. -> (RegSet, LiveInstr instr)
  700. liveness1 _ liveregs _ (LiveInstr instr _)
  701. | isMetaInstr instr
  702. = (liveregs, LiveInstr instr Nothing)
  703. liveness1 platform liveregs blockmap (LiveInstr instr _)
  704. | not_a_branch
  705. = (liveregs1, LiveInstr instr
  706. (Just $ Liveness
  707. { liveBorn = emptyUniqSet
  708. , liveDieRead = mkUniqSet r_dying
  709. , liveDieWrite = mkUniqSet w_dying }))
  710. | otherwise
  711. = (liveregs_br, LiveInstr instr
  712. (Just $ Liveness
  713. { liveBorn = emptyUniqSet
  714. , liveDieRead = mkUniqSet r_dying_br
  715. , liveDieWrite = mkUniqSet w_dying }))
  716. where
  717. !(RU read written) = regUsageOfInstr platform instr
  718. -- registers that were written here are dead going backwards.
  719. -- registers that were read here are live going backwards.
  720. liveregs1 = (liveregs `delListFromUniqSet` written)
  721. `addListToUniqSet` read
  722. -- registers that are not live beyond this point, are recorded
  723. -- as dying here.
  724. r_dying = [ reg | reg <- read, reg `notElem` written,
  725. not (elementOfUniqSet reg liveregs) ]
  726. w_dying = [ reg | reg <- written,
  727. not (elementOfUniqSet reg liveregs) ]
  728. -- union in the live regs from all the jump destinations of this
  729. -- instruction.
  730. targets = jumpDestsOfInstr instr -- where we go from here
  731. not_a_branch = null targets
  732. targetLiveRegs target
  733. = case mapLookup target blockmap of
  734. Just ra -> ra
  735. Nothing -> emptyRegMap
  736. live_from_branch = unionManyUniqSets (map targetLiveRegs targets)
  737. liveregs_br = liveregs1 `unionUniqSets` live_from_branch
  738. -- registers that are live only in the branch targets should
  739. -- be listed as dying here.
  740. live_branch_only = live_from_branch `minusUniqSet` liveregs
  741. r_dying_br = uniqSetToList (mkUniqSet r_dying `unionUniqSets`
  742. live_branch_only)