-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[mlir][EmitC]Allow Fields to have initial values #151437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fe28323
7c3a30b
bd85cce
76d729e
5cce6fa
aff4e37
953a8c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1398,6 +1398,45 @@ void FileOp::build(OpBuilder &builder, OperationState &state, StringRef id) { | |
//===----------------------------------------------------------------------===// | ||
// FieldOp | ||
//===----------------------------------------------------------------------===// | ||
static void printEmitCFieldOpTypeAndInitialValue(OpAsmPrinter &p, FieldOp op, | ||
TypeAttr type, | ||
Attribute initialValue) { | ||
p << type; | ||
if (initialValue) { | ||
p << " = "; | ||
p.printAttributeWithoutType(initialValue); | ||
} | ||
} | ||
|
||
static Type getInitializerTypeForField(Type type) { | ||
if (auto array = llvm::dyn_cast<ArrayType>(type)) | ||
return RankedTensorType::get(array.getShape(), array.getElementType()); | ||
return type; | ||
} | ||
|
||
static ParseResult | ||
parseEmitCFieldOpTypeAndInitialValue(OpAsmParser &parser, TypeAttr &typeAttr, | ||
Attribute &initialValue) { | ||
Type type; | ||
if (parser.parseType(type)) | ||
return failure(); | ||
|
||
typeAttr = TypeAttr::get(type); | ||
|
||
if (parser.parseOptionalEqual()) | ||
return success(); | ||
|
||
if (parser.parseAttribute(initialValue, getInitializerTypeForField(type))) | ||
return failure(); | ||
|
||
if (!llvm::isa<ElementsAttr, IntegerAttr, FloatAttr, emitc::OpaqueAttr>( | ||
initialValue)) | ||
return parser.emitError(parser.getNameLoc()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference in output if emitError() is used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use |
||
<< "initial value should be a integer, float, elements or opaque " | ||
"attribute"; | ||
return success(); | ||
} | ||
|
||
LogicalResult FieldOp::verify() { | ||
if (!isSupportedEmitCType(getType())) | ||
return emitOpError("expected valid emitc type"); | ||
|
@@ -1410,9 +1449,6 @@ LogicalResult FieldOp::verify() { | |
if (!symName || symName.getValue().empty()) | ||
return emitOpError("field must have a non-empty symbol name"); | ||
|
||
if (!getAttrs()) | ||
return success(); | ||
|
||
return success(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,15 +14,12 @@ emitc.class @modelClass { | |
|
||
// CHECK-LABEL: class modelClass { | ||
// CHECK-NEXT: public: | ||
// CHECK-NEXT: float[1] fieldName0; | ||
// CHECK-NEXT: float[1] fieldName1; | ||
// CHECK-NEXT: float fieldName0[1]; | ||
// CHECK-NEXT: float fieldName1[1]; | ||
// CHECK-NEXT: void execute() { | ||
// CHECK-NEXT: size_t v1 = 0; | ||
// CHECK-NEXT: float[1] v2 = fieldName0; | ||
// CHECK-NEXT: float[1] v3 = fieldName1; | ||
// CHECK-NEXT: return; | ||
// CHECK-NEXT: } | ||
// CHECK-EMPTY: | ||
// CHECK-NEXT: }; | ||
|
||
emitc.class final @finalClass { | ||
|
@@ -39,13 +36,43 @@ emitc.class final @finalClass { | |
|
||
// CHECK-LABEL: class finalClass final { | ||
// CHECK-NEXT: public: | ||
// CHECK-NEXT: float[1] fieldName0; | ||
// CHECK-NEXT: float[1] fieldName1; | ||
// CHECK-NEXT: float fieldName0[1]; | ||
// CHECK-NEXT: float fieldName1[1]; | ||
// CHECK-NEXT: void execute() { | ||
// CHECK-NEXT: size_t v1 = 0; | ||
// CHECK-NEXT: float[1] v2 = fieldName0; | ||
// CHECK-NEXT: float[1] v3 = fieldName1; | ||
// CHECK-NEXT: return; | ||
Comment on lines
42
to
43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These seem to go away, but I'm not sure what in this change causes that, given that you didn't change the input IR w/ an initial value. I can see that you're changing how the fields are printed, but that doesn't seem to be related to these statements. What part of this changes removed these? Should these assignments have been removed(I assume yes)? Do you need some calculation in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They go away because they aren't initialized. |
||
// CHECK-NEXT: } | ||
// CHECK-EMPTY: | ||
// CHECK-NEXT: }; | ||
|
||
emitc.class @mainClass { | ||
emitc.field @fieldName0 : !emitc.array<2xf32> = dense<0.0> {attrs = {emitc.name_hint = "another_feature"}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add a test also where the type is e.g. a std::map, with an initializer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ack, addressed in changes. |
||
emitc.func @get_fieldName0() { | ||
%0 = emitc.get_field @fieldName0 : !emitc.array<2xf32> | ||
return | ||
} | ||
} | ||
|
||
// CHECK-LABEL: class mainClass { | ||
// CHECK-NEXT: public: | ||
// CHECK-NEXT: float fieldName0[2] = {0.0e+00f, 0.0e+00f}; | ||
// CHECK-NEXT: void get_fieldName0() { | ||
// CHECK-NEXT: return; | ||
// CHECK-NEXT: } | ||
// CHECK-NEXT: }; | ||
|
||
emitc.class @reflectionClass { | ||
emitc.field @reflectionMap : !emitc.opaque<"const std::map<std::string, std::string>"> = #emitc.opaque<"{ { \22another_feature\22, \22fieldName0\22 } }"> | ||
emitc.func @get_reflectionMap() { | ||
%0 = emitc.get_field @reflectionMap : !emitc.opaque<"const std::map<std::string, std::string>"> | ||
return | ||
} | ||
} | ||
|
||
// CHECK-LABEL: class reflectionClass { | ||
// CHECK-NEXT: public: | ||
// CHECK-NEXT: const std::map<std::string, std::string> reflectionMap = { { "another_feature", "fieldName0" } }; | ||
// CHECK-NEXT: void get_reflectionMap() { | ||
// CHECK-NEXT: return; | ||
// CHECK-NEXT: } | ||
// CHECK-NEXT: }; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment here? (It feels a bit weird to go from ArrayType to RankedTensorType, if this is convention followed elsewhere or just here, good to document)
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is convention that is already documented since this is directly from how we have it in
GlobalOp
. And we have this:https://mlir.llvm.org/docs/Dialects/EmitC/#pointertype:~:text=If%20tensors%20are%20used%2C%20C%2B%2B%20is%20generated