Implement select and vselect instructions.
This gives us the opportunity to use the AsBool derived type variables and a Select instruction format with a non-default typevar_operand setting.
This commit is contained in:
@@ -283,6 +283,7 @@ class TypeVar(object):
|
||||
if self.is_derived:
|
||||
assert derived_func
|
||||
self.derived_func = derived_func
|
||||
self.name = '{}({})'.format(derived_func, base.name)
|
||||
else:
|
||||
self.type_set = TypeSet(
|
||||
allow_scalars=scalars,
|
||||
@@ -303,18 +304,14 @@ class TypeVar(object):
|
||||
When this type variable assumes a scalar type, the derived type will be
|
||||
the same scalar type.
|
||||
"""
|
||||
return TypeVar(
|
||||
"Lane type of " + self.name, '',
|
||||
base=self, derived_func='Lane')
|
||||
return TypeVar(None, None, base=self, derived_func='Lane')
|
||||
|
||||
def as_bool(self):
|
||||
"""
|
||||
Return a derived type variable that has the same vector geometry as
|
||||
this type variable, but with boolean lanes. Scalar types map to `b1`.
|
||||
"""
|
||||
return TypeVar(
|
||||
self.name + " as boolean", '',
|
||||
base=self, derived_func='AsBool')
|
||||
return TypeVar(None, None, base=self, derived_func='AsBool')
|
||||
|
||||
def operand_kind(self):
|
||||
# When a `TypeVar` object is used to describe the type of an `Operand`
|
||||
@@ -607,8 +604,8 @@ class Instruction(object):
|
||||
# No other derived typevars allowed.
|
||||
if typ is not tv:
|
||||
raise RuntimeError(
|
||||
"type variable {} must not be derived from {}"
|
||||
.format(typ.name, tv.name))
|
||||
"{}: type variable {} must be derived from {}"
|
||||
.format(self.ins[opidx], typ.name, ctrl_typevar))
|
||||
# Other free type variables can only be used once each.
|
||||
if tv in other_tvs:
|
||||
raise RuntimeError(
|
||||
|
||||
@@ -19,6 +19,9 @@ Testable = TypeVar(
|
||||
TxN = TypeVar(
|
||||
'%Tx%N', 'A SIMD vector type',
|
||||
ints=True, floats=True, bools=True, scalars=False, simd=True)
|
||||
Any = TypeVar(
|
||||
'Any', 'Any integer, float, or boolean scalar or vector type',
|
||||
ints=True, floats=True, bools=True, scalars=True, simd=True)
|
||||
|
||||
#
|
||||
# Control flow
|
||||
@@ -140,6 +143,41 @@ vconst = Instruction(
|
||||
ins=N, outs=a)
|
||||
|
||||
#
|
||||
# Generics.
|
||||
#
|
||||
|
||||
c = Operand('c', Testable, doc='Controlling value to test')
|
||||
x = Operand('x', Any, doc='Value to use when `c` is true')
|
||||
y = Operand('y', Any, doc='Value to use when `c` is false')
|
||||
a = Operand('a', Any)
|
||||
|
||||
select = Instruction(
|
||||
'select', r"""
|
||||
Conditional select.
|
||||
|
||||
This instruction selects whole values. Use :inst:`vselect` for
|
||||
lane-wise selection.
|
||||
""",
|
||||
ins=(c, x, y), outs=a)
|
||||
|
||||
#
|
||||
# Vector operations
|
||||
#
|
||||
|
||||
c = Operand('c', TxN.as_bool(), doc='Controlling vector')
|
||||
x = Operand('x', TxN, doc='Value to use where `c` is true')
|
||||
y = Operand('y', TxN, doc='Value to use where `c` is false')
|
||||
a = Operand('a', TxN)
|
||||
|
||||
vselect = Instruction(
|
||||
'vselect', r"""
|
||||
Vector lane select.
|
||||
|
||||
Select lanes from ``x`` or ``y`` controlled by the lanes of the boolean
|
||||
vector ``c``.
|
||||
""",
|
||||
ins=(c, x, y), outs=a)
|
||||
#
|
||||
# Integer arithmetic
|
||||
#
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@ BinaryImmRev = InstructionFormat(imm64, value)
|
||||
# Generate result + overflow flag.
|
||||
BinaryOverflow = InstructionFormat(value, value, multiple_results=True)
|
||||
|
||||
# The select instructions are controlled by the second value operand.
|
||||
# The first value operand is the controlling flag whisch has a derived type.
|
||||
Select = InstructionFormat(value, value, value, typevar_operand=1)
|
||||
|
||||
Jump = InstructionFormat(ebb, variable_args, boxed_storage=True)
|
||||
Branch = InstructionFormat(value, ebb, variable_args, boxed_storage=True)
|
||||
BranchTable = InstructionFormat(value, jump_table)
|
||||
|
||||
Reference in New Issue
Block a user