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

https://github.com/pepeiborra/ghc · Haskell · 88 lines · 56 code · 21 blank · 11 comment · 2 complexity · 989f30e9da2f603f34638a94ba88313b MD5 · raw file

  1. -- | Register coalescing.
  2. --
  3. module RegAlloc.Graph.Coalesce (
  4. regCoalesce,
  5. slurpJoinMovs
  6. )
  7. where
  8. import RegAlloc.Liveness
  9. import Instruction
  10. import Reg
  11. import OldCmm
  12. import Bag
  13. import Digraph
  14. import UniqFM
  15. import UniqSet
  16. import UniqSupply
  17. import Data.List
  18. -- | Do register coalescing on this top level thing
  19. -- For Reg -> Reg moves, if the first reg dies at the same time the second reg is born
  20. -- then the mov only serves to join live ranges. The two regs can be renamed to be
  21. -- the same and the move instruction 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. buildAlloc :: UniqFM Reg -> (Reg, Reg) -> UniqFM Reg
  35. buildAlloc fm (r1, r2)
  36. = let rmin = min r1 r2
  37. rmax = max r1 r2
  38. in addToUFM fm rmax rmin
  39. sinkReg :: UniqFM Reg -> Reg -> Reg
  40. sinkReg fm r
  41. = case lookupUFM fm r of
  42. Nothing -> r
  43. Just r' -> sinkReg fm r'
  44. -- | Slurp out mov instructions that only serve to join live ranges.
  45. -- During a mov, if the source reg dies and the destiation reg is born
  46. -- then we can rename the two regs to the same thing and eliminate the move.
  47. slurpJoinMovs
  48. :: Instruction instr
  49. => LiveCmmDecl statics instr
  50. -> Bag (Reg, Reg)
  51. slurpJoinMovs live
  52. = slurpCmm emptyBag live
  53. where
  54. slurpCmm rs CmmData{} = rs
  55. slurpCmm rs (CmmProc _ _ sccs) = foldl' slurpBlock rs (flattenSCCs sccs)
  56. slurpBlock rs (BasicBlock _ instrs) = foldl' slurpLI rs instrs
  57. slurpLI rs (LiveInstr _ Nothing) = rs
  58. slurpLI rs (LiveInstr instr (Just live))
  59. | Just (r1, r2) <- takeRegRegMoveInstr instr
  60. , elementOfUniqSet r1 $ liveDieRead live
  61. , elementOfUniqSet r2 $ liveBorn live
  62. -- only coalesce movs between two virtuals for now, else we end up with
  63. -- allocatable regs in the live regs list..
  64. , isVirtualReg r1 && isVirtualReg r2
  65. = consBag (r1, r2) rs
  66. | otherwise
  67. = rs