diff --git a/docs/langref.rst b/docs/langref.rst index 05ebfa9e05..8bf890b080 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -669,37 +669,9 @@ Vector operations Build a vector value from the provided lanes. -.. inst:: a = splat x - - Vector splat. - - Return a vector whose lanes are all ``x``. - - :arg T x: Scalar value to be replicated. - :result TxN a: Vector with identical lanes. - -.. inst:: a = insertlane x, Idx, y - - Insert ``y`` as lane ``Idx`` in x. - - The lane index, ``Idx``, is an immediate value, not an SSA value. It must - indicate a valid lane index for the type of ``x``. - - :arg TxN x: Vector to modify. - :arg Idx: Lane index smaller than N. - :arg T y: New lane value. - :result TxN y: Updated vector. - -.. inst:: a = extractlane x, Idx - - Extract lane ``Idx`` from ``x``. - - The lane index, ``Idx``, is an immediate value, not an SSA value. It must - indicate a valid lane index for the type of ``x``. - - :arg TxN x: Source vector - :arg Idx: Lane index - :result T a: Lane value. +.. autoinst:: splat +.. autoinst:: insertlane +.. autoinst:: extractlane Integer operations ------------------ diff --git a/meta/cretonne/__init__.py b/meta/cretonne/__init__.py index c0eec9e970..9660e9e602 100644 --- a/meta/cretonne/__init__.py +++ b/meta/cretonne/__init__.py @@ -296,7 +296,7 @@ class TypeVar(object): def __str__(self): return "`{}`".format(self.name) - def lane(self): + def lane_of(self): """ Return a derived type variable that is the scalar lane type of this type variable. @@ -304,7 +304,7 @@ class TypeVar(object): When this type variable assumes a scalar type, the derived type will be the same scalar type. """ - return TypeVar(None, None, base=self, derived_func='Lane') + return TypeVar(None, None, base=self, derived_func='LaneOf') def as_bool(self): """ diff --git a/meta/cretonne/base.py b/meta/cretonne/base.py index c28c3724a2..b41225ae00 100644 --- a/meta/cretonne/base.py +++ b/meta/cretonne/base.py @@ -6,7 +6,7 @@ support. """ from . import TypeVar, Operand, Instruction, InstructionGroup, variable_args from types import i8, f32, f64 -from immediates import imm64, ieee32, ieee64, immvector +from immediates import imm64, uimm8, ieee32, ieee64, immvector import entities instructions = InstructionGroup("base", "Shared base instruction set") @@ -17,7 +17,7 @@ Testable = TypeVar( 'Testable', 'A scalar boolean or integer type', ints=True, bools=True) TxN = TypeVar( - '%Tx%N', 'A SIMD vector type', + 'TxN', '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', @@ -177,6 +177,42 @@ vselect = Instruction( vector ``c``. """, ins=(c, x, y), outs=a) + +x = Operand('x', TxN.lane_of()) + +splat = Instruction( + 'splat', r""" + Vector splat. + + Return a vector whose lanes are all ``x``. + """, + ins=x, outs=a) + +x = Operand('x', TxN, doc='SIMD vector to modify') +y = Operand('y', TxN.lane_of(), doc='New lane value') +Idx = Operand('Idx', uimm8, doc='Lane index') + +insertlane = Instruction( + 'insertlane', r""" + Insert ``y`` as lane ``Idx`` in x. + + The lane index, ``Idx``, is an immediate value, not an SSA value. It + must indicate a valid lane index for the type of ``x``. + """, + ins=(x, Idx, y), outs=a) + +x = Operand('x', TxN) +a = Operand('a', TxN.lane_of()) + +extractlane = Instruction( + 'extractlane', r""" + Extract lane ``Idx`` from ``x``. + + The lane index, ``Idx``, is an immediate value, not an SSA value. It + must indicate a valid lane index for the type of ``x``. + """, + ins=(x, Idx), outs=a) + # # Integer arithmetic # diff --git a/meta/cretonne/formats.py b/meta/cretonne/formats.py index 4843befea9..6f09c4b5af 100644 --- a/meta/cretonne/formats.py +++ b/meta/cretonne/formats.py @@ -8,7 +8,7 @@ in this module. from . import InstructionFormat, value, variable_args -from immediates import imm64, ieee32, ieee64, immvector +from immediates import imm64, uimm8, ieee32, ieee64, immvector from entities import ebb, function, jump_table Nullary = InstructionFormat() @@ -30,6 +30,9 @@ BinaryOverflow = InstructionFormat(value, value, multiple_results=True) # The first value operand is the controlling flag whisch has a derived type. Select = InstructionFormat(value, value, value, typevar_operand=1) +InsertLane = InstructionFormat(value, uimm8, value) +ExtractLane = InstructionFormat(value, uimm8) + Jump = InstructionFormat(ebb, variable_args, boxed_storage=True) Branch = InstructionFormat(value, ebb, variable_args, boxed_storage=True) BranchTable = InstructionFormat(value, jump_table) diff --git a/meta/cretonne/immediates.py b/meta/cretonne/immediates.py index e8e581d64d..299b340bce 100644 --- a/meta/cretonne/immediates.py +++ b/meta/cretonne/immediates.py @@ -11,6 +11,12 @@ from . import ImmediateKind #: :py:class:`cretonne.IntType` type. imm64 = ImmediateKind('imm64', 'A 64-bit immediate integer.') +#: An unsigned 8-bit immediate integer operand. +#: +#: This small operand is used to indicate lane indexes in SIMD vectors and +#: immediate bit counts on shift instructions. +uimm8 = ImmediateKind('uimm8', 'An 8-bit immediate unsigned integer.') + #: A 32-bit immediate floating point operand. #: #: IEEE 754-2008 binary32 interchange format. diff --git a/src/libcretonne/instructions.rs b/src/libcretonne/instructions.rs index d1861fb669..338bf3f28b 100644 --- a/src/libcretonne/instructions.rs +++ b/src/libcretonne/instructions.rs @@ -163,6 +163,18 @@ pub enum InstructionData { ty: Type, args: [Value; 3], }, + InsertLane { + opcode: Opcode, + ty: Type, + lane: u8, + args: [Value; 2], + }, + ExtractLane { + opcode: Opcode, + ty: Type, + lane: u8, + arg: Value, + }, Jump { opcode: Opcode, ty: Type, @@ -401,7 +413,7 @@ enum OperandConstraint { Same, /// This operand is `ctrlType.lane_type()`. - Lane, + LaneOf, /// This operand is `ctrlType.as_bool()`. AsBool, @@ -418,7 +430,7 @@ impl OperandConstraint { Concrete(t) => Some(t), Free(_) => None, Same => Some(ctrl_type), - Lane => Some(ctrl_type.lane_type()), + LaneOf => Some(ctrl_type.lane_type()), AsBool => Some(ctrl_type.as_bool()), } } diff --git a/src/libcretonne/write.rs b/src/libcretonne/write.rs index e6eb3a477f..406296c2a3 100644 --- a/src/libcretonne/write.rs +++ b/src/libcretonne/write.rs @@ -159,6 +159,10 @@ pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result { Select { opcode, args, .. } => { writeln!(w, "{} {}, {}, {}", opcode, args[0], args[1], args[2]) } + InsertLane { opcode, lane, args, .. } => { + writeln!(w, "{} {}, {}, {}", opcode, args[0], lane, args[1]) + } + ExtractLane { opcode, lane, arg, .. } => writeln!(w, "{} {}, {}", opcode, arg, lane), 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), diff --git a/src/libreader/parser.rs b/src/libreader/parser.rs index 6aab089330..0344b6238f 100644 --- a/src/libreader/parser.rs +++ b/src/libreader/parser.rs @@ -669,6 +669,8 @@ impl<'a> Parser<'a> { } } InstructionFormat::Select | + InstructionFormat::InsertLane | + InstructionFormat::ExtractLane | InstructionFormat::Jump | InstructionFormat::Branch | InstructionFormat::BranchTable |