[GHC] #16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Incorrect result Unknown/Multiple | at runtime Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Consider this program: {{{#!hs module Main (main) where import Data.Bits import Data.Word main :: IO () main = print $ toInteger (shiftL 1 hm :: Word64) == toInteger (shiftL 1 hm :: Word64) hm :: Int hm = -1 {-# NOINLINE hm #-} }}} The result of this program depends greatly on what optimization levels are used, and whether `-fllvm` is used: {{{ $ /opt/ghc/8.6.3/bin/ghc -fforce-recomp -O0 Bug.hs && ./Bug [1 of 1] Compiling Main ( Bug.hs, Bug.o ) Linking Bug ... True $ /opt/ghc/8.6.3/bin/ghc -fforce-recomp -O1 Bug.hs && ./Bug [1 of 1] Compiling Main ( Bug.hs, Bug.o ) Linking Bug ... True $ /opt/ghc/8.6.3/bin/ghc -fforce-recomp -O2 Bug.hs && ./Bug [1 of 1] Compiling Main ( Bug.hs, Bug.o ) Linking Bug ... Bug: Bad shift length-1 $ /opt/ghc/8.6.3/bin/ghc -fforce-recomp -O0 -fllvm Bug.hs && ./Bug [1 of 1] Compiling Main ( Bug.hs, Bug.o ) Linking Bug ... True $ /opt/ghc/8.6.3/bin/ghc -fforce-recomp -O1 -fllvm Bug.hs && ./Bug [1 of 1] Compiling Main ( Bug.hs, Bug.o ) Linking Bug ... False $ /opt/ghc/8.6.3/bin/ghc -fforce-recomp -O2 -fllvm Bug.hs && ./Bug [1 of 1] Compiling Main ( Bug.hs, Bug.o ) Linking Bug ... Bug: Bad shift length-1 }}} This program manages to return all of `True`, `False`, and `Bad shift length-1` depending on which flags are used! -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Zemyla): Can you provide us with dumps, like with `-ddump-simpl` and such? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * Attachment "Bug.dump-simpl-O0-nollvm" added. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * Attachment "Bug.dump-simpl-O1-nollvm" added. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * Attachment "Bug.dump-simpl-O2-nollvm" added. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * Attachment "Bug.dump-simpl-O0-llvm" added. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * Attachment "Bug.dump-simpl-O1-llvm" added. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * Attachment "Bug.dump-simpl-O2-llvm" added. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): I've attached the `-ddump-simpl` output for each combination. (For instance, `Bug.dump-simpl-O0-nollvm` is for the `-O0` variant, and `Bug .dump-simpl-O0-llvm` is for the `-O0 -llvm` variant.) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by harpocrates): * cc: harpocrates (added) Comment: `shiftL` is ''not'' supposed to be called with a negative number of bits (that's what `shift` is for). It's documented in the Haddock for `shiftL`:
Shift the argument left by the specified number of bits (which must be non-negative).
Without any heavy optimizations, `shiftL 1 hm` turns into `shiftL#` turns into the `uncheckedShiftL#` primop, which explicitly says that a negative number of bits produces undefined output. I suspect it is nonetheless usually deterministic, hence the `True` outputs. On `-O2`, we'll trigger the `uncheckedShiftL#` builtin rule. That rule takes one look at the negative shift bits and decides to "optimize" this into a runtime error that prints out `"Bad shift length"` and the shift length. The only case that isn't yet covered is the `-O1 -fllvm` case. It's likely that the LLVM call we produce for `uncheckedShiftL#` also has undefined behaviour for negative shift values, and LLVM applies some more optimizations ultimately resulting in the `False` output. ---- This looks like a bad API: we really should have `shiftL :: a -> Word -> a` instead of `shiftL :: a -> Int -> a` (and same for `shiftR`). Instead of stomaching that breakage, we could also just add an extra check to the `Word`, `Int`, etc. instances of `shiftL` to guard against negative inputs: {{{ instance Bits Word where {- snipped -} (W# x#) `shift` (I# i#) | isTrue# (i# >=# 0#) = W# (x# `shiftL#` i#) | otherwise = W# (x# `shiftRL#` negateInt# i#) (W# x#) `shiftL` (I# i#) | isTrue# (i# >=# 0#) = W# (x# `shiftL#` i#) | otherwise = error "shiftL: expected non-negative number of bits" }}} Or even: deprecate `shiftL`/`shiftR` entirely in favour of `shift` (and let the default definitions, which fall back to the safer `shift`, take effect). Thoughts? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by harpocrates): Actually, given that Haskell report defines `shiftL` and `shiftR`, changing their types or deprecating them is definitely not a good idea... -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Without knowing anything about the implementation details of `shiftL`/`shiftR`, my hope would be that invoking them with a negative number of bits would throw an exception, regardless of the optimization level. I could certainly envision that an unsafe primop like `uncheckedShiftL#` would have undefined behavior if given a negative number of bits as an argument, but it feels like we should be able to do better for `shiftL`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/113 -------------------------------------+------------------------------------- Changes (by RyanGlScott): * differential: => https://gitlab.haskell.org/ghc/ghc/merge_requests/113 Comment: harpocrates, was this fixed in [https://gitlab.haskell.org/ghc/ghc/commit/5341edf3635f2875271acc469570481c52... 5341edf3]? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/113 -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: new => infoneeded -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/113 -------------------------------------+------------------------------------- Comment (by harpocrates): Oops yes it was! The inconsistent behaviour was fixed in the commit you referenced. All of the programs from the initial bug report should now error out. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/113 -------------------------------------+------------------------------------- Comment (by RyanGlScott): OK. Do you think the examples from this ticket can reasonably be added as test cases, or can this ticket be closed as-is? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: infoneeded Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/113 -------------------------------------+------------------------------------- Comment (by harpocrates): Test cases based on the Trac ticket sounds like a good idea. I'm not sure why they didn't make it into the initial MR... Unless you do it sooner, I can address that tomorrow. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/113 -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: infoneeded => new -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization levels and -fllvm -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: harpocrates Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/113 -------------------------------------+------------------------------------- Changes (by RyanGlScott): * owner: (none) => harpocrates -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16111#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#16111: Inconsistent behavior of Data.Bits.shiftL with different optimization
levels and -fllvm
-------------------------------------+-------------------------------------
Reporter: RyanGlScott | Owner: harpocrates
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.6.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Incorrect result | Unknown/Multiple
at runtime | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/113
-------------------------------------+-------------------------------------
Comment (by Ben Gamari
participants (1)
-
GHC