diff --git a/lib/cretonne/meta/check.sh b/lib/cretonne/meta/check.sh index e1e8b1f0b2..b0a6c853db 100755 --- a/lib/cretonne/meta/check.sh +++ b/lib/cretonne/meta/check.sh @@ -2,9 +2,6 @@ set -e cd $(dirname "$0") -echo "=== Python unit tests ===" -python -m unittest discover - runif() { if command -v "$1" > /dev/null; then echo "=== $1 ===" @@ -19,13 +16,17 @@ runif() { # Install pylint with 'pip install pylint'. runif pylint --py3k --reports=no -- *.py cretonne isa -# Then run the unit tests again with Python 3. -# We get deprecation warnings about assertRaisesRegexp which was renamed in -# Python 3, but there doesn't seem to be an easy workaround. -runif python3 -Wignore:Deprecation -m unittest discover - # Style linting. runif flake8 . # Type checking. runif mypy --py2 build.py + +echo "=== Python unit tests ===" +python -m unittest discover + +# Then run the unit tests again with Python 3. +# We get deprecation warnings about assertRaisesRegexp which was renamed in +# Python 3, but there doesn't seem to be an easy workaround. +runif python3 -Wignore:Deprecation -m unittest discover + diff --git a/lib/cretonne/meta/cretonne/ast.py b/lib/cretonne/meta/cretonne/ast.py index 693a0b5a2b..a43ddfadcb 100644 --- a/lib/cretonne/meta/cretonne/ast.py +++ b/lib/cretonne/meta/cretonne/ast.py @@ -73,6 +73,24 @@ class Expr(object): class Var(Expr): """ A free variable. + + When variables are used in `XForms` with source ans destination patterns, + they are classified as follows: + + Input values + Uses in the source pattern with no preceding def. These may appear as + inputs in the destination pattern too, but no new inputs can be + introduced. + Output values + Variables that are defined in both the source and destination pattern. + These values may have uses outside the source pattern, and the + destination pattern must compute the same value. + Intermediate values + Values that are defined in the source pattern, but not in the + destination pattern. These may have uses outside the source pattern, so + the defining instruction can't be deleted immediately. + Temporary values + Values that are defined only in the destination pattern. """ def __init__(self, name): @@ -82,15 +100,42 @@ class Var(Expr): # See XForm._rewrite_defs(). self.defctx = 0 + # Context bits for `defctx` indicating which pattern has defines of this + # var. + SRCCTX = 1 + DSTCTX = 2 + def __str__(self): + # type: () -> str return self.name def __repr__(self): + # type: () -> str s = self.name if self.defctx: s += ", d={:02b}".format(self.defctx) return "Var({})".format(s) + def is_input(self): + # type: () -> bool + """Is this an input value to the source pattern?""" + return self.defctx == 0 + + def is_output(self): + """Is this an output value, defined in both src and dest patterns?""" + # type: () -> bool + return self.defctx == self.SRCCTX | self.DSTCTX + + def is_intermediate(self): + """Is this an intermediate value, defined only in the src pattern?""" + # type: () -> bool + return self.defctx == self.SRCCTX + + def is_temp(self): + """Is this a temp value, defined only in the dest pattern?""" + # type: () -> bool + return self.defctx == self.DSTCTX + class Apply(Expr): """ diff --git a/lib/cretonne/meta/cretonne/legalize.py b/lib/cretonne/meta/cretonne/legalize.py index 21073d0aec..8dfa2e6b97 100644 --- a/lib/cretonne/meta/cretonne/legalize.py +++ b/lib/cretonne/meta/cretonne/legalize.py @@ -114,5 +114,5 @@ expand.legalize( Rtl( (a1, b1) << isub_bout(x, y), (a, b2) << isub_bout(a1, b_in), - c << bor(b1, b2) + b << bor(b1, b2) )) diff --git a/lib/cretonne/meta/cretonne/xform.py b/lib/cretonne/meta/cretonne/xform.py index 5149c02991..2888b9c26c 100644 --- a/lib/cretonne/meta/cretonne/xform.py +++ b/lib/cretonne/meta/cretonne/xform.py @@ -11,10 +11,6 @@ except ImportError: pass -SRCCTX = 1 -DSTCTX = 2 - - def canonicalize_defapply(node): # type: (DefApply) -> Def """ @@ -87,13 +83,13 @@ class XForm(object): # Rewrite variables in src and dst RTL lists to our own copies. # Map name -> private Var. symtab = dict() # type: Dict[str, Var] - self._rewrite_rtl(src, symtab, SRCCTX) + self._rewrite_rtl(src, symtab, Var.SRCCTX) num_src_inputs = len(self.inputs) - self._rewrite_rtl(dst, symtab, DSTCTX) + self._rewrite_rtl(dst, symtab, Var.DSTCTX) # Check for inconsistently used inputs. for i in self.inputs: - if i.defctx: + if not i.is_input(): raise AssertionError( "'{}' used as both input and def".format(i)) @@ -189,6 +185,22 @@ class XForm(object): self.inputs.append(var) yield var + def verify_legalize(self): + # type: () -> None + """ + Verify that this is a valid legalization XForm. + + - The source pattern must describe a single instruction. + - All values defined in the output pattern must be defined in the + destination pattern. + """ + assert len(self.src.rtl) == 1, "Legalize needs single instruction." + defs, expr = self.src.rtl[0].defs_expr() + for d in defs: + if not d.is_output(): + raise AssertionError( + '{} not defined in dest pattern'.format(d)) + class XFormGroup(object): """ @@ -209,4 +221,6 @@ class XFormGroup(object): :param src: Single `Def` or `Apply` to be legalized. :param dst: `Rtl` list of replacement instructions. """ - self.xforms.append(XForm(Rtl(src), dst)) + xform = XForm(Rtl(src), dst) + xform.verify_legalize() + self.xforms.append(xform) diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 0fdfc921af..2a2387723f 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -14,7 +14,7 @@ from cretonne.ast import Def, Apply # noqa from cretonne.xform import XForm, XFormGroup # noqa try: - from typing import Union # noqa + from typing import Union DefApply = Union[Def, Apply] except ImportError: pass