[GHC] #8335: Create more specialized entries to GC

#8335: Create more specialized entries to GC ------------------------------------+------------------------------------- Reporter: jstolarek | Owner: Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.7 Keywords: | Operating System: Unknown/Multiple Architecture: Unknown/Multiple | Type of failure: None/Unknown Difficulty: Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | ------------------------------------+------------------------------------- Consider this Cmm code (taken from #8326): {{{ {offset cFd: // stack check if ((Sp + -16) < SpLim) goto cFr; else goto cFs; cFr: // not enough place on the stack, call GC R2 = R2; R1 = A.f_closure; call (stg_gc_fun)(R2, R1) args: 8, res: 0, upd: 8; cFs: // scrutinize (x ># 0#) _sEU::I64 = R2; _sEV::I64 = %MO_S_Gt_W64(R2, 0); if (_sEV::I64 != 1) goto cFg; else goto cFo; cFg: // False branch Hp = Hp + 16; if (Hp > HpLim) goto cFy; else goto cFx; cFy: // not enough heap, call GC HpAlloc = 16; I64[Sp - 16] = cFf; R1 = _sEV::I64; I64[Sp - 8] = _sEU::I64; Sp = Sp - 16; call stg_gc_unbx_r1(R1) returns to cFf, args: 8, res: 8, upd: 8; cFf: // re-do the False branch _sEU::I64 = I64[Sp + 8]; Sp = Sp + 16; _sEV::I64 = R1; goto cFg; cFx: // RHS of False branch I64[Hp - 8] = GHC.Types.I#_con_info; I64[Hp] = -_sEU::I64; R1 = Hp - 7; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; cFo: // True branch Hp = Hp + 16; if (Hp > HpLim) goto cFv; else goto cFu; cFv: // not enough heap, call GC HpAlloc = 16; I64[Sp - 16] = cFn; R1 = _sEV::I64; I64[Sp - 8] = _sEU::I64; Sp = Sp - 16; call stg_gc_unbx_r1(R1) returns to cFn, args: 8, res: 8, upd: 8; cFn: // re-do the True branch _sEU::I64 = I64[Sp + 8]; Sp = Sp + 16; _sEV::I64 = R1; goto cFo; cFu: // RHS of True branch I64[Hp - 8] = GHC.Types.I#_con_info; I64[Hp] = _sEU::I64; R1 = Hp - 7; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } }}} We perform two different calls to garbage collection here. Calling GC after making initial stack check obviously can't use any stack, so we pass parameter to GC in regsiters: {{{ R2 = R2; R1 = A.f_closure; call (stg_gc_fun)(R2, R1) args: 8, res: 0, upd: 8; }}} But in the calls that are made later on inside the function we do put some parameters on the stack, thus increasing stack usage: {{{ cFv: // not enough heap, call GC HpAlloc = 16; I64[Sp - 16] = cFn; R1 = _sEV::I64; I64[Sp - 8] = _sEU::I64; Sp = Sp - 16; call stg_gc_unbx_r1(R1) returns to cFn, args: 8, res: 8, upd: 8; }}} If we had more specialized entries to GC that would allow us to pass parameters in registers (or in some fixed memory location associated with TCO?) then this function would not require any stack at all. Note that there is a separate issue here - `_sEV` variable is in fact dead and should be eliminated (see #8327). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8335 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8335: Create more specialized entries to GC -------------------------------------+------------------------------------- Reporter: jstolarek | Owner: bgamari Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by bgamari): * owner: => bgamari Comment: There should be a check in the stack allocator to catch this case. It's possible that this isn't firing. I'll have a look at this. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8335#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8335: Create more specialized entries to GC -------------------------------------+------------------------------------- Reporter: jstolarek | Owner: bgamari Type: task | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.7 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): -------------------------------------+------------------------------------- Changes (by bgamari): * status: new => closed * resolution: => fixed Comment: I think this may be fixed (at least in the current state of `master`, a3c78abcbdfe5025dc704acdcd0a85c78cabbd6b). This program (taken from #8326), {{{#!hs {-# LANGUAGE MagicHash #-} module Test where import GHC.Prim import GHC.Types f :: Int# -> Int f x | isTrue# (x ># 0#) = I# x | otherwise = -(I# x) }}} produces this Core, {{{#!hs f :: Int# -> Int f = \ (x_anw :: Int#) -> case tagToEnum# @ Bool (># x_anw 0#) of _ [Occ=Dead] { False -> I# (negateInt# x_anw); True -> I# x_anw } }}} which is ultimately lowered to this C--, {{{ Test.f_entry() // [R2] { info_tbl: [(cyv, label: Test.f_info rep:HeapRep static { Fun {arity: 1 fun_type: ArgSpec 4} })] stack_info: arg_space: 8 updfr_space: Just 8 } {offset cyv: Hp = Hp + 16; if (Hp > HpLim) goto cyz; else goto cyy; cyz: HpAlloc = 16; R2 = R2; R1 = Test.f_closure; call (stg_gc_fun)(R2, R1) args: 8, res: 0, upd: 8; cyy: if (%MO_S_Gt_W64(R2, 0)) goto cyL; else goto cyI; cyL: I64[Hp - 8] = GHC.Types.I#_con_info; I64[Hp] = R2; R1 = Hp - 7; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; cyI: I64[Hp - 8] = GHC.Types.I#_con_info; I64[Hp] = -R2; R1 = Hp - 7; call (P64[Sp])(R1) args: 8, res: 0, upd: 8; } }] }}} Jan, would you agree that all looks okay here? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8335#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC