[project @ 2004-08-13 10:45:16 by simonmar]
[ghc-hetmet.git] / ghc / compiler / absCSyn / Costs.lhs
index b6d955c..17ea6d5 100644 (file)
@@ -1,7 +1,9 @@
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
-%     Hans Wolfgang Loidl
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
+% $Id: Costs.lhs,v 1.33 2003/07/28 16:05:30 simonmar Exp $
+%
+% Only needed in a GranSim setup -- HWL
 % ---------------------------------------------------------------------------
 
 \section[Costs]{Evaluating the costs of computing some abstract C code}
@@ -28,9 +30,11 @@ The meaning of the result tuple is:
    instructions.
 \end{itemize}
 
-This function is needed in GrAnSim for parallelism.
+This function is needed in GranSim for costing pieces of abstract C.
 
-These are first suggestions for scaling the costs. But, this scaling should be done in the RTS rather than the compiler (this really should be tunable!):
+These are first suggestions for scaling the costs. But, this scaling should
+be done in the RTS rather than the compiler (this really should be
+tunable!):
 
 \begin{pseudocode}
 
@@ -58,18 +62,16 @@ module Costs( costs,
 #include "HsVersions.h"
 
 import AbsCSyn
+import StgSyn          ( StgOp(..) )
 import PrimOp          ( primOpNeedsWrapper, PrimOp(..) )
 import Panic           ( trace )
 
 -- --------------------------------------------------------------------------
 data CostRes = Cost (Int, Int, Int, Int, Int)
-              deriving (Text)
+              deriving (Show)
 
 nullCosts    = Cost (0, 0, 0, 0, 0) :: CostRes
 initHdrCosts = Cost (2, 0, 0, 1, 0) :: CostRes
-errorCosts   = Cost (-1, -1, -1, -1, -1)  -- just for debugging
-
-oneArithm = Cost (1, 0, 0, 0, 0) :: CostRes
 
 instance Eq CostRes where
  (==) t1 t2 = i && b && l && s && f
@@ -82,14 +84,11 @@ instance Num CostRes where
  negate         = mapOp negate
  abs    = mapOp abs
  signum         = mapOp signum
+ fromInteger _ = error "fromInteger not defined"
 
 mapOp :: (Int -> Int) -> CostRes -> CostRes
 mapOp g ( Cost (i, b, l, s, f) )  = Cost (g i, g b, g l, g s, g f)
 
-foldrOp :: (Int -> a -> a) -> a -> CostRes -> a
-foldrOp o x  ( Cost (i1, b1, l1, s1, f1) )   =
-       i1 `o` ( b1 `o` ( l1 `o` ( s1 `o` ( f1 `o` x))))
-
 binOp :: (Int -> Int -> Int) -> CostRes -> CostRes -> CostRes
 binOp o ( Cost (i1, b1, l1, s1, f1) ) ( Cost  (i2, b2, l2, s2, f2) )  =
        ( Cost (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2) )
@@ -168,7 +167,7 @@ costs absC =
 
    CCodeBlock _ absC         -> costs absC
 
-   CInitHdr cl_info reg_rel cost_centre -> initHdrCosts
+   CInitHdr cl_info reg_rel cost_centre _ -> initHdrCosts
 
                        {- This is more fancy but superflous: The addr modes
                           are fixed and so the costs are const!
@@ -183,7 +182,7 @@ costs absC =
                           For costing the args of this macro
                           see PprAbsC.lhs where args are inserted -}
 
-   COpStmt modes_res primOp modes_args _ ->
+   COpStmt modes_res op modes_args _ ->
        {-
           let
                n = length modes_res
@@ -196,13 +195,14 @@ costs absC =
        -}
        foldl (+) nullCosts [addrModeCosts mode Lhs | mode <- modes_res]  +
        foldl (+) nullCosts [addrModeCosts mode Rhs | mode <- modes_args]  +
-       primOpCosts primOp +
-       if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
-                                    else nullCosts
+       opCosts op
 
    CSimultaneous absC       -> costs absC
 
-   CCheck _ amodes code             -> Cost (2, 1, 0, 0, 0)
+   CCheck _ amodes code             -> Cost (2, 1, 0, 0, 0) -- ToDo: refine this by 
+                                                     -- looking at the first arg 
+
+   CRetDirect _ _ _ _       -> nullCosts
 
    CMacroStmt  macro modes  -> stmtMacroCosts macro modes
 
@@ -215,19 +215,29 @@ costs absC =
   -- *** the next three [or so...] are DATA (those above are CODE) ***
   -- as they are data rather than code they all have nullCosts        -- HWL
 
+   CCallTypedef _ _ _ _ _    -> nullCosts
+
    CStaticClosure _ _ _ _    -> nullCosts
 
-   CClosureInfoAndCode _ _ _ _ -> nullCosts
+   CSRT _ _                  -> nullCosts
 
-   CRetDirect _ _ _ _       -> nullCosts
+   CBitmap _                 -> nullCosts
+
+   CClosureInfoAndCode _ _   -> nullCosts
 
    CRetVector _ _ _ _        -> nullCosts
 
+   CClosureTbl _             -> nullCosts
+
    CCostCentreDecl _ _      -> nullCosts
+
    CCostCentreStackDecl _    -> nullCosts
 
    CSplitMarker                     -> nullCosts
 
+   _ -> trace ("Costs.costs") nullCosts
+
+
 -- ---------------------------------------------------------------------------
 
 addrModeCosts :: CAddrMode -> Side -> CostRes
@@ -242,7 +252,11 @@ addrModeCosts addr_mode side =
     CVal _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
                       else Cost (0, 0, 1, 0, 0)
 
-    CReg _   -> nullCosts       {- loading from, storing to reg is free ! -}
+    CAddr (CIndex _ n _ ) -> Cost (1, 0, 1, 0, 0) -- does pointer arithmetic
+
+    CAddr _ -> nullCosts
+
+    CReg _  -> nullCosts        {- loading from, storing to reg is free ! -}
                                 {- for costing CReg->Creg ops see special -}
                                 {- case in costs fct -}
 
@@ -268,10 +282,6 @@ addrModeCosts addr_mode side =
     CLit    _     -> if lhs then nullCosts            -- should never occur
                             else Cost (1, 0, 0, 0, 0) -- typ.: mov lit,%reg
 
-    CLitLit _  _   -> if lhs then nullCosts
-                            else Cost (1, 0, 0, 0, 0)
-                     -- same es CLit
-
     CJoinPoint _         -> if lhs then Cost (0, 0, 0, 1, 0)
                                    else Cost (0, 0, 1, 0, 0)
 
@@ -288,28 +298,20 @@ exprMacroCosts side macro mode_list =
   in
   arg_costs +
   case macro of
-    ENTRY_CODE -> nullCosts
-    ARG_TAG -> nullCosts -- XXX
-    GET_TAG -> nullCosts -- XXX
-    
+    ENTRY_CODE -> nullCosts -- nothing 
+    ARG_TAG -> nullCosts -- nothing
+    GET_TAG -> Cost (0, 0, 1, 0, 0)  -- indirect load
 
 -- ---------------------------------------------------------------------------
 
 stmtMacroCosts :: CStmtMacro -> [CAddrMode] -> CostRes
 
 stmtMacroCosts macro modes =
-  let
-    arg_costs =          foldl (+) nullCosts
-                       [addrModeCosts mode Rhs | mode <- modes]
-  in
   case macro of
-    ARGS_CHK_LOAD_NODE  ->  Cost (2, 1, 0, 0, 0)        {- StgMacros.lh  -}
-               -- p=probability of PAP (instead of AP): + p*(3,1,0,0,0)
-    ARGS_CHK             ->  Cost (2, 1, 0, 0, 0)       {- StgMacros.lh  -}
     UPD_CAF              ->  Cost (7, 0, 1, 3, 0)       {- SMupdate.lh  -}
     UPD_BH_UPDATABLE     ->  Cost (3, 0, 0, 1, 0)       {- SMupdate.lh  -}
     UPD_BH_SINGLE_ENTRY          ->  Cost (3, 0, 0, 1, 0)       {- SMupdate.lh  -}
-    PUSH_UPD_FRAME       ->  Cost (3, 0, 0, 4, 0)       {- SMupdate.lh  -}
+    PUSH_UPD_FRAME       ->  Cost (3, 0, 0, 4, 0)       {- Updates.h    -}
     SET_TAG              ->  nullCosts             {- COptRegs.lh -}
     GRAN_FETCH                 ->  nullCosts     {- GrAnSim bookkeeping -}
     GRAN_RESCHEDULE            ->  nullCosts     {- GrAnSim bookkeeping -}
@@ -346,36 +348,38 @@ floatOps =
 gmpOps :: [PrimOp]
 gmpOps =
   [   IntegerAddOp , IntegerSubOp , IntegerMulOp
-    , IntegerQuotRemOp , IntegerDivModOp , IntegerNegOp
+    , IntegerQuotRemOp , IntegerDivModOp
     , IntegerCmpOp
     , Integer2IntOp  , Int2IntegerOp
-    , Addr2IntegerOp
   ]
 
 
-abs_costs = nullCosts   -- NB:  This is normal STG code with costs already 
-                       --      included; no need to add costs again.
-
 umul_costs = Cost (21,4,0,0,0)    -- due to spy counts
 rem_costs =  Cost (30,15,0,0,0)           -- due to spy counts
 div_costs =  Cost (30,15,0,0,0)           -- due to spy counts
 
-primOpCosts :: PrimOp -> CostRes
 
--- Special cases
 
-primOpCosts (CCallOp _ _ _ _) = SAVE_COSTS + RESTORE_COSTS     
-                                 -- don't guess costs of ccall proper
-                                  -- for exact costing use a GRAN_EXEC
-                                  -- in the C code
+-- ---------------------------------------------------------------------------
+
+opCosts :: StgOp -> CostRes
 
--- Usually 3 mov instructions are needed to get args and res in right place.
+opCosts (StgFCallOp _ _) = SAVE_COSTS + RESTORE_COSTS          
+       -- Don't guess costs of ccall proper
+        -- for exact costing use a GRAN_EXEC in the C code
+
+opCosts (StgPrimOp primop)
+  = primOpCosts primop +
+    if primOpNeedsWrapper primop then SAVE_COSTS + RESTORE_COSTS
+                                else nullCosts
+
+primOpCosts :: PrimOp -> CostRes
 
+-- Usually 3 mov instructions are needed to get args and res in right place.
 primOpCosts IntMulOp  = Cost (3, 1, 0, 0, 0)  + umul_costs
 primOpCosts IntQuotOp = Cost (3, 1, 0, 0, 0)  + div_costs
 primOpCosts IntRemOp  = Cost (3, 1, 0, 0, 0)  + rem_costs
 primOpCosts IntNegOp  = Cost (1, 1, 0, 0, 0) -- translates into 1 sub
-primOpCosts IntAbsOp  = Cost (0, 1, 0, 0, 0) -- abs closure already costed
 
 primOpCosts FloatGtOp  = Cost (2, 0, 0, 0, 2) -- expensive f-comp
 primOpCosts FloatGeOp  = Cost (2, 0, 0, 0, 2) -- expensive f-comp
@@ -414,140 +418,4 @@ primOpCosts primOp
   | primOp `elem` gmpOps   = Cost (30, 5, 10, 10, 0) :: CostRes  -- GUESS; check it
   | otherwise             = Cost (1, 0, 0, 0, 0)
 
--- ---------------------------------------------------------------------------
-{- HWL: currently unused
-
-costsByKind :: PrimRep -> Side -> CostRes
-
--- The following PrimKinds say that the data is already in a reg
-
-costsByKind CharRep    _ = nullCosts
-costsByKind IntRep     _ = nullCosts
-costsByKind WordRep    _ = nullCosts
-costsByKind AddrRep    _ = nullCosts
-costsByKind FloatRep   _ = nullCosts
-costsByKind DoubleRep  _ = nullCosts
--}
--- ---------------------------------------------------------------------------
 \end{code}
-
-This is the data structure of {\tt PrimOp} copied from prelude/PrimOp.lhs.
-I include here some comments about the estimated costs for these @PrimOps@.
-Compare with the @primOpCosts@ fct above.  -- HWL
-
-\begin{pseudocode}
-data PrimOp
-    -- I assume all these basic comparisons take just one ALU instruction
-    -- Checked that for Char, Int; Word, Addr should be the same as Int.
-
-    = CharGtOp  | CharGeOp   | CharEqOp   | CharNeOp   | CharLtOp   | CharLeOp
-    | IntGtOp   | IntGeOp    | IntEqOp    | IntNeOp    | IntLtOp    | IntLeOp
-    | WordGtOp  | WordGeOp   | WordEqOp   | WordNeOp   | WordLtOp   | WordLeOp
-    | AddrGtOp  | AddrGeOp   | AddrEqOp   | AddrNeOp   | AddrLtOp   | AddrLeOp
-
-    -- Analogously, these take one FP unit instruction
-    -- Haven't checked that, yet.
-
-    | FloatGtOp         | FloatGeOp  | FloatEqOp  | FloatNeOp  | FloatLtOp  | FloatLeOp
-    | DoubleGtOp | DoubleGeOp | DoubleEqOp | DoubleNeOp | DoubleLtOp | DoubleLeOp
-
-    -- 1 ALU op; unchecked
-    | OrdOp | ChrOp
-
-    -- these just take 1 ALU op; checked
-    | IntAddOp | IntSubOp
-
-    -- but these take more than that; see special cases in primOpCosts
-    -- I counted the generated ass. instructions for these -> checked
-    | IntMulOp | IntQuotOp
-    | IntRemOp | IntNegOp | IntAbsOp
-
-    -- Rest is unchecked so far -- HWL
-
-    -- Word#-related ops:
-    | AndOp   | OrOp  | NotOp | XorOp | ShiftLOp | ShiftROp
-    | Int2WordOp | Word2IntOp -- casts
-
-    -- Addr#-related ops:
-    | Int2AddrOp | Addr2IntOp -- casts
-
-    -- Float#-related ops:
-    | FloatAddOp | FloatSubOp | FloatMulOp | FloatDivOp | FloatNegOp
-    | Float2IntOp | Int2FloatOp
-
-    | FloatExpOp   | FloatLogOp          | FloatSqrtOp
-    | FloatSinOp   | FloatCosOp          | FloatTanOp
-    | FloatAsinOp  | FloatAcosOp  | FloatAtanOp
-    | FloatSinhOp  | FloatCoshOp  | FloatTanhOp
-    -- not all machines have these available conveniently:
-    -- | FloatAsinhOp | FloatAcoshOp | FloatAtanhOp
-    | FloatPowerOp -- ** op
-
-    -- Double#-related ops:
-    | DoubleAddOp | DoubleSubOp | DoubleMulOp | DoubleDivOp | DoubleNegOp
-    | Double2IntOp | Int2DoubleOp
-    | Double2FloatOp | Float2DoubleOp
-
-    | DoubleExpOp   | DoubleLogOp   | DoubleSqrtOp
-    | DoubleSinOp   | DoubleCosOp   | DoubleTanOp
-    | DoubleAsinOp  | DoubleAcosOp  | DoubleAtanOp
-    | DoubleSinhOp  | DoubleCoshOp  | DoubleTanhOp
-    -- not all machines have these available conveniently:
-    -- | DoubleAsinhOp | DoubleAcoshOp | DoubleAtanhOp
-    | DoublePowerOp -- ** op
-
-    -- Integer (and related...) ops:
-    -- slightly weird -- to match GMP package.
-    | IntegerAddOp | IntegerSubOp | IntegerMulOp
-    | IntegerQuotRemOp | IntegerDivModOp | IntegerNegOp
-
-    | IntegerCmpOp
-
-    | Integer2IntOp  | Int2IntegerOp
-    | Addr2IntegerOp -- "Addr" is *always* a literal string
-    -- ?? gcd, etc?
-
-    | FloatEncodeOp  | FloatDecodeOp
-    | DoubleEncodeOp | DoubleDecodeOp
-
-    -- primitive ops for primitive arrays
-
-    | NewArrayOp
-    | NewByteArrayOp PrimRep
-
-    | SameMutableArrayOp
-    | SameMutableByteArrayOp
-
-    | ReadArrayOp | WriteArrayOp | IndexArrayOp -- for arrays of Haskell ptrs
-
-    | ReadByteArrayOp  PrimRep
-    | WriteByteArrayOp PrimRep
-    | IndexByteArrayOp PrimRep
-    | IndexOffAddrOp   PrimRep
-       -- PrimRep can be one of {Char,Int,Addr,Float,Double}Kind.
-       -- This is just a cheesy encoding of a bunch of ops.
-       -- Note that ForeignObjRep is not included -- the only way of
-       -- creating a ForeignObj is with a ccall or casm.
-
-    | UnsafeFreezeArrayOp | UnsafeFreezeByteArrayOp
-
-    | MakeStablePtrOp | DeRefStablePtrOp
-\end{pseudocode}
-
-A special ``trap-door'' to use in making calls direct to C functions:
-Note: From GrAn point of view, CCall is probably very expensive 
-      The programmer can specify the costs of the Ccall by inserting
-      a GRAN_EXEC(a,b,l,s,f) at the end of the C- code, specifing the
-      number or arithm., branch, load, store and floating point instructions
-      -- HWL
-
-\begin{pseudocode}
-    | CCallOp  String  -- An "unboxed" ccall# to this named function
-               Bool    -- True <=> really a "casm"
-               Bool    -- True <=> might invoke Haskell GC
-               [Type]  -- Unboxed argument; the state-token
-                       -- argument will have been put *first*
-               Type    -- Return type; one of the "StateAnd<blah>#" types
-
-    -- (... to be continued ... )
-\end{pseudocode}