"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)