Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 68 additions & 10 deletions mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ def EmitC_ExpressionOp

let arguments = (ins Variadic<AnyTypeOf<[EmitCType, EmitC_LValueType]>>:$defs,
UnitAttr:$do_not_inline);
let results = (outs EmitCType:$result);
let results = (outs AnyTypeOf<[EmitCType, EmitC_LValueType]>:$result);
let regions = (region SizedRegion<1>:$region);

let hasVerifier = 1;
Expand Down Expand Up @@ -873,7 +873,7 @@ def EmitC_IncludeOp
let hasCustomAssemblyFormat = 1;
}

def EmitC_LiteralOp : EmitC_Op<"literal", [Pure]> {
def EmitC_LiteralOp : EmitC_Op<"literal", [Pure, CExpressionInterface]> {
let summary = "Literal operation";
let description = [{
The `emitc.literal` operation produces an SSA value equal to some constant
Expand All @@ -896,6 +896,15 @@ def EmitC_LiteralOp : EmitC_Op<"literal", [Pure]> {

let hasVerifier = 1;
let assemblyFormat = "$value attr-dict `:` type($result)";

let extraClassDeclaration = [{
bool hasSideEffects() {
return false;
}
bool alwaysInline() {
return true; // C doesn't support variable references.
}
}];
}

def EmitC_LogicalAndOp : EmitC_BinaryOp<"logical_and", []> {
Expand Down Expand Up @@ -1062,7 +1071,7 @@ def EmitC_SubOp : EmitC_BinaryOp<"sub", []> {
let hasVerifier = 1;
}

def EmitC_MemberOp : EmitC_Op<"member"> {
def EmitC_MemberOp : EmitC_Op<"member", [CExpressionInterface]> {
let summary = "Member operation";
let description = [{
With the `emitc.member` operation the member access operator `.` can be
Expand All @@ -1083,9 +1092,18 @@ def EmitC_MemberOp : EmitC_Op<"member"> {
EmitC_LValueOf<[EmitC_OpaqueType]>:$operand
);
let results = (outs AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>);

let extraClassDeclaration = [{
bool hasSideEffects() {
return false;
}
bool alwaysInline() {
return true; // C doesn't support variable references.
}
}];
}

def EmitC_MemberOfPtrOp : EmitC_Op<"member_of_ptr"> {
def EmitC_MemberOfPtrOp : EmitC_Op<"member_of_ptr", [CExpressionInterface]> {
let summary = "Member of pointer operation";
let description = [{
With the `emitc.member_of_ptr` operation the member access operator `->`
Expand All @@ -1108,6 +1126,15 @@ def EmitC_MemberOfPtrOp : EmitC_Op<"member_of_ptr"> {
EmitC_LValueOf<[EmitC_OpaqueType,EmitC_PointerType]>:$operand
);
let results = (outs AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>);

let extraClassDeclaration = [{
bool hasSideEffects() {
return false;
}
bool alwaysInline() {
return true; // C doesn't support variable references.
}
}];
}

def EmitC_ConditionalOp : EmitC_Op<"conditional",
Expand Down Expand Up @@ -1277,8 +1304,10 @@ def EmitC_GlobalOp : EmitC_Op<"global", [Symbol]> {
let hasVerifier = 1;
}

def EmitC_GetGlobalOp : EmitC_Op<"get_global",
[Pure, DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
def EmitC_GetGlobalOp
: EmitC_Op<"get_global", [Pure,
DeclareOpInterfaceMethods<SymbolUserOpInterface>,
CExpressionInterface]> {
let summary = "Obtain access to a global variable";
let description = [{
The `emitc.get_global` operation retrieves the lvalue of a
Expand All @@ -1296,6 +1325,15 @@ def EmitC_GetGlobalOp : EmitC_Op<"get_global",
let arguments = (ins FlatSymbolRefAttr:$name);
let results = (outs AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>:$result);
let assemblyFormat = "$name `:` type($result) attr-dict";

let extraClassDeclaration = [{
bool hasSideEffects() {
return false;
}
bool alwaysInline() {
return true; // C doesn't support variable references.
}
}];
}

def EmitC_VerbatimOp : EmitC_Op<"verbatim"> {
Expand Down Expand Up @@ -1406,7 +1444,8 @@ def EmitC_YieldOp : EmitC_Op<"yield",
value is yielded.
}];

let arguments = (ins Optional<EmitCType>:$result);
let arguments =
(ins Optional<AnyTypeOf<[EmitCType, EmitC_LValueType]>>:$result);
let builders = [OpBuilder<(ins), [{ /* nothing to do */ }]>];

let hasVerifier = 1;
Expand Down Expand Up @@ -1477,7 +1516,7 @@ def EmitC_IfOp : EmitC_Op<"if",
let hasCustomAssemblyFormat = 1;
}

def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {
def EmitC_SubscriptOp : EmitC_Op<"subscript", [CExpressionInterface]> {
let summary = "Subscript operation";
let description = [{
With the `emitc.subscript` operation the subscript operator `[]` can be applied
Expand Down Expand Up @@ -1525,6 +1564,15 @@ def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {

let hasVerifier = 1;
let assemblyFormat = "$value `[` $indices `]` attr-dict `:` functional-type(operands, results)";

let extraClassDeclaration = [{
bool hasSideEffects() {
return false;
}
bool alwaysInline() {
return true; // C doesn't support variable references.
}
}];
}

def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
Expand Down Expand Up @@ -1707,8 +1755,9 @@ def EmitC_FieldOp : EmitC_Op<"field", [Symbol]> {
}

def EmitC_GetFieldOp
: EmitC_Op<"get_field", [Pure, DeclareOpInterfaceMethods<
SymbolUserOpInterface>]> {
: EmitC_Op<"get_field", [Pure,
DeclareOpInterfaceMethods<SymbolUserOpInterface>,
CExpressionInterface]> {
let summary = "Obtain access to a field within a class instance";
let description = [{
The `emitc.get_field` operation retrieves the lvalue of a
Expand All @@ -1725,6 +1774,15 @@ def EmitC_GetFieldOp
let results = (outs EmitCType:$result);
let assemblyFormat = "$field_name `:` type($result) attr-dict";
let hasVerifier = 1;

let extraClassDeclaration = [{
bool hasSideEffects() {
return false;
}
bool alwaysInline() {
return true; // C doesn't support variable references.
}
}];
}

#endif // MLIR_DIALECT_EMITC_IR_EMITC
27 changes: 23 additions & 4 deletions mlir/include/mlir/Dialect/EmitC/IR/EmitCInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ def CExpressionInterface : OpInterface<"CExpressionInterface"> {
}];

let cppNamespace = "::mlir::emitc";
let methods = [
InterfaceMethod<[{
let methods =
[InterfaceMethod<[{
Check whether operation has side effects that may affect the expression
evaluation.

Expand All @@ -38,9 +38,28 @@ def CExpressionInterface : OpInterface<"CExpressionInterface"> {
};
```
}],
"bool", "hasSideEffects", (ins), /*methodBody=*/[{}],
/*defaultImplementation=*/[{
"bool", "hasSideEffects", (ins), /*methodBody=*/[{}],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong format?

/*defaultImplementation=*/[{
return true;
}]>,
InterfaceMethod<[{
Check whether operation must be inlined into all its users.

By default operation is not marked as always inlined.

```c++
class ConcreteOp ... {
public:
bool alwaysInline() {
// That way we can override the default implementation.
return true;
}
};
```
}],
"bool", "alwaysInline", (ins), /*methodBody=*/[{}],
/*defaultImplementation=*/[{
return false;
}]>,
];
}
Expand Down
13 changes: 12 additions & 1 deletion mlir/lib/Dialect/EmitC/IR/EmitC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,8 @@ LogicalResult ExpressionOp::verify() {
Operation *op = worklist.back();
worklist.pop_back();
if (visited.contains(op)) {
if (cast<CExpressionInterface>(op).hasSideEffects())
auto cExpr = cast<CExpressionInterface>(op);
if (!cExpr.alwaysInline() && cExpr.hasSideEffects())
return emitOpError(
"requires exactly one use for operations with side effects");
}
Expand All @@ -494,6 +495,12 @@ LogicalResult ExpressionOp::verify() {
}
}

if (getDoNotInline() &&
cast<emitc::CExpressionInterface>(rootOp).alwaysInline()) {
return emitOpError("root operation must be inlined but expression is marked"
" do-not-inline");
}

return success();
}

Expand Down Expand Up @@ -980,6 +987,10 @@ LogicalResult emitc::YieldOp::verify() {
if (!result && containingOp->getNumResults() != 0)
return emitOpError() << "does not yield a value to be returned by parent";

if (result && isa<emitc::LValueType>(result.getType()) &&
!isa<ExpressionOp>(containingOp))
return emitOpError() << "yielding lvalues is not supported for this op";

return success();
}

Expand Down
Loading
Loading