summaryrefslogtreecommitdiff
path: root/compiler/GHC/CmmToAsm/Reg/Graph/X86.hs
blob: d63cc819acfd0868526e6cdf865cea2075d47fce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

-- | A description of the register set of the X86.
--
--   This isn't used directly in GHC proper.
--
--   See RegArchBase.hs for the reference.
--   See MachRegs.hs for the actual trivColorable function used in GHC.
--
module GHC.CmmToAsm.Reg.Graph.X86 (
        classOfReg,
        regsOfClass,
        regName,
        regAlias,
        worst,
        squeese,
) where

import GHC.Prelude

import GHC.CmmToAsm.Reg.Graph.Base  (Reg(..), RegSub(..), RegClass(..))
import GHC.Types.Unique.Set

import qualified Data.Array as A


-- | Determine the class of a register
classOfReg :: Reg -> RegClass
classOfReg reg
 = case reg of
        Reg c _         -> c

        RegSub SubL16 _ -> ClassG16
        RegSub SubL8  _ -> ClassG8
        RegSub SubL8H _ -> ClassG8


-- | Determine all the regs that make up a certain class.
regsOfClass :: RegClass -> UniqSet Reg
regsOfClass c
 = case c of
        ClassG32
         -> mkUniqSet   [ Reg ClassG32  i
                        | i <- [0..7] ]

        ClassG16
         -> mkUniqSet   [ RegSub SubL16 (Reg ClassG32 i)
                        | i <- [0..7] ]

        ClassG8
         -> unionUniqSets
                (mkUniqSet [ RegSub SubL8  (Reg ClassG32 i) | i <- [0..3] ])
                (mkUniqSet [ RegSub SubL8H (Reg ClassG32 i) | i <- [0..3] ])

        ClassF64
         -> mkUniqSet   [ Reg ClassF64  i
                        | i <- [0..5] ]


-- | Determine the common name of a reg
--      returns Nothing if this reg is not part of the machine.
regName :: Reg -> Maybe String
regName reg
 = case reg of
        Reg ClassG32 i
         | i <= 7 ->
           let names = A.listArray (0,8)
                       [ "eax", "ebx", "ecx", "edx"
                       , "ebp", "esi", "edi", "esp" ]
           in Just $ names A.! i

        RegSub SubL16 (Reg ClassG32 i)
         | i <= 7 ->
           let names = A.listArray (0,8)
                       [ "ax", "bx", "cx", "dx"
                       , "bp", "si", "di", "sp"]
           in Just $ names A.! i

        RegSub SubL8  (Reg ClassG32 i)
         | i <= 3 ->
           let names = A.listArray (0,4) [ "al", "bl", "cl", "dl"]
           in Just $ names A.! i

        RegSub SubL8H (Reg ClassG32 i)
         | i <= 3 ->
           let names = A.listArray (0,4) [ "ah", "bh", "ch", "dh"]
           in Just $ names A.! i

        _         -> Nothing


-- | Which regs alias what other regs.
regAlias :: Reg -> UniqSet Reg
regAlias reg
 = case reg of

        -- 32 bit regs alias all of the subregs
        Reg ClassG32 i

         -- for eax, ebx, ecx, eds
         |  i <= 3
         -> mkUniqSet
         $ [ Reg ClassG32 i,   RegSub SubL16 reg
           , RegSub SubL8 reg, RegSub SubL8H reg ]

         -- for esi, edi, esp, ebp
         | 4 <= i && i <= 7
         -> mkUniqSet
         $ [ Reg ClassG32 i,   RegSub SubL16 reg ]

        -- 16 bit subregs alias the whole reg
        RegSub SubL16 r@(Reg ClassG32 _)
         ->     regAlias r

        -- 8 bit subregs alias the 32 and 16, but not the other 8 bit subreg
        RegSub SubL8  r@(Reg ClassG32 _)
         -> mkUniqSet $ [ r, RegSub SubL16 r, RegSub SubL8 r ]

        RegSub SubL8H r@(Reg ClassG32 _)
         -> mkUniqSet $ [ r, RegSub SubL16 r, RegSub SubL8H r ]

        -- fp
        Reg ClassF64 _
         -> unitUniqSet reg

        _ -> error "regAlias: invalid register"


-- | Optimised versions of RegColorBase.{worst, squeese} specific to x86
worst :: Int -> RegClass -> RegClass -> Int
worst n classN classC
 = case classN of
        ClassG32
         -> case classC of
                ClassG32        -> min n 8
                ClassG16        -> min n 8
                ClassG8         -> min n 4
                ClassF64        -> 0

        ClassG16
         -> case classC of
                ClassG32        -> min n 8
                ClassG16        -> min n 8
                ClassG8         -> min n 4
                ClassF64        -> 0

        ClassG8
         -> case classC of
                ClassG32        -> min (n*2) 8
                ClassG16        -> min (n*2) 8
                ClassG8         -> min n 8
                ClassF64        -> 0

        ClassF64
         -> case classC of
                ClassF64        -> min n 6
                _               -> 0

squeese :: RegClass -> [(Int, RegClass)] -> Int
squeese classN countCs
        = sum (map (\(i, classC) -> worst i classN classC) countCs)