Ticket #952 (closed merge: fixed)

Opened 7 years ago

Last modified 5 years ago

gcc should be passed the -fwrapv flag

Reported by: simonmar Owned by: igloo
Priority: normal Milestone: 6.6.1
Component: Compiler Version: 6.6
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

I get a floating point exception building HEAD with 6.6. I tracked it down to getCommonNodeUFMData in UniqFM:

getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData

getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
  | p ==# p2	= getCommonNodeUFMData_ p j j2
  | p <# p2	= getCommonNodeUFMData_ p2 (j `quotFastInt` (p2 `quotFastInt` p)) j2
  | otherwise	= getCommonNodeUFMData_ p j (j2 `quotFastInt` (p `quotFastInt` p2))
  where
    l  = (_ILIT(1) :: FastInt)
    j  = i  `quotFastInt` (p  `shiftL_` l)
    j2 = i2 `quotFastInt` (p2 `shiftL_` l)

    getCommonNodeUFMData_ :: FastInt -> FastInt -> FastInt -> NodeUFMData

    getCommonNodeUFMData_ p j j_
      | j ==# j_
      = NodeUFMData (((j `shiftL_` l) +# l) *# p) p
      | otherwise
      = getCommonNodeUFMData_ (p `shiftL_`  l) (j `shiftR_` l) (j_ `shiftR_` l)

The division j2 is a divide-by-zero; p2 is zero.

Compiling UniqFM with DEBUG makes it go away. Compiling with -fasm has no effect, so it isn't dependent on the back-end.

This may be architecture-specific; I've only seen it on x86_64 so far.

Change History

Changed 7 years ago by simonmar

  • status changed from new to closed
  • resolution set to fixed
  • os changed from Linux to Multiple
  • architecture changed from x86_64 (amd64) to Multiple

Fixed:

Fri Oct 20 16:39:25 BST 2006  Simon Marlow <simonmar@microsoft.com>
  * In hashExpr, use Word32 rather than relying on wrapping behaviour of Int
  Fixes #952, as it turns out.
  
  When compiling via C, we are at the mercy of C's undefined behaviour
  with respect to overflow of signed integer operations, and this was
  biting us here.
  
  Perhaps we should always add the -fwrapv flag to gcc, but since
  Haskell doesn't define overflow on Int either, it seemed the right
  thing to do to fix this code anyway.

    M ./compiler/coreSyn/CoreUtils.lhs -9 +17

Changed 7 years ago by simonmar

  • status changed from closed to reopened
  • resolution fixed deleted
  • summary changed from Floating point exception building HEAD with 6.6 to gcc should be passed the -fwrapv flag

re-opening. After giving this some more thought, I realised that the Haskell report's meaning of "undefined" is different from the C language specification's meaning of "undefined", and that in fact ghc -fvia-C is behaving incorrectly here.

Overflow of Int should return either _|_ or an implementation-defined value, according to the Haskell report. In the code affected by this bug, we were returning an implementation-defined value (2's complement wrapping) but a subsequent test on the value was returning an inconsistent answer; this is allowed by the C spec, but not by Haskell.

The upshot is that I believe we should invoke gcc with -fwrapv where it is supported (gcc 3.4+). This is more than required: it forces 2's complement wrapping behviour, but prevents the illegal optimisations that give rise to this bug.

Changed 6 years ago by igloo

  • owner set to igloo
  • status changed from reopened to new

Changed 6 years ago by igloo

  • type changed from bug to merge

Fixed in the HEAD by

Mon Jan 15 19:42:50 GMT 2007  Ian Lynagh <igloo@earth.li>
  * Give -fwrapv to gcc when it supports it
  Fixes trac #952: Haskell requires consistent overflow behaviour, which
  gcc doesn't give without this flag.

Changed 6 years ago by igloo

  • status changed from new to closed
  • resolution set to fixed

Merged to the 6.6 branch.

Changed 5 years ago by simonmar

  • architecture changed from Multiple to Unknown/Multiple

Changed 5 years ago by simonmar

  • os changed from Multiple to Unknown/Multiple
Note: See TracTickets for help on using tickets.