Small optimisation to the code generated for CAFs
authorSimon Marlow <marlowsd@gmail.com>
Thu, 19 Jul 2012 10:32:45 +0000 (11:32 +0100)
committerSimon Marlow <marlowsd@gmail.com>
Mon, 30 Jul 2012 10:56:20 +0000 (11:56 +0100)
compiler/codeGen/StgCmmBind.hs
compiler/codeGen/StgCmmHeap.hs

index 5530721..e40c660 100644 (file)
@@ -578,7 +578,7 @@ setupUpdate closure_info node body
        ; if closureUpdReqd closure_info
          then do       -- Blackhole the (updatable) CAF:
                 { upd_closure <- link_caf True
-               ; pushUpdateFrame [CmmReg (CmmLocal upd_closure),
+                ; pushUpdateFrame [upd_closure,
                                    mkLblExpr mkBHUpdInfoLabel] body }
          else do {tickyUpdateFrameOmitted; body}
     }
@@ -633,8 +633,8 @@ pushUpdateFrame es body
 -- be closer together, and the compiler wouldn't need to know
 -- about off_indirectee etc.
 
-link_caf :: Bool                -- True <=> updatable, False <=> single-entry
-         -> FCode LocalReg      -- Returns amode for closure to be updated
+link_caf :: Bool               -- True <=> updatable, False <=> single-entry
+         -> FCode CmmExpr      -- Returns amode for closure to be updated
 -- To update a CAF we must allocate a black hole, link the CAF onto the
 -- CAF list, then update the CAF to point to the fresh black hole.
 -- This function returns the address of the black hole, so it can be
@@ -648,19 +648,24 @@ link_caf _is_upd = do
         blame_cc = use_cc
         tso      = CmmReg (CmmGlobal CurrentTSO)
 
-  ; (hp_rel, init) <- allocDynClosureCmm cafBlackHoleInfoTable mkLFBlackHole
+  ; hp_rel <- allocDynClosureCmm cafBlackHoleInfoTable mkLFBlackHole
                                          use_cc blame_cc [(tso,fixedHdrSize dflags)]
-  ; emit init
-
-       -- Call the RTS function newCAF to add the CAF to the CafList
-       -- so that the garbage collector can find them
+        -- small optimisation: we duplicate the hp_rel expression in
+        -- both the newCAF call and the value returned below.
+        -- If we instead used allocDynClosureReg which assigns it to a reg,
+        -- then the reg is live across the newCAF call and gets spilled,
+        -- which is stupid.  Really we should have an optimisation pass to
+        -- fix this, but we don't yet. --SDM
+
+        -- Call the RTS function newCAF to add the CAF to the CafList
+        -- so that the garbage collector can find them
        -- This must be done *before* the info table pointer is overwritten,
        -- because the old info table ptr is needed for reversion
   ; ret <- newTemp bWord
   ; emitRtsCallGen [(ret,NoHint)] rtsPackageId (fsLit "newCAF")
       [ (CmmReg (CmmGlobal BaseReg),  AddrHint),
         (CmmReg nodeReg, AddrHint),
-        (CmmReg (CmmLocal hp_rel), AddrHint) ]
+        (hp_rel, AddrHint) ]
       (Just [node]) False
         -- node is live, so save it.
 
index e177b72..be4497a 100644 (file)
@@ -15,7 +15,8 @@ module StgCmmHeap (
         mkVirtHeapOffsets, mkVirtConstrOffsets,
         mkStaticClosureFields, mkStaticClosure,
 
-        allocDynClosure, allocDynClosureCmm, emitSetDynHdr
+        allocDynClosure, allocDynClosureReg, allocDynClosureCmm,
+        emitSetDynHdr
     ) where
 
 #include "HsVersions.h"
@@ -64,11 +65,16 @@ allocDynClosure
                                                 -- No void args in here
         -> FCode (LocalReg, CmmAGraph)
 
-allocDynClosureCmm
+allocDynClosureReg
         :: CmmInfoTable -> LambdaFormInfo -> CmmExpr -> CmmExpr
         -> [(CmmExpr, VirtualHpOffset)]
         -> FCode (LocalReg, CmmAGraph)
 
+allocDynClosureCmm
+        :: CmmInfoTable -> LambdaFormInfo -> CmmExpr -> CmmExpr
+        -> [(CmmExpr, VirtualHpOffset)]
+        -> FCode CmmExpr -- returns Hp+n
+
 -- allocDynClosure allocates the thing in the heap,
 -- and modifies the virtual Hp to account for this.
 -- The second return value is the graph that sets the value of the
@@ -89,10 +95,18 @@ allocDynClosureCmm
 allocDynClosure info_tbl lf_info use_cc _blame_cc args_w_offsets
   = do  { let (args, offsets) = unzip args_w_offsets
         ; cmm_args <- mapM getArgAmode args     -- No void args
-        ; allocDynClosureCmm info_tbl lf_info
+        ; allocDynClosureReg info_tbl lf_info
                              use_cc _blame_cc (zip cmm_args offsets)
         }
 
+allocDynClosureReg  info_tbl lf_info use_cc _blame_cc amodes_w_offsets
+  = do  { hp_rel <- allocDynClosureCmm info_tbl lf_info
+                                       use_cc _blame_cc amodes_w_offsets
+
+        -- Note [Return a LocalReg]
+        ; getCodeR $ assignTemp hp_rel
+        }
+
 allocDynClosureCmm info_tbl lf_info use_cc _blame_cc amodes_w_offsets
   = do  { virt_hp <- getVirtHp
 
@@ -121,10 +135,8 @@ allocDynClosureCmm info_tbl lf_info use_cc _blame_cc amodes_w_offsets
         ; dflags <- getDynFlags
         ; setVirtHp (virt_hp + heapClosureSize dflags rep)
 
-        -- Assign to a temporary and return
-        -- Note [Return a LocalReg]
-        ; hp_rel <- getHpRelOffset info_offset
-        ; getCodeR $ assignTemp hp_rel }
+        ; getHpRelOffset info_offset
+        }
 
 emitSetDynHdr :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
 emitSetDynHdr base info_ptr ccs