Here is an example of a very simple program getting strange results on
low fuel:
main = do
putStrLn "a"
f
putStrLn "b"
f = putStrLn "c"
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=0 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test ...
a
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=1 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
ghc-stage2: panic! (the 'impossible' happened)
(GHC version 7.1.20110128 for i386-unknown-linux):
ASSERT failed! file compiler/cmm/CmmBuildInfoTables.hs, line 128
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=2 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
ghc-stage2: panic! (the 'impossible' happened)
(GHC version 7.1.20110128 for i386-unknown-linux):
ASSERT failed! file compiler/cmm/CmmBuildInfoTables.hs, line 128
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=3 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
ghc-stage2: panic! (the 'impossible' happened)
(GHC version 7.1.20110128 for i386-unknown-linux):
ASSERT failed! file compiler/cmm/CmmBuildInfoTables.hs, line 128
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=4 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test ...
a
c
Segmentation fault (core dumped)
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=5 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test ...
a
c
b
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=6 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test ...
a
Segmentation fault (core dumped)
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=7 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test ...
a
Segmentation fault (core dumped)
ezyang@javelin:~/Dev/ghc-build-nco-default/testsuite/tests/ghc-regress/simple$
'/home/ezyang/Dev/ghc-build-nco-default/inplace/bin/ghc-stage2' -fforce-recomp
-dno-debug-output -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts
-dstub-dead-values -dopt-fuel=8 -o test test.hs && ./test
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test ...
a
c
b
Quoting ezyang <ezy...@mit.edu>:
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 <marlo...@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
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users