Skip to content

"IntMulMayOfloOp" primop compiles to wrong Aarch64 assembly

Summary

The primop IntMulMayOfloOp is being translated to a MUL instruction followed by a CSET (conditional set, with overflow flag) instruction on Aarch64 (see https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs#L894).

However, this is not correct: the overflow flag is never set on a MUL instruction. According to A64 documentation,

Overflow occurs if the result of a signed add, subtract, or compare is greater than or equal to 2^31, or less than -2^31.

This means that the current primop will most likely return 0 all the time, which is wrong and potentially dangerous.

Steps to reproduce

The following code always prints 0 in ghc 9.2.2 on Apple M1, but not in ghc 8.10.7 (which uses LLVM backend):

{-# LANGUAGE MagicHash #-}

module Main where
  
import GHC.Exts
import Data.Bits

unpack (I# a#) = a#

k :: Int
k = 134534534134534000 -- obviously does not fit in an int32, and so will overflow when squared.

bakaVariable = I# (mulIntMayOflo# (unpack k) (unpack k))

main = do
  print bakaVariable

Expected behavior

Should not print 0 at all.

Environment

  • GHC version used: 9.2.2

Optional:

  • Operating System: Mac OS Monterey 12.3.1
  • System Architecture: Aarch64 (Apple M1 Macbook Air)
Edited by Natsu Kagami
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information