[Mlir-commits] [mlir] 2f90764 - [mlir:Bytecode] Add encoding support for a majority of the builtin attributes
River Riddle
llvmlistbot at llvm.org
Fri Aug 26 13:33:42 PDT 2022
Author: River Riddle
Date: 2022-08-26T13:31:05-07:00
New Revision: 2f90764ce887ee5647d7ee41f4dca064e874aed1
URL: https://github.com/llvm/llvm-project/commit/2f90764ce887ee5647d7ee41f4dca064e874aed1
DIFF: https://github.com/llvm/llvm-project/commit/2f90764ce887ee5647d7ee41f4dca064e874aed1.diff
LOG: [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
Added:
Modified:
mlir/docs/BytecodeFormat.md
mlir/include/mlir/Bytecode/BytecodeImplementation.h
mlir/lib/Bytecode/Reader/BytecodeReader.cpp
mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
mlir/lib/Bytecode/Writer/IRNumbering.cpp
mlir/lib/IR/BuiltinDialectBytecode.cpp
mlir/test/Dialect/Builtin/Bytecode/attrs.mlir
Removed:
################################################################################
diff --git a/mlir/docs/BytecodeFormat.md b/mlir/docs/BytecodeFormat.md
index 5260c996a880d..fc332869d6400 100644
--- a/mlir/docs/BytecodeFormat.md
+++ b/mlir/docs/BytecodeFormat.md
@@ -65,6 +65,22 @@ x1000000: 49 value bits, the encoding uses 7 bytes
00000000: 64 value bits, the encoding uses 9 bytes
```
+##### Signed Variable-Width Integers
+
+Signed variable width integer values are encoded in a similar fashion to
+[varints](#variable-width-integers), but employ
+[zigzag encoding](https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding).
+This encoding uses the low bit of the value to indicate the sign, which allows
+for more efficiently encoding negative numbers. If a negative value were encoded
+using a normal [varint](#variable-width-integers), it would be treated as an
+extremely large unsigned value. Using zigzag encoding allows for a smaller
+number of active bits in the value, leading to a smaller encoding. Below is the
+basic computation for generating a zigzag encoding:
+
+```
+(value << 1) ^ (value >> 63)
+```
+
#### Strings
Strings are blobs of characters with an associated length.
diff --git a/mlir/include/mlir/Bytecode/BytecodeImplementation.h b/mlir/include/mlir/Bytecode/BytecodeImplementation.h
index 01bada7e0572f..921d795068fbd 100644
--- a/mlir/include/mlir/Bytecode/BytecodeImplementation.h
+++ b/mlir/include/mlir/Bytecode/BytecodeImplementation.h
@@ -78,14 +78,14 @@ class DialectBytecodeReader {
return readList(attrs, [this](T &attr) { return readAttribute(attr); });
}
template <typename T>
- LogicalResult parseAttribute(T &result) {
+ LogicalResult readAttribute(T &result) {
Attribute baseResult;
- if (failed(parseAttribute(baseResult)))
+ if (failed(readAttribute(baseResult)))
return failure();
if ((result = baseResult.dyn_cast<T>()))
return success();
- return emitError() << "expected attribute of type: "
- << llvm::getTypeName<T>() << ", but got: " << baseResult;
+ return emitError() << "expected " << llvm::getTypeName<T>()
+ << ", but got: " << baseResult;
}
/// Read a reference to the given type.
@@ -94,15 +94,35 @@ class DialectBytecodeReader {
LogicalResult readTypes(SmallVectorImpl<T> &types) {
return readList(types, [this](T &type) { return readType(type); });
}
+ template <typename T>
+ LogicalResult readType(T &result) {
+ Type baseResult;
+ if (failed(readType(baseResult)))
+ return failure();
+ if ((result = baseResult.dyn_cast<T>()))
+ return success();
+ return emitError() << "expected " << llvm::getTypeName<T>()
+ << ", but got: " << baseResult;
+ }
//===--------------------------------------------------------------------===//
// Primitives
//===--------------------------------------------------------------------===//
/// Read a variable width integer.
- // TODO: Add a signed variant when necessary.
virtual LogicalResult readVarInt(uint64_t &result) = 0;
+ /// Read a signed variable width integer.
+ virtual LogicalResult readSignedVarInt(int64_t &result) = 0;
+
+ /// Read an APInt that is known to have been encoded with the given width.
+ virtual FailureOr<APInt> readAPIntWithKnownWidth(unsigned bitWidth) = 0;
+
+ /// Read an APFloat that is known to have been encoded with the given
+ /// semantics.
+ virtual FailureOr<APFloat>
+ readAPFloatWithKnownSemantics(const llvm::fltSemantics &semantics) = 0;
+
/// Read a string from the bytecode.
virtual LogicalResult readString(StringRef &result) = 0;
};
@@ -153,9 +173,25 @@ class DialectBytecodeWriter {
/// Write a variable width integer to the output stream. This should be the
/// preferred method for emitting integers whenever possible.
- // TODO: Add a signed variant when necessary.
virtual void writeVarInt(uint64_t value) = 0;
+ /// Write a signed variable width integer to the output stream. This should be
+ /// the preferred method for emitting signed integers whenever possible.
+ virtual void writeSignedVarInt(int64_t value) = 0;
+
+ /// Write an APInt to the bytecode stream whose bitwidth will be known
+ /// externally at read time. This method is useful for encoding APInt values
+ /// when the width is known via external means, such as via a type. This
+ /// method should generally only be invoked if you need an APInt, otherwise
+ /// use the varint methods above. APInt values are generally encoded using
+ /// zigzag encoding, to enable more efficient encodings for negative values.
+ virtual void writeAPIntWithKnownWidth(const APInt &value) = 0;
+
+ /// Write an APFloat to the bytecode stream whose semantics will be known
+ /// externally at read time. This method is useful for encoding APFloat values
+ /// when the semantics are known via external means, such as via a type.
+ virtual void writeAPFloatWithKnownSemantics(const APFloat &value) = 0;
+
/// Write a string to the bytecode, which is owned by the caller and is
/// guaranteed to not die before the end of the bytecode process. This should
/// only be called if such a guarantee can be made, such as when the string is
diff --git a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
index 78d60a0b5a3fe..7343ec5f96882 100644
--- a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
+++ b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
@@ -128,6 +128,17 @@ class EncodingReader {
return parseMultiByteVarInt(result);
}
+ /// Parse a signed variable length encoded integer from the byte stream. A
+ /// signed varint is encoded as a normal varint with zigzag encoding applied,
+ /// i.e. the low bit of the value is used to indicate the sign.
+ LogicalResult parseSignedVarInt(uint64_t &result) {
+ if (failed(parseVarInt(result)))
+ return failure();
+ // Essentially (but using unsigned): (x >> 1) ^ -(x & 1)
+ result = (result >> 1) ^ (~(result & 1) + 1);
+ return success();
+ }
+
/// Parse a variable length encoded integer whose low bit is used to encode an
/// unrelated flag, i.e: `(integerValue << 1) | (flag ? 1 : 0)`.
LogicalResult parseVarIntWithFlag(uint64_t &result, bool &flag) {
@@ -511,6 +522,52 @@ class DialectReader : public DialectBytecodeReader {
return reader.parseVarInt(result);
}
+ LogicalResult readSignedVarInt(int64_t &result) override {
+ uint64_t unsignedResult;
+ if (failed(reader.parseSignedVarInt(unsignedResult)))
+ return failure();
+ result = static_cast<int64_t>(unsignedResult);
+ return success();
+ }
+
+ FailureOr<APInt> readAPIntWithKnownWidth(unsigned bitWidth) override {
+ // Small values are encoded using a single byte.
+ if (bitWidth <= 8) {
+ uint8_t value;
+ if (failed(reader.parseByte(value)))
+ return failure();
+ return APInt(bitWidth, value);
+ }
+
+ // Large values up to 64 bits are encoded using a single varint.
+ if (bitWidth <= 64) {
+ uint64_t value;
+ if (failed(reader.parseSignedVarInt(value)))
+ return failure();
+ return APInt(bitWidth, value);
+ }
+
+ // Otherwise, for really big values we encode the array of active words in
+ // the value.
+ uint64_t numActiveWords;
+ if (failed(reader.parseVarInt(numActiveWords)))
+ return failure();
+ SmallVector<uint64_t, 4> words(numActiveWords);
+ for (uint64_t i = 0; i < numActiveWords; ++i)
+ if (failed(reader.parseSignedVarInt(words[i])))
+ return failure();
+ return APInt(bitWidth, words);
+ }
+
+ FailureOr<APFloat>
+ readAPFloatWithKnownSemantics(const llvm::fltSemantics &semantics) override {
+ FailureOr<APInt> intVal =
+ readAPIntWithKnownWidth(APFloat::getSizeInBits(semantics));
+ if (failed(intVal))
+ return failure();
+ return APFloat(semantics, *intVal);
+ }
+
LogicalResult readString(StringRef &result) override {
return stringReader.parseString(reader, result);
}
diff --git a/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp b/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
index 460471b649e52..7a420e448beca 100644
--- a/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
+++ b/mlir/lib/Bytecode/Writer/BytecodeWriter.cpp
@@ -85,6 +85,14 @@ class EncodingEmitter {
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 @@ class DialectWriter : public DialectBytecodeWriter {
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));
}
diff --git a/mlir/lib/Bytecode/Writer/IRNumbering.cpp b/mlir/lib/Bytecode/Writer/IRNumbering.cpp
index 88a69034d557f..549a6ac0957e3 100644
--- a/mlir/lib/Bytecode/Writer/IRNumbering.cpp
+++ b/mlir/lib/Bytecode/Writer/IRNumbering.cpp
@@ -27,6 +27,9 @@ struct IRNumberingState::NumberingDialectWriter : public DialectBytecodeWriter {
/// Stubbed out methods that are not used for numbering.
void writeVarInt(uint64_t) override {}
+ void writeSignedVarInt(int64_t value) override {}
+ void writeAPIntWithKnownWidth(const APInt &value) override {}
+ void writeAPFloatWithKnownSemantics(const APFloat &value) override {}
void writeOwnedString(StringRef) override {
// TODO: It might be nice to prenumber strings and sort by the number of
// references. This could potentially be useful for optimizing things like
diff --git a/mlir/lib/IR/BuiltinDialectBytecode.cpp b/mlir/lib/IR/BuiltinDialectBytecode.cpp
index 619a342e61024..4c47aceff12b9 100644
--- a/mlir/lib/IR/BuiltinDialectBytecode.cpp
+++ b/mlir/lib/IR/BuiltinDialectBytecode.cpp
@@ -38,9 +38,49 @@ enum AttributeCode {
kDictionaryAttr = 1,
/// StringAttr {
- /// string
+ /// value: string
/// }
kStringAttr = 2,
+
+ /// StringAttrWithType {
+ /// value: string,
+ /// type: Type
+ /// }
+ /// A variant of StringAttr with a type.
+ kStringAttrWithType = 3,
+
+ /// FlatSymbolRefAttr {
+ /// rootReference: StringAttr
+ /// }
+ /// A variant of SymbolRefAttr with no leaf references.
+ kFlatSymbolRefAttr = 4,
+
+ /// SymbolRefAttr {
+ /// rootReference: StringAttr,
+ /// leafReferences: FlatSymbolRefAttr[]
+ /// }
+ kSymbolRefAttr = 5,
+
+ /// TypeAttr {
+ /// value: Type
+ /// }
+ kTypeAttr = 6,
+
+ /// UnitAttr {
+ /// }
+ kUnitAttr = 7,
+
+ /// IntegerAttr {
+ /// type: Type
+ /// value: APInt,
+ /// }
+ kIntegerAttr = 8,
+
+ /// FloatAttr {
+ /// type: FloatType
+ /// value: APFloat
+ /// }
+ kFloatAttr = 9,
};
/// This enum contains marker codes used to indicate which type is currently
@@ -86,13 +126,22 @@ struct BuiltinDialectBytecodeInterface : public BytecodeDialectInterface {
Attribute readAttribute(DialectBytecodeReader &reader) const override;
ArrayAttr readArrayAttr(DialectBytecodeReader &reader) const;
DictionaryAttr readDictionaryAttr(DialectBytecodeReader &reader) const;
- StringAttr readStringAttr(DialectBytecodeReader &reader) const;
+ FloatAttr readFloatAttr(DialectBytecodeReader &reader) const;
+ IntegerAttr readIntegerAttr(DialectBytecodeReader &reader) const;
+ StringAttr readStringAttr(DialectBytecodeReader &reader, bool hasType) const;
+ SymbolRefAttr readSymbolRefAttr(DialectBytecodeReader &reader,
+ bool hasNestedRefs) const;
+ TypeAttr readTypeAttr(DialectBytecodeReader &reader) const;
LogicalResult writeAttribute(Attribute attr,
DialectBytecodeWriter &writer) const override;
void write(ArrayAttr attr, DialectBytecodeWriter &writer) const;
void write(DictionaryAttr attr, DialectBytecodeWriter &writer) const;
+ void write(IntegerAttr attr, DialectBytecodeWriter &writer) const;
+ void write(FloatAttr attr, DialectBytecodeWriter &writer) const;
void write(StringAttr attr, DialectBytecodeWriter &writer) const;
+ void write(SymbolRefAttr attr, DialectBytecodeWriter &writer) const;
+ void write(TypeAttr attr, DialectBytecodeWriter &writer) const;
//===--------------------------------------------------------------------===//
// Types
@@ -126,7 +175,21 @@ Attribute BuiltinDialectBytecodeInterface::readAttribute(
case builtin_encoding::kDictionaryAttr:
return readDictionaryAttr(reader);
case builtin_encoding::kStringAttr:
- return readStringAttr(reader);
+ return readStringAttr(reader, /*hasType=*/false);
+ case builtin_encoding::kStringAttrWithType:
+ return readStringAttr(reader, /*hasType=*/true);
+ case builtin_encoding::kFlatSymbolRefAttr:
+ return readSymbolRefAttr(reader, /*hasNestedRefs=*/false);
+ case builtin_encoding::kSymbolRefAttr:
+ return readSymbolRefAttr(reader, /*hasNestedRefs=*/true);
+ case builtin_encoding::kTypeAttr:
+ return readTypeAttr(reader);
+ case builtin_encoding::kUnitAttr:
+ return UnitAttr::get(getContext());
+ case builtin_encoding::kIntegerAttr:
+ return readIntegerAttr(reader);
+ case builtin_encoding::kFloatAttr:
+ return readFloatAttr(reader);
default:
reader.emitError() << "unknown builtin attribute code: " << code;
return Attribute();
@@ -157,12 +220,75 @@ DictionaryAttr BuiltinDialectBytecodeInterface::readDictionaryAttr(
return DictionaryAttr::get(getContext(), attrs);
}
-StringAttr BuiltinDialectBytecodeInterface::readStringAttr(
+FloatAttr BuiltinDialectBytecodeInterface::readFloatAttr(
+ DialectBytecodeReader &reader) const {
+ FloatType type;
+ if (failed(reader.readType(type)))
+ return FloatAttr();
+ FailureOr<APFloat> value =
+ reader.readAPFloatWithKnownSemantics(type.getFloatSemantics());
+ if (failed(value))
+ return FloatAttr();
+ return FloatAttr::get(type, *value);
+}
+
+IntegerAttr BuiltinDialectBytecodeInterface::readIntegerAttr(
DialectBytecodeReader &reader) const {
+ Type type;
+ if (failed(reader.readType(type)))
+ return IntegerAttr();
+
+ // Extract the value storage width from the type.
+ unsigned bitWidth;
+ if (auto intType = type.dyn_cast<IntegerType>()) {
+ bitWidth = intType.getWidth();
+ } else if (type.isa<IndexType>()) {
+ bitWidth = IndexType::kInternalStorageBitWidth;
+ } else {
+ reader.emitError()
+ << "expected integer or index type for IntegerAttr, but got: " << type;
+ return IntegerAttr();
+ }
+
+ FailureOr<APInt> value = reader.readAPIntWithKnownWidth(bitWidth);
+ if (failed(value))
+ return IntegerAttr();
+ return IntegerAttr::get(type, *value);
+}
+
+StringAttr
+BuiltinDialectBytecodeInterface::readStringAttr(DialectBytecodeReader &reader,
+ bool hasType) const {
StringRef string;
if (failed(reader.readString(string)))
return StringAttr();
- return StringAttr::get(getContext(), string);
+
+ // Read the type if present.
+ Type type;
+ if (!hasType)
+ type = NoneType::get(getContext());
+ else if (failed(reader.readType(type)))
+ return StringAttr();
+ return StringAttr::get(string, type);
+}
+
+SymbolRefAttr BuiltinDialectBytecodeInterface::readSymbolRefAttr(
+ DialectBytecodeReader &reader, bool hasNestedRefs) const {
+ StringAttr rootReference;
+ if (failed(reader.readAttribute(rootReference)))
+ return SymbolRefAttr();
+ SmallVector<FlatSymbolRefAttr> nestedReferences;
+ if (hasNestedRefs && failed(reader.readAttributes(nestedReferences)))
+ return SymbolRefAttr();
+ return SymbolRefAttr::get(rootReference, nestedReferences);
+}
+
+TypeAttr BuiltinDialectBytecodeInterface::readTypeAttr(
+ DialectBytecodeReader &reader) const {
+ Type type;
+ if (failed(reader.readType(type)))
+ return TypeAttr();
+ return TypeAttr::get(type);
}
//===----------------------------------------------------------------------===//
@@ -171,10 +297,15 @@ StringAttr BuiltinDialectBytecodeInterface::readStringAttr(
LogicalResult BuiltinDialectBytecodeInterface::writeAttribute(
Attribute attr, DialectBytecodeWriter &writer) const {
return TypeSwitch<Attribute, LogicalResult>(attr)
- .Case<ArrayAttr, DictionaryAttr, StringAttr>([&](auto attr) {
+ .Case<ArrayAttr, DictionaryAttr, FloatAttr, IntegerAttr, StringAttr,
+ SymbolRefAttr, TypeAttr>([&](auto attr) {
write(attr, writer);
return success();
})
+ .Case([&](UnitAttr) {
+ writer.writeVarInt(builtin_encoding::kUnitAttr);
+ return success();
+ })
.Default([&](Attribute) { return failure(); });
}
@@ -193,12 +324,52 @@ void BuiltinDialectBytecodeInterface::write(
});
}
+void BuiltinDialectBytecodeInterface::write(
+ FloatAttr attr, DialectBytecodeWriter &writer) const {
+ writer.writeVarInt(builtin_encoding::kFloatAttr);
+ writer.writeType(attr.getType());
+ writer.writeAPFloatWithKnownSemantics(attr.getValue());
+}
+
+void BuiltinDialectBytecodeInterface::write(
+ IntegerAttr attr, DialectBytecodeWriter &writer) const {
+ writer.writeVarInt(builtin_encoding::kIntegerAttr);
+ writer.writeType(attr.getType());
+ writer.writeAPIntWithKnownWidth(attr.getValue());
+}
+
void BuiltinDialectBytecodeInterface::write(
StringAttr attr, DialectBytecodeWriter &writer) const {
+ // We only encode the type if it isn't NoneType, which is significantly less
+ // common.
+ Type type = attr.getType();
+ if (!type.isa<NoneType>()) {
+ writer.writeVarInt(builtin_encoding::kStringAttrWithType);
+ writer.writeOwnedString(attr.getValue());
+ writer.writeType(type);
+ return;
+ }
writer.writeVarInt(builtin_encoding::kStringAttr);
writer.writeOwnedString(attr.getValue());
}
+void BuiltinDialectBytecodeInterface::write(
+ SymbolRefAttr attr, DialectBytecodeWriter &writer) const {
+ ArrayRef<FlatSymbolRefAttr> nestedRefs = attr.getNestedReferences();
+ writer.writeVarInt(nestedRefs.empty() ? builtin_encoding::kFlatSymbolRefAttr
+ : builtin_encoding::kSymbolRefAttr);
+
+ writer.writeAttribute(attr.getRootReference());
+ if (!nestedRefs.empty())
+ writer.writeAttributes(nestedRefs);
+}
+
+void BuiltinDialectBytecodeInterface::write(
+ TypeAttr attr, DialectBytecodeWriter &writer) const {
+ writer.writeVarInt(builtin_encoding::kTypeAttr);
+ writer.writeType(attr.getValue());
+}
+
//===----------------------------------------------------------------------===//
// Types: Reader
diff --git a/mlir/test/Dialect/Builtin/Bytecode/attrs.mlir b/mlir/test/Dialect/Builtin/Bytecode/attrs.mlir
index 8f91a25768196..c309b85e0ce29 100644
--- a/mlir/test/Dialect/Builtin/Bytecode/attrs.mlir
+++ b/mlir/test/Dialect/Builtin/Bytecode/attrs.mlir
@@ -3,14 +3,78 @@
// Bytecode currently does not support big-endian platforms
// UNSUPPORTED: s390x-
+//===----------------------------------------------------------------------===//
+// ArrayAttr
+//===----------------------------------------------------------------------===//
+
// CHECK-LABEL: @TestArray
module @TestArray attributes {
// CHECK: bytecode.array = [unit]
bytecode.array = [unit]
} {}
+//===----------------------------------------------------------------------===//
+// FloatAttr
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @TestFloat
+module @TestFloat attributes {
+ // CHECK: bytecode.float = 1.000000e+01 : f64
+ // CHECK: bytecode.float1 = 0.10000{{.*}} : f80
+ // CHECK: bytecode.float2 = 0.10000{{.*}} : f128
+ // CHECK: bytecode.float3 = -5.000000e-01 : bf16
+ bytecode.float = 10.0 : f64,
+ bytecode.float1 = 0.1 : f80,
+ bytecode.float2 = 0.1 : f128,
+ bytecode.float3 = -0.5 : bf16
+} {}
+
+//===----------------------------------------------------------------------===//
+// IntegerAttr
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @TestInt
+module @TestInt attributes {
+ // CHECK: bytecode.int = false
+ // CHECK: bytecode.int1 = -1 : i8
+ // CHECK: bytecode.int2 = 800 : ui64
+ // CHECK: bytecode.int3 = 90000000000000000300000000000000000001 : i128
+ bytecode.int = false,
+ bytecode.int1 = -1 : i8,
+ bytecode.int2 = 800 : ui64,
+ bytecode.int3 = 90000000000000000300000000000000000001 : i128
+} {}
+
+//===----------------------------------------------------------------------===//
+// StringAttr
+//===----------------------------------------------------------------------===//
+
// CHECK-LABEL: @TestString
module @TestString attributes {
// CHECK: bytecode.string = "hello"
- bytecode.string = "hello"
+ // CHECK: bytecode.string2 = "hello" : i32
+ bytecode.string = "hello",
+ bytecode.string2 = "hello" : i32
+} {}
+
+//===----------------------------------------------------------------------===//
+// SymbolRefAttr
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @TestSymbolRef
+module @TestSymbolRef attributes {
+ // CHECK: bytecode.ref = @foo
+ // CHECK: bytecode.ref2 = @foo::@bar::@foo
+ bytecode.ref = @foo,
+ bytecode.ref2 = @foo::@bar::@foo
+} {}
+
+//===----------------------------------------------------------------------===//
+// TypeAttr
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @TestType
+module @TestType attributes {
+ // CHECK: bytecode.type = i178
+ bytecode.type = i178
} {}
More information about the Mlir-commits
mailing list