[GHC] #11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- {{{ $ make TEST=GEq1 WAY=optasm TEST_HC=ghc-7.11.20151225 ... cd ./generics/GEq && ./GEq1 GEq1.run.stdout 2> GEq1.run.stderr Actual stdout output differs from expected: --- ./generics/GEq/GEq1.stdout.normalised 2015-12-26 15:32:22.984189653 +0100 +++ ./generics/GEq/GEq1.run.stdout.normalised 2015-12-26 15:32:22.984189653 +0100 @@ -3,5 +3,5 @@ True True False -True -True \ No newline at end of file +False +False \ No newline at end of file *** unexpected failure for GEq1(optasm) }}} The test was last touched by Ryan in 6cde981a8788b225819be28659caddc35b77972d (#10868) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): This doesn't appear to be specific to generics. Rather, it's an issue with `eqAddr#` and how it's affected by optimization levels. Here's a simplified example that takes away the complexity of `GEq1`: {{{#!hs {-# LANGUAGE MagicHash #-} module Main (main) where import GHC.Exts (Addr#, isTrue#) import GHC.Prim (eqAddr#) data A = A { runA :: Addr# } a :: A a = A "a"# main :: IO () main = print (isTrue# (eqAddr# (runA a) (runA a))) }}} Compiling this with `-O0` makes the program return `True`, but compiling with `-O1` or higher returns `False`. Is pointer equality unpredictable enough that it can fail the reflexive property if optimized enough? If so, I can just modify `GEq1` so as not to include `Addr#`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by rwbarton): It looks like GHC is happy to inline everything in your simplified example leaving {{{ Main.main2 = case GHC.Prim.tagToEnum# @ GHC.Types.Bool (GHC.Prim.eqAddr# "a"# "a"#) of _ [Occ=Dead] { GHC.Types.False -> GHC.Show.shows26; GHC.Types.True -> GHC.Show.shows24 } }}} The value `"a"#` has been duplicated, so there are now two copies of the string constant in the program, with different addresses. For your test you can presumably work around this with NOINLINE annotations on `u0` and `uf0`. This duplication seems like generally undesirable behavior though; leaving aside the question of whether or not it is "semantically correct", it makes the resulting object file unnecessarily large (imagine the string was much longer than a single character). Probably worth opening a separate ticket. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: new => patch * differential: => Phab:D1714 * related: => #11312 Comment: Adding `{-# NOINLINE #-}` pragmas does indeed do the trick. I've opened Phab:D1714 for that workaround. I've also opened #11312 regarding the inlining issue. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing
-------------------------------------+-------------------------------------
Reporter: thomie | Owner:
Type: bug | Status: patch
Priority: normal | Milestone:
Component: Compiler | Version: 7.11
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: #11312 | Differential Rev(s): Phab:D1714
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ben Gamari

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: patch => new Comment: RyanGlScott, did you mean to add a `T11292` test in this diff? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Not originally, but I suppose I did accidentally mention such a test in the Validation field. I should probably add a standalone test for this behavior with the proper flags always set (and possibly adjust it depending on the result of #11312). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Changes (by thomie): * status: new => closed * resolution: => fixed Comment: Replying to [comment:6 RyanGlScott]:
I should probably add a standalone test for this behavior
I don't know, but this issue is fixed. `TEST=GEq1 WAY=optasm` is passing again. Thanks. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Where is this `eqAddr#` test coming from?? It's utterly bogus to compare two strings by address. This is functional programming! I'm very uncomfortable about "fixing" this by some new delicate stuff like NOINLINE pragmas, especially as they are entirely un-explained. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Replying to [comment:8 simonpj]:
Where is this `eqAddr#` test coming from?? It's utterly bogus to compare two strings by address. This is functional programming!
I'm very uncomfortable about "fixing" this by some new delicate stuff
We have to test `eqAddr#` here because that's how `deriving Eq` deals with `Addr#`. `Addr#` is [http://git.haskell.org/ghc.git/blob/2f923ce2ab8bad6d01645c735c81bbf1b9ff1e05... one of six] privileged unlifted types which a datatype can have and still have a derived `Eq`/`Ord` instance. Internally, the `deriving` machinery compares `Addr#` fields in a datatype with `eqAddr#`/`ltAddr#`/etc., so this test just checks to see if GHC generics is equally as expressive. like NOINLINE pragmas, especially as they are entirely un-explained. I'm inclined to agree, but if we do fix this, we'd probably need to change the way `Addr#` is dealt with in datatypes as well for the sake of consistency. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj):
I'm inclined to agree, but if we do fix this, we'd probably need to change the way `Addr#` is dealt with in datatypes as well for the sake of consistency.
No... an `Addr#` might be returned from C-land by `malloc`, and might be perfectly stable. It's just that primitive strings should not be compared with `eqAddr#`. The bug is that primitive strings have type `Addr#`; they should have type `String#`. And to compare `String#` you should use `strcmp`. I suppose that means a new primitive type and family of operations over it... but that looks to me like the Right Thing to do. This NOINLINE stuff looks desperately fragile.... a bug waiting to happen. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj):
I'm inclined to agree, but if we do fix this, we'd probably need to change the way `Addr#` is dealt with in datatypes as well for the sake of consistency.
No... an `Addr#` might be returned from C-land by `malloc`, and might be perfectly stable. It's just that primitive strings should not be compared with `eqAddr#`. The bug is that primitive strings have type `Addr#`; they should have type `String#`. And to compare `String#` you should use `strcmp`. I suppose that means a new primitive type and family of operations over it... but that looks to me like the Right Thing to do. This NOINLINE stuff looks desperately fragile.... a bug waiting to happen. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by rwbarton): This test just needs a way to generate two different `Addr#`s so that it can test whether a derived Eq instance compares them correctly. Using string literals guarded by NOINLINE is one easy way to do that, and has the advantage (for the way the test is structured) of being pure. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): I suppose I could just replace the primitive string literals with `nullAddr#`, no? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by rwbarton): I don't know, do you really only need one `Addr#`? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): At the moment I'm only testing if something with unlifted types can be equal to itself, so one `Addr#` suffices. I could conceivably add a test for two things that aren't equal, in which the two unequal fields are something like `nullAddr#` and `plusAddr# 1# nullAddr#` (disclaimer: I don't know how safe that would be in general). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11292: Generics unboxed types: TEST=GEq1 WAY=optasm is failing -------------------------------------+------------------------------------- Reporter: thomie | Owner: Type: bug | Status: closed Priority: normal | Milestone: 8.0.1 Component: Compiler | Version: 7.11 Resolution: fixed | Keywords: Generics Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #11312 | Differential Rev(s): Phab:D1714 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * keywords: => Generics -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11292#comment:16 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC