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

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

https://github.com/albertz/ghc
Haskell | 747 lines | 360 code | 144 blank | 243 comment | 8 complexity | c800b0cb96adec55645fc691f20b79c8 MD5 | raw file
  1. {-# OPTIONS -fno-warn-missing-signatures #-}
  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 real register clobbered by this instruction:
  23. If a temporary resides in it,
  24. If the temporary is live after this instruction,
  25. Move the temporary to another (non-clobbered & free) reg,
  26. or spill it to memory. Mark the temporary as residing
  27. in both memory and a register if it was spilled (it might
  28. need to be read by this instruction).
  29. (ToDo: this is wrong for jump instructions?)
  30. (b) For each temporary *read* by the instruction:
  31. If the temporary does not have a real register allocation:
  32. - Allocate a real register from the free list. If
  33. the list is empty:
  34. - Find a temporary to spill. Pick one that is
  35. not used in this instruction (ToDo: not
  36. used for a while...)
  37. - generate a spill instruction
  38. - If the temporary was previously spilled,
  39. generate an instruction to read the temp from its spill loc.
  40. (optimisation: if we can see that a real register is going to
  41. be used soon, then don't use it for allocation).
  42. (c) Update the current assignment
  43. (d) If the instruction is a branch:
  44. if the destination block already has a register assignment,
  45. Generate a new block with fixup code and redirect the
  46. jump to the new block.
  47. else,
  48. Update the block id->assignment mapping with the current
  49. assignment.
  50. (e) Delete all register assignments for temps which are read
  51. (only) and die here. Update the free register list.
  52. (f) Mark all registers clobbered by this instruction as not free,
  53. and mark temporaries which have been spilled due to clobbering
  54. as in memory (step (a) marks then as in both mem & reg).
  55. (g) For each temporary *written* by this instruction:
  56. Allocate a real register as for (b), spilling something
  57. else if necessary.
  58. - except when updating the assignment, drop any memory
  59. locations that the temporary was previously in, since
  60. they will be no longer valid after this instruction.
  61. (h) Delete all register assignments for temps which are
  62. written and die here (there should rarely be any). Update
  63. the free register list.
  64. (i) Rewrite the instruction with the new mapping.
  65. (j) For each spilled reg known to be now dead, re-add its stack slot
  66. to the free list.
  67. -}
  68. module RegAlloc.Linear.Main (
  69. regAlloc,
  70. module RegAlloc.Linear.Base,
  71. module RegAlloc.Linear.Stats
  72. ) where
  73. #include "HsVersions.h"
  74. import RegAlloc.Linear.State
  75. import RegAlloc.Linear.Base
  76. import RegAlloc.Linear.StackMap
  77. import RegAlloc.Linear.FreeRegs
  78. import RegAlloc.Linear.Stats
  79. import RegAlloc.Linear.JoinToTargets
  80. import TargetReg
  81. import RegAlloc.Liveness
  82. import Instruction
  83. import Reg
  84. import BlockId
  85. import OldCmm hiding (RegSet)
  86. import Digraph
  87. import Unique
  88. import UniqSet
  89. import UniqFM
  90. import UniqSupply
  91. import Outputable
  92. import Data.Maybe
  93. import Data.List
  94. import Control.Monad
  95. #include "../includes/stg/MachRegs.h"
  96. -- -----------------------------------------------------------------------------
  97. -- Top level of the register allocator
  98. -- Allocate registers
  99. regAlloc
  100. :: (Outputable instr, Instruction instr)
  101. => LiveCmmTop instr
  102. -> UniqSM (NatCmmTop instr, Maybe RegAllocStats)
  103. regAlloc (CmmData sec d)
  104. = return
  105. ( CmmData sec d
  106. , Nothing )
  107. regAlloc (CmmProc (LiveInfo info _ _ _) lbl [])
  108. = return ( CmmProc info lbl (ListGraph [])
  109. , Nothing )
  110. regAlloc (CmmProc static lbl sccs)
  111. | LiveInfo info (Just first_id) (Just block_live) _ <- static
  112. = do
  113. -- do register allocation on each component.
  114. (final_blocks, stats)
  115. <- linearRegAlloc first_id block_live sccs
  116. -- make sure the block that was first in the input list
  117. -- stays at the front of the output
  118. let ((first':_), rest')
  119. = partition ((== first_id) . blockId) final_blocks
  120. return ( CmmProc info lbl (ListGraph (first' : rest'))
  121. , Just stats)
  122. -- bogus. to make non-exhaustive match warning go away.
  123. regAlloc (CmmProc _ _ _)
  124. = panic "RegAllocLinear.regAlloc: no match"
  125. -- -----------------------------------------------------------------------------
  126. -- Linear sweep to allocate registers
  127. -- | Do register allocation on some basic blocks.
  128. -- But be careful to allocate a block in an SCC only if it has
  129. -- an entry in the block map or it is the first block.
  130. --
  131. linearRegAlloc
  132. :: (Outputable instr, Instruction instr)
  133. => BlockId -- ^ the first block
  134. -> BlockMap RegSet -- ^ live regs on entry to each basic block
  135. -> [SCC (LiveBasicBlock instr)] -- ^ instructions annotated with "deaths"
  136. -> UniqSM ([NatBasicBlock instr], RegAllocStats)
  137. linearRegAlloc first_id block_live sccs
  138. = do us <- getUs
  139. let (_, _, stats, blocks) =
  140. runR emptyBlockMap initFreeRegs emptyRegMap emptyStackMap us
  141. $ linearRA_SCCs first_id block_live [] sccs
  142. return (blocks, stats)
  143. linearRA_SCCs _ _ blocksAcc []
  144. = return $ reverse blocksAcc
  145. linearRA_SCCs first_id block_live blocksAcc (AcyclicSCC block : sccs)
  146. = do blocks' <- processBlock block_live block
  147. linearRA_SCCs first_id block_live
  148. ((reverse blocks') ++ blocksAcc)
  149. sccs
  150. linearRA_SCCs first_id block_live blocksAcc (CyclicSCC blocks : sccs)
  151. = do
  152. blockss' <- process first_id block_live blocks [] (return []) False
  153. linearRA_SCCs first_id block_live
  154. (reverse (concat blockss') ++ blocksAcc)
  155. sccs
  156. {- from John Dias's patch 2008/10/16:
  157. The linear-scan allocator sometimes allocates a block
  158. before allocating one of its predecessors, which could lead to
  159. inconsistent allocations. Make it so a block is only allocated
  160. if a predecessor has set the "incoming" assignments for the block, or
  161. if it's the procedure's entry block.
  162. BL 2009/02: Careful. If the assignment for a block doesn't get set for
  163. some reason then this function will loop. We should probably do some
  164. more sanity checking to guard against this eventuality.
  165. -}
  166. process _ _ [] [] accum _
  167. = return $ reverse accum
  168. process first_id block_live [] next_round accum madeProgress
  169. | not madeProgress
  170. {- BUGS: There are so many unreachable blocks in the code the warnings are overwhelming.
  171. pprTrace "RegAlloc.Linear.Main.process: no progress made, bailing out."
  172. ( text "Unreachable blocks:"
  173. $$ vcat (map ppr next_round)) -}
  174. = return $ reverse accum
  175. | otherwise
  176. = process first_id block_live
  177. next_round [] accum False
  178. process first_id block_live (b@(BasicBlock id _) : blocks)
  179. next_round accum madeProgress
  180. = do
  181. block_assig <- getBlockAssigR
  182. if isJust (mapLookup id block_assig)
  183. || id == first_id
  184. then do
  185. b' <- processBlock block_live b
  186. process first_id block_live blocks
  187. next_round (b' : accum) True
  188. else process first_id block_live blocks
  189. (b : next_round) accum madeProgress
  190. -- | Do register allocation on this basic block
  191. --
  192. processBlock
  193. :: (Outputable instr, Instruction instr)
  194. => BlockMap RegSet -- ^ live regs on entry to each basic block
  195. -> LiveBasicBlock instr -- ^ block to do register allocation on
  196. -> RegM [NatBasicBlock instr] -- ^ block with registers allocated
  197. processBlock block_live (BasicBlock id instrs)
  198. = do initBlock id
  199. (instrs', fixups)
  200. <- linearRA block_live [] [] id instrs
  201. return $ BasicBlock id instrs' : fixups
  202. -- | Load the freeregs and current reg assignment into the RegM state
  203. -- for the basic block with this BlockId.
  204. initBlock :: BlockId -> RegM ()
  205. initBlock id
  206. = do block_assig <- getBlockAssigR
  207. case mapLookup id block_assig of
  208. -- no prior info about this block: assume everything is
  209. -- free and the assignment is empty.
  210. Nothing
  211. -> do -- pprTrace "initFreeRegs" (text $ show initFreeRegs) (return ())
  212. setFreeRegsR initFreeRegs
  213. setAssigR emptyRegMap
  214. -- load info about register assignments leading into this block.
  215. Just (freeregs, assig)
  216. -> do setFreeRegsR freeregs
  217. setAssigR assig
  218. -- | Do allocation for a sequence of instructions.
  219. linearRA
  220. :: (Outputable instr, Instruction instr)
  221. => BlockMap RegSet -- ^ map of what vregs are live on entry to each block.
  222. -> [instr] -- ^ accumulator for instructions already processed.
  223. -> [NatBasicBlock instr] -- ^ accumulator for blocks of fixup code.
  224. -> BlockId -- ^ id of the current block, for debugging.
  225. -> [LiveInstr instr] -- ^ liveness annotated instructions in this block.
  226. -> RegM ( [instr] -- instructions after register allocation
  227. , [NatBasicBlock instr]) -- fresh blocks of fixup code.
  228. linearRA _ accInstr accFixup _ []
  229. = return
  230. ( reverse accInstr -- instrs need to be returned in the correct order.
  231. , accFixup) -- it doesn't matter what order the fixup blocks are returned in.
  232. linearRA block_live accInstr accFixups id (instr:instrs)
  233. = do
  234. (accInstr', new_fixups)
  235. <- raInsn block_live accInstr id instr
  236. linearRA block_live accInstr' (new_fixups ++ accFixups) id instrs
  237. -- | Do allocation for a single instruction.
  238. raInsn
  239. :: (Outputable instr, Instruction instr)
  240. => BlockMap RegSet -- ^ map of what vregs are love on entry to each block.
  241. -> [instr] -- ^ accumulator for instructions already processed.
  242. -> BlockId -- ^ the id of the current block, for debugging
  243. -> LiveInstr instr -- ^ the instr to have its regs allocated, with liveness info.
  244. -> RegM
  245. ( [instr] -- new instructions
  246. , [NatBasicBlock instr]) -- extra fixup blocks
  247. raInsn _ new_instrs _ (LiveInstr ii Nothing)
  248. | Just n <- takeDeltaInstr ii
  249. = do setDeltaR n
  250. return (new_instrs, [])
  251. raInsn _ new_instrs _ (LiveInstr ii Nothing)
  252. | isMetaInstr ii
  253. = return (new_instrs, [])
  254. raInsn block_live new_instrs id (LiveInstr (Instr instr) (Just live))
  255. = do
  256. assig <- getAssigR
  257. -- If we have a reg->reg move between virtual registers, where the
  258. -- src register is not live after this instruction, and the dst
  259. -- register does not already have an assignment,
  260. -- and the source register is assigned to a register, not to a spill slot,
  261. -- then we can eliminate the instruction.
  262. -- (we can't eliminate it if the source register is on the stack, because
  263. -- we do not want to use one spill slot for different virtual registers)
  264. case takeRegRegMoveInstr instr of
  265. Just (src,dst) | src `elementOfUniqSet` (liveDieRead live),
  266. isVirtualReg dst,
  267. not (dst `elemUFM` assig),
  268. Just (InReg _) <- (lookupUFM assig src) -> do
  269. case src of
  270. (RegReal rr) -> setAssigR (addToUFM assig dst (InReg rr))
  271. -- if src is a fixed reg, then we just map dest to this
  272. -- reg in the assignment. src must be an allocatable reg,
  273. -- otherwise it wouldn't be in r_dying.
  274. _virt -> case lookupUFM assig src of
  275. Nothing -> panic "raInsn"
  276. Just loc ->
  277. setAssigR (addToUFM (delFromUFM assig src) dst loc)
  278. -- we have eliminated this instruction
  279. {-
  280. freeregs <- getFreeRegsR
  281. assig <- getAssigR
  282. pprTrace "raInsn" (text "ELIMINATED: " <> docToSDoc (pprInstr instr)
  283. $$ ppr r_dying <+> ppr w_dying $$ text (show freeregs) $$ ppr assig) $ do
  284. -}
  285. return (new_instrs, [])
  286. _ -> genRaInsn block_live new_instrs id instr
  287. (uniqSetToList $ liveDieRead live)
  288. (uniqSetToList $ liveDieWrite live)
  289. raInsn _ _ _ instr
  290. = pprPanic "raInsn" (text "no match for:" <> ppr instr)
  291. genRaInsn block_live new_instrs block_id instr r_dying w_dying =
  292. case regUsageOfInstr instr of { RU read written ->
  293. do
  294. let real_written = [ rr | (RegReal rr) <- written ]
  295. let virt_written = [ vr | (RegVirtual vr) <- written ]
  296. -- we don't need to do anything with real registers that are
  297. -- only read by this instr. (the list is typically ~2 elements,
  298. -- so using nub isn't a problem).
  299. let virt_read = nub [ vr | (RegVirtual vr) <- read ]
  300. -- (a) save any temporaries which will be clobbered by this instruction
  301. clobber_saves <- saveClobberedTemps real_written r_dying
  302. -- debugging
  303. {- freeregs <- getFreeRegsR
  304. assig <- getAssigR
  305. pprTrace "genRaInsn"
  306. (ppr instr
  307. $$ text "r_dying = " <+> ppr r_dying
  308. $$ text "w_dying = " <+> ppr w_dying
  309. $$ text "virt_read = " <+> ppr virt_read
  310. $$ text "virt_written = " <+> ppr virt_written
  311. $$ text "freeregs = " <+> text (show freeregs)
  312. $$ text "assig = " <+> ppr assig)
  313. $ do
  314. -}
  315. -- (b), (c) allocate real regs for all regs read by this instruction.
  316. (r_spills, r_allocd) <-
  317. allocateRegsAndSpill True{-reading-} virt_read [] [] virt_read
  318. -- (d) Update block map for new destinations
  319. -- NB. do this before removing dead regs from the assignment, because
  320. -- these dead regs might in fact be live in the jump targets (they're
  321. -- only dead in the code that follows in the current basic block).
  322. (fixup_blocks, adjusted_instr)
  323. <- joinToTargets block_live block_id instr
  324. -- (e) Delete all register assignments for temps which are read
  325. -- (only) and die here. Update the free register list.
  326. releaseRegs r_dying
  327. -- (f) Mark regs which are clobbered as unallocatable
  328. clobberRegs real_written
  329. -- (g) Allocate registers for temporaries *written* (only)
  330. (w_spills, w_allocd) <-
  331. allocateRegsAndSpill False{-writing-} virt_written [] [] virt_written
  332. -- (h) Release registers for temps which are written here and not
  333. -- used again.
  334. releaseRegs w_dying
  335. let
  336. -- (i) Patch the instruction
  337. patch_map
  338. = listToUFM
  339. [ (t, RegReal r)
  340. | (t, r) <- zip virt_read r_allocd
  341. ++ zip virt_written w_allocd ]
  342. patched_instr
  343. = patchRegsOfInstr adjusted_instr patchLookup
  344. patchLookup x
  345. = case lookupUFM patch_map x of
  346. Nothing -> x
  347. Just y -> y
  348. -- (j) free up stack slots for dead spilled regs
  349. -- TODO (can't be bothered right now)
  350. -- erase reg->reg moves where the source and destination are the same.
  351. -- If the src temp didn't die in this instr but happened to be allocated
  352. -- to the same real reg as the destination, then we can erase the move anyway.
  353. let squashed_instr = case takeRegRegMoveInstr patched_instr of
  354. Just (src, dst)
  355. | src == dst -> []
  356. _ -> [patched_instr]
  357. let code = squashed_instr ++ w_spills ++ reverse r_spills
  358. ++ clobber_saves ++ new_instrs
  359. -- pprTrace "patched-code" ((vcat $ map (docToSDoc . pprInstr) code)) $ do
  360. -- pprTrace "pached-fixup" ((ppr fixup_blocks)) $ do
  361. return (code, fixup_blocks)
  362. }
  363. -- -----------------------------------------------------------------------------
  364. -- releaseRegs
  365. releaseRegs regs = do
  366. assig <- getAssigR
  367. free <- getFreeRegsR
  368. loop assig free regs
  369. where
  370. loop _ free _ | free `seq` False = undefined
  371. loop assig free [] = do setAssigR assig; setFreeRegsR free; return ()
  372. loop assig free (RegReal rr : rs) = loop assig (releaseReg rr free) rs
  373. loop assig free (r:rs) =
  374. case lookupUFM assig r of
  375. Just (InBoth real _) -> loop (delFromUFM assig r) (releaseReg real free) rs
  376. Just (InReg real) -> loop (delFromUFM assig r) (releaseReg real free) rs
  377. _other -> loop (delFromUFM assig r) free rs
  378. -- -----------------------------------------------------------------------------
  379. -- Clobber real registers
  380. -- For each temp in a register that is going to be clobbered:
  381. -- - if the temp dies after this instruction, do nothing
  382. -- - otherwise, put it somewhere safe (another reg if possible,
  383. -- otherwise spill and record InBoth in the assignment).
  384. -- - for allocateRegs on the temps *read*,
  385. -- - clobbered regs are allocatable.
  386. --
  387. -- for allocateRegs on the temps *written*,
  388. -- - clobbered regs are not allocatable.
  389. --
  390. -- TODO: instead of spilling, try to copy clobbered
  391. -- temps to another register if possible.
  392. --
  393. saveClobberedTemps
  394. :: (Outputable instr, Instruction instr)
  395. => [RealReg] -- real registers clobbered by this instruction
  396. -> [Reg] -- registers which are no longer live after this insn
  397. -> RegM [instr] -- return: instructions to spill any temps that will
  398. -- be clobbered.
  399. saveClobberedTemps [] _
  400. = return []
  401. saveClobberedTemps clobbered dying
  402. = do
  403. assig <- getAssigR
  404. let to_spill
  405. = [ (temp,reg)
  406. | (temp, InReg reg) <- ufmToList assig
  407. , any (realRegsAlias reg) clobbered
  408. , temp `notElem` map getUnique dying ]
  409. (instrs,assig') <- clobber assig [] to_spill
  410. setAssigR assig'
  411. return instrs
  412. where
  413. clobber assig instrs []
  414. = return (instrs, assig)
  415. clobber assig instrs ((temp, reg) : rest)
  416. = do
  417. (spill, slot) <- spillR (RegReal reg) temp
  418. -- record why this reg was spilled for profiling
  419. recordSpill (SpillClobber temp)
  420. let new_assign = addToUFM assig temp (InBoth reg slot)
  421. clobber new_assign (spill : instrs) rest
  422. -- | Mark all these real regs as allocated,
  423. -- and kick out their vreg assignments.
  424. --
  425. clobberRegs :: [RealReg] -> RegM ()
  426. clobberRegs []
  427. = return ()
  428. clobberRegs clobbered
  429. = do
  430. freeregs <- getFreeRegsR
  431. setFreeRegsR $! foldr allocateReg freeregs clobbered
  432. assig <- getAssigR
  433. setAssigR $! clobber assig (ufmToList assig)
  434. where
  435. -- if the temp was InReg and clobbered, then we will have
  436. -- saved it in saveClobberedTemps above. So the only case
  437. -- we have to worry about here is InBoth. Note that this
  438. -- also catches temps which were loaded up during allocation
  439. -- of read registers, not just those saved in saveClobberedTemps.
  440. clobber assig []
  441. = assig
  442. clobber assig ((temp, InBoth reg slot) : rest)
  443. | any (realRegsAlias reg) clobbered
  444. = clobber (addToUFM assig temp (InMem slot)) rest
  445. clobber assig (_:rest)
  446. = clobber assig rest
  447. -- -----------------------------------------------------------------------------
  448. -- allocateRegsAndSpill
  449. -- Why are we performing a spill?
  450. data SpillLoc = ReadMem StackSlot -- reading from register only in memory
  451. | WriteNew -- writing to a new variable
  452. | WriteMem -- writing to register only in memory
  453. -- Note that ReadNew is not valid, since you don't want to be reading
  454. -- from an uninitialized register. We also don't need the location of
  455. -- the register in memory, since that will be invalidated by the write.
  456. -- Technically, we could coalesce WriteNew and WriteMem into a single
  457. -- entry as well. -- EZY
  458. -- This function does several things:
  459. -- For each temporary referred to by this instruction,
  460. -- we allocate a real register (spilling another temporary if necessary).
  461. -- We load the temporary up from memory if necessary.
  462. -- We also update the register assignment in the process, and
  463. -- the list of free registers and free stack slots.
  464. allocateRegsAndSpill
  465. :: (Outputable instr, Instruction instr)
  466. => Bool -- True <=> reading (load up spilled regs)
  467. -> [VirtualReg] -- don't push these out
  468. -> [instr] -- spill insns
  469. -> [RealReg] -- real registers allocated (accum.)
  470. -> [VirtualReg] -- temps to allocate
  471. -> RegM ( [instr]
  472. , [RealReg])
  473. allocateRegsAndSpill _ _ spills alloc []
  474. = return (spills, reverse alloc)
  475. allocateRegsAndSpill reading keep spills alloc (r:rs)
  476. = do assig <- getAssigR
  477. let doSpill = allocRegsAndSpill_spill reading keep spills alloc r rs assig
  478. case lookupUFM assig r of
  479. -- case (1a): already in a register
  480. Just (InReg my_reg) ->
  481. allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
  482. -- case (1b): already in a register (and memory)
  483. -- NB1. if we're writing this register, update its assignment to be
  484. -- InReg, because the memory value is no longer valid.
  485. -- NB2. This is why we must process written registers here, even if they
  486. -- are also read by the same instruction.
  487. Just (InBoth my_reg _)
  488. -> do when (not reading) (setAssigR (addToUFM assig r (InReg my_reg)))
  489. allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
  490. -- Not already in a register, so we need to find a free one...
  491. Just (InMem slot) | reading -> doSpill (ReadMem slot)
  492. | otherwise -> doSpill WriteMem
  493. Nothing | reading ->
  494. -- pprPanic "allocateRegsAndSpill: Cannot read from uninitialized register" (ppr r)
  495. -- ToDo: This case should be a panic, but we
  496. -- sometimes see an unreachable basic block which
  497. -- triggers this because the register allocator
  498. -- will start with an empty assignment.
  499. doSpill WriteNew
  500. | otherwise -> doSpill WriteNew
  501. -- reading is redundant with reason, but we keep it around because it's
  502. -- convenient and it maintains the recursive structure of the allocator. -- EZY
  503. allocRegsAndSpill_spill reading keep spills alloc r rs assig spill_loc
  504. = do
  505. freeRegs <- getFreeRegsR
  506. let freeRegs_thisClass = getFreeRegs (classOfVirtualReg r) freeRegs
  507. case freeRegs_thisClass of
  508. -- case (2): we have a free register
  509. (my_reg : _) ->
  510. do spills' <- loadTemp r spill_loc my_reg spills
  511. setAssigR (addToUFM assig r $! newLocation spill_loc my_reg)
  512. setFreeRegsR $ allocateReg my_reg freeRegs
  513. allocateRegsAndSpill reading keep spills' (my_reg : alloc) rs
  514. -- case (3): we need to push something out to free up a register
  515. [] ->
  516. do let keep' = map getUnique keep
  517. -- the vregs we could kick out that are already in a slot
  518. let candidates_inBoth
  519. = [ (temp, reg, mem)
  520. | (temp, InBoth reg mem) <- ufmToList assig
  521. , temp `notElem` keep'
  522. , targetClassOfRealReg reg == classOfVirtualReg r ]
  523. -- the vregs we could kick out that are only in a reg
  524. -- this would require writing the reg to a new slot before using it.
  525. let candidates_inReg
  526. = [ (temp, reg)
  527. | (temp, InReg reg) <- ufmToList assig
  528. , temp `notElem` keep'
  529. , targetClassOfRealReg reg == classOfVirtualReg r ]
  530. let result
  531. -- we have a temporary that is in both register and mem,
  532. -- just free up its register for use.
  533. | (temp, my_reg, slot) : _ <- candidates_inBoth
  534. = do spills' <- loadTemp r spill_loc my_reg spills
  535. let assig1 = addToUFM assig temp (InMem slot)
  536. let assig2 = addToUFM assig1 r $! newLocation spill_loc my_reg
  537. setAssigR assig2
  538. allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
  539. -- otherwise, we need to spill a temporary that currently
  540. -- resides in a register.
  541. | (temp_to_push_out, (my_reg :: RealReg)) : _
  542. <- candidates_inReg
  543. = do
  544. (spill_insn, slot) <- spillR (RegReal my_reg) temp_to_push_out
  545. let spill_store = (if reading then id else reverse)
  546. [ -- COMMENT (fsLit "spill alloc")
  547. spill_insn ]
  548. -- record that this temp was spilled
  549. recordSpill (SpillAlloc temp_to_push_out)
  550. -- update the register assignment
  551. let assig1 = addToUFM assig temp_to_push_out (InMem slot)
  552. let assig2 = addToUFM assig1 r $! newLocation spill_loc my_reg
  553. setAssigR assig2
  554. -- if need be, load up a spilled temp into the reg we've just freed up.
  555. spills' <- loadTemp r spill_loc my_reg spills
  556. allocateRegsAndSpill reading keep
  557. (spill_store ++ spills')
  558. (my_reg:alloc) rs
  559. -- there wasn't anything to spill, so we're screwed.
  560. | otherwise
  561. = pprPanic ("RegAllocLinear.allocRegsAndSpill: no spill candidates\n")
  562. $ vcat
  563. [ text "allocating vreg: " <> text (show r)
  564. , text "assignment: " <> text (show $ ufmToList assig)
  565. , text "freeRegs: " <> text (show freeRegs)
  566. , text "initFreeRegs: " <> text (show initFreeRegs) ]
  567. result
  568. -- | Calculate a new location after a register has been loaded.
  569. newLocation :: SpillLoc -> RealReg -> Loc
  570. -- if the tmp was read from a slot, then now its in a reg as well
  571. newLocation (ReadMem slot) my_reg = InBoth my_reg slot
  572. -- writes will always result in only the register being available
  573. newLocation _ my_reg = InReg my_reg
  574. -- | Load up a spilled temporary if we need to (read from memory).
  575. loadTemp
  576. :: (Outputable instr, Instruction instr)
  577. => VirtualReg -- the temp being loaded
  578. -> SpillLoc -- the current location of this temp
  579. -> RealReg -- the hreg to load the temp into
  580. -> [instr]
  581. -> RegM [instr]
  582. loadTemp vreg (ReadMem slot) hreg spills
  583. = do
  584. insn <- loadR (RegReal hreg) slot
  585. recordSpill (SpillLoad $ getUnique vreg)
  586. return $ {- COMMENT (fsLit "spill load") : -} insn : spills
  587. loadTemp _ _ _ spills =
  588. return spills