Skip to content

Commit 005a66e

Browse files
committed
FIXED: Reduce constants to NF before specialisation [#3129](#3129)
1 parent 0b6aa0d commit 005a66e

File tree

4 files changed

+45
-4
lines changed

4 files changed

+45
-4
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FIXED: Reduce constants to NF before specialisation [#3129](https://github.com/clash-lang/clash-compiler/issues/3129)

clash-lib/src/Clash/Normalize/Transformations/Specialize.hs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Copyright : (C) 2012-2016, University of Twente,
33
2016-2017, Myrtle Software Ltd,
44
2017-2018, Google Inc.,
5-
2021-2024, QBayLogic B.V.
5+
2021-2026, QBayLogic B.V.
66
License : BSD2 (see the file LICENSE)
77
Maintainer : QBayLogic B.V. <[email protected]>
88
@@ -87,7 +87,7 @@ import Clash.Rewrite.Types
8787
, typeTranslator, workFreeBinders, debugOpts, topEntities, specializationLimit)
8888
import Clash.Rewrite.Util
8989
( mkBinderFor, mkDerivedName, mkFunction, mkTmBinderFor, setChanged, changed
90-
, normalizeTermTypes, normalizeId)
90+
, normalizeTermTypes, normalizeId, whnfRW)
9191
import Clash.Rewrite.WorkFree (isWorkFree)
9292
import Clash.Normalize.Types
9393
( NormRewrite, NormalizeSession, specialisationCache, specialisationHistory)
@@ -290,9 +290,14 @@ constantSpec ctx@(TransformContext is0 tfCtx) e@(App e1 e2)
290290
= do specInfo<- constantSpecInfo ctx e2
291291
if csrFoundConstant specInfo then
292292
let newBindings = csrNewBindings specInfo in
293-
if null newBindings then
293+
if null newBindings then do
294294
-- Whole of e2 is constant
295-
specialize ctx (App e1 e2)
295+
e2Red <- case collectArgs e2 of
296+
(Prim p0, _) -> whnfRW False ctx e2 $ \_ctx1 e2Red -> case e2Red of
297+
(collectArgs -> (Prim p1, _)) | primName p0 == primName p1 -> return e2
298+
_ -> changed e2Red
299+
_ -> return e2
300+
specialize ctx (App e1 e2Red)
296301
else do
297302
-- Parts of e2 are constant
298303
let is1 = extendInScopeSetList is0 (fst <$> csrNewBindings specInfo)

tests/Main.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,7 @@ runClashTest = defaultMain
930930
, clashFlags = ["-main-is", "topEntity3"]
931931
}
932932
, runTest "T1139" def{hdlSim=[]}
933+
, runTest "T1139" def{hdlSim=[]}
933934
, let _opts = def { hdlTargets=[Verilog]
934935
, buildTargets=BuildSpecific ["PortNames_testBench"]
935936
}
@@ -962,6 +963,7 @@ runClashTest = defaultMain
962963
, outputTest "PortNamesWithRTree" def{hdlTargets=[Verilog]}
963964
, clashLibTest "T1182A" def
964965
, clashLibTest "T1182B" def
966+
, runTest "T3129" def{hdlSim=[], clashFlags=["-fclash-spec-limit=400"]}
965967
]
966968
, clashTestGroup "Unit"
967969
[ runTest "Imap" def
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module T3129 where
2+
3+
import Clash.Prelude
4+
5+
import GHC.Base (isTrue#)
6+
import GHC.Num.Natural (Natural (NS), naturalLogBase#)
7+
import GHC.Prim (eqWord#, plusWord#)
8+
9+
naturalCLogBase :: Natural -> Natural -> Natural
10+
naturalCLogBase x y =
11+
let z1 = naturalLogBase# x y
12+
z2 = naturalLogBase# x (y-1)
13+
in case y of
14+
1 -> 0
15+
_ | isTrue# (z1 `eqWord#` z2) -> NS (z1 `plusWord#` 1##)
16+
| otherwise -> NS z1
17+
18+
f :: Natural -> Natural
19+
f m = 2 * (naturalCLogBase 2 m)
20+
21+
g :: Natural -> Natural
22+
g m =
23+
let i = f m
24+
calc 0 _ _ = 1
25+
calc 1 val tmp = (val * tmp) `mod` m
26+
calc n val tmp = calc
27+
(if n `mod` 2 == 0 then n `div` 2 else n - 1 )
28+
(if n `mod` 2 == 0 then val * val `mod` m else val )
29+
(if n `mod` 2 == 0 then tmp `mod` m else (tmp * val) `mod` m)
30+
in calc (m - i - 1) 2 1
31+
32+
topEntity :: Natural
33+
topEntity = g 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff

0 commit comments

Comments
 (0)