From b7634ae5c323fb93e5e6b1a97bda5e67070eeecb Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 1 Nov 2016 11:55:07 -0700 Subject: [PATCH] Run unittests with Python 3 if it is available. The check.sh script always runs the Python unittests with 'python', but if 'python3' is in the path, run it with that too. Fix a Python 3 compat issue and avoid passing None to max() and min(). Use an explicit intersect() function instead to intersect intervals. --- lib/cretonne/meta/check.sh | 9 +++++ lib/cretonne/meta/cretonne/base.py | 6 +-- lib/cretonne/meta/cretonne/typevar.py | 55 +++++++++++++++++++-------- 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/lib/cretonne/meta/check.sh b/lib/cretonne/meta/check.sh index 072066ebec..e1e8b1f0b2 100755 --- a/lib/cretonne/meta/check.sh +++ b/lib/cretonne/meta/check.sh @@ -18,5 +18,14 @@ 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 diff --git a/lib/cretonne/meta/cretonne/base.py b/lib/cretonne/meta/cretonne/base.py index 27a8be9ac6..670d85cc0c 100644 --- a/lib/cretonne/meta/cretonne/base.py +++ b/lib/cretonne/meta/cretonne/base.py @@ -392,9 +392,9 @@ srem = Instruction( .. todo:: Integer remainder vs modulus. - Clarify whether the result has the sign of the divisor or the dividend. - Should we add a ``smod`` instruction for the case where the result has - the same sign as the divisor? + Clarify whether the result has the sign of the divisor or the + dividend. Should we add a ``smod`` instruction for the case where + the result has the same sign as the divisor? """, ins=(x, y), outs=a) diff --git a/lib/cretonne/meta/cretonne/typevar.py b/lib/cretonne/meta/cretonne/typevar.py index a29548af38..f4b227fd7e 100644 --- a/lib/cretonne/meta/cretonne/typevar.py +++ b/lib/cretonne/meta/cretonne/typevar.py @@ -8,19 +8,45 @@ from __future__ import absolute_import import math from . import value +try: + from typing import Tuple # noqa + Interval = Tuple[int, int] +except ImportError: + pass MAX_LANES = 256 MAX_BITS = 64 def is_power_of_two(x): + # type: (int) -> bool return x > 0 and x & (x-1) == 0 def int_log2(x): + # type: (int) -> int return int(math.log(x, 2)) +def intersect(a, b): + # type: (Interval, Interval) -> Interval + """ + Given two `(min, max)` inclusive intervals, compute their intersection. + + Use `(None, None)` to represent the empty interval on input and output. + """ + if a[0] is None or b[0] is None: + return (None, None) + lo = max(a[0], b[0]) + assert lo is not None + hi = min(a[1], b[1]) + assert hi is not None + if lo <= hi: + return (lo, hi) + else: + return (None, None) + + class TypeSet(object): """ A set of types. @@ -69,6 +95,7 @@ class TypeSet(object): """ def __init__(self, lanes=None, ints=None, floats=None, bools=None): + # type: (Interval, Interval, Interval, Interval) -> None if lanes: if lanes is True: lanes = (1, MAX_LANES) @@ -119,6 +146,7 @@ class TypeSet(object): self.max_bool = None def typeset_key(self): + # type: () -> Tuple[int, int, int, int, int, int, int, int] """Key tuple used for hashing and equality.""" return (self.min_lanes, self.max_lanes, self.min_int, self.max_int, @@ -126,6 +154,7 @@ class TypeSet(object): self.min_bool, self.max_bool) def __hash__(self): + # type: () -> int h = hash(self.typeset_key()) assert h == getattr(self, 'prev_hash', h), "TypeSet changed!" self.prev_hash = h @@ -135,6 +164,7 @@ class TypeSet(object): return self.typeset_key() == other.typeset_key() def __repr__(self): + # type: () -> str s = 'TypeSet(lanes=({}, {})'.format(self.min_lanes, self.max_lanes) if self.min_int is not None: s += ', ints=({}, {})'.format(self.min_int, self.max_int) @@ -161,6 +191,7 @@ class TypeSet(object): field, int_log2(max_val) + 1)) def __iand__(self, other): + # type: (TypeSet) -> TypeSet """ Intersect self with other type set. @@ -181,23 +212,17 @@ class TypeSet(object): self.min_lanes = max(self.min_lanes, other.min_lanes) self.max_lanes = min(self.max_lanes, other.max_lanes) - self.min_int = max(self.min_int, other.min_int) - self.max_int = min(self.max_int, other.max_int) - if self.min_int > self.max_int: - self.min_int = None - self.max_int = None + self.min_int, self.max_int = intersect( + (self.min_int, self.max_int), + (other.min_int, other.max_int)) - self.min_float = max(self.min_float, other.min_float) - self.max_float = min(self.max_float, other.max_float) - if self.min_float > self.max_float: - self.min_float = None - self.max_float = None + self.min_float, self.max_float = intersect( + (self.min_float, self.max_float), + (other.min_float, other.max_float)) - self.min_bool = max(self.min_bool, other.min_bool) - self.max_bool = min(self.max_bool, other.max_bool) - if self.min_bool > self.max_bool: - self.min_bool = None - self.max_bool = None + self.min_bool, self.max_bool = intersect( + (self.min_bool, self.max_bool), + (other.min_bool, other.max_bool)) return self