Add two new value types: iflags and fflags.

These two value types represent the state of CPU flags after an integer
comparison and a floating point comparison respectively.

Instructions using these types TBD.
This commit is contained in:
Jakob Stoklund Olesen
2017-10-12 12:49:10 -07:00
parent dbaa919ca9
commit 15461c1e4b
8 changed files with 119 additions and 27 deletions

View File

@@ -2,7 +2,7 @@
The base.types module predefines all the Cretonne scalar types.
"""
from __future__ import absolute_import
from cdsl.types import IntType, FloatType, BoolType
from cdsl.types import IntType, FloatType, BoolType, FlagsType
#: Boolean.
b1 = BoolType(1) #: 1-bit bool. Type is abstract (can't be stored in mem)
@@ -31,3 +31,16 @@ f64 = FloatType(
*binary64* interchange format. This corresponds to the :c:type:`double`
type in most C implementations.
""")
#: CPU flags from an integer comparison.
iflags = FlagsType(
'iflags', """
CPU flags representing the result of an integer comparison. These flags
can be tested with an `intcc` condition code.
""")
#: CPU flags from a floating point comparison.
fflags = FlagsType(
'fflags', """
CPU flags representing the result of a floating point comparison. These
flags can be tested with a `floatcc` condition code.
""")

View File

@@ -287,6 +287,22 @@ class BoolType(LaneType):
return self.bits
class FlagsType(SpecialType):
"""
A type representing CPU flags.
Flags can't be stored in memory.
"""
def __init__(self, name, doc):
# type: (str, str) -> None
super(FlagsType, self).__init__(name, 0, doc)
def __repr__(self):
# type: () -> str
return 'FlagsType({})'.format(self.name)
class BVType(ValueType):
"""A flat bitvector type. Used for semantics description only."""

View File

@@ -163,6 +163,9 @@ class TypeSet(object):
>>> TypeSet(lanes=True, ints=True)
TypeSet(lanes={1, 2, 4, 8, 16, 32, 64, 128, 256}, ints={8, 16, 32, 64})
Finally, a type set can contain special types (derived from `SpecialType`)
which can't appear as lane types.
:param lanes: `(min, max)` inclusive range of permitted vector lane counts.
:param ints: `(min, max)` inclusive range of permitted scalar integer
widths.
@@ -172,11 +175,19 @@ class TypeSet(object):
widths.
:param bitvecs : `(min, max)` inclusive range of permitted bitvector
widths.
:param specials: Sequence of speical types to appear in the set.
"""
def __init__(self, lanes=None, ints=None, floats=None, bools=None,
bitvecs=None):
# type: (BoolInterval, BoolInterval, BoolInterval, BoolInterval, BoolInterval) -> None # noqa
def __init__(
self,
lanes=None, # type: BoolInterval
ints=None, # type: BoolInterval
floats=None, # type: BoolInterval
bools=None, # type: BoolInterval
bitvecs=None, # type: BoolInterval
specials=None # type: Iterable[types.SpecialType]
):
# type: (...) -> None
self.lanes = interval_to_set(decode_interval(lanes, (1, MAX_LANES), 1))
self.ints = interval_to_set(decode_interval(ints, (8, MAX_BITS)))
self.floats = interval_to_set(decode_interval(floats, (32, 64)))
@@ -184,6 +195,7 @@ class TypeSet(object):
self.bools = set(filter(legal_bool, self.bools))
self.bitvecs = interval_to_set(decode_interval(bitvecs,
(1, MAX_BITVEC)))
self.specials = set(specials) if specials else set()
def copy(self):
# type: (TypeSet) -> TypeSet
@@ -194,13 +206,14 @@ class TypeSet(object):
return deepcopy(self)
def typeset_key(self):
# type: () -> Tuple[Tuple, Tuple, Tuple, Tuple, Tuple]
# type: () -> Tuple[Tuple, Tuple, Tuple, Tuple, Tuple, Tuple]
"""Key tuple used for hashing and equality."""
return (tuple(sorted(list(self.lanes))),
tuple(sorted(list(self.ints))),
tuple(sorted(list(self.floats))),
tuple(sorted(list(self.bools))),
tuple(sorted(list(self.bitvecs))))
tuple(sorted(list(self.bitvecs))),
tuple(sorted(list(self.specials))))
def __hash__(self):
# type: () -> int
@@ -231,6 +244,8 @@ class TypeSet(object):
s += ', bools={}'.format(pp_set(self.bools))
if len(self.bitvecs) > 0:
s += ', bitvecs={}'.format(pp_set(self.bitvecs))
if len(self.specials) > 0:
s += ', specials=[{}]'.format(pp_set(self.specials))
return s + ')'
def emit_fields(self, fmt):
@@ -273,6 +288,7 @@ class TypeSet(object):
self.floats.intersection_update(other.floats)
self.bools.intersection_update(other.bools)
self.bitvecs.intersection_update(other.bitvecs)
self.specials.intersection_update(other.specials)
return self
@@ -481,8 +497,9 @@ class TypeSet(object):
"""
Return the number of concrete types represented by this typeset
"""
return len(self.lanes) * (len(self.ints) + len(self.floats) +
len(self.bools) + len(self.bitvecs))
return (len(self.lanes) * (len(self.ints) + len(self.floats) +
len(self.bools) + len(self.bitvecs)) +
len(self.specials))
def concrete_types(self):
# type: () -> Iterable[types.ValueType]
@@ -504,6 +521,9 @@ class TypeSet(object):
assert nlanes == 1
yield types.BVType.with_bits(bits)
for spec in self.specials:
yield spec
def get_singleton(self):
# type: () -> types.ValueType
"""
@@ -545,11 +565,20 @@ class TypeVar(object):
"""
def __init__(
self, name, doc,
ints=False, floats=False, bools=False,
scalars=True, simd=False, bitvecs=False,
base=None, derived_func=None):
# type: (str, str, BoolInterval, BoolInterval, BoolInterval, bool, BoolInterval, BoolInterval, TypeVar, str) -> None # noqa
self,
name, # type: str
doc, # type: str
ints=False, # type: BoolInterval
floats=False, # type: BoolInterval
bools=False, # type: BoolInterval
scalars=True, # type: bool
simd=False, # type: BoolInterval
bitvecs=False, # type: BoolInterval
base=None, # type: TypeVar
derived_func=None, # type: str
specials=None # type: Iterable[types.SpecialType]
):
# type: (...) -> None
self.name = name
self.__doc__ = doc
self.is_derived = isinstance(base, TypeVar)
@@ -567,7 +596,8 @@ class TypeVar(object):
ints=ints,
floats=floats,
bools=bools,
bitvecs=bitvecs)
bitvecs=bitvecs,
specials=specials)
@staticmethod
def singleton(typ):
@@ -580,6 +610,8 @@ class TypeVar(object):
elif isinstance(typ, types.LaneType):
scalar = typ
lanes = (1, 1)
elif isinstance(typ, types.SpecialType):
return TypeVar(typ.name, typ.__doc__, specials=[typ])
else:
assert isinstance(typ, types.BVType)
scalar = typ
@@ -681,6 +713,8 @@ class TypeVar(object):
# Safety checks to avoid over/underflows.
ts = base.get_typeset()
assert len(ts.specials) == 0, "Can't derive from special types"
if derived_func == TypeVar.HALFWIDTH:
if len(ts.ints) > 0:
assert min(ts.ints) > 8, "Can't halve all integer types"

View File

@@ -45,6 +45,8 @@ def emit_vectors(bits, fmt):
def emit_types(fmt):
# type: (srcgen.Formatter) -> None
for spec in ValueType.all_special_types:
emit_type(spec, fmt)
for ty in ValueType.all_lane_types:
emit_type(ty, fmt)
# Emit vector definitions for common SIMD sizes.