[Git][ghc/ghc][wip/marge_bot_batch_merge_job] NCG x86: track the current block after word-to-float conversion (#27915)
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: 94876665 by Sylvain Henry at 2026-10-12T08:58:25-04:00 NCG x86: track the current block after word-to-float conversion (#27915) On x86-64, genWordToFloat introduces new basic blocks, but it was dispatched via genSimplePrim, which assumes no new blocks. The new current block was not given back to stmtsToInstrs, so a second conversion in the same Cmm block updated the CFG relative to a stale block id. This caused the panic "Can't find weight for edge that should have one" when the register allocator inserted a fixup block. genWordToFloat now returns the new current block and MO_UF_Conv is handled with the other block-introducing primops in genPrim. See Note [Keeping track of the current block]. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> - - - - - 5 changed files: - + changelog.d/27915 - compiler/GHC/CmmToAsm/X86/CodeGen.hs - + testsuite/tests/codeGen/should_run/T27915.hs - + testsuite/tests/codeGen/should_run/T27915.stdout - testsuite/tests/codeGen/should_run/all.T Changes: ===================================== changelog.d/27915 ===================================== @@ -0,0 +1,6 @@ +section: codegen +synopsis: Fix a panic ("Can't find weight for edge that should have one") in the + x86-64 native code generator when a basic block contains several + word-to-float conversions. +mrs: !16787 +issues: #27915 ===================================== compiler/GHC/CmmToAsm/X86/CodeGen.hs ===================================== @@ -4359,6 +4359,8 @@ genPrim bid (MO_AtomicRMW width amop) [dst] [addr, n] = genAtomicRMW bid width amop dst addr n genPrim bid (MO_Ctz width) [dst] [src] = genCtz bid width dst src +genPrim bid (MO_UF_Conv width) [dst] [src] + = genWordToFloat bid width dst src -- Then we deal with cases which not introducing new blocks in the stream. genPrim bid prim dst args @@ -4385,7 +4387,6 @@ genSimplePrim bid (MO_PopCnt width) [dst] [src] = genPopCnt bid wi genSimplePrim bid (MO_Pdep width) [dst] [src,mask] = genPdep bid width dst src mask genSimplePrim bid (MO_Pext width) [dst] [src,mask] = genPext bid width dst src mask genSimplePrim bid (MO_Clz width) [dst] [src] = genClz bid width dst src -genSimplePrim bid (MO_UF_Conv width) [dst] [src] = genWordToFloat bid width dst src genSimplePrim _ (MO_AtomicRead w mo) [dst] [addr] = genAtomicRead w mo dst addr genSimplePrim _ (MO_AtomicWrite w mo) [] [addr,val] = genAtomicWrite w mo addr val genSimplePrim bid (MO_Cmpxchg width) [dst] [addr,old,new] = genCmpXchg bid width dst addr old new @@ -6924,7 +6925,11 @@ The constant 65536.0 (= 0x47800000 in float32 bit-pattern) is loaded via a MOV + MOVD, avoiding a memory load. -} -genWordToFloat :: BlockId -> Width -> CmmFormal -> CmmActual -> NatM InstrBlock +-- | Convert an unsigned word to a float. +-- +-- On x86-64 this introduces new blocks: the returned BlockId is the new current +-- block (#27915). See Note [Keeping track of the current block]. +genWordToFloat :: BlockId -> Width -> CmmFormal -> CmmActual -> NatM (InstrBlock, Maybe BlockId) genWordToFloat bid width dst src = do is32Bit <- is32BitPlatform platform <- getPlatform @@ -6946,7 +6951,7 @@ genWordToFloat bid width dst src = do cst_r <- getNewRegNat srcFormat cst_v <- getNewRegNat dstFormat flip_r <- getNewRegNat srcFormat - return $ code_src `appOL` toOL + return $ (,Nothing) $ code_src `appOL` toOL [ MOV srcFormat (OpImm (ImmInt 0x4F000000)) (OpReg cst_r) -- load the constant , MOVD srcFormat (floatFormat W32) (OpReg cst_r) (OpReg cst_v) , CVTSS2SD cst_v cst_v @@ -6968,7 +6973,7 @@ genWordToFloat bid width dst src = do cst_r <- getNewRegNat srcFormat high_r <- getNewRegNat srcFormat low_r <- getNewRegNat srcFormat - return $ code_src `appOL` toOL + return $ (,Nothing) $ code_src `appOL` toOL [ MOV srcFormat (OpImm (ImmInt 0x47800000)) (OpReg cst_r) -- load the constant , MOVD srcFormat dstFormat (OpReg cst_r) (OpReg cst_v) , MOVZxL II16 (OpReg src_r) (OpReg low_r) -- low_r = low 16 bits @@ -7006,7 +7011,7 @@ genWordToFloat bid width dst src = do . addWeightEdge lblLarge lblAfter 1 . delEdge bid lblAfter ) - return $ appOL (code_src) + return $ (,Just lblAfter) $ appOL (code_src) $ toOL [ TEST srcFormat (OpReg src_r) (OpReg src_r) , JXX NEG lblLarge ===================================== testsuite/tests/codeGen/should_run/T27915.hs ===================================== @@ -0,0 +1,21 @@ +{-# LANGUAGE BangPatterns #-} +-- Two word-to-float conversions in one Cmm block, in a loop where the register +-- assignment differs at the back edge. The x86-64 NCG used to emit an +-- out-of-sync CFG and panic with "Can't find weight for edge that should have +-- one" (#27915). +module Main where + +go :: Word -> Word -> Word -> Double -> Double +go 0 _ _ !acc = acc +go n a b !acc = go (n-1) b a (acc + fromIntegral a * fromIntegral b) +{-# NOINLINE go #-} + +goF :: Word -> Word -> Word -> Float -> Float +goF 0 _ _ !acc = acc +goF n a b !acc = goF (n-1) b a (acc + fromIntegral a * fromIntegral b) +{-# NOINLINE goF #-} + +main :: IO () +main = do + print (go 10 3 maxBound 0) + print (goF 10 3 maxBound 0) ===================================== testsuite/tests/codeGen/should_run/T27915.stdout ===================================== @@ -0,0 +1,2 @@ +5.5340232221128655e20 +5.5340232e20 ===================================== testsuite/tests/codeGen/should_run/all.T ===================================== @@ -127,6 +127,7 @@ test('T7319', exit_code(1), compile_and_run, ['']) test('Word2Float32', unless(wordsize(32), skip), compile_and_run, ['']) test('Word2Float64', unless(wordsize(64), skip), compile_and_run, ['']) +test('T27915', normal, compile_and_run, ['-O']) test('T7361', normal, compile_and_run, ['']) test('T7600', normal, compile_and_run, ['']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/948766650f7e717c887b1da16b878b9a... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/948766650f7e717c887b1da16b878b9a... You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
participants (1)
-
Marge Bot (@marge-bot)