Simon Jakobi pushed to branch wip/sjakobi/T27448 at Glasgow Haskell Compiler / GHC Commits: 03649752 by Simon Jakobi at 2026-11-05T00:57:02+01:00 NCG: Scale the entry block in calcFreqs like any loop header calcFreqs fixed the frequency of the procedure entry at 1. With loopInfo now detecting loops headed by the entry (#28083), such an entry really runs once per iteration, so every frequency in the procedure came out too small by the same factor. The entry now gets an inflow of 1 and is scaled by its cycle probability like other loop headers. In T28083 the frequencies grow by a factor of 4. All current consumers only compare frequencies within a procedure, so no changes in generated code are expected. Assisted-by: Claude Opus 5.5 - - - - - 2 changed files: - compiler/GHC/CmmToAsm/CFG.hs - testsuite/tests/cmm/should_compile/T28083.stderr Changes: ===================================== compiler/GHC/CmmToAsm/CFG.hs ===================================== @@ -1241,17 +1241,17 @@ calcFreqs graph backEdges loops revPostOrder = runST $ do let !succFreq = f * prob setEdgeFreq block bi succFreq -- traceM $ "SetOut: " ++ show (block, bi, f, prob, succFreq) - when (bi == bhead) $ setBackProb block bi succFreq + when (Just bi == bhead) $ setBackProb block bi succFreq - let propFreq block head = do + let propFreq block mhead = do -- traceM ("prop:" ++ show (block,head)) -- traceShowM block !v <- visited block if v then return () --Dont look at nodes twice - else if block == head then + else if Just block == mhead then setFreq block 1.0 -- Loop header frequency is always 1 else do let preds = IS.elems $ predecessors block @@ -1263,7 +1263,7 @@ calcFreqs graph backEdges loops revPostOrder = runST $ do if irreducible then return () -- Rare we don't care else do - setFreq block 0 + setFreq block (if block == entry then 1 else 0) !cycleProb <- sum <$> (forM preds $ \pred -> do if isBackEdge pred block then @@ -1283,17 +1283,17 @@ calcFreqs graph backEdges loops revPostOrder = runST $ do setFreq block (f / (1.0 - cycleProb)) setVisited block - calcOutFreqs head block + calcOutFreqs mhead block -- Loops, by nesting, inner to outer forM_ loops $ \(head, body) -> do forM_ [0 .. nodeCount - 1] (\i -> unsafeWrite visitedNodes i True) -- Mark all nodes as visited. forM_ body (\i -> unsafeWrite visitedNodes i False) -- Mark all blocks reachable from head as not visited - forM_ body $ \block -> propFreq block head + forM_ body $ \block -> propFreq block (Just head) -- After dealing with all loops, deal with non-looping parts of the CFG forM_ [0 .. nodeCount - 1] (\i -> unsafeWrite visitedNodes i False) -- Everything in revPostOrder is reachable - forM_ revPostOrder $ \block -> propFreq block (head revPostOrder) + forM_ revPostOrder $ \block -> propFreq block Nothing -- trace ("Final freqs:") $ return () -- let freqString = pprFreqs freqs @@ -1304,6 +1304,8 @@ calcFreqs graph backEdges loops revPostOrder = runST $ do return (freqs', graph') where + entry = head revPostOrder + -- How can these lookups fail? Consider the CFG [A -> B] predecessors :: Int -> IS.IntSet predecessors b = fromMaybe IS.empty $ IM.lookup b revGraph ===================================== testsuite/tests/cmm/should_compile/T28083.stderr ===================================== @@ -1,7 +1,7 @@ ==================== CFG Weights - Final ==================== stg_loop: digraph { - c1 -> c4[label="0.25000",weight="0.25000"]; - c1 -> c2[label="0.75000",weight="0.75000"]; - c2 -> c1[label="0.75000",weight="0.75000"]; + c1 -> c4[label="1.00000",weight="1.00000"]; + c1 -> c2[label="3.00000",weight="3.00000"]; + c2 -> c1[label="3.00000",weight="3.00000"]; } View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/036497527e4b129fcbc6aa8bdb8049e5... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/036497527e4b129fcbc6aa8bdb8049e5... 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