[GHC] #10676: silly assembly for comparing the result of comparisons that return Int# against 0#

#10676: silly assembly for comparing the result of comparisons that return Int#
against 0#
-------------------------------------+-------------------------------------
Reporter: rwbarton | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.10.1
(CodeGen) |
Keywords: | Operating System: Unknown/Multiple
Architecture: x86_64 | Type of failure: Runtime
(amd64) | performance bug
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Revisions: |
-------------------------------------+-------------------------------------
Consider the module
{{{
{-# LANGUAGE MagicHash #-}
module Min where
import GHC.Exts
fgood :: Int# -> Int# -> Int
fgood x# y# = case isTrue# (x# <# y#) of
False -> I# y#
True -> I# x#
fbad :: Int# -> Int# -> Int
fbad x# y# = case x# <# y# of
0# -> I# y#
_ -> I# x#
}}}
The code for `fgood` looks fine:
{{{
0000000000000130

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by thomie): * cc: jstolarek (added) Comment: CC jstolarek as the author of [wiki:PrimBool]. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by bgamari): I think you are essentially seeing #8326. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by rwbarton): Yes, I think so. But there is a problem besides the fact that the heap check is duplicated. Referring to the Cmm listing in #8326, something seems to think that `_sEV` (the 0#-or-1# result of the primop) is live in the alternatives, even to the point of passing it through the GC, when really it will never be used after the branch. I think that's the reason that later passes are unable to avoid this ugly `cmp/setCC/movzbl/test/jne` sequence. Otherwise the definition of `_sEV` would be inlined at its only use site, the branch, and the code generator would then generate a nice `cmp/jCC` sequence. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: #8326 | Differential Revisions: -------------------------------------+------------------------------------- Changes (by rwbarton): * related: => #8326 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: duplicate | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: #8326, #8327 | Differential Revisions: -------------------------------------+------------------------------------- Changes (by rwbarton): * status: new => closed * resolution: => duplicate * related: #8326 => #8326, #8327 Comment: Oh, I just found #8327. Will close this one as a duplicate then. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10676: silly assembly for comparing the result of comparisons that return Int#
against 0#
-------------------------------------+-------------------------------------
Reporter: rwbarton | Owner:
Type: bug | Status: closed
Priority: normal | Milestone:
Component: Compiler | Version: 7.10.1
(CodeGen) |
Resolution: duplicate | Keywords:
Operating System: Unknown/Multiple | Architecture: x86_64
Type of failure: Runtime | (amd64)
performance bug | Test Case:
Blocked By: | Blocking:
Related Tickets: #8326, #8327 | Differential Revisions:
-------------------------------------+-------------------------------------
Comment (by Reid Barton

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: duplicate | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: #8326, #8327 | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Wait! I believe that you are saying that {{{ case na# ==# nb# of 0# -> e1 _ -> e2 }}} generates much worse code than {{{ case isTrue# (na# ==# nb#) of False -> e1 True -> e2 }}} even though the former appears more primitive. This is all very odd and either deserves to be fixed, or at least documented somewhere prominent! Where would be a good place to document it? Perhaps with the primops for `(==)#`, `(>=)#`, etc? Or with `isTrue#`? And we need a ticket to say "let's fix this". Speaking of which do you know why it behaves so badly? Just changing the code is leaving land-mines for future generations :-). Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: duplicate | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: #8326, #8327, | Differential Revisions: #9661 | -------------------------------------+------------------------------------- Changes (by jstolarek): * related: #8326, #8327 => #8326, #8327, #9661 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: duplicate | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: #8326, #8327, | Differential Revisions: #9661 | -------------------------------------+------------------------------------- Comment (by jstolarek): #9661 might be related here. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10676: silly assembly for comparing the result of comparisons that return Int# against 0# -------------------------------------+------------------------------------- Reporter: rwbarton | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 (CodeGen) | Resolution: duplicate | Keywords: Operating System: Unknown/Multiple | Architecture: x86_64 Type of failure: Runtime | (amd64) performance bug | Test Case: Blocked By: | Blocking: Related Tickets: #8326, #8327, | Differential Revisions: #9661 | -------------------------------------+------------------------------------- Comment (by rwbarton): Replying to [comment:7 simonpj]:
Wait!
I believe that you are saying that [...]
Yes that's right. Tickets #8326 and #8327 cover everything I had to say about the code generated here.
Where would be a good place to document it? Perhaps with the primops for `(==)#`, `(>=)#`, etc? Or with `isTrue#`?
Ideally with the comparison primops, but they are numerous and scattered throughout the list of primops, which is organized principally by type (`Char#`, then the integral types, etc.). There is some mention of this phenomenon in the Note `[Optimizing isTrue#]`, though you have to read between the lines a bit. It would be best to fix this of course, but if that stalls then I'll add a comment near the top of `primops.txt.pp`.
Speaking of which do you know why it behaves so badly?
There is a special case for `cgCase` on an enumeration type of a primop application: in this case we always raise heap checks out of the alternatives. I think this is the entire reason for the difference between the code generated for the two versions. I don't see why it makes sense to have different logic for how to place the heap checks in this case compared to the general case, and I'm not entirely sure it isn't a historical accident. Further comments on #8326. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10676#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC