let app invariant failure, HALP Re: how to write a ghc primop that acts on an unevaluated argument?

Carter Schonwald carter.schonwald at gmail.com
Thu Nov 27 22:37:45 UTC 2014


The version of the test hs file I attached might include the use of a
prefetch byte array primop. If so, commenting it out might suffice for
using it as a test case.  I'll re email a corrected version later tonight
of need be. Currently amidst family travel.
On Nov 27, 2014 1:25 PM, "Carter Schonwald" <carter.schonwald at gmail.com>
wrote:

> ok,
> the attached "output" file was made  using the following command
> ./inplace/bin/ghc-stage2 T8256.hs   -O2 -dcore-lint  -fforce-recomp
> -ddump-simpl  -dverbose-core2core -ddump-occur-anal -ddump-inlinings  >
> output ^&1
>
> i've also attached the test hs file i used
>
> the primop definitions i used were :
>
> primop PrefetchValueOp0 "prefetchValue0#" GenPrimOp
>    a -> State# s -> State# s
>    with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd]
> topRes }
>
>
> primop PrefetchValueOp1 "prefetchValue1#" GenPrimOp
>    a -> State# s -> State# s
>    with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd]
> topRes }
>
>
> primop PrefetchValueOp2 "prefetchValue2#" GenPrimOp
>    a ->  State# s -> State# s
>    with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd]
> topRes }
>
>
> primop PrefetchValueOp3 "prefetchValue3#" GenPrimOp
>    a -> State# s -> State# s
>    with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd]
> topRes }
>
>
>
> (the idea of those strictness attributes is that the operations should be
> lazy in their value arg)
>
> thanks!
> -Carter
>
>
> On Thu, Nov 27, 2014 at 12:03 PM, Simon Peyton Jones <
> simonpj at microsoft.com> wrote:
>
>>  are you quite sure you did –dverbose-core2core –ddump-occur-anal?   I
>> see none of that output in the file.
>>
>>
>>
>> Regardless of  the flags you set for the primop, I’m surprised that the
>> invariant is invalidated.  Should not happen.
>>
>>
>>
>> As well as the revised output, could you enclose a snippet of
>> primops.txt.pp for prefetchValue1,2,3#
>>
>>
>>
>> S
>>
>>
>>
>> *From:* Carter Schonwald [mailto:carter.schonwald at gmail.com]
>> *Sent:* 25 November 2014 06:47
>> *To:* Simon Peyton Jones
>> *Cc:* Edward Kmett; ghc-devs at haskell.org; Joachim Breitner
>>
>> *Subject:* Re: let app invariant failure, HALP Re: how to write a ghc
>> primop that acts on an unevaluated argument?
>>
>>
>>
>> ok attached is the log of
>>
>> ./inplace/bin/ghc-stage2 codetester.hs  -O2 -dcore-lint  -fforce-recomp
>> -ddump-simpl -ddump-to-file -dverbose-core2core -ddump-occur-anal
>> -ddump-inlinings  > output ^&1
>>
>>
>>
>>
>>
>> the relevant snippet is bellow.
>>
>>
>>
>> It looks like the Float-Out transformation is what tripping it.
>>
>>
>>
>>
>>
>> That said, reading through what the semantics are implied by
>> has_side_effects = True, the prefetch* family of operations ARE side
>> effectful with respect the fact that they DO modify the CPU cache in a way
>> that changes what memory locations are in various levels of CPU cache, so
>> despite seeming read-like, they are modifying the state of the system, just
>> in a way that is ONLY visible wrt the performance characteristics/runtime
>>  of the resulting program.
>>
>>
>>
>> specifically, Duplication, Floating out, and Specultive evaluation all
>> change *when* the prefetch runs and changes the CPU state, and Discard
>> means this "mutation" of the CPU cache state would not happen.
>>
>>
>>
>> if prefetch was pure semantically (ie equiv to a -> ()  ) , they'd just
>> be no op, they're exclusively a tool for performance engineering, and
>> accordingly when and where they appear in code matters!
>>
>>
>>
>> i'm more than happy to write out a more detailed version of this
>> explanation somewhere if you like.
>>
>>
>>
>> -Carter
>>
>>
>>
>> """"
>>
>>
>>
>> *** Core Linted result of Simplifier:
>>
>> *** Float out(FOS {Lam = Just 0, Consts = True, OverSatApps = True}):
>>
>> *** Core Linted result of Float out(FOS {Lam = Just 0, Consts = True,
>> OverSatApps = True}):
>>
>> *** Core Lint errors : in result of Float out(FOS {Lam = Just 0,
>>
>>                                                    Consts = True,
>>
>>                                                    OverSatApps = True})
>> ***
>>
>> <no location info>: Warning:
>>
>>     In the expression: prefetchValue2#
>>
>>                          @ [Char]
>>
>>                          @ RealWorld
>>
>>                          lvl_s3Oi
>>
>>                          (prefetchValue1#
>>
>>                             @ Int
>>
>>                             @ RealWorld
>>
>>                             lvl_s3Oj
>>
>>                             (prefetchAddr3# @ RealWorld ds1_a3zg 0
>> ds_a3zf))
>>
>>     This argument does not satisfy the let/app invariant:
>>
>>       prefetchValue1#
>>
>>         @ Int
>>
>>         @ RealWorld
>>
>>         lvl_s3Oj
>>
>>
>>
>>
>>
>> """
>>
>>
>>
>>
>>
>>
>>
>> On Mon, Nov 24, 2014 at 10:43 PM, Carter Schonwald <
>> carter.schonwald at gmail.com> wrote:
>>
>>  huh, apparently i was mixing up '-' and some other similar dash
>> character, time to let my rebuild of ghc go through then try gain :)
>>
>>
>>
>> On Mon, Nov 24, 2014 at 10:37 PM, Carter Schonwald <
>> carter.schonwald at gmail.com> wrote:
>>
>>  when i run
>>
>> ./inplace/bin/ghc-stage2 codetester.hs  -O2 -dcore-lint -S
>>  -fforce-recomp -ddump-simpl -ddump-to-file –dverbose-core2core
>> –ddump-occur-anal –ddump-inlinings
>>
>> i get
>>
>> target ‘–dverbose-core2core’ is not a module name or a source file
>>
>>
>>
>> what am I doing wrong in this CLI invocation?
>>
>>
>>
>> On Mon, Nov 24, 2014 at 10:23 AM, Simon Peyton Jones <
>> simonpj at microsoft.com> wrote:
>>
>>  Carter
>>
>>
>>
>> That smells wrong to me.  These flags have a very carefully defined
>> meaning; see
>>
>>             Note [PrimOp can_fail and has_side_effects]
>>
>> in PrimOp.lhs
>>
>>
>>
>> If you say it has side effects when it doesn’t, you’ll confuse your
>> successor reading the code in five years time.
>>
>>
>>
>> Better to find out what is going on and why.  Might you do that? What
>> transformation invalidates the let/app invariant?  Make a small test case,
>> use –dverbose-core2core –ddump-occur-anal –ddump-inlinings.  I would far
>> rather that than install a land-mine in the code.
>>
>>
>>
>> Simon
>>
>>
>>
>> *From:* Carter Schonwald [mailto:carter.schonwald at gmail.com]
>> *Sent:* 24 November 2014 00:54
>> *To:* Edward Kmett
>> *Cc:* ghc-devs at haskell.org; Simon Peyton Jones; Joachim Breitner
>> *Subject:* Re: let app invariant failure, HALP Re: how to write a ghc
>> primop that acts on an unevaluated argument?
>>
>>
>>
>> woot, solved it, at least in a way thats OK for now.
>>
>>
>>
>> if I mark the prefetchValue operations as has_side_effects=True, the core
>> lint failure goes away! I'm not sure if thats the right semantics in the
>> long term, but it does give me a simple way to make sure it works safely
>> for 7.10
>>
>>
>>
>> pardon all the noise
>>
>> -Carter
>>
>>
>>
>> On Sun, Nov 23, 2014 at 4:26 PM, Carter Schonwald <
>> carter.schonwald at gmail.com> wrote:
>>
>>  ok, i'm getting a let/app invariant failure when i build my test case
>> with O1 or O2 but not without
>>
>>
>>
>> http://lpaste.net/114881
>>
>>
>>
>> any help would be appreciated on how to address that
>>
>>
>>
>> On Sun, Nov 23, 2014 at 4:13 PM, Carter Schonwald <
>> carter.schonwald at gmail.com> wrote:
>>
>>  yup, i have that!
>>
>>
>>
>>     wrapFetch prefetchValue0# (error "this shouldn't get evaluated")
>>
>>
>>
>> in the test suite!
>>
>>
>>
>> in contrast
>>
>>     wrapFetch prefetchValue0# $! (error "this shouldn't get evaluated")
>> does explode
>>
>>
>>
>> shall I add a "should fail" test with the latter? (it doesn't seem
>> worthwhile)
>>
>>
>>
>> On Sun, Nov 23, 2014 at 3:53 PM, Edward Kmett <ekmett at gmail.com> wrote:
>>
>>  Maybe test for laziness in the argument by just putting something in
>> that goes boom when forced, e.g. 'undefined'?
>>
>>
>>
>>
>>
>> On Sun, Nov 23, 2014 at 2:04 PM, Carter Schonwald <
>> carter.schonwald at gmail.com> wrote:
>>
>>   Hey All,
>>
>> as part of trying to get some fixups for how prefetch works into 7.10,
>>
>> i'm adding a "prefetchValue" primop that prefetchs the memory location of
>> a lifted heap value
>>
>>
>>
>> namely
>>
>>
>>
>> several operations of the following form
>>
>>
>>
>> primop PrefetchValueOp1 "prefetchValue1#" GenPrimOp
>>
>>    a -> State# s -> State# s
>>
>>    with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd]
>> topRes }
>>
>>
>>
>> I'd like some feedback on the strictness information design by someone
>> who's familiar with how that piece of GHC. the idea being that
>> prefetchValue is lazy in its polymorphic argument (it doesn't force it, it
>> just does a prefetch on the heap location, which may or may not be
>> evaluated).
>>
>>
>>
>> https://phabricator.haskell.org/D350
>>
>>
>>
>> is the code in question. And i *believe* i'm testing for being lazy in
>> that argument correctly.
>>
>>
>>
>> thoughts?
>>
>>
>>
>> many thanks!
>>
>> -Carter
>>
>>
>>
>>
>>
>> _______________________________________________
>> ghc-devs mailing list
>> ghc-devs at haskell.org
>> http://www.haskell.org/mailman/listinfo/ghc-devs
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/ghc-devs/attachments/20141127/6001001e/attachment-0001.html>


More information about the ghc-devs mailing list