PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/khibino/ghc-hack
Haskell | 95 lines | 56 code | 22 blank | 17 comment | 1 complexity | 0b9694a632de17e25e1836f36b39b8b5 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause, LGPL-3.0
  1. -- | Register coalescing.
  2. --
  3. {-# OPTIONS -fno-warn-tabs #-}
  4. -- The above warning supression flag is a temporary kludge.
  5. -- While working on this module you are encouraged to remove it and
  6. -- detab the module (please do the detabbing in a separate patch). See
  7. -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces
  8. -- for details
  9. module RegAlloc.Graph.Coalesce (
  10. regCoalesce,
  11. slurpJoinMovs
  12. )
  13. where
  14. import RegAlloc.Liveness
  15. import Instruction
  16. import Reg
  17. import OldCmm
  18. import Bag
  19. import Digraph
  20. import UniqFM
  21. import UniqSet
  22. import UniqSupply
  23. import Data.List
  24. -- | Do register coalescing on this top level thing
  25. -- For Reg -> Reg moves, if the first reg dies at the same time the second reg is born
  26. -- then the mov only serves to join live ranges. The two regs can be renamed to be
  27. -- the same and the move instruction safely erased.
  28. regCoalesce
  29. :: Instruction instr
  30. => [LiveCmmDecl statics instr]
  31. -> UniqSM [LiveCmmDecl statics instr]
  32. regCoalesce code
  33. = do
  34. let joins = foldl' unionBags emptyBag
  35. $ map slurpJoinMovs code
  36. let alloc = foldl' buildAlloc emptyUFM
  37. $ bagToList joins
  38. let patched = map (patchEraseLive (sinkReg alloc)) code
  39. return patched
  40. buildAlloc :: UniqFM Reg -> (Reg, Reg) -> UniqFM Reg
  41. buildAlloc fm (r1, r2)
  42. = let rmin = min r1 r2
  43. rmax = max r1 r2
  44. in addToUFM fm rmax rmin
  45. sinkReg :: UniqFM Reg -> Reg -> Reg
  46. sinkReg fm r
  47. = case lookupUFM fm r of
  48. Nothing -> r
  49. Just r' -> sinkReg fm r'
  50. -- | Slurp out mov instructions that only serve to join live ranges.
  51. -- During a mov, if the source reg dies and the destiation reg is born
  52. -- then we can rename the two regs to the same thing and eliminate the move.
  53. slurpJoinMovs
  54. :: Instruction instr
  55. => LiveCmmDecl statics instr
  56. -> Bag (Reg, Reg)
  57. slurpJoinMovs live
  58. = slurpCmm emptyBag live
  59. where
  60. slurpCmm rs CmmData{} = rs
  61. slurpCmm rs (CmmProc _ _ sccs) = foldl' slurpBlock rs (flattenSCCs sccs)
  62. slurpBlock rs (BasicBlock _ instrs) = foldl' slurpLI rs instrs
  63. slurpLI rs (LiveInstr _ Nothing) = rs
  64. slurpLI rs (LiveInstr instr (Just live))
  65. | Just (r1, r2) <- takeRegRegMoveInstr instr
  66. , elementOfUniqSet r1 $ liveDieRead live
  67. , elementOfUniqSet r2 $ liveBorn live
  68. -- only coalesce movs between two virtuals for now, else we end up with
  69. -- allocatable regs in the live regs list..
  70. , isVirtualReg r1 && isVirtualReg r2
  71. = consBag (r1, r2) rs
  72. | otherwise
  73. = rs