summaryrefslogtreecommitdiff
path: root/compiler/codeGen
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2012-02-19 13:04:37 +0000
committerSimon Marlow <marlowsd@gmail.com>2012-02-19 13:04:37 +0000
commit13875c61d0dfef31ce0b1914d82c316531c27a67 (patch)
treeaeaf748cf55937537780b211ff393477503a487c /compiler/codeGen
parent8071691488802dbe5e67b5a47206f564a2d0bcbf (diff)
parent86a00474ef649f45e3abe3e1b42d51f04e7a5ee9 (diff)
downloadhaskell-13875c61d0dfef31ce0b1914d82c316531c27a67.tar.gz
Merge branch 'newcg' of /home/simonmar/code-all/work/ghc-newcg into newcg
Diffstat (limited to 'compiler/codeGen')
-rw-r--r--compiler/codeGen/CgInfoTbls.hs2
-rw-r--r--compiler/codeGen/StgCmmBind.hs30
-rw-r--r--compiler/codeGen/StgCmmClosure.hs29
-rw-r--r--compiler/codeGen/StgCmmCon.hs1
-rw-r--r--compiler/codeGen/StgCmmExpr.hs119
-rw-r--r--compiler/codeGen/StgCmmForeign.hs14
-rw-r--r--compiler/codeGen/StgCmmHeap.hs9
-rw-r--r--compiler/codeGen/StgCmmPrim.hs4
-rw-r--r--compiler/codeGen/StgCmmUtils.hs38
9 files changed, 128 insertions, 118 deletions
diff --git a/compiler/codeGen/CgInfoTbls.hs b/compiler/codeGen/CgInfoTbls.hs
index ee5fb594c7..f98d579e62 100644
--- a/compiler/codeGen/CgInfoTbls.hs
+++ b/compiler/codeGen/CgInfoTbls.hs
@@ -36,7 +36,7 @@ import CgBindery
import CgCallConv
import CgUtils
import CgMonad
-import CmmBuildInfoTables
+import CmmUtils
import OldCmm
import CLabel
diff --git a/compiler/codeGen/StgCmmBind.hs b/compiler/codeGen/StgCmmBind.hs
index 0222299ff2..7dbc9954c5 100644
--- a/compiler/codeGen/StgCmmBind.hs
+++ b/compiler/codeGen/StgCmmBind.hs
@@ -76,16 +76,16 @@ cgTopRhsClosure :: Id
cgTopRhsClosure id ccs _ upd_flag srt args body = do
{ -- LAY OUT THE OBJECT
let name = idName id
- ; lf_info <- mkClosureLFInfo id TopLevel [] upd_flag args
- ; srt_info <- getSRTInfo srt
+ ; lf_info <- mkClosureLFInfo id TopLevel [] upd_flag args
+ ; has_srt <- getSRTInfo srt
; mod_name <- getModuleName
; let descr = closureDescription mod_name name
- closure_info = mkClosureInfo True id lf_info 0 0 srt_info descr
+ closure_info = mkClosureInfo True id lf_info 0 0 descr
closure_label = mkLocalClosureLabel name (idCafInfo id)
cg_id_info = litIdInfo id lf_info (CmmLabel closure_label)
caffy = idCafInfo id
info_tbl = mkCmmInfo closure_info -- XXX short-cut
- closure_rep = mkStaticClosureFields info_tbl ccs caffy []
+ closure_rep = mkStaticClosureFields info_tbl ccs caffy has_srt []
-- BUILD THE OBJECT, AND GENERATE INFO TABLE (IF NECESSARY)
; emitDataLits closure_label closure_rep
@@ -161,8 +161,8 @@ cgRhs :: Id -> StgRhs -> FCode (CgIdInfo, CmmAGraph)
cgRhs name (StgRhsCon cc con args)
= buildDynCon name cc con args
-cgRhs name (StgRhsClosure cc bi fvs upd_flag srt args body)
- = mkRhsClosure name cc bi (nonVoidIds fvs) upd_flag srt args body
+cgRhs name (StgRhsClosure cc bi fvs upd_flag _srt args body)
+ = mkRhsClosure name cc bi (nonVoidIds fvs) upd_flag args body
------------------------------------------------------------------------
-- Non-constructor right hand sides
@@ -170,7 +170,7 @@ cgRhs name (StgRhsClosure cc bi fvs upd_flag srt args body)
mkRhsClosure :: Id -> CostCentreStack -> StgBinderInfo
-> [NonVoid Id] -- Free vars
- -> UpdateFlag -> SRT
+ -> UpdateFlag
-> [Id] -- Args
-> StgExpr
-> FCode (CgIdInfo, CmmAGraph)
@@ -214,8 +214,7 @@ for semi-obvious reasons.
mkRhsClosure bndr cc bi
[NonVoid the_fv] -- Just one free var
upd_flag -- Updatable thunk
- _srt
- [] -- A thunk
+ [] -- A thunk
body@(StgCase (StgApp scrutinee [{-no args-}])
_ _ _ _ -- ignore uniq, etc.
(AlgAlt _)
@@ -246,8 +245,7 @@ mkRhsClosure bndr cc bi
mkRhsClosure bndr cc bi
fvs
upd_flag
- _srt
- [] -- No args; a thunk
+ [] -- No args; a thunk
body@(StgApp fun_id args)
| args `lengthIs` (arity-1)
@@ -268,7 +266,7 @@ mkRhsClosure bndr cc bi
arity = length fvs
---------- Default case ------------------
-mkRhsClosure bndr cc _ fvs upd_flag srt args body
+mkRhsClosure bndr cc _ fvs upd_flag args body
= do { -- LAY OUT THE OBJECT
-- If the binder is itself a free variable, then don't store
-- it in the closure. Instead, just bind it to Node on entry.
@@ -287,8 +285,7 @@ mkRhsClosure bndr cc _ fvs upd_flag srt args body
-- MAKE CLOSURE INFO FOR THIS CLOSURE
; lf_info <- mkClosureLFInfo bndr NotTopLevel fvs upd_flag args
; mod_name <- getModuleName
- ; c_srt <- getSRTInfo srt
- ; let name = idName bndr
+ ; let name = idName bndr
descr = closureDescription mod_name name
fv_details :: [(NonVoid Id, VirtualHpOffset)]
(tot_wds, ptr_wds, fv_details)
@@ -296,7 +293,7 @@ mkRhsClosure bndr cc _ fvs upd_flag srt args body
(addIdReps (map stripNV reduced_fvs))
closure_info = mkClosureInfo False -- Not static
bndr lf_info tot_wds ptr_wds
- c_srt descr
+ descr
-- BUILD ITS INFO TABLE AND CODE
; forkClosureBody $
@@ -342,8 +339,7 @@ cgStdThunk bndr _cc _bndr_info _body lf_info payload
descr = closureDescription mod_name (idName bndr)
closure_info = mkClosureInfo False -- Not static
bndr lf_info tot_wds ptr_wds
- NoC_SRT -- No SRT for a std-form closure
- descr
+ descr
-- ; (use_cc, blame_cc) <- chooseDynCostCentres cc [{- no args-}] body
; let use_cc = curCCS; blame_cc = curCCS
diff --git a/compiler/codeGen/StgCmmClosure.hs b/compiler/codeGen/StgCmmClosure.hs
index 5c0741a65e..487c94daaa 100644
--- a/compiler/codeGen/StgCmmClosure.hs
+++ b/compiler/codeGen/StgCmmClosure.hs
@@ -650,7 +650,6 @@ data ClosureInfo
-- the rest is just an unpacked CmmInfoTable.
closureInfoLabel :: !CLabel,
closureSMRep :: !SMRep, -- representation used by storage mgr
- closureSRT :: !C_SRT, -- What SRT applies to this closure
closureProf :: !ProfilingInfo
}
@@ -660,7 +659,7 @@ mkCmmInfo ClosureInfo {..}
= CmmInfoTable { cit_lbl = closureInfoLabel
, cit_rep = closureSMRep
, cit_prof = closureProf
- , cit_srt = closureSRT }
+ , cit_srt = NoC_SRT }
--------------------------------------
@@ -671,16 +670,14 @@ mkClosureInfo :: Bool -- Is static
-> Id
-> LambdaFormInfo
-> Int -> Int -- Total and pointer words
- -> C_SRT
- -> String -- String descriptor
+ -> String -- String descriptor
-> ClosureInfo
-mkClosureInfo is_static id lf_info tot_wds ptr_wds srt_info val_descr
+mkClosureInfo is_static id lf_info tot_wds ptr_wds val_descr
= ClosureInfo { closureName = name,
closureLFInfo = lf_info,
- closureInfoLabel = info_lbl,
- closureSMRep = sm_rep, -- These four fields are a
- closureSRT = srt_info, -- CmmInfoTable
- closureProf = prof } -- ---
+ closureInfoLabel = info_lbl, -- These three fields are
+ closureSMRep = sm_rep, -- (almost) an info table
+ closureProf = prof } -- (we don't have an SRT yet)
where
name = idName id
sm_rep = mkHeapRep is_static ptr_wds nonptr_wds (lfClosureType lf_info)
@@ -906,15 +903,21 @@ cafBlackHoleInfoTable
, cit_prof = NoProfilingInfo
, cit_srt = NoC_SRT }
-staticClosureNeedsLink :: CmmInfoTable -> Bool
+staticClosureNeedsLink :: Bool -> CmmInfoTable -> Bool
-- A static closure needs a link field to aid the GC when traversing
-- the static closure graph. But it only needs such a field if either
-- a) it has an SRT
-- b) it's a constructor with one or more pointer fields
-- In case (b), the constructor's fields themselves play the role
-- of the SRT.
-staticClosureNeedsLink info_tbl@CmmInfoTable{ cit_rep = smrep }
+--
+-- At this point, the cit_srt field has not been calculated (that
+-- happens right at the end of the Cmm pipeline), but we do have the
+-- VarSet of CAFs that CoreToStg attached, and if that is empty there
+-- will definitely not be an SRT.
+--
+staticClosureNeedsLink has_srt CmmInfoTable{ cit_rep = smrep }
| isConRep smrep = not (isStaticNoCafCon smrep)
- | otherwise = needsSRT (cit_srt info_tbl)
-staticClosureNeedsLink _ = False
+ | otherwise = has_srt -- needsSRT (cit_srt info_tbl)
+staticClosureNeedsLink _ _ = False
diff --git a/compiler/codeGen/StgCmmCon.hs b/compiler/codeGen/StgCmmCon.hs
index e17ac4fd32..1a40a4273f 100644
--- a/compiler/codeGen/StgCmmCon.hs
+++ b/compiler/codeGen/StgCmmCon.hs
@@ -92,6 +92,7 @@ cgTopRhsCon id con args
info_tbl
dontCareCCS -- Because it's static data
caffy -- Has CAF refs
+ False -- no SRT
payload
-- BUILD THE OBJECT
diff --git a/compiler/codeGen/StgCmmExpr.hs b/compiler/codeGen/StgCmmExpr.hs
index fe41de83fa..ccc9e6b9c1 100644
--- a/compiler/codeGen/StgCmmExpr.hs
+++ b/compiler/codeGen/StgCmmExpr.hs
@@ -284,15 +284,63 @@ data GcPlan
-- of the case alternative(s) into the upstream check
-------------------------------------
--- See Note [case on Bool]
cgCase :: StgExpr -> Id -> SRT -> AltType -> [StgAlt] -> FCode ()
+
+cgCase (StgOpApp (StgPrimOp op) args _) bndr _srt (AlgAlt tycon) alts
+ | isEnumerationTyCon tycon -- Note [case on bool]
+ = do { tag_expr <- do_enum_primop op args
+
+ -- If the binder is not dead, convert the tag to a constructor
+ -- and assign it.
+ ; when (not (isDeadBinder bndr)) $ do
+ { tmp_reg <- bindArgToReg (NonVoid bndr)
+ ; emitAssign (CmmLocal tmp_reg)
+ (tagToClosure tycon tag_expr) }
+
+ ; (mb_deflt, branches) <- cgAlgAltRhss NoGcInAlts (NonVoid bndr) alts
+ ; emitSwitch tag_expr branches mb_deflt 0 (tyConFamilySize tycon - 1)
+ }
+ where
+ do_enum_primop :: PrimOp -> [StgArg] -> FCode CmmExpr
+ do_enum_primop TagToEnumOp [arg] -- No code!
+ = getArgAmode (NonVoid arg)
+ do_enum_primop primop args
+ = do tmp <- newTemp bWord
+ cgPrimOp [tmp] primop args
+ return (CmmReg (CmmLocal tmp))
+
{-
-cgCase (OpApp ) bndr srt AlgAlt [(DataAlt flase, a2]
- | isBoolTy (idType bndr)
- , isDeadBndr bndr
- =
+Note [case on bool]
+
+This special case handles code like
+
+ case a <# b of
+ True ->
+ False ->
+
+If we let the ordinary case code handle it, we'll get something like
+
+ tmp1 = a < b
+ tmp2 = Bool_closure_tbl[tmp1]
+ if (tmp2 & 7 != 0) then ... // normal tagged case
+
+but this junk won't optimise away. What we really want is just an
+inline comparison:
+
+ if (a < b) then ...
+
+So we add a special case to generate
+
+ tmp1 = a < b
+ if (tmp1 == 0) then ...
+
+and later optimisations will further improve this.
+
+We should really change all these primops to return Int# instead, that
+would make this special case go away.
-}
+
-- Note [ticket #3132]: we might be looking at a case of a lifted Id
-- that was cast to an unlifted type. The Id will always be bottom,
-- but we don't want the code generator to fall over here. If we
@@ -439,17 +487,10 @@ cgAlts gc_plan bndr (PrimAlt _) alts
; emitCmmLitSwitch (CmmReg bndr_reg) tagged_cmms' deflt }
cgAlts gc_plan bndr (AlgAlt tycon) alts
- = do { tagged_cmms <- cgAltRhss gc_plan bndr alts
-
+ = do { (mb_deflt, branches) <- cgAlgAltRhss gc_plan bndr alts
+
; let fam_sz = tyConFamilySize tycon
bndr_reg = CmmLocal (idToReg bndr)
- mb_deflt = case tagged_cmms of
- ((DEFAULT,rhs) : _) -> Just rhs
- _other -> Nothing
- -- DEFAULT is always first, if present
-
- branches = [ (dataConTagZ con, cmm)
- | (DataAlt con, cmm) <- tagged_cmms ]
-- Is the constructor tag in the node reg?
; if isSmallFamily fam_sz
@@ -470,6 +511,27 @@ cgAlts gc_plan bndr (AlgAlt tycon) alts
cgAlts _ _ _ _ = panic "cgAlts"
-- UbxTupAlt and PolyAlt have only one alternative
+
+-------------------
+cgAlgAltRhss :: GcPlan -> NonVoid Id -> [StgAlt]
+ -> FCode ( Maybe CmmAGraph
+ , [(ConTagZ, CmmAGraph)] )
+cgAlgAltRhss gc_plan bndr alts
+ = do { tagged_cmms <- cgAltRhss gc_plan bndr alts
+
+ ; let { mb_deflt = case tagged_cmms of
+ ((DEFAULT,rhs) : _) -> Just rhs
+ _other -> Nothing
+ -- DEFAULT is always first, if present
+
+ ; branches = [ (dataConTagZ con, cmm)
+ | (DataAlt con, cmm) <- tagged_cmms ]
+ }
+
+ ; return (mb_deflt, branches)
+ }
+
+
-------------------
cgAltRhss :: GcPlan -> NonVoid Id -> [StgAlt] -> FCode [(AltCon, CmmAGraph)]
cgAltRhss gc_plan bndr alts
@@ -617,35 +679,6 @@ emitEnter fun = do
}
-
-{- Note [case on Bool]
- ~~~~~~~~~~~~~~~~~~~
-A case on a Boolean value does two things:
- 1. It looks up the Boolean in a closure table and assigns the
- result to the binder.
- 2. It branches to the True or False case through analysis
- of the closure assigned to the binder.
-But the indirection through the closure table is unnecessary
-if the assignment to the binder will be dead code (use isDeadBndr).
-
-The following example illustrates how badly the code turns out:
- STG:
- case <=## [ww_s7Hx y_s7HD] of wild2_sbH8 {
- GHC.Types.False -> <true code> // sbH8 dead
- GHC.Types.True -> <false code> // sbH8 dead
- };
- Cmm:
- _s7HD::F64 = F64[_sbH7::I64 + 7]; // MidAssign
- _ccsW::I64 = %MO_F_Le_W64(_s7Hx::F64, _s7HD::F64); // MidAssign
- // emitReturn // MidComment
- _sbH8::I64 = I64[ghczmprim_GHCziBool_Bool_closure_tbl + (_ccsW::I64 << 3)]; // MidAssign
- _ccsX::I64 = _sbH8::I64 & 7; // MidAssign
- if (_ccsX::I64 >= 2) goto ccsH; else goto ccsI; // LastCondBranch
-
-The assignments to _sbH8 and _ccsX are completely unnecessary.
-Instead, we should branch based on the value of _ccsW.
--}
-
{- Note [Better Alt Heap Checks]
If two function calls can share a return point, then they will also
get the same info table. Therefore, it's worth our effort to make
diff --git a/compiler/codeGen/StgCmmForeign.hs b/compiler/codeGen/StgCmmForeign.hs
index 16edc9c4fb..f1a522b37d 100644
--- a/compiler/codeGen/StgCmmForeign.hs
+++ b/compiler/codeGen/StgCmmForeign.hs
@@ -72,10 +72,7 @@ cgForeignCall results result_hints (CCall (CCallSpec target cconv safety)) stg_a
fc = ForeignConvention cconv arg_hints result_hints
call_target = ForeignTarget cmm_target fc
- ; srt <- getSRTInfo NoSRT -- SLPJ: Not sure what SRT
- -- is right here
- -- JD: Does it matter in the new codegen?
- ; emitForeignCall safety results call_target call_args srt CmmMayReturn }
+ ; emitForeignCall safety results call_target call_args CmmMayReturn }
where
-- in the stdcall calling convention, the symbol needs @size appended
-- to it, where size is the total number of bytes of arguments. We
@@ -93,9 +90,7 @@ emitCCall :: [(CmmFormal,ForeignHint)]
-> [(CmmActual,ForeignHint)]
-> FCode ()
emitCCall hinted_results fn hinted_args
- = emitForeignCall PlayRisky results target args
- NoC_SRT -- No SRT b/c we PlayRisky
- CmmMayReturn
+ = emitForeignCall PlayRisky results target args CmmMayReturn
where
(args, arg_hints) = unzip hinted_args
(results, result_hints) = unzip hinted_results
@@ -105,7 +100,7 @@ emitCCall hinted_results fn hinted_args
emitPrimCall :: [CmmFormal] -> CallishMachOp -> [CmmActual] -> FCode ()
emitPrimCall res op args
- = emitForeignCall PlayRisky res (PrimTarget op) args NoC_SRT CmmMayReturn
+ = emitForeignCall PlayRisky res (PrimTarget op) args CmmMayReturn
-- alternative entry point, used by CmmParse
emitForeignCall
@@ -113,11 +108,10 @@ emitForeignCall
-> [CmmFormal] -- where to put the results
-> ForeignTarget -- the op
-> [CmmActual] -- arguments
- -> C_SRT -- the SRT of the calls continuation
-> CmmReturnInfo -- This can say "never returns"
-- only RTS procedures do this
-> FCode ()
-emitForeignCall safety results target args _srt _ret
+emitForeignCall safety results target args _ret
| not (playSafe safety) = do
let (caller_save, caller_load) = callerSaveVolatileRegs
emit caller_save
diff --git a/compiler/codeGen/StgCmmHeap.hs b/compiler/codeGen/StgCmmHeap.hs
index 68d078fb28..6533414703 100644
--- a/compiler/codeGen/StgCmmHeap.hs
+++ b/compiler/codeGen/StgCmmHeap.hs
@@ -151,9 +151,10 @@ mkStaticClosureFields
:: CmmInfoTable
-> CostCentreStack
-> CafInfo
+ -> Bool -- SRT is non-empty?
-> [CmmLit] -- Payload
-> [CmmLit] -- The full closure
-mkStaticClosureFields info_tbl ccs caf_refs payload
+mkStaticClosureFields info_tbl ccs caf_refs has_srt payload
= mkStaticClosure info_lbl ccs payload padding
static_link_field saved_info_field
where
@@ -178,8 +179,10 @@ mkStaticClosureFields info_tbl ccs caf_refs payload
| otherwise = ASSERT(null payload) [mkIntCLit 0]
static_link_field
- | is_caf || staticClosureNeedsLink info_tbl = [static_link_value]
- | otherwise = []
+ | is_caf || staticClosureNeedsLink has_srt info_tbl
+ = [static_link_value]
+ | otherwise
+ = []
saved_info_field
| is_caf = [mkIntCLit 0]
diff --git a/compiler/codeGen/StgCmmPrim.hs b/compiler/codeGen/StgCmmPrim.hs
index 1824ae9136..c95b1f02ff 100644
--- a/compiler/codeGen/StgCmmPrim.hs
+++ b/compiler/codeGen/StgCmmPrim.hs
@@ -14,7 +14,9 @@
-- for details
module StgCmmPrim (
- cgOpApp
+ cgOpApp,
+ cgPrimOp -- internal(ish), used by cgCase to get code for a
+ -- comparison without also turning it into a Bool.
) where
#include "HsVersions.h"
diff --git a/compiler/codeGen/StgCmmUtils.hs b/compiler/codeGen/StgCmmUtils.hs
index 16f741e929..246d57cda9 100644
--- a/compiler/codeGen/StgCmmUtils.hs
+++ b/compiler/codeGen/StgCmmUtils.hs
@@ -71,6 +71,7 @@ import Module
import Literal
import Digraph
import ListSetOps
+import VarSet
import Util
import Unique
import DynFlags
@@ -811,36 +812,13 @@ assignTemp' e
--
-------------------------------------------------------------------------
--- There is just one SRT for each top level binding; all the nested
--- bindings use sub-sections of this SRT. The label is passed down to
--- the nested bindings via the monad.
-
-getSRTInfo :: SRT -> FCode C_SRT
-getSRTInfo (SRTEntries {}) = return NoC_SRT --panic "getSRTInfo"
-
-getSRTInfo (SRT off len bmp)
- | len > hALF_WORD_SIZE_IN_BITS || bmp == [fromIntegral srt_escape]
- = do { id <- newUnique
- -- ; top_srt <- getSRTLabel
- ; let srt_desc_lbl = mkLargeSRTLabel id
- -- JD: We're not constructing and emitting SRTs in the back end,
- -- which renders this code wrong (it now names a now-non-existent label).
- -- ; emitRODataLits srt_desc_lbl
- -- ( cmmLabelOffW top_srt off
- -- : mkWordCLit (fromIntegral len)
- -- : map mkWordCLit bmp)
- ; return (C_SRT srt_desc_lbl 0 srt_escape) }
-
- | otherwise
- = do { top_srt <- getSRTLabel
- ; return (C_SRT top_srt off (fromIntegral (head bmp))) }
- -- The fromIntegral converts to StgHalfWord
-
-getSRTInfo NoSRT
- = -- TODO: Should we panic in this case?
- -- Someone obviously thinks there should be an SRT
- return NoC_SRT
-
+-- | Returns 'True' if there is a non-empty SRT, or 'False' otherwise
+-- NB. the SRT attached to an StgBind is still used in the new codegen
+-- to decide whether we need a static link field on a static closure
+-- or not.
+getSRTInfo :: SRT -> FCode Bool
+getSRTInfo (SRTEntries vs) = return (not (isEmptyVarSet vs))
+getSRTInfo _ = return False
srt_escape :: StgHalfWord
srt_escape = -1