Skip to content

Commit

Permalink
Use shiftL(Natural/Integer) instead of Bits.shiftL
Browse files Browse the repository at this point in the history
For some bizarre reason, which I cannot reproduce, the set of
optimizations that Clash picks results in a weird specialization
of the `natSing2` implementation for `GHC.TypeNats.^`, which
is specialized to the `y` in `x ^ y` being a negative number.

This then causes the:

> shiftL x y = if y <= 0 then shiftLNatural x y else shiftRNatural x (negate y)

to pick the else branch, which in turn causes fast power-of-two
calculation in `natSing2` to do  `1 shiftR y` instead of the
intended `1 shiftL y`.

Anyhow... I don't know what's going on... This patch ensures
we call `shiftLNatural` directly, since we know the exponent
never a negative number; and GHC won't be able to specialize.

Fixes clash-lang/clash-compiler#1454
  • Loading branch information
christiaanb committed Jul 25, 2020
1 parent 88c8a28 commit 7801a34
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog for the [`ghc-typelits-knownnat`](http://hackage.haskell.org/package/ghc-typelits-knownnat) package

## 0.7.3 *July 25th 2020*
* Fix https://github.com/clash-lang/clash-compiler/issues/1454

## 0.7.2 *February 6th 2020*
* Add support for GHC 8.10.0-alpha2

Expand Down
4 changes: 3 additions & 1 deletion ghc-typelits-knownnat.cabal
@@ -1,5 +1,5 @@
name: ghc-typelits-knownnat
version: 0.7.2
version: 0.7.3
synopsis: Derive KnownNat constraints from other KnownNat constraints
description:
A type checker plugin for GHC that can derive \"complex\" @KnownNat@
Expand Down Expand Up @@ -98,6 +98,8 @@ library
ghc-options: -Wall -Werror
else
ghc-options: -Wall
if impl(ghc < 8.2)
build-depends: integer-gmp >= 0.5.1.0

test-suite test-ghc-typelits-knownnat
type: exitcode-stdio-1.0
Expand Down
20 changes: 19 additions & 1 deletion src/GHC/TypeLits/KnownNat.hs
Expand Up @@ -99,6 +99,9 @@ type family Max (a :: Nat) (b :: Nat) :: Nat where
#if MIN_VERSION_ghc(8,6,0)
{-# LANGUAGE NoStarIsType #-}
#endif
#if !MIN_VERSION_ghc(8,2,0)
{-# LANGUAGE BangPatterns #-}
#endif

{-# LANGUAGE Trustworthy #-}

Expand Down Expand Up @@ -126,7 +129,14 @@ module GHC.TypeLits.KnownNat
)
where

#if MIN_VERSION_ghc(8,6,0)
import GHC.Natural (shiftLNatural)
#elif MIN_VERSION_ghc(8,2,0)
import Data.Bits (shiftL)
#else
import GHC.Int (Int (..))
import GHC.Integer (shiftLInteger)
#endif
import Data.Proxy (Proxy (..))
import Data.Type.Bool (If)
import GHC.Prim (Proxy#)
Expand Down Expand Up @@ -194,7 +204,15 @@ instance (KnownNat a, KnownNat b) => KnownNat2 $(nameToSymbol ''(^)) a b where
natSing2 = let x = natVal (Proxy @a)
y = natVal (Proxy @b)
z = case x of
2 -> shiftL 1 (fromIntegral y)
2 ->
#if MIN_VERSION_ghc(8,6,0)
shiftLNatural 1 (fromIntegral y)
#elif MIN_VERSION_ghc(8,2,0)
shiftL 1 (fromIntegral y)
#else
let !(I# y#) = fromIntegral y
in shiftLInteger 1 y#
#endif
_ -> x ^ y
in SNatKn z
{-# INLINE natSing2 #-}
Expand Down

0 comments on commit 7801a34

Please sign in to comment.