Classify Vars in patterns.

There's 4 classes of variables, depending on whether they have defs in
the source and destination patterns.

Add more XForm verification: In a legalize XForm, all source defs must
be outputs.

Fix a legalize pattern bug caught by this.
This commit is contained in:
Jakob Stoklund Olesen
2016-11-01 16:10:38 -07:00
parent 88cbd5a43b
commit 1ba8e9e05b
5 changed files with 78 additions and 18 deletions

View File

@@ -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

View File

@@ -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):
"""

View File

@@ -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)
))

View File

@@ -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)

View File

@@ -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