4221 on new codegen

ezyang ezyang at MIT.EDU
Thu Feb 3 00:12:18 CET 2011


Simon Peyton Jones, I have a question about optimization fuel and GHC panics.
When I vary the fuel using -dopt-fuel, I get the following varying behavior:

    ...
-dopt-fuel=144 = normal segfault (late in the program)
-dopt-fuel=143 = segfaults ~immediately
-dopt-fuel=142 = normal segfault
-dopt-fuel=141 = fails an assert in file compiler/cmm/CmmBuildInfoTables.hs,
line 128
-dopt-fuel=140 = ditto
-dopt-fuel=139 = resulting executable prints 'start' and then doesn't do
anything
    ...

My impression was that these optimizations should not affect program behavior,
in which case the first thing I should figure out is why -dopt-fuel results in
the programming terminating after it prints 'start'. However, I'm not sure if
this is a red herring. Am I on the right track?

Cheers,
Edward

Quoting Simon Marlow <marlowsd at gmail.com>:

> On 02/02/2011 00:29, Edward Z. Yang wrote:
>> More Hoopling later, I see this segment in the rewrite function:
>>
>>        middle m@(CmmUnsafeForeignCall _ fs _) live = return $
>>          case map spill  (filter (flip elemRegSet (on_stack live)) fs) ++
>>               map reload (uniqSetToList (kill fs (in_regs live))) of
>>            []      ->  Nothing
>>            reloads ->  Just $ mkMiddles (m : reloads)
>>
>> So, if I understand this code correctly, it unilaterally reloads
>> /anything/ in the registers according to the analysis at that point.
>>
>> Well, I could see that resulting in the behavior below.
>>
>> It's not so clear to me what the correct rewrite is; according to
>> Marlow's comment on IRC, we ought not to be spilling/reloading foreign
>> calls yet, so maybe the whole bit should get excised? Otherwise, it seems
>> to me that transfer function needs to accomodate unsafe foreign
>> functions.
>
> Right, there's no need to spill/reload anything around an *unsafe* 
> foreign call in the Cmm code generator.  The NCG's register allocator 
> will do any necessary spilling/reloading around foreign calls.
>
> Cheers,
> 	Simon
>
>
>
>> Cheers,
>> Edward
>>
>> Excerpts from Simon Marlow's message of Tue Feb 01 03:44:41 -0500 2011:
>>> On 01/02/2011 00:01, Edward Z. Yang wrote:
>>>> Current theory:
>>>>
>>>>     c1jj:
>>>>         _s1ep::I32 = I32[(slot<_s1ep::I32>   + 4)];   // CmmAssign
>>>>         _s1fP::I32 = I32[(slot<_s1fP::I32>   + 4)];   // CmmAssign
>>>>         // outOfLine should follow:
>>>>         _s1eq::F64 = F64[_s1fP::I32 + 3];   // CmmAssign
>>>>         I32[(young<c1jh>   + 4)] = c1jh;   // CmmStore
>>>>         foreign call "ccall" arg hints:  [PtrHint,]  result hints: 
>>>>  [] call_fn_blob(...) returns to c1jh args: ([_s1ep::I32,
>>>>                                                                    
>>>>                                               _s1eq::F64]) ress: 
>>>> ([_s1ev::F64]) with update frame 4;   // CmmForeignCall
>>>>     c1jh:
>>>>         _s1ev::F64 = F64[(slot<_s1ev::F64>   + 8)];   // CmmAssign
>>>>         // emitReturn: Sequel: Assign
>>>>         _s1ev::F64 = _s1ev::F64;   // CmmAssign
>>>>         F64[(slot<_s1ev::F64>   + 8)] = _s1ev::F64;   // CmmStore
>>>>         goto u1Ak;   // CmmBranch
>>>>
>>>> Note the line immediately after c1jh, where we reload the ostensibly
>>>> spilled _s1ev back into a register. Except that it was never spilled
>>>> there in the first place, and we just clobbered the real value. Oops.
>>>>
>>>> Is this interpretation correct?
>>>
>>> It sounds plausible, but I really have no idea.  The code generator does
>>> not have to generate spill/reloads around foreign calls, the register
>>> allocator will do that.
>>>
>>> Cheers,
>>>      Simon
>
>





More information about the Glasgow-haskell-users mailing list