Skip to content

Output value of program changes upon compiling with -O optimizations

The optimisation pass seems to affect the behaviour of the attached program (a basic ray-sphere intersection test, 40 lines long, no dependencies).

Specifically, compiling the attached source file with -O or -O2, and considering the definition of main:

result = sphereIntersection testRay testSphere

main :: IO()
main = do
  print $ result
  print $ sphereIntersection testRay testSphere

I get the troubling output:

> bug.exe
Just ((0.0,0.0,0.0),0.0)
Just ((0.0,0.0,100.0),1.0)

This is especially troubling because the second component of the output should always be 1.0:

testRay = ((0, 0, 0),(0, 0, 1))

sphereIntersection (orig, dir@(_, _, dirz)) (c,r)
  | disc < 0  = Nothing
  | t1   > 0  = Just (t1 *> dir <+> orig, dirz)
  | t2   > 0  = Just (t2 *> dir <+> orig, dirz)
  | otherwise = Nothing
    where ...

as we are returning the "dirz" component of the input ray straight back out.

On the other hand, when the program is run without optimisations, I get the expected output:

> bug.exe
Just ((0.0,0.0,100.0),1.0)
Just ((0.0,0.0,100.0),1.0)

This behaviour was present on all versions of GHC that I tested (7.10.1, 8.0.1, 8.2.1, 8.2.2). I initially ran into this issue when I noticed that the profiling builds of my program produced different results, which was boiled down to this problem.

Trac metadata
Trac field Value
Version 8.2.2
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system Windows
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information