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

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

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