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:
Jakob Stoklund Olesen
2016-05-20 15:10:31 -07:00
parent 692a85d720
commit b44d6c6541
7 changed files with 60 additions and 35 deletions

View File

@@ -656,35 +656,12 @@ load a constant into an SSA value.
.. autoinst:: f32const .. autoinst:: f32const
.. autoinst:: f64const .. autoinst:: f64const
.. autoinst:: vconst .. autoinst:: vconst
.. autoinst:: select
.. 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.
Vector operations Vector operations
----------------- -----------------
.. inst:: a = vselect c, x, y .. autoinst:: vselect
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``.
.. inst:: a = vbuild x, y, z, ... .. inst:: a = vbuild x, y, z, ...

View File

@@ -283,6 +283,7 @@ class TypeVar(object):
if self.is_derived: if self.is_derived:
assert derived_func assert derived_func
self.derived_func = derived_func self.derived_func = derived_func
self.name = '{}({})'.format(derived_func, base.name)
else: else:
self.type_set = TypeSet( self.type_set = TypeSet(
allow_scalars=scalars, allow_scalars=scalars,
@@ -303,18 +304,14 @@ class TypeVar(object):
When this type variable assumes a scalar type, the derived type will be When this type variable assumes a scalar type, the derived type will be
the same scalar type. the same scalar type.
""" """
return TypeVar( return TypeVar(None, None, base=self, derived_func='Lane')
"Lane type of " + self.name, '',
base=self, derived_func='Lane')
def as_bool(self): def as_bool(self):
""" """
Return a derived type variable that has the same vector geometry as Return a derived type variable that has the same vector geometry as
this type variable, but with boolean lanes. Scalar types map to `b1`. this type variable, but with boolean lanes. Scalar types map to `b1`.
""" """
return TypeVar( return TypeVar(None, None, base=self, derived_func='AsBool')
self.name + " as boolean", '',
base=self, derived_func='AsBool')
def operand_kind(self): def operand_kind(self):
# When a `TypeVar` object is used to describe the type of an `Operand` # 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. # No other derived typevars allowed.
if typ is not tv: if typ is not tv:
raise RuntimeError( raise RuntimeError(
"type variable {} must not be derived from {}" "{}: type variable {} must be derived from {}"
.format(typ.name, tv.name)) .format(self.ins[opidx], typ.name, ctrl_typevar))
# Other free type variables can only be used once each. # Other free type variables can only be used once each.
if tv in other_tvs: if tv in other_tvs:
raise RuntimeError( raise RuntimeError(

View File

@@ -19,6 +19,9 @@ Testable = TypeVar(
TxN = TypeVar( TxN = TypeVar(
'%Tx%N', 'A SIMD vector type', '%Tx%N', 'A SIMD vector type',
ints=True, floats=True, bools=True, scalars=False, simd=True) 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 # Control flow
@@ -140,6 +143,41 @@ vconst = Instruction(
ins=N, outs=a) 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 # Integer arithmetic
# #

View File

@@ -26,6 +26,10 @@ BinaryImmRev = InstructionFormat(imm64, value)
# Generate result + overflow flag. # Generate result + overflow flag.
BinaryOverflow = InstructionFormat(value, value, multiple_results=True) 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) Jump = InstructionFormat(ebb, variable_args, boxed_storage=True)
Branch = InstructionFormat(value, ebb, variable_args, boxed_storage=True) Branch = InstructionFormat(value, ebb, variable_args, boxed_storage=True)
BranchTable = InstructionFormat(value, jump_table) BranchTable = InstructionFormat(value, jump_table)

View File

@@ -158,6 +158,11 @@ pub enum InstructionData {
second_result: Value, second_result: Value,
args: [Value; 2], args: [Value; 2],
}, },
Select {
opcode: Opcode,
ty: Type,
args: [Value; 3],
},
Jump { Jump {
opcode: Opcode, opcode: Opcode,
ty: Type, ty: Type,
@@ -295,13 +300,13 @@ impl InstructionData {
/// ///
/// Bits 4-7: /// Bits 4-7:
/// Permitted set of types for the controlling type variable as an index into `TYPE_SETS`. /// Permitted set of types for the controlling type variable as an index into `TYPE_SETS`.
/// ///
/// Bits 8-15: /// Bits 8-15:
/// Offset into `OPERAND_CONSTRAINT` table of the descriptors for this opcode. The first /// Offset into `OPERAND_CONSTRAINT` table of the descriptors for this opcode. The first
/// `fixed_results()` entries describe the result constraints, then follows constraints for the /// `fixed_results()` entries describe the result constraints, then follows constraints for the
/// fixed `Value` input operands. The number of `Value` inputs isdetermined by the instruction /// fixed `Value` input operands. The number of `Value` inputs isdetermined by the instruction
/// format. /// format.
/// ///
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct OpcodeConstraints(u16); pub struct OpcodeConstraints(u16);

View File

@@ -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), BinaryImm { opcode, lhs, rhs, .. } => writeln!(w, "{} {}, {}", opcode, lhs, rhs),
BinaryImmRev { 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]), 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), Jump { opcode, ref data, .. } => writeln!(w, "{} {}", opcode, data),
Branch { opcode, ref data, .. } => writeln!(w, "{} {}", opcode, data), Branch { opcode, ref data, .. } => writeln!(w, "{} {}", opcode, data),
BranchTable { opcode, arg, table, .. } => writeln!(w, "{} {}, {}", opcode, arg, table), BranchTable { opcode, arg, table, .. } => writeln!(w, "{} {}, {}", opcode, arg, table),

View File

@@ -668,6 +668,7 @@ impl<'a> Parser<'a> {
args: [lhs, rhs], args: [lhs, rhs],
} }
} }
InstructionFormat::Select |
InstructionFormat::Jump | InstructionFormat::Jump |
InstructionFormat::Branch | InstructionFormat::Branch |
InstructionFormat::BranchTable | InstructionFormat::BranchTable |