PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

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

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