[GHC] #8425: ghc-7.6.3: crossmodule inline leads to buggy code (-O2)

GHC ghc-devs
Wed Oct 9 06:59:01 UTC 2013


#8425: ghc-7.6.3: crossmodule inline leads to buggy code (-O2)
----------------------------------+-------------------------------------
       Reporter:  slyfox          |             Owner:
           Type:  bug             |            Status:  new
       Priority:  normal          |         Milestone:
      Component:  Compiler        |           Version:  7.6.3
       Keywords:                  |  Operating System:  Unknown/Multiple
   Architecture:  x86_64 (amd64)  |   Type of failure:  Runtime crash
     Difficulty:  Unknown         |         Test Case:
     Blocked By:                  |          Blocking:
Related Tickets:                  |
----------------------------------+-------------------------------------
 The bug is found as a crash of gf-3.4 ('Grammatical Framework') package
 compiled with -O2.
 With some debugging I've come to roughly following minimal example:

 This code compiles incorrectly:
 {{{
 import BuggyOpt() -- bug inducer!

 import qualified Data.Map as Map
 import Data.Array.IArray

 {-# NOINLINE mkLin #-}
 mkLin :: Array Int (Array Int Int) -> Map.Map (Array Int Int) Int -> Int
 -> (Map.Map (Array Int Int) Int, Int)
 mkLin mseqs seqs seqid =
     let seq_ = mseqs ! seqid
     -- lookup/insert pair. exactly as in 'BuggyOpt' module
     in case Map.lookup seq_ seqs of
         Just seqid' -> (seqs,seqid')
         Nothing    -> let seqid'' = Map.size seqs
                           seqs'   = Map.insert seq_ seqid'' seqs
                       in (seqs',seqid'')
 }}}

 And this works fine:
 {{{
 --import BuggyOpt() -- bug inducer!

 import qualified Data.Map as Map
 import Data.Array.IArray

 {-# NOINLINE mkLin #-}
 mkLin :: Array Int (Array Int Int) -> Map.Map (Array Int Int) Int -> Int
 -> (Map.Map (Array Int Int) Int, Int)
 mkLin mseqs seqs seqid =
     let seq_ = mseqs ! seqid
     -- lookup/insert pair. exactly as in 'BuggyOpt' module
     in case Map.lookup seq_ seqs of
         Just seqid' -> (seqs,seqid')
         Nothing    -> let seqid'' = Map.size seqs
                           seqs'   = Map.insert seq_ seqid'' seqs
                       in (seqs',seqid'')
 }}}

 Attached minimal test tarball and my results on it are:
 {{{
  [("Project name","The Glorious Glasgow Haskell Compilation System")
  ,("GCC extra via C opts"," -fwrapv")
  ,("C compiler command","x86_64-pc-linux-gnu-gcc")
  ,("C compiler flags"," -fno-stack-protector  -Wl,--hash-size=31 -Wl
 ,--reduce-memory-overheads")
  ,("ar command","/usr/bin/ar")
  ,("ar flags","q")
  ,("ar supports at file","YES")
  ,("touch command","touch")
  ,("dllwrap command","/bin/false")
  ,("windres command","/bin/false")
  ,("perl command","/usr/bin/perl")
  ,("target os","OSLinux")
  ,("target arch","ArchX86_64")
  ,("target word size","8")
  ,("target has GNU nonexec stack","True")
  ,("target has .ident directive","True")
  ,("target has subsections via symbols","False")
  ,("LLVM llc command","/usr/bin/llc")
  ,("LLVM opt command","/usr/bin/opt")
  ,("Project version","7.6.3")
  ,("Booter version","7.6.3")
  ,("Stage","2")
  ,("Build platform","x86_64-unknown-linux")
  ,("Host platform","x86_64-unknown-linux")
  ,("Target platform","x86_64-unknown-linux")
  ,("Have interpreter","YES")
  ,("Object splitting supported","YES")
  ,("Have native code generator","YES")
  ,("Support SMP","YES")
  ,("Unregisterised","NO")
  ,("Tables next to code","YES")
  ,("RTS ways","l debug  thr thr_debug thr_l thr_p dyn debug_dyn thr_dyn
 thr_debug_dyn")
  ,("Leading underscore","NO")
  ,("Debug on","False")
  ,("LibDir","/usr/lib64/ghc-7.6.3")
  ,("Global Package DB","/usr/lib64/ghc-7.6.3/package.conf.d")
  ,("Gcc Linker flags","[\"-Wl,--hash-size=31\",\"-Wl,--reduce-memory-
 overheads\"]")
  ,("Ld Linker flags","[\"--hash-size=31\",\"--reduce-memory-overheads\"]")
  ]
 RUN good
 [1 of 2] Compiling Susp             ( good/Susp.hs, good/Susp.o )
 [2 of 2] Compiling Main             ( good/main.hs, good/main.o )
 Linking good/main ...
 (fromList [(array (0,0) [(0,42)],0)],0)
 RUN bad
 [1 of 3] Compiling BuggyOpt         ( bad/BuggyOpt.hs, bad/BuggyOpt.o )
 [2 of 3] Compiling Susp             ( bad/Susp.hs, bad/Susp.o )
 [3 of 3] Compiling Main             ( bad/main.hs, bad/main.o )
 Linking bad/main ...
 main: Error in array index; 0 not in range [0..0)
 TEST FAILED in bad
 }}}

 What we see here is the test with useless import mysteriously fails:
 > main: Error in array index; 0 not in range [0..0)

 while without import it works fine:
 > (fromList [(array (0,0) [(0,42)],0)],0)

 The functions in both BuggyOpt and Susp modules contain suspiciously
 similar code:
 {{{
   case Map.lookup seq' seqs of
     Just id' -> (seqs,id')
     Nothing -> let last_seq = Map.size seqs
                in (Map.insert seq' last_seq seqs, last_seq)
 }}}

 But in BuggyOpt ghc somehow deduces some arguments
 and applies that effect to (unrelated, but looking similar)
 Susp module.

 Thanks!

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8425>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler



More information about the ghc-tickets mailing list