b2a107c1cc39b2eba058debd88b6df80a8b15eb5
[ghc-hetmet.git] / ghc / compiler / cmm / CmmUtils.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Cmm utilities.
4 --
5 -- (c) The University of Glasgow 2004
6 --
7 -----------------------------------------------------------------------------
8
9 module CmmUtils( 
10         CmmStmts, noStmts, oneStmt, mkStmts, plusStmts, stmtList,
11         isNopStmt,
12
13         isTrivialCmmExpr,
14
15         cmmRegOff, cmmLabelOff, cmmOffset, cmmOffsetLit, cmmIndex,
16         cmmOffsetExpr, cmmIndexExpr, cmmLoadIndex,
17
18         mkIntCLit, zeroCLit,
19
20         mkLblExpr,
21   ) where
22
23 #include "HsVersions.h"
24
25 import CLabel           ( CLabel )
26 import Cmm
27 import MachOp
28 import OrdList
29 import Outputable
30
31 ---------------------------------------------------
32 --
33 --      CmmStmts
34 --
35 ---------------------------------------------------
36
37 type CmmStmts = OrdList CmmStmt
38
39 noStmts :: CmmStmts
40 noStmts = nilOL
41
42 oneStmt :: CmmStmt -> CmmStmts
43 oneStmt = unitOL
44
45 mkStmts :: [CmmStmt] -> CmmStmts
46 mkStmts = toOL
47
48 plusStmts :: CmmStmts -> CmmStmts -> CmmStmts
49 plusStmts = appOL
50
51 stmtList :: CmmStmts -> [CmmStmt]
52 stmtList = fromOL
53
54
55 ---------------------------------------------------
56 --
57 --      CmmStmt
58 --
59 ---------------------------------------------------
60
61 isNopStmt :: CmmStmt -> Bool
62 -- If isNopStmt returns True, the stmt is definitely a no-op;
63 -- but it might be a no-op even if isNopStmt returns False
64 isNopStmt CmmNop                       = True
65 isNopStmt (CmmAssign r e)              = cheapEqReg r e
66 isNopStmt (CmmStore e1 (CmmLoad e2 _)) = cheapEqExpr e1 e2
67 isNopStmt s                            = False
68
69 cheapEqExpr :: CmmExpr -> CmmExpr -> Bool
70 cheapEqExpr (CmmReg r)      e                 = cheapEqReg r e
71 cheapEqExpr (CmmRegOff r 0) e                 = cheapEqReg r e
72 cheapEqExpr (CmmRegOff r n) (CmmRegOff r' n') = r==r' && n==n'
73 cheapEqExpr e1              e2                = False
74
75 cheapEqReg :: CmmReg -> CmmExpr -> Bool
76 cheapEqReg r (CmmReg r')      = r==r'
77 cheapEqReg r (CmmRegOff r' 0) = r==r'
78 cheapEqReg r e                = False
79
80 ---------------------------------------------------
81 --
82 --      CmmExpr
83 --
84 ---------------------------------------------------
85
86 isTrivialCmmExpr :: CmmExpr -> Bool
87 isTrivialCmmExpr (CmmLoad _ _)   = False
88 isTrivialCmmExpr (CmmMachOp _ _) = False
89 isTrivialCmmExpr (CmmLit _)      = True
90 isTrivialCmmExpr (CmmReg _)      = True
91 isTrivialCmmExpr (CmmRegOff _ _) = True
92
93 ---------------------------------------------------
94 --
95 --      Expr Construction helpers
96 --
97 ---------------------------------------------------
98
99 cmmOffsetExpr :: CmmExpr -> CmmExpr -> CmmExpr
100 -- assumes base and offset have the same MachRep
101 cmmOffsetExpr e (CmmLit (CmmInt n _)) = cmmOffset e (fromInteger n)
102 cmmOffsetExpr e byte_off = CmmMachOp (MO_Add (cmmExprRep e)) [e, byte_off]
103
104 -- NB. Do *not* inspect the value of the offset in these smart constructors!!!
105 --
106 -- because the offset is sometimes involved in a loop in the code generator
107 -- (we don't know the real Hp offset until we've generated code for the entire
108 -- basic block, for example).  So we cannot eliminate zero offsets at this
109 -- stage; they're eliminated later instead (either during printing or
110 -- a later optimisation step on Cmm).
111 --
112 cmmOffset :: CmmExpr -> Int -> CmmExpr
113 cmmOffset (CmmReg reg)      byte_off = cmmRegOff reg byte_off
114 cmmOffset (CmmRegOff reg m) byte_off = cmmRegOff reg (m+byte_off)
115 cmmOffset (CmmLit lit)      byte_off = CmmLit (cmmOffsetLit lit byte_off)
116 cmmOffset (CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt byte_off1 _rep)]) byte_off2
117   = CmmMachOp (MO_Add rep) 
118               [expr, CmmLit (CmmInt (byte_off1 + toInteger byte_off2) rep)]
119 cmmOffset expr byte_off
120   = CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt (toInteger byte_off) rep)]
121   where
122     rep = cmmExprRep expr
123
124 -- Smart constructor for CmmRegOff.  Same caveats as cmmOffset above.
125 cmmRegOff :: CmmReg -> Int -> CmmExpr
126 cmmRegOff reg byte_off = CmmRegOff reg byte_off
127
128 cmmOffsetLit :: CmmLit -> Int -> CmmLit
129 cmmOffsetLit (CmmLabel l)      byte_off = cmmLabelOff   l byte_off
130 cmmOffsetLit (CmmLabelOff l m) byte_off = cmmLabelOff   l (m+byte_off)
131 cmmOffsetLit (CmmInt m rep)    byte_off = CmmInt (m + fromIntegral byte_off) rep
132 cmmOffsetLit other             byte_off = pprPanic "cmmOffsetLit" (ppr byte_off)
133
134 cmmLabelOff :: CLabel -> Int -> CmmLit
135 -- Smart constructor for CmmLabelOff
136 cmmLabelOff lbl 0        = CmmLabel lbl
137 cmmLabelOff lbl byte_off = CmmLabelOff lbl byte_off
138
139 -- | Useful for creating an index into an array, with a staticaly known offset.
140 cmmIndex :: MachRep -> CmmExpr -> Int -> CmmExpr
141 cmmIndex rep base idx = cmmOffset base (idx * machRepByteWidth rep)
142
143 -- | Useful for creating an index into an array, with an unknown offset.
144 cmmIndexExpr :: MachRep -> CmmExpr -> CmmExpr -> CmmExpr
145 cmmIndexExpr rep base (CmmLit (CmmInt n _)) = cmmIndex rep base (fromInteger n)
146 cmmIndexExpr rep base idx =
147   cmmOffsetExpr base byte_off
148   where
149     idx_rep = cmmExprRep idx
150     byte_off = CmmMachOp (MO_Shl idx_rep) [
151                   idx, CmmLit (mkIntCLit (machRepLogWidth rep))]
152
153 cmmLoadIndex :: MachRep -> CmmExpr -> Int -> CmmExpr
154 cmmLoadIndex rep expr ix = CmmLoad (cmmIndex rep expr ix) rep
155
156 ---------------------------------------------------
157 --
158 --      Literal construction functions
159 --
160 ---------------------------------------------------
161
162 mkIntCLit :: Int -> CmmLit
163 mkIntCLit i = CmmInt (toInteger i) wordRep
164
165 zeroCLit :: CmmLit
166 zeroCLit = CmmInt 0 wordRep
167
168 mkLblExpr :: CLabel -> CmmExpr
169 mkLblExpr lbl = CmmLit (CmmLabel lbl)