blob: 756673e819570b465e86c3e3dd7c202963b694bb [file]
// VMVX (Virtual Machine-based Vector eXtensions) runtime module imports.
//
// This is embedded in the compiler binary and inserted into any module
// containing VMVX dialect ops (vmvx.*) that is lowered to the VM dialect.
//
// Element types are embedded in the function. The convention used (mostly)
// follows MLIR type names:
// * 'x' : don't-care, bit-depth only.
// * 'i' : signless integer (+ bit depth) ex: i1 i8 i16 i32 i64
// * 'si': signed integer (+ bit depth) ex: si32 ...
// * 'ui': unsigned integer (+ bit depth) ex: ui32 ...
// * 'f' : IREE float (+ bit depth) ex: f32 f64
//
// See the README.md for more more details on the implementation.
//
// NOTE: each method added here requires a corresponding method in
// `iree/modules/vmvx/exports.inl` and `iree/modules/vmvx/module.c`.
//
// NOTE: there's a maintenance burden to adding new ops as they may have to be
// carried around forever. Always try to convert to the ops that exist unless
// it's performance critical - a few lines of a conversion pattern saves future
// us a lot of pain and breaking changes.
//
// NOTE: experimental functions that are not yet ready to be parts of the core
// module must be prefixed with `ex.` like `vmvx.ex.my_test_op`.
vm.module @vmvx {
//===----------------------------------------------------------------------===//
// VMVX Binary Elementwise Kernels
// Each is specialized by opcode, rank and type width.
//===----------------------------------------------------------------------===//
vm.import private @add.2d.f32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @add.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @and.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @div.2d.f32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @divs.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @divu.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @mul.2d.f32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @mul.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @or.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @shl.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @shrs.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @shru.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @sub.2d.f32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @sub.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @xor.2d.i32(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_strides : tuple<i64, i64>,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
//===----------------------------------------------------------------------===//
// VMVX Unary Elementwise Kernels
// Each is specialized by opcode, rank and type width.
//===----------------------------------------------------------------------===//
vm.import private @abs.2d.f32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @ceil.2d.f32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @ctlz.2d.i32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @exp.2d.f32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @floor.2d.f32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @log.2d.f32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @neg.2d.f32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @rsqrt.2d.f32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
//==============================================================================
// Strided copy ops
// Variants of copy ops exist for power of two rank and datatype sizes.
// Current max rank is 2d.
//==============================================================================
vm.import private @copy.2d.x8(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @copy.2d.x16(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @copy.2d.x32(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
vm.import private @copy.2d.x64(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_strides : tuple<i64, i64>,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_strides : tuple<i64, i64>,
%sizes : tuple<i64, i64>
)
//==============================================================================
// Strided fill ops
//==============================================================================
vm.import private @fill.2d.x32(
%fill_value : i32,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_row_stride : i64,
%size_m : i64,
%size_n : i64
)
//==============================================================================
// mmt4d ops
//==============================================================================
vm.import private @mmt4d(
%lhs_buffer : !vm.buffer,
%lhs_offset : i64,
%lhs_row_stride : i64,
%rhs_buffer : !vm.buffer,
%rhs_offset : i64,
%rhs_row_stride : i64,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_row_stride : i64,
%m : i64,
%n : i64,
%k : i64,
%m0 : i32,
%n0 : i32,
%k0 : i32,
%flags : i32
)
//==============================================================================
// pack ops
//==============================================================================
vm.import private @pack(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_stride0 : i64,
%in_stride1 : i64,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_stride0 : i64,
%out_stride1 : i64,
%in_size0 : i64,
%in_size1 : i64,
%out_size0 : i64,
%out_size1 : i64,
%out_size2 : i64,
%out_size3 : i64,
%padding_value : i64,
%flags : i32
)
//==============================================================================
// unpack ops
//==============================================================================
vm.import private @unpack(
%in_buffer : !vm.buffer,
%in_offset : i64,
%in_stride0 : i64,
%in_stride1 : i64,
%out_buffer : !vm.buffer,
%out_offset : i64,
%out_stride0 : i64,
%out_stride1 : i64,
%in_size0 : i64,
%in_size1 : i64,
%in_size2 : i64,
%in_size3 : i64,
%out_size0 : i64,
%out_size1 : i64,
%flags : i32
)
//==============================================================================
// query_tile_size ops
//==============================================================================
vm.import private @query_tile_sizes.2d(
%size0 : i64,
%size1 : i64,
%flags : i32
) -> (i64, i64)
} // module