summaryrefslogtreecommitdiff
path: root/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
diff options
context:
space:
mode:
authorRiver Riddle <riddleriver@gmail.com>2022-08-23 23:39:18 -0700
committerRiver Riddle <riddleriver@gmail.com>2022-08-26 13:31:05 -0700
commit2f90764ce887ee5647d7ee41f4dca064e874aed1 (patch)
tree9b3d687b57b81f2fc965063c4e715e3efa5954cd /mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
parent937aaead87f055caa4d91d7ba637d442a94a24a6 (diff)
[mlir:Bytecode] Add encoding support for a majority of the builtin attributes
This adds support for the non-location, non-elements, non-affine builtin attributes. Differential Revision: https://reviews.llvm.org/D132539
Diffstat (limited to 'mlir/lib/Bytecode/Writer/BytecodeWriter.cpp')
-rw-r--r--mlir/lib/Bytecode/Writer/BytecodeWriter.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp b/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
index 460471b649e5..7a420e448bec 100644
--- a/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
+++ b/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
@@ -85,6 +85,14 @@ public:
emitMultiByteVarInt(value);
}
+ /// Emit a signed variable length integer. Signed varints are encoded using
+ /// a varint with zigzag encoding, meaning that we use the low bit of the
+ /// value to indicate the sign of the value. This allows for more efficient
+ /// encoding of negative values by limiting the number of active bits
+ void emitSignedVarInt(uint64_t value) {
+ emitVarInt((value << 1) ^ (uint64_t)((int64_t)value >> 63));
+ }
+
/// Emit a variable length integer whose low bit is used to encode the
/// provided flag, i.e. encoded as: (value << 1) | (flag ? 1 : 0).
void emitVarIntWithFlag(uint64_t value, bool flag) {
@@ -384,6 +392,37 @@ public:
void writeVarInt(uint64_t value) override { emitter.emitVarInt(value); }
+ void writeSignedVarInt(int64_t value) override {
+ emitter.emitSignedVarInt(value);
+ }
+
+ void writeAPIntWithKnownWidth(const APInt &value) override {
+ size_t bitWidth = value.getBitWidth();
+
+ // If the value is a single byte, just emit it directly without going
+ // through a varint.
+ if (bitWidth <= 8)
+ return emitter.emitByte(value.getLimitedValue());
+
+ // If the value fits within a single varint, emit it directly.
+ if (bitWidth <= 64)
+ return emitter.emitSignedVarInt(value.getLimitedValue());
+
+ // Otherwise, we need to encode a variable number of active words. We use
+ // active words instead of the number of total words under the observation
+ // that smaller values will be more common.
+ unsigned numActiveWords = value.getActiveWords();
+ emitter.emitVarInt(numActiveWords);
+
+ const uint64_t *rawValueData = value.getRawData();
+ for (unsigned i = 0; i < numActiveWords; ++i)
+ emitter.emitSignedVarInt(rawValueData[i]);
+ }
+
+ void writeAPFloatWithKnownSemantics(const APFloat &value) override {
+ writeAPIntWithKnownWidth(value.bitcastToAPInt());
+ }
+
void writeOwnedString(StringRef str) override {
emitter.emitVarInt(stringSection.insert(str));
}