PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/nativeGen/RegAlloc/Graph/Coalesce.hs

https://github.com/dorchard/ghc
Haskell | 99 lines | 58 code | 21 blank | 20 comment | 1 complexity | edcd050e27bd85410cf7bdac452c5c8f MD5 | raw file
  1. -- | Register coalescing.
  2. module RegAlloc.Graph.Coalesce (
  3. regCoalesce,
  4. slurpJoinMovs
  5. ) where
  6. import RegAlloc.Liveness
  7. import Instruction
  8. import Reg
  9. import Cmm
  10. import Bag
  11. import Digraph
  12. import UniqFM
  13. import UniqSet
  14. import UniqSupply
  15. import Data.List
  16. -- | Do register coalescing on this top level thing
  17. --
  18. -- For Reg -> Reg moves, if the first reg dies at the same time the
  19. -- second reg is born then the mov only serves to join live ranges.
  20. -- The two regs can be renamed to be the same and the move instruction
  21. -- safely erased.
  22. regCoalesce
  23. :: Instruction instr
  24. => [LiveCmmDecl statics instr]
  25. -> UniqSM [LiveCmmDecl statics instr]
  26. regCoalesce code
  27. = do
  28. let joins = foldl' unionBags emptyBag
  29. $ map slurpJoinMovs code
  30. let alloc = foldl' buildAlloc emptyUFM
  31. $ bagToList joins
  32. let patched = map (patchEraseLive (sinkReg alloc)) code
  33. return patched
  34. -- | Add a v1 = v2 register renaming to the map.
  35. -- The register with the lowest lexical name is set as the
  36. -- canonical version.
  37. buildAlloc :: UniqFM Reg -> (Reg, Reg) -> UniqFM Reg
  38. buildAlloc fm (r1, r2)
  39. = let rmin = min r1 r2
  40. rmax = max r1 r2
  41. in addToUFM fm rmax rmin
  42. -- | Determine the canonical name for a register by following
  43. -- v1 = v2 renamings in this map.
  44. sinkReg :: UniqFM Reg -> Reg -> Reg
  45. sinkReg fm r
  46. = case lookupUFM fm r of
  47. Nothing -> r
  48. Just r' -> sinkReg fm r'
  49. -- | Slurp out mov instructions that only serve to join live ranges.
  50. --
  51. -- During a mov, if the source reg dies and the destiation reg is
  52. -- born then we can rename the two regs to the same thing and
  53. -- eliminate the move.
  54. slurpJoinMovs
  55. :: Instruction instr
  56. => LiveCmmDecl statics instr
  57. -> Bag (Reg, Reg)
  58. slurpJoinMovs live
  59. = slurpCmm emptyBag live
  60. where
  61. slurpCmm rs CmmData{}
  62. = rs
  63. slurpCmm rs (CmmProc _ _ _ sccs)
  64. = foldl' slurpBlock rs (flattenSCCs sccs)
  65. slurpBlock rs (BasicBlock _ instrs)
  66. = foldl' slurpLI rs instrs
  67. slurpLI rs (LiveInstr _ Nothing) = rs
  68. slurpLI rs (LiveInstr instr (Just live))
  69. | Just (r1, r2) <- takeRegRegMoveInstr instr
  70. , elementOfUniqSet r1 $ liveDieRead live
  71. , elementOfUniqSet r2 $ liveBorn live
  72. -- only coalesce movs between two virtuals for now,
  73. -- else we end up with allocatable regs in the live
  74. -- regs list..
  75. , isVirtualReg r1 && isVirtualReg r2
  76. = consBag (r1, r2) rs
  77. | otherwise
  78. = rs