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:
@@ -656,35 +656,12 @@ load a constant into an SSA value.
|
||||
.. autoinst:: f32const
|
||||
.. autoinst:: f64const
|
||||
.. autoinst:: vconst
|
||||
|
||||
.. inst:: a = select c, x, y
|
||||
|
||||
Conditional select.
|
||||
|
||||
:arg b1 c: Controlling flag.
|
||||
:arg T x: Value to return when ``c`` is true.
|
||||
:arg T y: Value to return when ``c`` is false. Must be same type as ``x``.
|
||||
:result T a: Same type as ``x`` and ``y``.
|
||||
|
||||
This instruction selects whole values. Use :inst:`vselect` for lane-wise
|
||||
selection.
|
||||
.. autoinst:: select
|
||||
|
||||
Vector operations
|
||||
-----------------
|
||||
|
||||
.. inst:: a = vselect c, x, y
|
||||
|
||||
Vector lane select.
|
||||
|
||||
Select lanes from ``x`` or ``y`` controlled by the lanes of the boolean
|
||||
vector ``c``.
|
||||
|
||||
:arg b1xN c: Controlling flag vector.
|
||||
:arg TxN x: Vector with lanes selected by the true lanes of ``c``.
|
||||
Must be a vector type with the same number of lanes as ``c``.
|
||||
:arg TxN y: Vector with lanes selected by the false lanes of ``c``.
|
||||
Must be same type as ``x``.
|
||||
:result TxN a: Same type as ``x`` and ``y``.
|
||||
.. autoinst:: vselect
|
||||
|
||||
.. inst:: a = vbuild x, y, z, ...
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -158,6 +158,11 @@ pub enum InstructionData {
|
||||
second_result: Value,
|
||||
args: [Value; 2],
|
||||
},
|
||||
Select {
|
||||
opcode: Opcode,
|
||||
ty: Type,
|
||||
args: [Value; 3],
|
||||
},
|
||||
Jump {
|
||||
opcode: Opcode,
|
||||
ty: Type,
|
||||
|
||||
@@ -156,6 +156,9 @@ pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result {
|
||||
BinaryImm { opcode, lhs, rhs, .. } => writeln!(w, "{} {}, {}", opcode, lhs, rhs),
|
||||
BinaryImmRev { opcode, lhs, rhs, .. } => writeln!(w, "{} {}, {}", opcode, lhs, rhs),
|
||||
BinaryOverflow { opcode, args, .. } => writeln!(w, "{} {}, {}", opcode, args[0], args[1]),
|
||||
Select { opcode, args, .. } => {
|
||||
writeln!(w, "{} {}, {}, {}", opcode, args[0], args[1], args[2])
|
||||
}
|
||||
Jump { opcode, ref data, .. } => writeln!(w, "{} {}", opcode, data),
|
||||
Branch { opcode, ref data, .. } => writeln!(w, "{} {}", opcode, data),
|
||||
BranchTable { opcode, arg, table, .. } => writeln!(w, "{} {}, {}", opcode, arg, table),
|
||||
|
||||
@@ -668,6 +668,7 @@ impl<'a> Parser<'a> {
|
||||
args: [lhs, rhs],
|
||||
}
|
||||
}
|
||||
InstructionFormat::Select |
|
||||
InstructionFormat::Jump |
|
||||
InstructionFormat::Branch |
|
||||
InstructionFormat::BranchTable |
|
||||
|
||||
Reference in New Issue
Block a user