Skip to content

Commit 0bcc782

Browse files
marbremgehre-amd
authored andcommitted
[mlir][EmitC] Add func, call and return operations and conversions (llvm#79612)
This adds a `func`, `call` and `return` operation to the EmitC dialect, closely related to the corresponding operations of the Func dialect. In contrast to the operations of the Func dialect, the EmitC operations do not support multiple results. The `emitc.func` op features a `specifiers` argument that for example allows, with corresponding support in the emitter, to emit `inline static` functions. Furthermore, this adds patterns and a pass to convert the Func dialect to EmitC. A `func.func` op that is `private` is converted to `emitc.func` with a `"static"` specifier.
1 parent 763ebf9 commit 0bcc782

File tree

18 files changed

+815
-30
lines changed

18 files changed

+815
-30
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===- FuncToEmitC.h - Func to EmitC Patterns -------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITC_H
10+
#define MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITC_H
11+
12+
namespace mlir {
13+
class RewritePatternSet;
14+
15+
void populateFuncToEmitCPatterns(RewritePatternSet &patterns);
16+
} // namespace mlir
17+
18+
#endif // MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITC_H
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===- FuncToEmitCPass.h - Func to EmitC Pass -------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITCPASS_H
10+
#define MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITCPASS_H
11+
12+
#include <memory>
13+
14+
namespace mlir {
15+
class Pass;
16+
17+
#define GEN_PASS_DECL_CONVERTFUNCTOEMITC
18+
#include "mlir/Conversion/Passes.h.inc"
19+
} // namespace mlir
20+
21+
#endif // MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITCPASS_H

mlir/include/mlir/Conversion/Passes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "mlir/Conversion/ControlFlowToSPIRV/ControlFlowToSPIRV.h"
3030
#include "mlir/Conversion/ControlFlowToSPIRV/ControlFlowToSPIRVPass.h"
3131
#include "mlir/Conversion/ConvertToLLVM/ToLLVMPass.h"
32+
#include "mlir/Conversion/FuncToEmitC/FuncToEmitCPass.h"
3233
#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h"
3334
#include "mlir/Conversion/FuncToSPIRV/FuncToSPIRVPass.h"
3435
#include "mlir/Conversion/GPUCommon/GPUCommonPass.h"

mlir/include/mlir/Conversion/Passes.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,15 @@ def ConvertControlFlowToSPIRV : Pass<"convert-cf-to-spirv"> {
356356
];
357357
}
358358

359+
//===----------------------------------------------------------------------===//
360+
// FuncToEmitC
361+
//===----------------------------------------------------------------------===//
362+
363+
def ConvertFuncToEmitC : Pass<"convert-func-to-emitc", "ModuleOp"> {
364+
let summary = "Convert Func dialect to EmitC dialect";
365+
let dependentDialects = ["emitc::EmitCDialect"];
366+
}
367+
359368
//===----------------------------------------------------------------------===//
360369
// FuncToLLVM
361370
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/EmitC/IR/EmitC.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "mlir/IR/Dialect.h"
2121
#include "mlir/Interfaces/CastInterfaces.h"
2222
#include "mlir/Interfaces/ControlFlowInterfaces.h"
23+
#include "mlir/Interfaces/FunctionInterfaces.h"
2324
#include "mlir/Interfaces/SideEffectInterfaces.h"
2425

2526
#include "mlir/Dialect/EmitC/IR/EmitCDialect.h.inc"

mlir/include/mlir/Dialect/EmitC/IR/EmitC.td

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
include "mlir/Dialect/EmitC/IR/EmitCAttributes.td"
1717
include "mlir/Dialect/EmitC/IR/EmitCTypes.td"
1818

19+
include "mlir/Interfaces/CallInterfaces.td"
1920
include "mlir/Interfaces/CastInterfaces.td"
2021
include "mlir/Interfaces/ControlFlowInterfaces.td"
22+
include "mlir/Interfaces/FunctionInterfaces.td"
2123
include "mlir/Interfaces/SideEffectInterfaces.td"
2224
include "mlir/IR/RegionKindInterface.td"
2325

@@ -386,6 +388,174 @@ def EmitC_ForOp : EmitC_Op<"for",
386388
let hasRegionVerifier = 1;
387389
}
388390

391+
def EmitC_CallOp : EmitC_Op<"call",
392+
[CallOpInterface,
393+
DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
394+
let summary = "call operation";
395+
let description = [{
396+
The `emitc.call` operation represents a direct call to an `emitc.func`
397+
that is within the same symbol scope as the call. The operands and result type
398+
of the call must match the specified function type. The callee is encoded as a
399+
symbol reference attribute named "callee".
400+
401+
Example:
402+
403+
```mlir
404+
%2 = emitc.call @my_add(%0, %1) : (f32, f32) -> f32
405+
```
406+
}];
407+
let arguments = (ins FlatSymbolRefAttr:$callee, Variadic<AnyType>:$operands);
408+
let results = (outs Variadic<AnyType>);
409+
410+
let builders = [
411+
OpBuilder<(ins "FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{
412+
$_state.addOperands(operands);
413+
$_state.addAttribute("callee", SymbolRefAttr::get(callee));
414+
$_state.addTypes(callee.getFunctionType().getResults());
415+
}]>,
416+
OpBuilder<(ins "SymbolRefAttr":$callee, "TypeRange":$results,
417+
CArg<"ValueRange", "{}">:$operands), [{
418+
$_state.addOperands(operands);
419+
$_state.addAttribute("callee", callee);
420+
$_state.addTypes(results);
421+
}]>,
422+
OpBuilder<(ins "StringAttr":$callee, "TypeRange":$results,
423+
CArg<"ValueRange", "{}">:$operands), [{
424+
build($_builder, $_state, SymbolRefAttr::get(callee), results, operands);
425+
}]>,
426+
OpBuilder<(ins "StringRef":$callee, "TypeRange":$results,
427+
CArg<"ValueRange", "{}">:$operands), [{
428+
build($_builder, $_state, StringAttr::get($_builder.getContext(), callee),
429+
results, operands);
430+
}]>];
431+
432+
let extraClassDeclaration = [{
433+
FunctionType getCalleeType();
434+
435+
/// Get the argument operands to the called function.
436+
operand_range getArgOperands() {
437+
return {arg_operand_begin(), arg_operand_end()};
438+
}
439+
440+
MutableOperandRange getArgOperandsMutable() {
441+
return getOperandsMutable();
442+
}
443+
444+
operand_iterator arg_operand_begin() { return operand_begin(); }
445+
operand_iterator arg_operand_end() { return operand_end(); }
446+
447+
/// Return the callee of this operation.
448+
CallInterfaceCallable getCallableForCallee() {
449+
return (*this)->getAttrOfType<SymbolRefAttr>("callee");
450+
}
451+
452+
/// Set the callee for this operation.
453+
void setCalleeFromCallable(CallInterfaceCallable callee) {
454+
(*this)->setAttr("callee", callee.get<SymbolRefAttr>());
455+
}
456+
}];
457+
458+
let assemblyFormat = [{
459+
$callee `(` $operands `)` attr-dict `:` functional-type($operands, results)
460+
}];
461+
}
462+
463+
def EmitC_FuncOp : EmitC_Op<"func", [
464+
AutomaticAllocationScope,
465+
FunctionOpInterface, IsolatedFromAbove
466+
]> {
467+
let summary = "An operation with a name containing a single `SSACFG` region";
468+
let description = [{
469+
Operations within the function cannot implicitly capture values defined
470+
outside of the function, i.e. Functions are `IsolatedFromAbove`. All
471+
external references must use function arguments or attributes that establish
472+
a symbolic connection (e.g. symbols referenced by name via a string
473+
attribute like SymbolRefAttr). While the MLIR textual form provides a nice
474+
inline syntax for function arguments, they are internally represented as
475+
“block arguments” to the first block in the region.
476+
477+
Only dialect attribute names may be specified in the attribute dictionaries
478+
for function arguments, results, or the function itself.
479+
480+
Example:
481+
482+
```mlir
483+
// A function with no results:
484+
emitc.func @foo(%arg0 : i32) {
485+
emitc.call_opaque "bar" (%arg0) : (i32) -> ()
486+
emitc.return
487+
}
488+
489+
// A function with its argument as single result:
490+
emitc.func @foo(%arg0 : i32) -> i32 {
491+
emitc.return %arg0 : i32
492+
}
493+
494+
// A function with specifiers attribute:
495+
emitc.func @example_specifiers_fn_attr() -> i32
496+
attributes {specifiers = ["static","inline"]} {
497+
%0 = emitc.call_opaque "foo" (): () -> i32
498+
emitc.return %0 : i32
499+
}
500+
501+
```
502+
}];
503+
let arguments = (ins SymbolNameAttr:$sym_name,
504+
TypeAttrOf<FunctionType>:$function_type,
505+
OptionalAttr<StrArrayAttr>:$specifiers,
506+
OptionalAttr<DictArrayAttr>:$arg_attrs,
507+
OptionalAttr<DictArrayAttr>:$res_attrs);
508+
let regions = (region AnyRegion:$body);
509+
510+
let builders = [OpBuilder<(ins
511+
"StringRef":$name, "FunctionType":$type,
512+
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs,
513+
CArg<"ArrayRef<DictionaryAttr>", "{}">:$argAttrs)
514+
>];
515+
let extraClassDeclaration = [{
516+
//===------------------------------------------------------------------===//
517+
// FunctionOpInterface Methods
518+
//===------------------------------------------------------------------===//
519+
520+
/// Returns the region on the current operation that is callable. This may
521+
/// return null in the case of an external callable object, e.g. an external
522+
/// function.
523+
::mlir::Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); }
524+
525+
/// Returns the argument types of this function.
526+
ArrayRef<Type> getArgumentTypes() { return getFunctionType().getInputs(); }
527+
528+
/// Returns the result types of this function.
529+
ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); }
530+
}];
531+
let hasCustomAssemblyFormat = 1;
532+
let hasVerifier = 1;
533+
}
534+
535+
def EmitC_ReturnOp : EmitC_Op<"return", [Pure, HasParent<"FuncOp">,
536+
ReturnLike, Terminator]> {
537+
let summary = "Function return operation";
538+
let description = [{
539+
The `emitc.return` operation represents a return operation within a function.
540+
The operation takes zero or exactly one operand and produces no results.
541+
The operand number and type must match the signature of the function
542+
that contains the operation.
543+
544+
Example:
545+
546+
```mlir
547+
emitc.func @foo() : (i32) {
548+
...
549+
emitc.return %0 : i32
550+
}
551+
```
552+
}];
553+
let arguments = (ins Optional<AnyType>:$operand);
554+
555+
let assemblyFormat = "attr-dict ($operand^ `:` type($operand))?";
556+
let hasVerifier = 1;
557+
}
558+
389559
def EmitC_IncludeOp
390560
: EmitC_Op<"include", [HasParent<"ModuleOp">]> {
391561
let summary = "Include operation";

mlir/lib/Conversion/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ add_subdirectory(ControlFlowToLLVM)
1818
add_subdirectory(ControlFlowToSCF)
1919
add_subdirectory(ControlFlowToSPIRV)
2020
add_subdirectory(ConvertToLLVM)
21+
add_subdirectory(FuncToEmitC)
2122
add_subdirectory(FuncToLLVM)
2223
add_subdirectory(FuncToSPIRV)
2324
add_subdirectory(GPUCommon)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
add_mlir_conversion_library(MLIRFuncToEmitC
2+
FuncToEmitC.cpp
3+
FuncToEmitCPass.cpp
4+
5+
ADDITIONAL_HEADER_DIRS
6+
${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/FuncToEmitC
7+
8+
DEPENDS
9+
MLIRConversionPassIncGen
10+
11+
LINK_LIBS PUBLIC
12+
MLIREmitCDialect
13+
MLIRFuncDialect
14+
MLIRPass
15+
MLIRTransformUtils
16+
)

0 commit comments

Comments
 (0)