From a1e9a350f3e1488485bd02f003d9820d2e0dc353 Mon Sep 17 00:00:00 2001 From: Quinn Dawkins Date: Tue, 26 Dec 2023 13:56:17 -0500 Subject: [PATCH 1/3] Add vm.buffer.hash and util.buffer.hash ops This adds support for computing the SipHash24 of a byte range of a buffer, with the goal of using this as a primitive for building a hash table out of VM IR. --- .../iree/compiler/Dialect/Util/IR/UtilOps.cpp | 19 +++++ .../iree/compiler/Dialect/Util/IR/UtilOps.td | 34 ++++++++ .../Dialect/Util/IR/test/buffer_ops.mlir | 11 +++ .../Conversion/UtilToVM/ConvertBufferOps.cpp | 20 ++++- .../Conversion/UtilToVM/test/buffer_ops.mlir | 17 ++++ .../Conversion/VMToEmitC/ConvertVMToEmitC.cpp | 2 + .../Conversion/VMToEmitC/test/buffer_ops.mlir | 13 +++ .../compiler/Dialect/VM/IR/VMOpcodesCore.td | 4 +- .../src/iree/compiler/Dialect/VM/IR/VMOps.td | 32 +++++++ runtime/src/iree/vm/BUILD.bazel | 1 + runtime/src/iree/vm/CMakeLists.txt | 1 + runtime/src/iree/vm/buffer.c | 85 +++++++++++++++++++ runtime/src/iree/vm/buffer.h | 6 ++ runtime/src/iree/vm/bytecode/disassembler.c | 21 +++++ runtime/src/iree/vm/bytecode/dispatch.c | 18 ++++ .../vm/bytecode/utils/generated/op_table.h | 4 +- runtime/src/iree/vm/bytecode/verifier.c | 6 ++ runtime/src/iree/vm/test/buffer_ops.mlir | 36 ++++++++ 18 files changed, 326 insertions(+), 4 deletions(-) diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp index 6cebbb989095..216e2a34059d 100644 --- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp +++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.cpp @@ -1506,6 +1506,25 @@ void BufferStoreOp::setSubrangeOperand(unsigned operandIndex, getLengthMutable().assign(operand.length); } +SubrangeOperand BufferHashOp::getSubrangeOperand(unsigned operandIndex) { + if (operandIndex == 0) { + return SubrangeOperand{getSource(), getSourceSize(), getSourceOffset(), + getLength()}; + } else { + assert(false && "only source is a subrange"); + return {}; + } +} + +void BufferHashOp::setSubrangeOperand(unsigned operandIndex, + SubrangeOperand operand) { + assert(operandIndex == 0 && "only source is a subrange"); + getSourceMutable().assign(operand.resource); + getSourceSizeMutable().assign(operand.resourceSize); + getSourceOffsetMutable().assign(operand.offset); + getLengthMutable().assign(operand.length); +} + } // namespace mlir::iree_compiler::IREE::Util #define GET_OP_CLASSES diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td index 919dfd6bd941..ab2c669ef687 100644 --- a/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td +++ b/compiler/src/iree/compiler/Dialect/Util/IR/UtilOps.td @@ -1341,6 +1341,40 @@ def Util_BufferStoreOp : Util_Op<"buffer.store", [ }]; } +def Util_BufferHashOp : Util_Op<"buffer.hash", [ + MemoryEffects<[MemRead]>, + Util_SizeAwareOp, + DeclareOpInterfaceMethods, +]> { + let summary = [{computes the hash of a byte range of a buffer}]; + let description = [{ + Computes the SipHash-2-4 of a value at a byte offset with the given length. + This always uses a seed of `0x0001020304...0e0f` and produces a single 64 + bit value. + }]; + + let arguments = (ins + Util_BufferType:$source, + Util_Size:$source_size, + Util_Offset:$source_offset, + Util_Size:$length + ); + let results = (outs + I64:$result + ); + + let assemblyFormat = [{ + $source `[` $source_offset `for` $length `]` + `:` type($source) `` `{` $source_size `}` `->` type($result) + attr-dict-with-keyword + }]; + + let extraClassDeclaration = [{ + Value getOperandSize(unsigned idx) { return getSourceSize(); } + Value getResultSize(unsigned idx) { return {}; } + }]; +} + } // OpGroupBufferOps //===----------------------------------------------------------------------===// diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir b/compiler/src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir index 1f36809b6e8e..3c37c62d7b5f 100644 --- a/compiler/src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir +++ b/compiler/src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir @@ -126,3 +126,14 @@ func.func @buffer_store(%arg0: !util.buffer, %arg1: index, %arg2: i32) { util.buffer.store %arg2, %arg0[%c100 for %c4] : i32 -> !util.buffer{%arg1} return } + +// ----- + +// CHECK-LABEL: @buffer_hash +func.func @buffer_hash(%arg0: !util.buffer, %arg1: index) -> i64 { + %c17 = arith.constant 17 : index + %c100 = arith.constant 100 : index + // CHECK: = util.buffer.hash %arg0[%c100 for %c17] : !util.buffer{%arg1} -> i64 + %0 = util.buffer.hash %arg0[%c100 for %c17] : !util.buffer{%arg1} -> i64 + return %0 : i64 +} \ No newline at end of file diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp index 8c27824cad89..55671a1368c5 100644 --- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp +++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/ConvertBufferOps.cpp @@ -318,6 +318,22 @@ struct BufferStoreOpConversion } }; +struct BufferHashOpConversion + : public OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(IREE::Util::BufferHashOp hashOp, OpAdaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + auto newType = + getTypeConverter()->convertType(hashOp.getResult().getType()); + auto byteOffset = castToI64(adaptor.getSourceOffset(), rewriter); + auto length = castToI64(adaptor.getLength(), rewriter); + rewriter.replaceOpWithNewOp( + hashOp, newType, adaptor.getSource(), byteOffset, length); + return success(); + } +}; + } // namespace void populateUtilBufferToVMPatterns(MLIRContext *context, @@ -341,7 +357,8 @@ void populateUtilBufferToVMPatterns(MLIRContext *context, IREE::Util::BufferDeallocOp, IREE::Util::BufferSliceOp, IREE::Util::BufferSizeOp, IREE::Util::BufferCopyOp, IREE::Util::BufferCompareOp, IREE::Util::BufferFillOp, - IREE::Util::BufferLoadOp, IREE::Util::BufferStoreOp>(); + IREE::Util::BufferLoadOp, IREE::Util::BufferStoreOp, + IREE::Util::BufferHashOp>(); patterns.insert(typeConverter, context); patterns.insert(typeConverter, context); @@ -353,6 +370,7 @@ void populateUtilBufferToVMPatterns(MLIRContext *context, patterns.insert(typeConverter, context); patterns.insert(typeConverter, context); patterns.insert(typeConverter, context); + patterns.insert(typeConverter, context); } } // namespace mlir::iree_compiler diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir index ac7ef7e8d13e..6de0ad23d145 100644 --- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir +++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir @@ -295,3 +295,20 @@ func.func @buffer_store_index(%arg0: !util.buffer, %arg1: index, %arg2: index) { util.buffer.store %arg2, %arg0[%byte_offset for %element_size] : index -> !util.buffer{%arg1} return } + +// ----- + +// CHECK-LABEL: @buffer_hash +func.func @buffer_hash(%arg0: !util.buffer, %arg1: index) -> i64 { + %byte_offset = arith.constant 128 : index + %length = arith.constant 17 : index + // CHECK-32-DAG: %[[BYTE_OFFSET:.+]] = vm.const.i64 128 + // CHECK-32-DAG: %[[LENGTH:.+]] = vm.const.i64 17 + // CHECK-32: %[[VALUE:.+]] = vm.buffer.hash %arg0, %[[BYTE_OFFSET]], %[[LENGTH]] : !vm.buffer -> i64 + // CHECK-64-DAG: %[[BYTE_OFFSET:.+]] = vm.const.i64 128 + // CHECK-64-DAG: %[[LENGTH:.+]] = vm.const.i64 17 + // CHECK-64: %[[VALUE:.+]] = vm.buffer.hash %arg0, %[[BYTE_OFFSET]], %[[LENGTH]] : !vm.buffer -> i64 + %0 = util.buffer.hash %arg0[%byte_offset for %length] : !util.buffer{%arg1} -> i64 + // CHECK: return %[[VALUE]] + return %0 : i64 +} \ No newline at end of file diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp index dd3e05fc3c12..cef828954e59 100644 --- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp +++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp @@ -4518,6 +4518,8 @@ void populateVMToEmitCPatterns(ConversionTarget &conversionTarget, DenseSet({0}), true); ADD_CONTAINER_PATTERN(IREE::VM::BufferStoreI64Op, "vm_buffer_store_i64", DenseSet({0}), true); + ADD_CONTAINER_PATTERN(IREE::VM::BufferHashOp, "iree_vm_buffer_hash", + DenseSet({0}), true); ADD_CONTAINER_PATTERN(IREE::VM::ListReserveOp, "iree_vm_list_reserve", DenseSet({0}), true); ADD_CONTAINER_PATTERN(IREE::VM::ListResizeOp, "iree_vm_list_resize", diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir index 1ebf5d26a5bb..b4b992cf4fd9 100644 --- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir +++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir @@ -236,3 +236,16 @@ vm.module @my_module { vm.return } } + +// ----- + +vm.module @my_module { + // CHECK-LABEL: @my_module_buffer_hash + vm.func @buffer_hash(%buf : !vm.buffer) { + // CHECK: %[[STATUS:.+]] = emitc.call_opaque "iree_vm_buffer_hash" + %c0 = vm.const.i64 0 + %c10 = vm.const.i64 10 + %v0 = vm.buffer.hash %buf, %c0, %c10 : !vm.buffer -> i64 + vm.return + } +} \ No newline at end of file diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesCore.td b/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesCore.td index 1757cbd52bc3..e191c0b136b5 100644 --- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesCore.td +++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesCore.td @@ -47,7 +47,7 @@ class VM_OPC_EnumAttr; @@ -222,6 +222,7 @@ def VM_OPC_BufferFillI8 : VM_OPC<0x71, "BufferFillI8">; def VM_OPC_BufferFillI16 : VM_OPC<0x72, "BufferFillI16">; def VM_OPC_BufferFillI32 : VM_OPC<0x73, "BufferFillI32">; def VM_OPC_BufferFillI64 : VM_OPC<0x74, "BufferFillI64">; +def VM_OPC_BufferHash : VM_OPC<0x84, "BufferHash">; // Extension prefixes: def VM_OPC_PrefixExtF32 : VM_OPC<0xE0, "PrefixExtF32">; @@ -380,6 +381,7 @@ def VM_CoreOpcodeAttr : VM_OPC_BufferFillI64, VM_OPC_BufferCopy, VM_OPC_BufferCompare, + VM_OPC_BufferHash, VM_OPC_Block, diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td index 025cf65fde00..afeedc65dd43 100644 --- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td +++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td @@ -1598,6 +1598,38 @@ def VM_BufferStoreF64Op : let summary = [{64-bit floating-point store}]; } +def VM_BufferHashOp : VM_Op<"buffer.hash", [ + DeclareOpInterfaceMethods, + MemoryEffects<[MemRead]>, + ]> { + let description = [{ + Computes the SipHash-2-4 of the source buffer at the given offset for + |length| bytes using seed `0x0001020304...0e0f`. + }]; + + let arguments = (ins + VM_RefOf:$source_buffer, + VM_BufferIndex:$source_offset, + VM_BufferIndex:$length + ); + let results = (outs + I64:$result + ); + + let assemblyFormat = [{ + $source_buffer `,` $source_offset `,` $length + attr-dict `:` type($source_buffer) `->` type($result) + }]; + + let encoding = [ + VM_EncOpcode, + VM_EncOperand<"source_buffer", 0>, + VM_EncOperand<"source_offset", 1>, + VM_EncOperand<"length", 2>, + VM_EncResult<"result">, + ]; +} + } // OpGroupBufferOps //===----------------------------------------------------------------------===// diff --git a/runtime/src/iree/vm/BUILD.bazel b/runtime/src/iree/vm/BUILD.bazel index c7e2eef640b8..07fc6a70ff53 100644 --- a/runtime/src/iree/vm/BUILD.bazel +++ b/runtime/src/iree/vm/BUILD.bazel @@ -78,6 +78,7 @@ iree_runtime_cc_library( ], deps = [ "//runtime/src/iree/base", + "//runtime/src/iree/base:core_headers", "//runtime/src/iree/base/internal", "//runtime/src/iree/base/internal:synchronization", ], diff --git a/runtime/src/iree/vm/CMakeLists.txt b/runtime/src/iree/vm/CMakeLists.txt index 9a8eeb32e7d2..a83273e467ab 100644 --- a/runtime/src/iree/vm/CMakeLists.txt +++ b/runtime/src/iree/vm/CMakeLists.txt @@ -65,6 +65,7 @@ iree_cc_library( "stack.c" DEPS iree::base + iree::base::core_headers iree::base::internal iree::base::internal::synchronization PUBLIC diff --git a/runtime/src/iree/vm/buffer.c b/runtime/src/iree/vm/buffer.c index f5c6dc9e33cd..229ff2981b7e 100644 --- a/runtime/src/iree/vm/buffer.c +++ b/runtime/src/iree/vm/buffer.c @@ -9,6 +9,7 @@ #include #include +#include "iree/base/alignment.h" #include "iree/vm/instance.h" IREE_VM_DEFINE_TYPE_ADAPTERS(iree_vm_buffer, iree_vm_buffer_t); @@ -314,6 +315,90 @@ IREE_API_EXPORT iree_status_t iree_vm_buffer_write_elements( return iree_ok_status(); } +// Based on reference implementation from https://github.com/veorq/SipHash +// By Jean-Philippe Aumasson and Daniel J. Bernstein. +#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) +#define SIPROUND(v0, v1, v2, v3) \ + v0 += v1; \ + v1 = ROTL(v1, 13); \ + v1 ^= v0; \ + v0 = ROTL(v0, 32); \ + v2 += v3; \ + v3 = ROTL(v3, 16); \ + v3 ^= v2; \ + v0 += v3; \ + v3 = ROTL(v3, 21); \ + v3 ^= v0; \ + v2 += v1; \ + v1 = ROTL(v1, 17); \ + v1 ^= v2; \ + v2 = ROTL(v2, 32) + +// Using SipHash-2-4. +#ifndef cROUNDS +#define cROUNDS 2 +#endif +#ifndef dROUNDS +#define dROUNDS 4 +#endif + +IREE_API_EXPORT iree_status_t iree_vm_buffer_hash( + const iree_vm_buffer_t* source_buffer, iree_host_size_t source_offset, + iree_host_size_t length, int64_t* result) { + IREE_TRACE_ZONE_BEGIN(z0); + IREE_ASSERT_ARGUMENT(source_buffer); + // Get the byte span for the source data. + iree_const_byte_span_t source_span = iree_const_byte_span_empty(); + IREE_RETURN_AND_END_ZONE_IF_ERROR( + z0, iree_vm_buffer_map_ro(source_buffer, source_offset, length, 1, + &source_span)); + const uint8_t* source = source_span.data; + const uint8_t* end = source + source_span.data_length - + (source_span.data_length % sizeof(uint64_t)); + const int left = source_span.data_length & 7; + uint64_t hash = ((uint64_t)source_span.data_length) << 56; + + // Using key = 0x000102030405060708090a0b0c0d0e0f + uint64_t v0 = UINT64_C(0x736f6d6570736575 ^ 0x0706050403020100); + uint64_t v1 = UINT64_C(0x646f72616e646f6d ^ 0x0f0e0d0c0b0a0908); + uint64_t v2 = UINT64_C(0x6c7967656e657261 ^ 0x0706050403020100); + uint64_t v3 = UINT64_C(0x7465646279746573 ^ 0x0f0e0d0c0b0a0908); + uint64_t m; + + for (; source != end; source += 8) { + m = iree_unaligned_load_le_u64((const uint64_t*)source); + v3 ^= m; + for (int i = 0; i < cROUNDS; ++i) { + SIPROUND(v0, v1, v2, v3); + } + v0 ^= m; + } + + uint64_t tmp = 0; + for (int l = left; l > 0; --l) { + tmp = tmp << 8; + tmp |= (uint64_t)source[l - 1]; + } + hash |= tmp; + v3 ^= hash; + + for (int i = 0; i < cROUNDS; ++i) { + SIPROUND(v0, v1, v2, v3); + } + + v0 ^= hash; + v2 ^= 0xff; + + for (int i = 0; i < dROUNDS; ++i) { + SIPROUND(v0, v1, v2, v3); + } + + hash = v0 ^ v1 ^ v2 ^ v3; + iree_unaligned_store_le_u64(result, hash); + IREE_TRACE_ZONE_END(z0); + return iree_ok_status(); +} + iree_status_t iree_vm_buffer_register_types(iree_vm_instance_t* instance) { static const iree_vm_ref_type_descriptor_t descriptor = { .destroy = iree_vm_buffer_destroy, diff --git a/runtime/src/iree/vm/buffer.h b/runtime/src/iree/vm/buffer.h index 848ab3e646d6..7ddcc896f752 100644 --- a/runtime/src/iree/vm/buffer.h +++ b/runtime/src/iree/vm/buffer.h @@ -199,6 +199,12 @@ IREE_API_EXPORT iree_status_t iree_vm_buffer_write_elements( iree_host_size_t target_offset, iree_host_size_t element_count, iree_host_size_t element_length); +// Computes the SipHash-2-4 of the source buffer along the byte range starting +// as |source_offset| of |length| bytes. Uses 128-bit key `0x00010203...0e0f`. +IREE_API_EXPORT iree_status_t iree_vm_buffer_hash( + const iree_vm_buffer_t* source_buffer, iree_host_size_t source_offset, + iree_host_size_t length, int64_t* result); + // Low-level helper for accessing a typed view of a buffer for read access. // The calling function must be safe to return from. Assumes buffer is non-null. // Prefer iree_vm_buffer_read_elements for larger reads. diff --git a/runtime/src/iree/vm/bytecode/disassembler.c b/runtime/src/iree/vm/bytecode/disassembler.c index 039e03711eb0..ac78b72d9c03 100644 --- a/runtime/src/iree/vm/bytecode/disassembler.c +++ b/runtime/src/iree/vm/bytecode/disassembler.c @@ -1024,6 +1024,27 @@ iree_status_t iree_vm_bytecode_disassemble_op( break; } + DISASM_OP(CORE, BufferHash) { + bool buffer_is_move; + uint16_t buffer_reg = + VM_ParseOperandRegRef("source_buffer", &buffer_is_move); + uint16_t offset_reg = VM_ParseOperandRegI64("source_offset"); + uint16_t length_reg = VM_ParseOperandRegI64("length"); + uint16_t result_reg = VM_ParseResultRegI64("result"); + EMIT_I32_REG_NAME(result_reg); + IREE_RETURN_IF_ERROR( + iree_string_builder_append_cstring(b, " = vm.buffer.hash ")); + EMIT_REF_REG_NAME(buffer_reg); + EMIT_OPTIONAL_VALUE_REF(®s->ref[buffer_reg]); + IREE_RETURN_IF_ERROR(iree_string_builder_append_cstring(b, ", ")); + EMIT_I64_REG_NAME(offset_reg); + EMIT_OPTIONAL_VALUE_I64(regs->i32[offset_reg]); + IREE_RETURN_IF_ERROR(iree_string_builder_append_cstring(b, ", ")); + EMIT_I64_REG_NAME(length_reg); + EMIT_OPTIONAL_VALUE_I64(regs->i32[length_reg]); + break; + } + //===------------------------------------------------------------------===// // Lists //===------------------------------------------------------------------===// diff --git a/runtime/src/iree/vm/bytecode/dispatch.c b/runtime/src/iree/vm/bytecode/dispatch.c index eb2649a79ce6..1c3d528e2d55 100644 --- a/runtime/src/iree/vm/bytecode/dispatch.c +++ b/runtime/src/iree/vm/bytecode/dispatch.c @@ -1176,6 +1176,24 @@ static iree_status_t iree_vm_bytecode_dispatch( vm_buffer_store_i64_inline(buffer, offset, value); }); + DISPATCH_OP(CORE, BufferHash, { + bool source_buffer_is_move; + iree_vm_ref_t* source_buffer_ref = + VM_DecOperandRegRef("source_buffer", &source_buffer_is_move); + iree_vm_buffer_t* source_buffer = + iree_vm_buffer_deref(*source_buffer_ref); + if (IREE_UNLIKELY(!source_buffer)) { + return iree_make_status(IREE_STATUS_INVALID_ARGUMENT, + "source_buffer is null"); + } + iree_host_size_t source_offset = + VM_DecOperandRegI64HostSize("source_offset"); + iree_host_size_t length = VM_DecOperandRegI64HostSize("length"); + uint64_t* result = VM_DecResultRegI64("result"); + IREE_RETURN_IF_ERROR( + iree_vm_buffer_hash(source_buffer, source_offset, length, result)); + }); + //===------------------------------------------------------------------===// // Lists //===------------------------------------------------------------------===// diff --git a/runtime/src/iree/vm/bytecode/utils/generated/op_table.h b/runtime/src/iree/vm/bytecode/utils/generated/op_table.h index 5359b22a3ba1..1e9e7b47a988 100644 --- a/runtime/src/iree/vm/bytecode/utils/generated/op_table.h +++ b/runtime/src/iree/vm/bytecode/utils/generated/op_table.h @@ -139,7 +139,7 @@ typedef enum { IREE_VM_OP_CORE_MaxI64U = 0x81, IREE_VM_OP_CORE_CastAnyRef = 0x82, IREE_VM_OP_CORE_BranchTable = 0x83, - IREE_VM_OP_CORE_RSV_0x84, + IREE_VM_OP_CORE_BufferHash = 0x84, IREE_VM_OP_CORE_RSV_0x85, IREE_VM_OP_CORE_RSV_0x86, IREE_VM_OP_CORE_RSV_0x87, @@ -398,7 +398,7 @@ typedef enum { OPC(0x81, MaxI64U) \ OPC(0x82, CastAnyRef) \ OPC(0x83, BranchTable) \ - RSV(0x84) \ + OPC(0x84, BufferHash) \ RSV(0x85) \ RSV(0x86) \ RSV(0x87) \ diff --git a/runtime/src/iree/vm/bytecode/verifier.c b/runtime/src/iree/vm/bytecode/verifier.c index 3122a70d7296..2dc51fdc1d48 100644 --- a/runtime/src/iree/vm/bytecode/verifier.c +++ b/runtime/src/iree/vm/bytecode/verifier.c @@ -1270,6 +1270,12 @@ static iree_status_t iree_vm_bytecode_function_verify_bytecode_op( VM_VerifyOperandRegI64HostSize(target_offset); VM_VerifyOperandRegI64(value); }); + VERIFY_OP(CORE, BufferHash, { + VM_VerifyOperandRegRef(source_buffer); + VM_VerifyOperandRegI64HostSize(source_offset); + VM_VerifyOperandRegI64HostSize(length); + VM_VerifyResultRegI64(result); + }); //===------------------------------------------------------------------===// // Lists diff --git a/runtime/src/iree/vm/test/buffer_ops.mlir b/runtime/src/iree/vm/test/buffer_ops.mlir index 84a751781b7f..74eebabcade9 100644 --- a/runtime/src/iree/vm/test/buffer_ops.mlir +++ b/runtime/src/iree/vm/test/buffer_ops.mlir @@ -680,4 +680,40 @@ vm.module @buffer_ops { vm.return } + //===--------------------------------------------------------------------===// + // Hash + //===--------------------------------------------------------------------===// + + //vm.rodata private @test_hash_i8_data dense<[0x00, 0x01, 0x7F, 0x80, 0xFF]> : tensor<5xui8> + vm.rodata private @test_hash_i8_data dense<[0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f]> : tensor<32xui8> + + vm.export @test_hash + vm.func @test_hash() { + %c0 = vm.const.i64 0 + %c5 = vm.const.i64 5 + %c16 = vm.const.i64 16 + %c25 = vm.const.i64 25 + %c32 = vm.const.i64 32 + %rodata = vm.const.ref.rodata @test_hash_i8_data : !vm.buffer + %h0 = vm.buffer.hash %rodata, %c0, %c5 : !vm.buffer -> i64 + %e0 = vm.const.i64 0x18765564cd99a68d + vm.check.eq %h0, %e0, "0-4: 0x18765564cd99a68d" : i64 + %h1 = vm.buffer.hash %rodata, %c0, %c16 : !vm.buffer -> i64 + %e1 = vm.const.i64 0x3f2acc7f57c29bdb + vm.check.eq %h1, %e1, "0-15: 0x3f2acc7f57c29bdb" : i64 + %h2 = vm.buffer.hash %rodata, %c0, %c25 : !vm.buffer -> i64 + %e2 = vm.const.i64 0xbce192de8a85b8ea + vm.check.eq %h2, %e2, "0-24: 0xbce192de8a85b8ea" : i64 + %h3 = vm.buffer.hash %rodata, %c0, %c32 : !vm.buffer -> i64 + %e3 = vm.const.i64 0x7127512f72f27cce + vm.check.eq %h3, %e3, "0-31: 0x7127512f72f27cce" : i64 + vm.return + } + } From 618073654325bb70c6b8572e2ef6eb2780bdfbfc Mon Sep 17 00:00:00 2001 From: Quinn Dawkins Date: Mon, 8 Jan 2024 21:35:47 -0500 Subject: [PATCH 2/3] Address comments --- .../src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir | 2 +- .../Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir | 2 +- .../Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir | 2 +- runtime/src/iree/vm/BUILD.bazel | 1 - runtime/src/iree/vm/CMakeLists.txt | 1 - runtime/src/iree/vm/buffer.c | 6 +++--- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir b/compiler/src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir index 3c37c62d7b5f..736ae4891d63 100644 --- a/compiler/src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir +++ b/compiler/src/iree/compiler/Dialect/Util/IR/test/buffer_ops.mlir @@ -136,4 +136,4 @@ func.func @buffer_hash(%arg0: !util.buffer, %arg1: index) -> i64 { // CHECK: = util.buffer.hash %arg0[%c100 for %c17] : !util.buffer{%arg1} -> i64 %0 = util.buffer.hash %arg0[%c100 for %c17] : !util.buffer{%arg1} -> i64 return %0 : i64 -} \ No newline at end of file +} diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir index 6de0ad23d145..3f0e3e69a642 100644 --- a/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir +++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/UtilToVM/test/buffer_ops.mlir @@ -311,4 +311,4 @@ func.func @buffer_hash(%arg0: !util.buffer, %arg1: index) -> i64 { %0 = util.buffer.hash %arg0[%byte_offset for %length] : !util.buffer{%arg1} -> i64 // CHECK: return %[[VALUE]] return %0 : i64 -} \ No newline at end of file +} diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir index b4b992cf4fd9..0517fe0cc9d7 100644 --- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir +++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/test/buffer_ops.mlir @@ -248,4 +248,4 @@ vm.module @my_module { %v0 = vm.buffer.hash %buf, %c0, %c10 : !vm.buffer -> i64 vm.return } -} \ No newline at end of file +} diff --git a/runtime/src/iree/vm/BUILD.bazel b/runtime/src/iree/vm/BUILD.bazel index 07fc6a70ff53..c7e2eef640b8 100644 --- a/runtime/src/iree/vm/BUILD.bazel +++ b/runtime/src/iree/vm/BUILD.bazel @@ -78,7 +78,6 @@ iree_runtime_cc_library( ], deps = [ "//runtime/src/iree/base", - "//runtime/src/iree/base:core_headers", "//runtime/src/iree/base/internal", "//runtime/src/iree/base/internal:synchronization", ], diff --git a/runtime/src/iree/vm/CMakeLists.txt b/runtime/src/iree/vm/CMakeLists.txt index a83273e467ab..9a8eeb32e7d2 100644 --- a/runtime/src/iree/vm/CMakeLists.txt +++ b/runtime/src/iree/vm/CMakeLists.txt @@ -65,7 +65,6 @@ iree_cc_library( "stack.c" DEPS iree::base - iree::base::core_headers iree::base::internal iree::base::internal::synchronization PUBLIC diff --git a/runtime/src/iree/vm/buffer.c b/runtime/src/iree/vm/buffer.c index 229ff2981b7e..eab436c7b611 100644 --- a/runtime/src/iree/vm/buffer.c +++ b/runtime/src/iree/vm/buffer.c @@ -9,7 +9,6 @@ #include #include -#include "iree/base/alignment.h" #include "iree/vm/instance.h" IREE_VM_DEFINE_TYPE_ADAPTERS(iree_vm_buffer, iree_vm_buffer_t); @@ -316,7 +315,7 @@ IREE_API_EXPORT iree_status_t iree_vm_buffer_write_elements( } // Based on reference implementation from https://github.com/veorq/SipHash -// By Jean-Philippe Aumasson and Daniel J. Bernstein. +// By Jean-Philippe Aumasson and Daniel J. Bernstein. (CC0 Licensed) #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) #define SIPROUND(v0, v1, v2, v3) \ v0 += v1; \ @@ -347,6 +346,7 @@ IREE_API_EXPORT iree_status_t iree_vm_buffer_hash( iree_host_size_t length, int64_t* result) { IREE_TRACE_ZONE_BEGIN(z0); IREE_ASSERT_ARGUMENT(source_buffer); + // Get the byte span for the source data. iree_const_byte_span_t source_span = iree_const_byte_span_empty(); IREE_RETURN_AND_END_ZONE_IF_ERROR( @@ -394,7 +394,7 @@ IREE_API_EXPORT iree_status_t iree_vm_buffer_hash( } hash = v0 ^ v1 ^ v2 ^ v3; - iree_unaligned_store_le_u64(result, hash); + *result = hash; IREE_TRACE_ZONE_END(z0); return iree_ok_status(); } From d21b362a7d18f3733f1e91d0aa5ca0940841f011 Mon Sep 17 00:00:00 2001 From: Quinn Dawkins Date: Mon, 8 Jan 2024 21:48:12 -0500 Subject: [PATCH 3/3] result -> out_result --- runtime/src/iree/vm/buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/src/iree/vm/buffer.c b/runtime/src/iree/vm/buffer.c index eab436c7b611..2421ab75fafe 100644 --- a/runtime/src/iree/vm/buffer.c +++ b/runtime/src/iree/vm/buffer.c @@ -343,7 +343,7 @@ IREE_API_EXPORT iree_status_t iree_vm_buffer_write_elements( IREE_API_EXPORT iree_status_t iree_vm_buffer_hash( const iree_vm_buffer_t* source_buffer, iree_host_size_t source_offset, - iree_host_size_t length, int64_t* result) { + iree_host_size_t length, int64_t* out_result) { IREE_TRACE_ZONE_BEGIN(z0); IREE_ASSERT_ARGUMENT(source_buffer); @@ -394,7 +394,7 @@ IREE_API_EXPORT iree_status_t iree_vm_buffer_hash( } hash = v0 ^ v1 ^ v2 ^ v3; - *result = hash; + *out_result = hash; IREE_TRACE_ZONE_END(z0); return iree_ok_status(); }