PageRenderTime 26ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

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

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