Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
c2989784
by sheaf at 2026-06-04T13:07:45-04:00
-
e834d92a
by Simon Jakobi at 2026-06-04T13:07:46-04:00
6 changed files:
- + changelog.d/T27046
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
- testsuite/driver/runtests.py
- + testsuite/tests/codeGen/should_run/T27046.hs
- + testsuite/tests/codeGen/should_run/T27046_cmm.cmm
- testsuite/tests/codeGen/should_run/all.T
Changes:
| 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. |
| ... | ... | @@ -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`
|
| ... | ... | @@ -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:
|
| 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 | + ] |
| 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 | +} |
| ... | ... | @@ -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
|