PageRenderTime 30ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/compiler/nativeGen/RegAlloc/Linear/Main.hs

https://github.com/ezyang/ghc
Haskell | 911 lines | 472 code | 155 blank | 284 comment | 8 complexity | a5acf8704f0c9b687c0f97ab6fd7ca57 MD5 | raw file
  1. {-# LANGUAGE BangPatterns, CPP, ScopedTypeVariables #-}
  2. -----------------------------------------------------------------------------
  3. --
  4. -- The register allocator
  5. --
  6. -- (c) The University of Glasgow 2004
  7. --
  8. -----------------------------------------------------------------------------
  9. {-
  10. The algorithm is roughly:
  11. 1) Compute strongly connected components of the basic block list.
  12. 2) Compute liveness (mapping from pseudo register to
  13. point(s) of death?).
  14. 3) Walk instructions in each basic block. We keep track of
  15. (a) Free real registers (a bitmap?)
  16. (b) Current assignment of temporaries to machine registers and/or
  17. spill slots (call this the "assignment").
  18. (c) Partial mapping from basic block ids to a virt-to-loc mapping.
  19. When we first encounter a branch to a basic block,
  20. we fill in its entry in this table with the current mapping.
  21. For each instruction:
  22. (a) For each temporary *read* by the instruction:
  23. If the temporary does not have a real register allocation:
  24. - Allocate a real register from the free list. If
  25. the list is empty:
  26. - Find a temporary to spill. Pick one that is
  27. not used in this instruction (ToDo: not
  28. used for a while...)
  29. - generate a spill instruction
  30. - If the temporary was previously spilled,
  31. generate an instruction to read the temp from its spill loc.
  32. (optimisation: if we can see that a real register is going to
  33. be used soon, then don't use it for allocation).
  34. (b) For each real register clobbered by this instruction:
  35. If a temporary resides in it,
  36. If the temporary is live after this instruction,
  37. Move the temporary to another (non-clobbered & free) reg,
  38. or spill it to memory. Mark the temporary as residing
  39. in both memory and a register if it was spilled (it might
  40. need to be read by this instruction).
  41. (ToDo: this is wrong for jump instructions?)
  42. We do this after step (a), because if we start with
  43. movq v1, %rsi
  44. which is an instruction that clobbers %rsi, if v1 currently resides
  45. in %rsi we want to get
  46. movq %rsi, %freereg
  47. movq %rsi, %rsi -- will disappear
  48. instead of
  49. movq %rsi, %freereg
  50. movq %freereg, %rsi
  51. (c) Update the current assignment
  52. (d) If the instruction is a branch:
  53. if the destination block already has a register assignment,
  54. Generate a new block with fixup code and redirect the
  55. jump to the new block.
  56. else,
  57. Update the block id->assignment mapping with the current
  58. assignment.
  59. (e) Delete all register assignments for temps which are read
  60. (only) and die here. Update the free register list.
  61. (f) Mark all registers clobbered by this instruction as not free,
  62. and mark temporaries which have been spilled due to clobbering
  63. as in memory (step (a) marks then as in both mem & reg).
  64. (g) For each temporary *written* by this instruction:
  65. Allocate a real register as for (b), spilling something
  66. else if necessary.
  67. - except when updating the assignment, drop any memory
  68. locations that the temporary was previously in, since
  69. they will be no longer valid after this instruction.
  70. (h) Delete all register assignments for temps which are
  71. written and die here (there should rarely be any). Update
  72. the free register list.
  73. (i) Rewrite the instruction with the new mapping.
  74. (j) For each spilled reg known to be now dead, re-add its stack slot
  75. to the free list.
  76. -}
  77. module RegAlloc.Linear.Main (
  78. regAlloc,
  79. module RegAlloc.Linear.Base,
  80. module RegAlloc.Linear.Stats
  81. ) where
  82. #include "HsVersions.h"
  83. import GhcPrelude
  84. import RegAlloc.Linear.State
  85. import RegAlloc.Linear.Base
  86. import RegAlloc.Linear.StackMap
  87. import RegAlloc.Linear.FreeRegs
  88. import RegAlloc.Linear.Stats
  89. import RegAlloc.Linear.JoinToTargets
  90. import qualified RegAlloc.Linear.PPC.FreeRegs as PPC
  91. import qualified RegAlloc.Linear.SPARC.FreeRegs as SPARC
  92. import qualified RegAlloc.Linear.X86.FreeRegs as X86
  93. import qualified RegAlloc.Linear.X86_64.FreeRegs as X86_64
  94. import TargetReg
  95. import RegAlloc.Liveness
  96. import Instruction
  97. import Reg
  98. import BlockId
  99. import Hoopl.Collections
  100. import Cmm hiding (RegSet)
  101. import Digraph
  102. import DynFlags
  103. import Unique
  104. import UniqSet
  105. import UniqFM
  106. import UniqSupply
  107. import Outputable
  108. import Platform
  109. import Data.Maybe
  110. import Data.List
  111. import Control.Monad
  112. -- -----------------------------------------------------------------------------
  113. -- Top level of the register allocator
  114. -- Allocate registers
  115. regAlloc
  116. :: (Outputable instr, Instruction instr)
  117. => DynFlags
  118. -> LiveCmmDecl statics instr
  119. -> UniqSM ( NatCmmDecl statics instr
  120. , Maybe Int -- number of extra stack slots required,
  121. -- beyond maxSpillSlots
  122. , Maybe RegAllocStats)
  123. regAlloc _ (CmmData sec d)
  124. = return
  125. ( CmmData sec d
  126. , Nothing
  127. , Nothing )
  128. regAlloc _ (CmmProc (LiveInfo info _ _ _) lbl live [])
  129. = return ( CmmProc info lbl live (ListGraph [])
  130. , Nothing
  131. , Nothing )
  132. regAlloc dflags (CmmProc static lbl live sccs)
  133. | LiveInfo info entry_ids@(first_id:_) (Just block_live) _ <- static
  134. = do
  135. -- do register allocation on each component.
  136. (final_blocks, stats, stack_use)
  137. <- linearRegAlloc dflags entry_ids block_live sccs
  138. -- make sure the block that was first in the input list
  139. -- stays at the front of the output
  140. let ((first':_), rest')
  141. = partition ((== first_id) . blockId) final_blocks
  142. let max_spill_slots = maxSpillSlots dflags
  143. extra_stack
  144. | stack_use > max_spill_slots
  145. = Just (stack_use - max_spill_slots)
  146. | otherwise
  147. = Nothing
  148. return ( CmmProc info lbl live (ListGraph (first' : rest'))
  149. , extra_stack
  150. , Just stats)
  151. -- bogus. to make non-exhaustive match warning go away.
  152. regAlloc _ (CmmProc _ _ _ _)
  153. = panic "RegAllocLinear.regAlloc: no match"
  154. -- -----------------------------------------------------------------------------
  155. -- Linear sweep to allocate registers
  156. -- | Do register allocation on some basic blocks.
  157. -- But be careful to allocate a block in an SCC only if it has
  158. -- an entry in the block map or it is the first block.
  159. --
  160. linearRegAlloc
  161. :: (Outputable instr, Instruction instr)
  162. => DynFlags
  163. -> [BlockId] -- ^ entry points
  164. -> BlockMap RegSet
  165. -- ^ live regs on entry to each basic block
  166. -> [SCC (LiveBasicBlock instr)]
  167. -- ^ instructions annotated with "deaths"
  168. -> UniqSM ([NatBasicBlock instr], RegAllocStats, Int)
  169. linearRegAlloc dflags entry_ids block_live sccs
  170. = case platformArch platform of
  171. ArchX86 -> go $ (frInitFreeRegs platform :: X86.FreeRegs)
  172. ArchX86_64 -> go $ (frInitFreeRegs platform :: X86_64.FreeRegs)
  173. ArchSPARC -> go $ (frInitFreeRegs platform :: SPARC.FreeRegs)
  174. ArchSPARC64 -> panic "linearRegAlloc ArchSPARC64"
  175. ArchPPC -> go $ (frInitFreeRegs platform :: PPC.FreeRegs)
  176. ArchARM _ _ _ -> panic "linearRegAlloc ArchARM"
  177. ArchARM64 -> panic "linearRegAlloc ArchARM64"
  178. ArchPPC_64 _ -> go $ (frInitFreeRegs platform :: PPC.FreeRegs)
  179. ArchAlpha -> panic "linearRegAlloc ArchAlpha"
  180. ArchMipseb -> panic "linearRegAlloc ArchMipseb"
  181. ArchMipsel -> panic "linearRegAlloc ArchMipsel"
  182. ArchJavaScript -> panic "linearRegAlloc ArchJavaScript"
  183. ArchUnknown -> panic "linearRegAlloc ArchUnknown"
  184. where
  185. go f = linearRegAlloc' dflags f entry_ids block_live sccs
  186. platform = targetPlatform dflags
  187. linearRegAlloc'
  188. :: (FR freeRegs, Outputable instr, Instruction instr)
  189. => DynFlags
  190. -> freeRegs
  191. -> [BlockId] -- ^ entry points
  192. -> BlockMap RegSet -- ^ live regs on entry to each basic block
  193. -> [SCC (LiveBasicBlock instr)] -- ^ instructions annotated with "deaths"
  194. -> UniqSM ([NatBasicBlock instr], RegAllocStats, Int)
  195. linearRegAlloc' dflags initFreeRegs entry_ids block_live sccs
  196. = do us <- getUniqueSupplyM
  197. let (_, stack, stats, blocks) =
  198. runR dflags mapEmpty initFreeRegs emptyRegMap (emptyStackMap dflags) us
  199. $ linearRA_SCCs entry_ids block_live [] sccs
  200. return (blocks, stats, getStackUse stack)
  201. linearRA_SCCs :: (FR freeRegs, Instruction instr, Outputable instr)
  202. => [BlockId]
  203. -> BlockMap RegSet
  204. -> [NatBasicBlock instr]
  205. -> [SCC (LiveBasicBlock instr)]
  206. -> RegM freeRegs [NatBasicBlock instr]
  207. linearRA_SCCs _ _ blocksAcc []
  208. = return $ reverse blocksAcc
  209. linearRA_SCCs entry_ids block_live blocksAcc (AcyclicSCC block : sccs)
  210. = do blocks' <- processBlock block_live block
  211. linearRA_SCCs entry_ids block_live
  212. ((reverse blocks') ++ blocksAcc)
  213. sccs
  214. linearRA_SCCs entry_ids block_live blocksAcc (CyclicSCC blocks : sccs)
  215. = do
  216. blockss' <- process entry_ids block_live blocks [] (return []) False
  217. linearRA_SCCs entry_ids block_live
  218. (reverse (concat blockss') ++ blocksAcc)
  219. sccs
  220. {- from John Dias's patch 2008/10/16:
  221. The linear-scan allocator sometimes allocates a block
  222. before allocating one of its predecessors, which could lead to
  223. inconsistent allocations. Make it so a block is only allocated
  224. if a predecessor has set the "incoming" assignments for the block, or
  225. if it's the procedure's entry block.
  226. BL 2009/02: Careful. If the assignment for a block doesn't get set for
  227. some reason then this function will loop. We should probably do some
  228. more sanity checking to guard against this eventuality.
  229. -}
  230. process :: (FR freeRegs, Instruction instr, Outputable instr)
  231. => [BlockId]
  232. -> BlockMap RegSet
  233. -> [GenBasicBlock (LiveInstr instr)]
  234. -> [GenBasicBlock (LiveInstr instr)]
  235. -> [[NatBasicBlock instr]]
  236. -> Bool
  237. -> RegM freeRegs [[NatBasicBlock instr]]
  238. process _ _ [] [] accum _
  239. = return $ reverse accum
  240. process entry_ids block_live [] next_round accum madeProgress
  241. | not madeProgress
  242. {- BUGS: There are so many unreachable blocks in the code the warnings are overwhelming.
  243. pprTrace "RegAlloc.Linear.Main.process: no progress made, bailing out."
  244. ( text "Unreachable blocks:"
  245. $$ vcat (map ppr next_round)) -}
  246. = return $ reverse accum
  247. | otherwise
  248. = process entry_ids block_live
  249. next_round [] accum False
  250. process entry_ids block_live (b@(BasicBlock id _) : blocks)
  251. next_round accum madeProgress
  252. = do
  253. block_assig <- getBlockAssigR
  254. if isJust (mapLookup id block_assig)
  255. || id `elem` entry_ids
  256. then do
  257. b' <- processBlock block_live b
  258. process entry_ids block_live blocks
  259. next_round (b' : accum) True
  260. else process entry_ids block_live blocks
  261. (b : next_round) accum madeProgress
  262. -- | Do register allocation on this basic block
  263. --
  264. processBlock
  265. :: (FR freeRegs, Outputable instr, Instruction instr)
  266. => BlockMap RegSet -- ^ live regs on entry to each basic block
  267. -> LiveBasicBlock instr -- ^ block to do register allocation on
  268. -> RegM freeRegs [NatBasicBlock instr] -- ^ block with registers allocated
  269. processBlock block_live (BasicBlock id instrs)
  270. = do initBlock id block_live
  271. (instrs', fixups)
  272. <- linearRA block_live [] [] id instrs
  273. return $ BasicBlock id instrs' : fixups
  274. -- | Load the freeregs and current reg assignment into the RegM state
  275. -- for the basic block with this BlockId.
  276. initBlock :: FR freeRegs
  277. => BlockId -> BlockMap RegSet -> RegM freeRegs ()
  278. initBlock id block_live
  279. = do dflags <- getDynFlags
  280. let platform = targetPlatform dflags
  281. block_assig <- getBlockAssigR
  282. case mapLookup id block_assig of
  283. -- no prior info about this block: we must consider
  284. -- any fixed regs to be allocated, but we can ignore
  285. -- virtual regs (presumably this is part of a loop,
  286. -- and we'll iterate again). The assignment begins
  287. -- empty.
  288. Nothing
  289. -> do -- pprTrace "initFreeRegs" (text $ show initFreeRegs) (return ())
  290. case mapLookup id block_live of
  291. Nothing ->
  292. setFreeRegsR (frInitFreeRegs platform)
  293. Just live ->
  294. setFreeRegsR $ foldl' (flip $ frAllocateReg platform) (frInitFreeRegs platform)
  295. [ r | RegReal r <- nonDetEltsUniqSet live ]
  296. -- See Note [Unique Determinism and code generation]
  297. setAssigR emptyRegMap
  298. -- load info about register assignments leading into this block.
  299. Just (freeregs, assig)
  300. -> do setFreeRegsR freeregs
  301. setAssigR assig
  302. -- | Do allocation for a sequence of instructions.
  303. linearRA
  304. :: (FR freeRegs, Outputable instr, Instruction instr)
  305. => BlockMap RegSet -- ^ map of what vregs are live on entry to each block.
  306. -> [instr] -- ^ accumulator for instructions already processed.
  307. -> [NatBasicBlock instr] -- ^ accumulator for blocks of fixup code.
  308. -> BlockId -- ^ id of the current block, for debugging.
  309. -> [LiveInstr instr] -- ^ liveness annotated instructions in this block.
  310. -> RegM freeRegs
  311. ( [instr] -- instructions after register allocation
  312. , [NatBasicBlock instr]) -- fresh blocks of fixup code.
  313. linearRA _ accInstr accFixup _ []
  314. = return
  315. ( reverse accInstr -- instrs need to be returned in the correct order.
  316. , accFixup) -- it doesn't matter what order the fixup blocks are returned in.
  317. linearRA block_live accInstr accFixups id (instr:instrs)
  318. = do
  319. (accInstr', new_fixups) <- raInsn block_live accInstr id instr
  320. linearRA block_live accInstr' (new_fixups ++ accFixups) id instrs
  321. -- | Do allocation for a single instruction.
  322. raInsn
  323. :: (FR freeRegs, Outputable instr, Instruction instr)
  324. => BlockMap RegSet -- ^ map of what vregs are love on entry to each block.
  325. -> [instr] -- ^ accumulator for instructions already processed.
  326. -> BlockId -- ^ the id of the current block, for debugging
  327. -> LiveInstr instr -- ^ the instr to have its regs allocated, with liveness info.
  328. -> RegM freeRegs
  329. ( [instr] -- new instructions
  330. , [NatBasicBlock instr]) -- extra fixup blocks
  331. raInsn _ new_instrs _ (LiveInstr ii Nothing)
  332. | Just n <- takeDeltaInstr ii
  333. = do setDeltaR n
  334. return (new_instrs, [])
  335. raInsn _ new_instrs _ (LiveInstr ii@(Instr i) Nothing)
  336. | isMetaInstr ii
  337. = return (i : new_instrs, [])
  338. raInsn block_live new_instrs id (LiveInstr (Instr instr) (Just live))
  339. = do
  340. assig <- getAssigR
  341. -- If we have a reg->reg move between virtual registers, where the
  342. -- src register is not live after this instruction, and the dst
  343. -- register does not already have an assignment,
  344. -- and the source register is assigned to a register, not to a spill slot,
  345. -- then we can eliminate the instruction.
  346. -- (we can't eliminate it if the source register is on the stack, because
  347. -- we do not want to use one spill slot for different virtual registers)
  348. case takeRegRegMoveInstr instr of
  349. Just (src,dst) | src `elementOfUniqSet` (liveDieRead live),
  350. isVirtualReg dst,
  351. not (dst `elemUFM` assig),
  352. isRealReg src || isInReg src assig -> do
  353. case src of
  354. (RegReal rr) -> setAssigR (addToUFM assig dst (InReg rr))
  355. -- if src is a fixed reg, then we just map dest to this
  356. -- reg in the assignment. src must be an allocatable reg,
  357. -- otherwise it wouldn't be in r_dying.
  358. _virt -> case lookupUFM assig src of
  359. Nothing -> panic "raInsn"
  360. Just loc ->
  361. setAssigR (addToUFM (delFromUFM assig src) dst loc)
  362. -- we have eliminated this instruction
  363. {-
  364. freeregs <- getFreeRegsR
  365. assig <- getAssigR
  366. pprTrace "raInsn" (text "ELIMINATED: " <> docToSDoc (pprInstr instr)
  367. $$ ppr r_dying <+> ppr w_dying $$ text (show freeregs) $$ ppr assig) $ do
  368. -}
  369. return (new_instrs, [])
  370. _ -> genRaInsn block_live new_instrs id instr
  371. (nonDetEltsUniqSet $ liveDieRead live)
  372. (nonDetEltsUniqSet $ liveDieWrite live)
  373. -- See Note [Unique Determinism and code generation]
  374. raInsn _ _ _ instr
  375. = pprPanic "raInsn" (text "no match for:" <> ppr instr)
  376. -- ToDo: what can we do about
  377. --
  378. -- R1 = x
  379. -- jump I64[x] // [R1]
  380. --
  381. -- where x is mapped to the same reg as R1. We want to coalesce x and
  382. -- R1, but the register allocator doesn't know whether x will be
  383. -- assigned to again later, in which case x and R1 should be in
  384. -- different registers. Right now we assume the worst, and the
  385. -- assignment to R1 will clobber x, so we'll spill x into another reg,
  386. -- generating another reg->reg move.
  387. isInReg :: Reg -> RegMap Loc -> Bool
  388. isInReg src assig | Just (InReg _) <- lookupUFM assig src = True
  389. | otherwise = False
  390. genRaInsn :: (FR freeRegs, Instruction instr, Outputable instr)
  391. => BlockMap RegSet
  392. -> [instr]
  393. -> BlockId
  394. -> instr
  395. -> [Reg]
  396. -> [Reg]
  397. -> RegM freeRegs ([instr], [NatBasicBlock instr])
  398. genRaInsn block_live new_instrs block_id instr r_dying w_dying = do
  399. dflags <- getDynFlags
  400. let platform = targetPlatform dflags
  401. case regUsageOfInstr platform instr of { RU read written ->
  402. do
  403. let real_written = [ rr | (RegReal rr) <- written ]
  404. let virt_written = [ vr | (RegVirtual vr) <- written ]
  405. -- we don't need to do anything with real registers that are
  406. -- only read by this instr. (the list is typically ~2 elements,
  407. -- so using nub isn't a problem).
  408. let virt_read = nub [ vr | (RegVirtual vr) <- read ]
  409. -- debugging
  410. {- freeregs <- getFreeRegsR
  411. assig <- getAssigR
  412. pprDebugAndThen (defaultDynFlags Settings{ sTargetPlatform=platform } undefined) trace "genRaInsn"
  413. (ppr instr
  414. $$ text "r_dying = " <+> ppr r_dying
  415. $$ text "w_dying = " <+> ppr w_dying
  416. $$ text "virt_read = " <+> ppr virt_read
  417. $$ text "virt_written = " <+> ppr virt_written
  418. $$ text "freeregs = " <+> text (show freeregs)
  419. $$ text "assig = " <+> ppr assig)
  420. $ do
  421. -}
  422. -- (a), (b) allocate real regs for all regs read by this instruction.
  423. (r_spills, r_allocd) <-
  424. allocateRegsAndSpill True{-reading-} virt_read [] [] virt_read
  425. -- (c) save any temporaries which will be clobbered by this instruction
  426. clobber_saves <- saveClobberedTemps real_written r_dying
  427. -- (d) Update block map for new destinations
  428. -- NB. do this before removing dead regs from the assignment, because
  429. -- these dead regs might in fact be live in the jump targets (they're
  430. -- only dead in the code that follows in the current basic block).
  431. (fixup_blocks, adjusted_instr)
  432. <- joinToTargets block_live block_id instr
  433. -- (e) Delete all register assignments for temps which are read
  434. -- (only) and die here. Update the free register list.
  435. releaseRegs r_dying
  436. -- (f) Mark regs which are clobbered as unallocatable
  437. clobberRegs real_written
  438. -- (g) Allocate registers for temporaries *written* (only)
  439. (w_spills, w_allocd) <-
  440. allocateRegsAndSpill False{-writing-} virt_written [] [] virt_written
  441. -- (h) Release registers for temps which are written here and not
  442. -- used again.
  443. releaseRegs w_dying
  444. let
  445. -- (i) Patch the instruction
  446. patch_map
  447. = listToUFM
  448. [ (t, RegReal r)
  449. | (t, r) <- zip virt_read r_allocd
  450. ++ zip virt_written w_allocd ]
  451. patched_instr
  452. = patchRegsOfInstr adjusted_instr patchLookup
  453. patchLookup x
  454. = case lookupUFM patch_map x of
  455. Nothing -> x
  456. Just y -> y
  457. -- (j) free up stack slots for dead spilled regs
  458. -- TODO (can't be bothered right now)
  459. -- erase reg->reg moves where the source and destination are the same.
  460. -- If the src temp didn't die in this instr but happened to be allocated
  461. -- to the same real reg as the destination, then we can erase the move anyway.
  462. let squashed_instr = case takeRegRegMoveInstr patched_instr of
  463. Just (src, dst)
  464. | src == dst -> []
  465. _ -> [patched_instr]
  466. let code = squashed_instr ++ w_spills ++ reverse r_spills
  467. ++ clobber_saves ++ new_instrs
  468. -- pprTrace "patched-code" ((vcat $ map (docToSDoc . pprInstr) code)) $ do
  469. -- pprTrace "pached-fixup" ((ppr fixup_blocks)) $ do
  470. return (code, fixup_blocks)
  471. }
  472. -- -----------------------------------------------------------------------------
  473. -- releaseRegs
  474. releaseRegs :: FR freeRegs => [Reg] -> RegM freeRegs ()
  475. releaseRegs regs = do
  476. dflags <- getDynFlags
  477. let platform = targetPlatform dflags
  478. assig <- getAssigR
  479. free <- getFreeRegsR
  480. let loop assig !free [] = do setAssigR assig; setFreeRegsR free; return ()
  481. loop assig !free (RegReal rr : rs) = loop assig (frReleaseReg platform rr free) rs
  482. loop assig !free (r:rs) =
  483. case lookupUFM assig r of
  484. Just (InBoth real _) -> loop (delFromUFM assig r)
  485. (frReleaseReg platform real free) rs
  486. Just (InReg real) -> loop (delFromUFM assig r)
  487. (frReleaseReg platform real free) rs
  488. _ -> loop (delFromUFM assig r) free rs
  489. loop assig free regs
  490. -- -----------------------------------------------------------------------------
  491. -- Clobber real registers
  492. -- For each temp in a register that is going to be clobbered:
  493. -- - if the temp dies after this instruction, do nothing
  494. -- - otherwise, put it somewhere safe (another reg if possible,
  495. -- otherwise spill and record InBoth in the assignment).
  496. -- - for allocateRegs on the temps *read*,
  497. -- - clobbered regs are allocatable.
  498. --
  499. -- for allocateRegs on the temps *written*,
  500. -- - clobbered regs are not allocatable.
  501. --
  502. saveClobberedTemps
  503. :: (Instruction instr, FR freeRegs)
  504. => [RealReg] -- real registers clobbered by this instruction
  505. -> [Reg] -- registers which are no longer live after this insn
  506. -> RegM freeRegs [instr] -- return: instructions to spill any temps that will
  507. -- be clobbered.
  508. saveClobberedTemps [] _
  509. = return []
  510. saveClobberedTemps clobbered dying
  511. = do
  512. assig <- getAssigR
  513. let to_spill
  514. = [ (temp,reg)
  515. | (temp, InReg reg) <- nonDetUFMToList assig
  516. -- This is non-deterministic but we do not
  517. -- currently support deterministic code-generation.
  518. -- See Note [Unique Determinism and code generation]
  519. , any (realRegsAlias reg) clobbered
  520. , temp `notElem` map getUnique dying ]
  521. (instrs,assig') <- clobber assig [] to_spill
  522. setAssigR assig'
  523. return instrs
  524. where
  525. clobber assig instrs []
  526. = return (instrs, assig)
  527. clobber assig instrs ((temp, reg) : rest)
  528. = do dflags <- getDynFlags
  529. let platform = targetPlatform dflags
  530. freeRegs <- getFreeRegsR
  531. let regclass = targetClassOfRealReg platform reg
  532. freeRegs_thisClass = frGetFreeRegs platform regclass freeRegs
  533. case filter (`notElem` clobbered) freeRegs_thisClass of
  534. -- (1) we have a free reg of the right class that isn't
  535. -- clobbered by this instruction; use it to save the
  536. -- clobbered value.
  537. (my_reg : _) -> do
  538. setFreeRegsR (frAllocateReg platform my_reg freeRegs)
  539. let new_assign = addToUFM assig temp (InReg my_reg)
  540. let instr = mkRegRegMoveInstr platform
  541. (RegReal reg) (RegReal my_reg)
  542. clobber new_assign (instr : instrs) rest
  543. -- (2) no free registers: spill the value
  544. [] -> do
  545. (spill, slot) <- spillR (RegReal reg) temp
  546. -- record why this reg was spilled for profiling
  547. recordSpill (SpillClobber temp)
  548. let new_assign = addToUFM assig temp (InBoth reg slot)
  549. clobber new_assign (spill : instrs) rest
  550. -- | Mark all these real regs as allocated,
  551. -- and kick out their vreg assignments.
  552. --
  553. clobberRegs :: FR freeRegs => [RealReg] -> RegM freeRegs ()
  554. clobberRegs []
  555. = return ()
  556. clobberRegs clobbered
  557. = do dflags <- getDynFlags
  558. let platform = targetPlatform dflags
  559. freeregs <- getFreeRegsR
  560. setFreeRegsR $! foldl' (flip $ frAllocateReg platform) freeregs clobbered
  561. assig <- getAssigR
  562. setAssigR $! clobber assig (nonDetUFMToList assig)
  563. -- This is non-deterministic but we do not
  564. -- currently support deterministic code-generation.
  565. -- See Note [Unique Determinism and code generation]
  566. where
  567. -- if the temp was InReg and clobbered, then we will have
  568. -- saved it in saveClobberedTemps above. So the only case
  569. -- we have to worry about here is InBoth. Note that this
  570. -- also catches temps which were loaded up during allocation
  571. -- of read registers, not just those saved in saveClobberedTemps.
  572. clobber assig []
  573. = assig
  574. clobber assig ((temp, InBoth reg slot) : rest)
  575. | any (realRegsAlias reg) clobbered
  576. = clobber (addToUFM assig temp (InMem slot)) rest
  577. clobber assig (_:rest)
  578. = clobber assig rest
  579. -- -----------------------------------------------------------------------------
  580. -- allocateRegsAndSpill
  581. -- Why are we performing a spill?
  582. data SpillLoc = ReadMem StackSlot -- reading from register only in memory
  583. | WriteNew -- writing to a new variable
  584. | WriteMem -- writing to register only in memory
  585. -- Note that ReadNew is not valid, since you don't want to be reading
  586. -- from an uninitialized register. We also don't need the location of
  587. -- the register in memory, since that will be invalidated by the write.
  588. -- Technically, we could coalesce WriteNew and WriteMem into a single
  589. -- entry as well. -- EZY
  590. -- This function does several things:
  591. -- For each temporary referred to by this instruction,
  592. -- we allocate a real register (spilling another temporary if necessary).
  593. -- We load the temporary up from memory if necessary.
  594. -- We also update the register assignment in the process, and
  595. -- the list of free registers and free stack slots.
  596. allocateRegsAndSpill
  597. :: (FR freeRegs, Outputable instr, Instruction instr)
  598. => Bool -- True <=> reading (load up spilled regs)
  599. -> [VirtualReg] -- don't push these out
  600. -> [instr] -- spill insns
  601. -> [RealReg] -- real registers allocated (accum.)
  602. -> [VirtualReg] -- temps to allocate
  603. -> RegM freeRegs ( [instr] , [RealReg])
  604. allocateRegsAndSpill _ _ spills alloc []
  605. = return (spills, reverse alloc)
  606. allocateRegsAndSpill reading keep spills alloc (r:rs)
  607. = do assig <- getAssigR
  608. let doSpill = allocRegsAndSpill_spill reading keep spills alloc r rs assig
  609. case lookupUFM assig r of
  610. -- case (1a): already in a register
  611. Just (InReg my_reg) ->
  612. allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
  613. -- case (1b): already in a register (and memory)
  614. -- NB1. if we're writing this register, update its assignment to be
  615. -- InReg, because the memory value is no longer valid.
  616. -- NB2. This is why we must process written registers here, even if they
  617. -- are also read by the same instruction.
  618. Just (InBoth my_reg _)
  619. -> do when (not reading) (setAssigR (addToUFM assig r (InReg my_reg)))
  620. allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
  621. -- Not already in a register, so we need to find a free one...
  622. Just (InMem slot) | reading -> doSpill (ReadMem slot)
  623. | otherwise -> doSpill WriteMem
  624. Nothing | reading ->
  625. pprPanic "allocateRegsAndSpill: Cannot read from uninitialized register" (ppr r)
  626. -- NOTE: if the input to the NCG contains some
  627. -- unreachable blocks with junk code, this panic
  628. -- might be triggered. Make sure you only feed
  629. -- sensible code into the NCG. In CmmPipeline we
  630. -- call removeUnreachableBlocks at the end for this
  631. -- reason.
  632. | otherwise -> doSpill WriteNew
  633. -- reading is redundant with reason, but we keep it around because it's
  634. -- convenient and it maintains the recursive structure of the allocator. -- EZY
  635. allocRegsAndSpill_spill :: (FR freeRegs, Instruction instr, Outputable instr)
  636. => Bool
  637. -> [VirtualReg]
  638. -> [instr]
  639. -> [RealReg]
  640. -> VirtualReg
  641. -> [VirtualReg]
  642. -> UniqFM Loc
  643. -> SpillLoc
  644. -> RegM freeRegs ([instr], [RealReg])
  645. allocRegsAndSpill_spill reading keep spills alloc r rs assig spill_loc
  646. = do dflags <- getDynFlags
  647. let platform = targetPlatform dflags
  648. freeRegs <- getFreeRegsR
  649. let freeRegs_thisClass = frGetFreeRegs platform (classOfVirtualReg r) freeRegs
  650. case freeRegs_thisClass of
  651. -- case (2): we have a free register
  652. (my_reg : _) ->
  653. do spills' <- loadTemp r spill_loc my_reg spills
  654. setAssigR (addToUFM assig r $! newLocation spill_loc my_reg)
  655. setFreeRegsR $ frAllocateReg platform my_reg freeRegs
  656. allocateRegsAndSpill reading keep spills' (my_reg : alloc) rs
  657. -- case (3): we need to push something out to free up a register
  658. [] ->
  659. do let inRegOrBoth (InReg _) = True
  660. inRegOrBoth (InBoth _ _) = True
  661. inRegOrBoth _ = False
  662. let candidates' =
  663. flip delListFromUFM keep $
  664. filterUFM inRegOrBoth $
  665. assig
  666. -- This is non-deterministic but we do not
  667. -- currently support deterministic code-generation.
  668. -- See Note [Unique Determinism and code generation]
  669. let candidates = nonDetUFMToList candidates'
  670. -- the vregs we could kick out that are already in a slot
  671. let candidates_inBoth
  672. = [ (temp, reg, mem)
  673. | (temp, InBoth reg mem) <- candidates
  674. , targetClassOfRealReg platform reg == classOfVirtualReg r ]
  675. -- the vregs we could kick out that are only in a reg
  676. -- this would require writing the reg to a new slot before using it.
  677. let candidates_inReg
  678. = [ (temp, reg)
  679. | (temp, InReg reg) <- candidates
  680. , targetClassOfRealReg platform reg == classOfVirtualReg r ]
  681. let result
  682. -- we have a temporary that is in both register and mem,
  683. -- just free up its register for use.
  684. | (temp, my_reg, slot) : _ <- candidates_inBoth
  685. = do spills' <- loadTemp r spill_loc my_reg spills
  686. let assig1 = addToUFM assig temp (InMem slot)
  687. let assig2 = addToUFM assig1 r $! newLocation spill_loc my_reg
  688. setAssigR assig2
  689. allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
  690. -- otherwise, we need to spill a temporary that currently
  691. -- resides in a register.
  692. | (temp_to_push_out, (my_reg :: RealReg)) : _
  693. <- candidates_inReg
  694. = do
  695. (spill_insn, slot) <- spillR (RegReal my_reg) temp_to_push_out
  696. let spill_store = (if reading then id else reverse)
  697. [ -- COMMENT (fsLit "spill alloc")
  698. spill_insn ]
  699. -- record that this temp was spilled
  700. recordSpill (SpillAlloc temp_to_push_out)
  701. -- update the register assignment
  702. let assig1 = addToUFM assig temp_to_push_out (InMem slot)
  703. let assig2 = addToUFM assig1 r $! newLocation spill_loc my_reg
  704. setAssigR assig2
  705. -- if need be, load up a spilled temp into the reg we've just freed up.
  706. spills' <- loadTemp r spill_loc my_reg spills
  707. allocateRegsAndSpill reading keep
  708. (spill_store ++ spills')
  709. (my_reg:alloc) rs
  710. -- there wasn't anything to spill, so we're screwed.
  711. | otherwise
  712. = pprPanic ("RegAllocLinear.allocRegsAndSpill: no spill candidates\n")
  713. $ vcat
  714. [ text "allocating vreg: " <> text (show r)
  715. , text "assignment: " <> ppr assig
  716. , text "freeRegs: " <> text (show freeRegs)
  717. , text "initFreeRegs: " <> text (show (frInitFreeRegs platform `asTypeOf` freeRegs)) ]
  718. result
  719. -- | Calculate a new location after a register has been loaded.
  720. newLocation :: SpillLoc -> RealReg -> Loc
  721. -- if the tmp was read from a slot, then now its in a reg as well
  722. newLocation (ReadMem slot) my_reg = InBoth my_reg slot
  723. -- writes will always result in only the register being available
  724. newLocation _ my_reg = InReg my_reg
  725. -- | Load up a spilled temporary if we need to (read from memory).
  726. loadTemp
  727. :: (Instruction instr)
  728. => VirtualReg -- the temp being loaded
  729. -> SpillLoc -- the current location of this temp
  730. -> RealReg -- the hreg to load the temp into
  731. -> [instr]
  732. -> RegM freeRegs [instr]
  733. loadTemp vreg (ReadMem slot) hreg spills
  734. = do
  735. insn <- loadR (RegReal hreg) slot
  736. recordSpill (SpillLoad $ getUnique vreg)
  737. return $ {- COMMENT (fsLit "spill load") : -} insn : spills
  738. loadTemp _ _ _ spills =
  739. return spills