Reorganisation of the source tree
[ghc-hetmet.git] / compiler / cmm / CmmUtils.hs
diff --git a/compiler/cmm/CmmUtils.hs b/compiler/cmm/CmmUtils.hs
new file mode 100644 (file)
index 0000000..a04935b
--- /dev/null
@@ -0,0 +1,177 @@
+-----------------------------------------------------------------------------
+--
+-- Cmm utilities.
+--
+-- (c) The University of Glasgow 2004
+--
+-----------------------------------------------------------------------------
+
+module CmmUtils( 
+       CmmStmts, noStmts, oneStmt, mkStmts, plusStmts, stmtList,
+       isNopStmt,
+
+       isTrivialCmmExpr, hasNoGlobalRegs,
+
+       cmmRegOff, cmmLabelOff, cmmOffset, cmmOffsetLit, cmmIndex,
+       cmmOffsetExpr, cmmIndexExpr, cmmLoadIndex,
+
+       mkIntCLit, zeroCLit,
+
+       mkLblExpr,
+  ) where
+
+#include "HsVersions.h"
+
+import CLabel          ( CLabel )
+import Cmm
+import MachOp
+import OrdList
+import Outputable
+
+---------------------------------------------------
+--
+--     CmmStmts
+--
+---------------------------------------------------
+
+type CmmStmts = OrdList CmmStmt
+
+noStmts :: CmmStmts
+noStmts = nilOL
+
+oneStmt :: CmmStmt -> CmmStmts
+oneStmt = unitOL
+
+mkStmts :: [CmmStmt] -> CmmStmts
+mkStmts = toOL
+
+plusStmts :: CmmStmts -> CmmStmts -> CmmStmts
+plusStmts = appOL
+
+stmtList :: CmmStmts -> [CmmStmt]
+stmtList = fromOL
+
+
+---------------------------------------------------
+--
+--     CmmStmt
+--
+---------------------------------------------------
+
+isNopStmt :: CmmStmt -> Bool
+-- If isNopStmt returns True, the stmt is definitely a no-op;
+-- but it might be a no-op even if isNopStmt returns False
+isNopStmt CmmNop                      = True
+isNopStmt (CmmAssign r e)             = cheapEqReg r e
+isNopStmt (CmmStore e1 (CmmLoad e2 _)) = cheapEqExpr e1 e2
+isNopStmt s                           = False
+
+cheapEqExpr :: CmmExpr -> CmmExpr -> Bool
+cheapEqExpr (CmmReg r)      e                = cheapEqReg r e
+cheapEqExpr (CmmRegOff r 0) e                = cheapEqReg r e
+cheapEqExpr (CmmRegOff r n) (CmmRegOff r' n') = r==r' && n==n'
+cheapEqExpr e1                     e2                = False
+
+cheapEqReg :: CmmReg -> CmmExpr -> Bool
+cheapEqReg r (CmmReg r')      = r==r'
+cheapEqReg r (CmmRegOff r' 0) = r==r'
+cheapEqReg r e               = False
+
+---------------------------------------------------
+--
+--     CmmExpr
+--
+---------------------------------------------------
+
+isTrivialCmmExpr :: CmmExpr -> Bool
+isTrivialCmmExpr (CmmLoad _ _)   = False
+isTrivialCmmExpr (CmmMachOp _ _) = False
+isTrivialCmmExpr (CmmLit _)      = True
+isTrivialCmmExpr (CmmReg _)      = True
+isTrivialCmmExpr (CmmRegOff _ _) = True
+
+hasNoGlobalRegs :: CmmExpr -> Bool
+hasNoGlobalRegs (CmmLoad e _)             = hasNoGlobalRegs e
+hasNoGlobalRegs (CmmMachOp _ es)          = all hasNoGlobalRegs es
+hasNoGlobalRegs (CmmLit _)                = True
+hasNoGlobalRegs (CmmReg (CmmLocal _))      = True
+hasNoGlobalRegs (CmmRegOff (CmmLocal _) _) = True
+hasNoGlobalRegs _ = False
+
+---------------------------------------------------
+--
+--     Expr Construction helpers
+--
+---------------------------------------------------
+
+cmmOffsetExpr :: CmmExpr -> CmmExpr -> CmmExpr
+-- assumes base and offset have the same MachRep
+cmmOffsetExpr e (CmmLit (CmmInt n _)) = cmmOffset e (fromInteger n)
+cmmOffsetExpr e byte_off = CmmMachOp (MO_Add (cmmExprRep e)) [e, byte_off]
+
+-- NB. Do *not* inspect the value of the offset in these smart constructors!!!
+--
+-- because the offset is sometimes involved in a loop in the code generator
+-- (we don't know the real Hp offset until we've generated code for the entire
+-- basic block, for example).  So we cannot eliminate zero offsets at this
+-- stage; they're eliminated later instead (either during printing or
+-- a later optimisation step on Cmm).
+--
+cmmOffset :: CmmExpr -> Int -> CmmExpr
+cmmOffset (CmmReg reg)      byte_off = cmmRegOff reg byte_off
+cmmOffset (CmmRegOff reg m) byte_off = cmmRegOff reg (m+byte_off)
+cmmOffset (CmmLit lit)      byte_off = CmmLit (cmmOffsetLit lit byte_off)
+cmmOffset (CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt byte_off1 _rep)]) byte_off2
+  = CmmMachOp (MO_Add rep) 
+             [expr, CmmLit (CmmInt (byte_off1 + toInteger byte_off2) rep)]
+cmmOffset expr byte_off
+  = CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt (toInteger byte_off) rep)]
+  where
+    rep = cmmExprRep expr
+
+-- Smart constructor for CmmRegOff.  Same caveats as cmmOffset above.
+cmmRegOff :: CmmReg -> Int -> CmmExpr
+cmmRegOff reg byte_off = CmmRegOff reg byte_off
+
+cmmOffsetLit :: CmmLit -> Int -> CmmLit
+cmmOffsetLit (CmmLabel l)      byte_off = cmmLabelOff  l byte_off
+cmmOffsetLit (CmmLabelOff l m) byte_off = cmmLabelOff  l (m+byte_off)
+cmmOffsetLit (CmmInt m rep)    byte_off = CmmInt (m + fromIntegral byte_off) rep
+cmmOffsetLit other            byte_off = pprPanic "cmmOffsetLit" (ppr byte_off)
+
+cmmLabelOff :: CLabel -> Int -> CmmLit
+-- Smart constructor for CmmLabelOff
+cmmLabelOff lbl 0        = CmmLabel lbl
+cmmLabelOff lbl byte_off = CmmLabelOff lbl byte_off
+
+-- | Useful for creating an index into an array, with a staticaly known offset.
+cmmIndex :: MachRep -> CmmExpr -> Int -> CmmExpr
+cmmIndex rep base idx = cmmOffset base (idx * machRepByteWidth rep)
+
+-- | Useful for creating an index into an array, with an unknown offset.
+cmmIndexExpr :: MachRep -> CmmExpr -> CmmExpr -> CmmExpr
+cmmIndexExpr rep base (CmmLit (CmmInt n _)) = cmmIndex rep base (fromInteger n)
+cmmIndexExpr rep base idx =
+  cmmOffsetExpr base byte_off
+  where
+    idx_rep = cmmExprRep idx
+    byte_off = CmmMachOp (MO_Shl idx_rep) [
+                 idx, CmmLit (mkIntCLit (machRepLogWidth rep))]
+
+cmmLoadIndex :: MachRep -> CmmExpr -> Int -> CmmExpr
+cmmLoadIndex rep expr ix = CmmLoad (cmmIndex rep expr ix) rep
+
+---------------------------------------------------
+--
+--     Literal construction functions
+--
+---------------------------------------------------
+
+mkIntCLit :: Int -> CmmLit
+mkIntCLit i = CmmInt (toInteger i) wordRep
+
+zeroCLit :: CmmLit
+zeroCLit = CmmInt 0 wordRep
+
+mkLblExpr :: CLabel -> CmmExpr
+mkLblExpr lbl = CmmLit (CmmLabel lbl)