Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • changelog.d/T27046
    1
    +section: compiler
    
    2
    +issues: #27046
    
    3
    +mrs: !16031
    
    4
    +synopsis:
    
    5
    +  Avoid AArch64 register clobbering bug in MUL2
    
    6
    +description:
    
    7
    +  Fixes an issue in which, on AArch64, code generation for the MUL2 operation
    
    8
    +  could clobber one of the input operands when computing the lower bits, which
    
    9
    +  rendered invalid the subsequent computation of the high bits.

  • compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
    ... ... @@ -2300,11 +2300,19 @@ genCCall target dest_regs arg_regs = do
    2300 2300
                   let lo = getRegisterReg platform (CmmLocal dst_lo)
    
    2301 2301
                       hi = getRegisterReg platform (CmmLocal dst_hi)
    
    2302 2302
                       nd = getRegisterReg platform (CmmLocal dst_needed)
    
    2303
    +
    
    2304
    +              -- Generate a fresh virtual register for the low word computation.
    
    2305
    +              -- This avoids clobbering reg_a or reg_b in the first MUL instruction,
    
    2306
    +              -- which could for example happen if 'lo' and 'reg_a' are the same
    
    2307
    +              -- virtual register.
    
    2308
    +              tmp_lo <- getNewRegNat II64
    
    2309
    +
    
    2303 2310
                   return $
    
    2304 2311
                       code_x `appOL`
    
    2305 2312
                       code_y `snocOL`
    
    2306
    -                  MUL   II64 (OpReg W64 lo) (OpReg W64 reg_a) (OpReg W64 reg_b) `snocOL`
    
    2313
    +                  MUL   II64 (OpReg W64 tmp_lo) (OpReg W64 reg_a) (OpReg W64 reg_b) `snocOL`
    
    2307 2314
                       SMULH (OpReg W64 hi) (OpReg W64 reg_a) (OpReg W64 reg_b) `snocOL`
    
    2315
    +                  MOV   (OpReg W64 lo) (OpReg W64 tmp_lo) `snocOL`
    
    2308 2316
                       -- Are all high bits equal to the sign bit of the low word?
    
    2309 2317
                       -- nd = (hi == ASR(lo,width-1)) ? 1 : 0
    
    2310 2318
                       CMP   (OpReg W64 hi) (OpRegShift W64 lo SASR (widthInBits w - 1)) `snocOL`
    

  • testsuite/driver/runtests.py
    ... ... @@ -133,7 +133,7 @@ if args.unexpected_output_dir:
    133 133
         config.unexpected_output_dir = Path(args.unexpected_output_dir)
    
    134 134
     
    
    135 135
     if args.only:
    
    136
    -    config.only = args.only
    
    136
    +    config.only = set(args.only)
    
    137 137
         config.run_only_some_tests = True
    
    138 138
     
    
    139 139
     if args.skip:
    

  • testsuite/tests/codeGen/should_run/T27046.hs
    1
    +{-# LANGUAGE MagicHash #-}
    
    2
    +{-# LANGUAGE ForeignFunctionInterface, GHCForeignImportPrim, UnliftedFFITypes #-}
    
    3
    +
    
    4
    +module Main where
    
    5
    +
    
    6
    +import Control.Monad
    
    7
    +  ( unless )
    
    8
    +import Data.Bits
    
    9
    +  ( shiftL )
    
    10
    +import GHC.Exts
    
    11
    +  ( Int64# )
    
    12
    +import GHC.Int
    
    13
    +  ( Int64(..) )
    
    14
    +
    
    15
    +foreign import prim "test_mul2_clobber"
    
    16
    +  test_mul2_clobber :: Int64# -> Int64# -> Int64#
    
    17
    +
    
    18
    +main :: IO ()
    
    19
    +main = do
    
    20
    +  let
    
    21
    +    I64# x = 1 `shiftL` 32
    
    22
    +    hi = I64# $ test_mul2_clobber x x
    
    23
    +
    
    24
    +  unless ( hi == 1 ) $
    
    25
    +    error $ unlines
    
    26
    +      [ "Incorrect result for Mul2 operation."
    
    27
    +      , "Expected high word: 1"
    
    28
    +      , "  Actual high word: " ++ show hi
    
    29
    +      ]

  • testsuite/tests/codeGen/should_run/T27046_cmm.cmm
    1
    +#include "Cmm.h"
    
    2
    +
    
    3
    +// Test for #27046
    
    4
    +test_mul2_clobber (bits64 x, bits64 y)
    
    5
    +{
    
    6
    +    bits64 hi, nd;
    
    7
    +
    
    8
    +    // Deliberately alias the destination 'lo' with the source 'x'
    
    9
    +    // This forces the NCG to use the same virtual register for both.
    
    10
    +    (nd, hi, x) = prim %mul2_64(x, y);
    
    11
    +
    
    12
    +    return (hi);
    
    13
    +}

  • testsuite/tests/codeGen/should_run/all.T
    ... ... @@ -260,6 +260,7 @@ test('T25364', normal, compile_and_run, [''])
    260 260
     test('T26061', normal, compile_and_run, [''])
    
    261 261
     test('T26537', normal, compile_and_run, ['-O2 -fregs-graph'])
    
    262 262
     test('T24016', normal, compile_and_run, ['-O1 -fPIC'])
    
    263
    +test('T27046', [req_cmm], compile_and_run, ['T27046_cmm.cmm'])
    
    263 264
     
    
    264 265
     # Check that GHC-generated finalizers run on Darwin. The Apple linker doesn't
    
    265 266
     # support --wrap, so we can't intercept hs_spt_remove directly.  Instead we