Move apply() -> Xform.apply(); is_concrete_rtl() -> Rtl.is_concrete(); cleanup_concrete_rtl() -> Rtl.cleanup_concrete_rtl(). Documnetation nits in semantics.elaborate

This commit is contained in:
Dimo
2017-07-26 16:30:31 -07:00
committed by Jakob Stoklund Olesen
parent a92021ebce
commit 80a42fdeaa
2 changed files with 88 additions and 89 deletions

View File

@@ -5,6 +5,7 @@ from __future__ import absolute_import
from .ast import Def, Var, Apply from .ast import Def, Var, Apply
from .ti import ti_xform, TypeEnv, get_type_env from .ti import ti_xform, TypeEnv, get_type_env
from functools import reduce from functools import reduce
from .typevar import TypeVar
try: try:
from typing import Union, Iterator, Sequence, Iterable, List, Dict # noqa from typing import Union, Iterator, Sequence, Iterable, List, Dict # noqa
@@ -12,7 +13,6 @@ try:
from .ast import Expr, VarMap # noqa from .ast import Expr, VarMap # noqa
from .isa import TargetISA # noqa from .isa import TargetISA # noqa
from .ti import TypeConstraint # noqa from .ti import TypeConstraint # noqa
from .typevar import TypeVar # noqa
DefApply = Union[Def, Apply] DefApply = Union[Def, Apply]
except ImportError: except ImportError:
pass pass
@@ -86,6 +86,37 @@ class Rtl(object):
return s return s
def is_concrete(self):
# type: (Rtl) -> bool
"""Return True iff every Var in the self has a singleton type."""
return all(v.get_typevar().singleton_type() is not None
for v in self.vars())
def cleanup_concrete_rtl(self):
# type: (Rtl) -> None
"""
Given that there is only 1 possible concrete typing T for self, assign
a singleton TV with the single type t=T[v] for each Var v \in self.
Its an error to call this on an Rtl with more than 1 possible typing.
"""
from .ti import ti_rtl, TypeEnv
# 1) Infer the types of all vars in res
typenv = get_type_env(ti_rtl(self, TypeEnv()))
typenv.normalize()
typenv = typenv.extract()
# 2) Make sure there is only one possible type assignment
typings = list(typenv.concrete_typings())
assert len(typings) == 1
typing = typings[0]
# 3) Assign the only possible type to each variable.
for v in typenv.vars:
if v.get_typevar().singleton_type() is not None:
continue
v.set_typevar(TypeVar.singleton(typing[v].singleton_type()))
class XForm(object): class XForm(object):
""" """
@@ -279,6 +310,27 @@ class XForm(object):
raise AssertionError( raise AssertionError(
'{} not defined in dest pattern'.format(d)) '{} not defined in dest pattern'.format(d))
def apply(self, r, suffix=None):
# type: (Rtl, str) -> Rtl
"""
Given a concrete Rtl r s.t. r matches self.src, return the
corresponding concrete self.dst. If suffix is provided, any temporary
defs are renamed with '.suffix' appended to their old name.
"""
assert r.is_concrete()
s = self.src.substitution(r, {}) # type: VarMap
assert s is not None
if (suffix is not None):
for v in self.dst.vars():
if v.is_temp():
assert v not in s
s[v] = Var(v.name + '.' + suffix)
dst = self.dst.copy(s)
dst.cleanup_concrete_rtl()
return dst
class XFormGroup(object): class XFormGroup(object):
""" """

View File

@@ -4,8 +4,6 @@ equivalent primitive version. Its elaborated primitive version contains only
primitive cretonne instructions, which map well to SMTLIB functions. primitive cretonne instructions, which map well to SMTLIB functions.
""" """
from .primitives import GROUP as PRIMITIVES, prim_to_bv, prim_from_bv from .primitives import GROUP as PRIMITIVES, prim_to_bv, prim_from_bv
from cdsl.ti import ti_rtl, TypeEnv, get_type_env
from cdsl.typevar import TypeVar
from cdsl.xform import Rtl from cdsl.xform import Rtl
from cdsl.ast import Var from cdsl.ast import Var
@@ -18,60 +16,6 @@ except ImportError:
TYPE_CHECKING = False TYPE_CHECKING = False
def is_rtl_concrete(r):
# type: (Rtl) -> bool
"""Return True iff every Var in the Rtl r has a single type."""
return all(v.get_typevar().singleton_type() is not None for v in r.vars())
def cleanup_concrete_rtl(r):
# type: (Rtl) -> Rtl
"""
Given an Rtl r
1) assert that there is only 1 possible concrete typing T for r
2) Assign a singleton TV with the single type t \in T for each Var v \in r
"""
# 1) Infer the types of any of the remaining vars in res
typenv = get_type_env(ti_rtl(r, TypeEnv()))
typenv.normalize()
typenv = typenv.extract()
# 2) Make sure there is only one possible type assignment
typings = list(typenv.concrete_typings())
assert len(typings) == 1
typing = typings[0]
# 3) Assign the only possible type to each variable.
for v in typenv.vars:
if v.get_typevar().singleton_type() is not None:
continue
v.set_typevar(TypeVar.singleton(typing[v].singleton_type()))
return r
def apply(r, x, suffix=None):
# type: (Rtl, XForm, str) -> Rtl
"""
Given a concrete Rtl r and XForm x, s.t. r matches x.src, return the
corresponding concrete x.dst. If suffix is provided, any temporary defs are
renamed with '.suffix' appended to their old name.
"""
assert is_rtl_concrete(r)
s = x.src.substitution(r, {}) # type: VarMap
assert s is not None
if (suffix is not None):
for v in x.dst.vars():
if v.is_temp():
assert v not in s
s[v] = Var(v.name + '.' + suffix)
dst = x.dst.copy(s)
return cleanup_concrete_rtl(dst)
def find_matching_xform(d): def find_matching_xform(d):
# type: (Def) -> XForm # type: (Def) -> XForm
""" """
@@ -93,41 +37,10 @@ def find_matching_xform(d):
if x.ti.permits({subst[v]: tv for (v, tv) in typing.items()}): if x.ti.permits({subst[v]: tv for (v, tv) in typing.items()}):
res.append(x) res.append(x)
assert len(res) == 1 assert len(res) == 1, "Couldn't find semantic transform for {}".format(d)
return res[0] return res[0]
def elaborate(r):
# type: (Rtl) -> Rtl
"""
Given an Rtl r, return a semantically equivalent Rtl r1 consisting only
primitive instructions.
"""
fp = False
primitives = set(PRIMITIVES.instructions)
idx = 0
while not fp:
assert is_rtl_concrete(r)
new_defs = [] # type: List[Def]
fp = True
for d in r.rtl:
inst = d.expr.inst
if (inst not in primitives):
transformed = apply(Rtl(d), find_matching_xform(d), str(idx))
idx += 1
new_defs.extend(transformed.rtl)
fp = False
else:
new_defs.append(d)
r.rtl = tuple(new_defs)
return r
def cleanup_semantics(r, outputs): def cleanup_semantics(r, outputs):
# type: (Rtl, Set[Var]) -> Rtl # type: (Rtl, Set[Var]) -> Rtl
""" """
@@ -176,3 +89,37 @@ def cleanup_semantics(r, outputs):
d.defs[0] not in live)] d.defs[0] not in live)]
return Rtl(*new_defs) return Rtl(*new_defs)
def elaborate(r):
# type: (Rtl) -> Rtl
"""
Given a concrete Rtl r, return a semantically equivalent Rtl r1 containing
only primitive instructions.
"""
fp = False
primitives = set(PRIMITIVES.instructions)
idx = 0
outputs = r.definitions()
while not fp:
assert r.is_concrete()
new_defs = [] # type: List[Def]
fp = True
for d in r.rtl:
inst = d.expr.inst
if (inst not in primitives):
t = find_matching_xform(d)
transformed = t.apply(Rtl(d), str(idx))
idx += 1
new_defs.extend(transformed.rtl)
fp = False
else:
new_defs.append(d)
r.rtl = tuple(new_defs)
return cleanup_semantics(r, outputs)