Skip to content

Commit

Permalink
Do not inline let-bound recursive calls
Browse files Browse the repository at this point in the history
This prevents `recToLetRec` from turning a globally recursive
function into a local let-bound recursive function which can
be synthesized to hardware.

Fixes #2839

(cherry picked from commit 0072241)
  • Loading branch information
christiaanb committed Nov 26, 2024
1 parent bace7a5 commit 68b6dc7
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog/2024-11-18T13_43_58+01_00_fix2839
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FIXED: Clash errored saying it cannot translate a globally recursive function in code that originally only contains let-bound (local) recursion [#2839](https://github.com/clash-lang/clash-compiler/issues/2839).
9 changes: 8 additions & 1 deletion clash-lib/src/Clash/Normalize/Transformations/Inline.hs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,14 @@ bindConstantVar = inlineBinders test
True -> return (i `notElemFreeVars` e)
_ -> do
tcm <- Lens.view tcCache
case isWorkFreeIsh tcm e of
(fn,_) <- Lens.use curFun
-- Don't inline things that perform work, it increases the circuit size.
--
-- Also don't inline globally recursive calls, it prevents the
-- recToLetRec transformation from transforming global recursion to
-- local recursion.
-- See https://github.com/clash-lang/clash-compiler/issues/2839
case isWorkFreeIsh tcm e && not (e == Var fn) of
True -> Lens.view inlineConstantLimit >>= \case
0 -> return True
n -> return (termSize e <= n)
Expand Down
1 change: 1 addition & 0 deletions tests/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,7 @@ runClashTest = defaultMain $ clashTestRoot
, runTest "T2623CaseConFVs" def{hdlLoad=[],hdlSim=[],hdlTargets=[VHDL]}
, runTest "T2781" def{hdlLoad=[],hdlSim=[],hdlTargets=[VHDL]}
, runTest "T2628" def{hdlTargets=[VHDL], buildTargets=BuildSpecific ["TACacheServerStep"], hdlSim=[]}
, runTest "T2839" def{hdlLoad=[],hdlSim=[],hdlTargets=[VHDL]}
] <>
if compiledWith == Cabal then
-- This tests fails without environment files present, which are only
Expand Down
12 changes: 12 additions & 0 deletions tests/shouldwork/Issues/T2839.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module T2839 where

import Clash.Explicit.Prelude
import Clash.Explicit.Testbench

topEntity ::
Signal System (Unsigned 8)
topEntity = register clk noReset enableGen 100 0
where
cntr = register clk noReset enableGen (0 :: Unsigned 8) 0
done = (== 100) <$> cntr
clk = tbClockGen $ not <$> done

0 comments on commit 68b6dc7

Please sign in to comment.