llvm-dsl-0.2: src/LLVM/DSL/Example/Median.hs
module LLVM.DSL.Example.Median where
import qualified LLVM.DSL.Expression as Expr
import LLVM.DSL.Expression (Exp, (==*), (<=*), (&&*), (||*))
import qualified LLVM.Extra.Nice.Vector as NVec
import qualified LLVM.Extra.Nice.Value as NV
import qualified LLVM.Core as LLVM
import Data.Tuple.HT (uncurry3)
import Data.Word (Word8)
median3IfThen :: (NV.Comparison a) => Exp a -> Exp a -> Exp a -> Exp a
median3IfThen a b c =
Expr.ifThenElse (a<=*b)
(Expr.ifThenElse (b<=*c)
b
(Expr.ifThenElse (a<=*c) c a))
(Expr.ifThenElse (a<=*c)
a
(Expr.ifThenElse (b<=*c) c b))
median3Select ::
(NV.Comparison a, NV.Select a) => Exp a -> Exp a -> Exp a -> Exp a
median3Select a b c =
Expr.select (a<=*b)
(Expr.select (b<=*c)
b
(Expr.select (a<=*c) c a))
(Expr.select (a<=*c)
a
(Expr.select (b<=*c) c b))
median3SelectShared ::
(NV.Comparison a, NV.Select a) => Exp a -> Exp a -> Exp a -> Exp a
median3SelectShared a b c =
Expr.with (a<=*b) $ \a_le_b ->
Expr.with (b<=*c) $ \b_le_c ->
Expr.with (a<=*c) $ \a_le_c ->
Expr.select a_le_b
(Expr.select b_le_c b (Expr.select a_le_c c a))
(Expr.select a_le_c a (Expr.select b_le_c c b))
median3MinMax ::
(NV.Comparison a, NV.Select a) => Exp a -> Exp a -> Exp a -> Exp a
median3MinMax a b c =
let minab = Expr.min a b in
let maxab = Expr.max a b in
Expr.select (maxab <=* c) maxab $ Expr.select (minab <=* c) c minab
median3MinMaxVector ::
(LLVM.Positive n, NVec.C a) =>
(NV.Comparison a, NV.Select a) =>
NVec.T n a -> NVec.T n a -> NVec.T n a ->
LLVM.CodeGenFunction r (NVec.T n a)
median3MinMaxVector a b c =
NVec.map (uncurry3 (Expr.unliftM3 median3MinMax) . NV.unzip3) $
NVec.zip3 a b c
type NV = NV.T
median3Case ::
(NV.Comparison a, NV.Select a) =>
NV a -> NV a -> NV a -> LLVM.CodeGenFunction r (NV a)
median3Case a b c = do
a_le_b <- NV.cmp LLVM.CmpLE a b
a_le_c <- NV.cmp LLVM.CmpLE a c
b_le_c <- NV.cmp LLVM.CmpLE b c
let mask = NV.fromInteger'
a_le_b_mask <- NV.select a_le_b (mask 1) (mask 0)
a_le_c_mask <- NV.select a_le_c (mask 2) (mask 0)
b_le_c_mask <- NV.select b_le_c (mask 4) (mask 0)
maskNV <- NV.or a_le_b_mask =<< NV.or a_le_c_mask b_le_c_mask
let maskE = Expr.lift0 (maskNV :: NV Word8)
selectB <- Expr.unExp (maskE ==* 0 ||* maskE ==* 7)
selectA <- Expr.unExp (maskE ==* 1 ||* maskE ==* 6)
NV.select selectA a =<< NV.select selectB b c
median3CaseVec ::
(NV.Comparison a, NV.Select a) =>
NV a -> NV a -> NV a -> LLVM.CodeGenFunction r (NV a)
median3CaseVec a b c = do
a_le_b <- NV.cmp LLVM.CmpLE a b
a_le_c <- NV.cmp LLVM.CmpLE a c
b_le_c <- NV.cmp LLVM.CmpLE b c
let check ab ac bc =
Expr.select (Expr.lift0 a_le_b) 1 0 ==* (ab :: Exp Word8)
&&*
Expr.select (Expr.lift0 a_le_c) 1 0 ==* (ac :: Exp Word8)
&&*
Expr.select (Expr.lift0 b_le_c) 1 0 ==* (bc :: Exp Word8)
selectB <- Expr.unExp (check 0 0 0 ||* check 1 1 1)
selectA <- Expr.unExp (check 1 0 0 ||* check 0 1 1)
NV.select selectA a =<< NV.select selectB b c