futhark-0.17.1: src/Futhark/Analysis/PrimExp/Generalize.hs
-- | Generalization (anti-unification) of 'PrimExp's.
module Futhark.Analysis.PrimExp.Generalize
( leastGeneralGeneralization,
)
where
import Data.List (elemIndex)
import Futhark.Analysis.PrimExp
import Futhark.IR.Syntax.Core (Ext (..))
-- | Generalize two 'PrimExp's of the the same type.
leastGeneralGeneralization ::
(Eq v) =>
[(PrimExp v, PrimExp v)] ->
PrimExp v ->
PrimExp v ->
(PrimExp (Ext v), [(PrimExp v, PrimExp v)])
leastGeneralGeneralization m exp1@(LeafExp v1 t1) exp2@(LeafExp v2 _) =
if v1 == v2
then (LeafExp (Free v1) t1, m)
else generalize m exp1 exp2
leastGeneralGeneralization m exp1@(ValueExp v1) exp2@(ValueExp v2) =
if v1 == v2
then (ValueExp v1, m)
else generalize m exp1 exp2
leastGeneralGeneralization m exp1@(BinOpExp op1 e11 e12) exp2@(BinOpExp op2 e21 e22) =
if op1 == op2
then
let (e1, m1) = leastGeneralGeneralization m e11 e21
(e2, m2) = leastGeneralGeneralization m1 e12 e22
in (BinOpExp op1 e1 e2, m2)
else generalize m exp1 exp2
leastGeneralGeneralization m exp1@(CmpOpExp op1 e11 e12) exp2@(CmpOpExp op2 e21 e22) =
if op1 == op2
then
let (e1, m1) = leastGeneralGeneralization m e11 e21
(e2, m2) = leastGeneralGeneralization m1 e12 e22
in (CmpOpExp op1 e1 e2, m2)
else generalize m exp1 exp2
leastGeneralGeneralization m exp1@(UnOpExp op1 e1) exp2@(UnOpExp op2 e2) =
if op1 == op2
then
let (e, m1) = leastGeneralGeneralization m e1 e2
in (UnOpExp op1 e, m1)
else generalize m exp1 exp2
leastGeneralGeneralization m exp1@(ConvOpExp op1 e1) exp2@(ConvOpExp op2 e2) =
if op1 == op2
then
let (e, m1) = leastGeneralGeneralization m e1 e2
in (ConvOpExp op1 e, m1)
else generalize m exp1 exp2
leastGeneralGeneralization m exp1@(FunExp s1 args1 t1) exp2@(FunExp s2 args2 _) =
if s1 == s2 && length args1 == length args2
then
let (args, m') =
foldl
( \(arg_acc, m_acc) (a1, a2) ->
let (a, m'') = leastGeneralGeneralization m_acc a1 a2
in (a : arg_acc, m'')
)
([], m)
(zip args1 args2)
in (FunExp s1 (reverse args) t1, m')
else generalize m exp1 exp2
leastGeneralGeneralization m exp1 exp2 =
generalize m exp1 exp2
generalize :: Eq v => [(PrimExp v, PrimExp v)] -> PrimExp v -> PrimExp v -> (PrimExp (Ext v), [(PrimExp v, PrimExp v)])
generalize m exp1 exp2 =
let t = primExpType exp1
in case elemIndex (exp1, exp2) m of
Just i -> (LeafExp (Ext i) t, m)
Nothing -> (LeafExp (Ext $ length m) t, m ++ [(exp1, exp2)])