[GHC] #9038: Foreign calls don't make their arguments look strict

#9038: Foreign calls don't make their arguments look strict ------------------------------------+------------------------------------- Reporter: tibbe | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Keywords: | Operating System: Unknown/Multiple Architecture: Unknown/Multiple | Type of failure: None/Unknown Difficulty: Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | ------------------------------------+------------------------------------- Here's a function that takes a `Double` which is always passed to a `foreign import` expecting a `Double#`. Since the value is always unpacked, I'd expect `add3` to be strict in the `Double` argument and thereby avoid some allocation. {{{ add3 :: Distribution -> Double -> Int64 -> State# RealWorld -> (# State# RealWorld, () #) add3 = \ (distrib_a1uw :: Distribution) (val_a1ux :: Double) (n_a1uy :: Int64) (eta_X22 :: State# RealWorld) -> case myThreadId# eta_X22 of _ { (# ipv_i229, ipv1_i22a #) -> case threadStatus# ipv1_i22a ipv_i229 of _ { (# ipv2_i22e, _, ipv4_i22g, _ #) -> case modInt# ipv4_i22g 8 of ww1_i1NM { __DEFAULT -> case distrib_a1uw `cast` (NTCo:Distribution :: Distribution ~# Array Stripe) of _ { Array ds2_i22q -> case indexArray# ds2_i22q ww1_i1NM of _ { (# ipv6_i1Nz #) -> case ipv6_i1Nz of _ { Stripe ipv7_s22v ipv8_s22w ipv9_s22x ipv10_s22y -> case {__pkg_ccall main hs_lock Addr# -> State# RealWorld -> (# State# RealWorld #)}_i20J ipv9_s22x ipv2_i22e of _ { (# ds4_i20P #) -> case touch# ipv10_s22y ds4_i20P of s'_i20R { __DEFAULT -> case val_a1ux of _ { D# ds6_d1D8 -> case n_a1uy of _ { I64# ds8_d1Da -> case {__pkg_ccall main hs_distrib_add_n Addr# -> Double# -> Int# -> State# RealWorld -> (# State# RealWorld #)}_d1Dd ipv7_s22v ds6_d1D8 ds8_d1Da s'_i20R of _ { (# ds9_d1Db #) -> case {__pkg_ccall main hs_unlock Addr# -> State# RealWorld -> (# State# RealWorld #)}_i20m ipv9_s22x ds9_d1Db of _ { (# ds10_i20s #) -> case touch# ipv10_s22y ds10_i20s of s'1_i20u { __DEFAULT -> case touch# ipv8_s22w s'1_i20u of s'2_i1YT { __DEFAULT -> (# s'2_i1YT, () #) } } } } } } } } } } } } } } }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9038 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9038: Foreign calls don't make their arguments look strict -------------------------------------+------------------------------------ Reporter: tibbe | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: 1592 -------------------------------------+------------------------------------ Changes (by tibbe): * related: => 1592 Comment: #1592 looks related and I think I understanding the reasoning (the earlier `hs_lock` call might exit the program and hence the argument won't be used). I'm fine with this behavior but it'd be nice if I was able to tell the compiler that the function is strict. Adding bang patterns on the arguments has no effect at all. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9038#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9038: Foreign calls don't make their arguments look strict -------------------------------------+------------------------------------ Reporter: tibbe | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: 1592 -------------------------------------+------------------------------------ Comment (by tibbe): I tried to add a call to `evaluate val` the very first thing in the function, which resulted in an extra `seq#` call in the function, but it didn't make the function strict. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9038#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9038: Foreign calls don't make their arguments look strict -------------------------------------+------------------------------------ Reporter: tibbe | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: 1592 -------------------------------------+------------------------------------ Comment (by simonpj): Can you give the actual example (as simple as possible) so I can reproduce what you are seeing? Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9038#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9038: Foreign calls don't make their arguments look strict -------------------------------------+------------------------------------ Reporter: tibbe | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: 1592 -------------------------------------+------------------------------------ Comment (by tibbe): Here's a trivially simple example: Test.hs: {{{ {-# LANGUAGE BangPatterns #-} module Test ( f ) where f :: Int -> IO () f !val = do cFunction1 cFunction2 val foreign import ccall unsafe "function1" cFunction1 :: IO () foreign import ccall unsafe "function2" cFunction2 :: Int -> IO () }}} Compile with: {{{ ghc -c -O2 -ddump-simpl Test.hs }}} Here's the core: {{{ f1 :: Int -> State# RealWorld -> (# State# RealWorld, () #) f1 = \ (val_aeK :: Int) (eta_B1 :: State# RealWorld) -> case val_aeK of _ { I# ipv_sfl -> case {__pkg_ccall main function1 State# RealWorld -> (# State# RealWorld #)}_df8 eta_B1 of _ { (# ds_df6 #) -> case {__pkg_ccall main function2 Int# -> State# RealWorld -> (# State# RealWorld #)}_df4 ipv_sfl ds_df6 of _ { (# ds1_df2 #) -> (# ds1_df2, () #) } } } f :: Int -> IO () f = f1 `cast` ... }}} Adding the bang pattern has one effect: the argument gets unboxed earlier. It doesn't make the function take an unboxed argument however (i.e. there's no worker-wrapper). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9038#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9038: Foreign calls don't make their arguments look strict
-------------------------------------+------------------------------------
Reporter: tibbe | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.8.2
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture: Unknown/Multiple
Type of failure: None/Unknown | Difficulty: Unknown
Test Case: | Blocked By:
Blocking: | Related Tickets: 1592
-------------------------------------+------------------------------------
Comment (by simonpj):
Are you sure? I get this:
{{{
simonpj@cam-05-unx:~/tmp$ ghc -c -O -ddump-simpl T9038.hs
==================== Tidy Core ====================
Result size of Tidy Core = {terms: 20, types: 28, coercions: 5}
T9038.f1
:: GHC.Types.Int
-> GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld, () #)
[GblId,
Arity=2,
Caf=NoCafRefs,
Str=DmdType ,
Unf=Unf{Src=InlineStable, TopLvl=True, Arity=2, Value=True,
ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(unsat_ok=True,boring_ok=False)
Tmpl= \ (val_arX [Occ=Once!] :: GHC.Types.Int)
(eta_B1 [Occ=Once] :: GHC.Prim.State# GHC.Prim.RealWorld)
->
case val_arX of _ [Occ=Dead] { GHC.Types.I# ipv_sKN
[Occ=Once] ->
case {__pkg_ccall main function1 GHC.Prim.State#
GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld
#)}_dKB
eta_B1
of _ [Occ=Dead] { (# ds_dKz [Occ=Once] #) ->
case {__pkg_ccall main function2 GHC.Prim.Int#
-> GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld
#)}_dKx
ipv_sKN ds_dKz
of _ [Occ=Dead] { (# ds1_dKv [Occ=Once] #) ->
(# ds1_dKv, GHC.Tuple.() #)
}
}
}}]
T9038.f1 =
\ (val_arX :: GHC.Types.Int)
(eta_B1 :: GHC.Prim.State# GHC.Prim.RealWorld) ->
case val_arX of _ [Occ=Dead] { GHC.Types.I# ipv_sKN ->
case {__pkg_ccall main function1 GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld
#)}_dKB
eta_B1
of _ [Occ=Dead] { (# ds_dKz #) ->
case {__pkg_ccall main function2 GHC.Prim.Int#
-> GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld
#)}_dKx
ipv_sKN ds_dKz
of _ [Occ=Dead] { (# ds1_dKv #) ->
(# ds1_dKv, GHC.Tuple.() #)
}
}
}
T9038.f :: GHC.Types.Int -> GHC.Types.IO ()
[GblId,
Arity=2,
Caf=NoCafRefs,
Str=DmdType ,
Unf=Unf{Src=InlineStable, TopLvl=True, Arity=0, Value=True,
ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(unsat_ok=True,boring_ok=True)
Tmpl= T9038.f1
`cast` (

#9038: Foreign calls don't make their arguments look strict -------------------------------------+------------------------------------- Reporter: tibbe | Owner: Type: bug | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: | Architecture: Unknown/Multiple Unknown/Multiple | Difficulty: Unknown Type of failure: | Blocked By: None/Unknown | Related Tickets: 1592 Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Changes (by rwbarton): * status: new => infoneeded Comment: tibbe's and Simon's cores look identical to me modulo suppressions and alpha-renaming. The only thing that sounds potentially wrong to me here is the behavior of tibbe's original function with `evaluate val`, but it's hard to tell without the actual function and Core output. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9038#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9038: Foreign calls don't make their arguments look strict
-------------------------------------+-------------------------------------
Reporter: tibbe | Owner:
Type: bug | Status: infoneeded
Priority: normal | Milestone:
Component: Compiler | Version: 7.8.2
Resolution: | Keywords:
Operating System: | Architecture: Unknown/Multiple
Unknown/Multiple | Difficulty: Unknown
Type of failure: | Blocked By:
None/Unknown | Related Tickets: 1592
Test Case: |
Blocking: |
Differential Revisions: |
-------------------------------------+-------------------------------------
Comment (by tibbe):
I might have been mistaken. I read the core for `add3` above and assumed
that since `add3` isn't worker-wrappered the argument wouldn't be unboxed.
I tried calling add3 (which is really the
`System.Metrics.Distribution.add` function in the ekg-core package)
function in this little test program
{{{
module Test where
import System.Metrics.Distribution
test :: Distribution -> IO ()
test distrib = add distrib 1.0
}}}
and things seem to be unboxed correctly.
Here's the demand signature for `add3`:
{{{
add3
:: Distribution
-> Double
-> Int64
-> State# RealWorld
-> (# State# RealWorld, () #)
[GblId,
Arity=4,
Caf=NoCafRefs,
Str=DmdType

#9038: Foreign calls don't make their arguments look strict
-------------------------------------+-------------------------------------
Reporter: tibbe | Owner:
Type: bug | Status: infoneeded
Priority: normal | Milestone:
Component: Compiler | Version: 7.8.2
Resolution: | Keywords:
Operating System: | Architecture: Unknown/Multiple
Unknown/Multiple | Difficulty: Unknown
Type of failure: | Blocked By:
None/Unknown | Related Tickets: 1592
Test Case: |
Blocking: |
Differential Revisions: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
The notation is `

#9038: Foreign calls don't make their arguments look strict
-------------------------------------+-------------------------------------
Reporter: tibbe | Owner:
Type: bug | Status: infoneeded
Priority: normal | Milestone:
Component: Compiler | Version: 7.8.2
Resolution: | Keywords:
Operating System: | Architecture: Unknown/Multiple
Unknown/Multiple | Difficulty: Unknown
Type of failure: | Blocked By:
None/Unknown | Related Tickets: 1592
Test Case: |
Blocking: |
Differential Revisions: |
-------------------------------------+-------------------------------------
Comment (by tibbe):
I assume that `

#9038: Foreign calls don't make their arguments look strict -------------------------------------+------------------------------------- Reporter: tibbe | Owner: Type: bug | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: | Keywords: Operating System: | Architecture: Unknown/Multiple Unknown/Multiple | Difficulty: Unknown Type of failure: | Blocked By: None/Unknown | Related Tickets: 1592 Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Comment (by simonpj): Oh yes, arguments of unboxed type are, well, unboxed. Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9038#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#9038: Foreign calls don't make their arguments look strict -------------------------------------+------------------------------------- Reporter: tibbe | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.8.2 Resolution: worksforme | Keywords: Operating System: | Architecture: Unknown/Multiple Unknown/Multiple | Difficulty: Unknown Type of failure: | Blocked By: None/Unknown | Related Tickets: 1592 Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Changes (by tibbe): * status: infoneeded => closed * resolution: => worksforme -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9038#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC