@@ -1858,6 +1858,36 @@ def FuncOp : CIR_Op<"func", [
18581858// CallOp
18591859//===----------------------------------------------------------------------===//
18601860
1861+ def CIR_SideEffect : CIR_I32EnumAttr<
1862+ "SideEffect", "allowed side effects of a function", [
1863+ I32EnumAttrCase<"All", 1, "all">,
1864+ I32EnumAttrCase<"Pure", 2, "pure">,
1865+ I32EnumAttrCase<"Const", 3, "const">
1866+ ]> {
1867+ let description = [{
1868+ The side effect attribute specifies the possible side effects of the callee
1869+ of a call operation. This is an enumeration attribute and all possible
1870+ enumerators are:
1871+
1872+ - all: The callee can have any side effects. This is the default if no side
1873+ effects are explicitly listed.
1874+ - pure: The callee may read data from memory, but it cannot write data to
1875+ memory. This has the same effect as the GNU C/C++ attribute
1876+ `__attribute__((pure))`.
1877+ - const: The callee may not read or write data from memory. This has the
1878+ same effect as the GNU C/C++ attribute `__attribute__((const))`.
1879+
1880+ Examples:
1881+
1882+ ```mlir
1883+ %2 = cir.call @add(%0, %1) : (!s32i, !s32i) -> !s32i
1884+ %2 = cir.call @add(%0, %1) : (!s32i, !s32i) -> !s32i side_effect(pure)
1885+ %2 = cir.call @add(%0, %1) : (!s32i, !s32i) -> !s32i side_effect(const)
1886+ ```
1887+ }];
1888+ let cppNamespace = "::cir";
1889+ }
1890+
18611891class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
18621892 : Op<CIR_Dialect, mnemonic,
18631893 !listconcat(extra_traits,
@@ -1911,7 +1941,8 @@ class CIR_CallOpBase<string mnemonic, list<Trait> extra_traits = []>
19111941 // will add in the future.
19121942
19131943 dag commonArgs = (ins OptionalAttr<FlatSymbolRefAttr>:$callee,
1914- Variadic<CIR_AnyType>:$args);
1944+ Variadic<CIR_AnyType>:$args,
1945+ DefaultValuedAttr<CIR_SideEffect, "SideEffect::All">:$side_effect);
19151946}
19161947
19171948def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
@@ -1942,20 +1973,26 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
19421973 let builders = [
19431974 // Build a call op for a direct call
19441975 OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType,
1945- "mlir::ValueRange":$operands), [{
1976+ "mlir::ValueRange":$operands,
1977+ CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{
19461978 assert(callee && "callee attribute is required for direct call");
19471979 $_state.addOperands(operands);
19481980 $_state.addAttribute("callee", callee);
1981+ $_state.addAttribute("side_effect",
1982+ SideEffectAttr::get($_builder.getContext(), sideEffect));
19491983 if (resType && !isa<VoidType>(resType))
19501984 $_state.addTypes(resType);
19511985 }]>,
19521986 // Build a call op for an indirect call
19531987 OpBuilder<(ins "mlir::Value":$calleePtr, "mlir::Type":$resType,
1954- "mlir::ValueRange":$operands), [{
1988+ "mlir::ValueRange":$operands,
1989+ CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{
19551990 $_state.addOperands(calleePtr);
19561991 $_state.addOperands(operands);
19571992 if (resType && !isa<VoidType>(resType))
19581993 $_state.addTypes(resType);
1994+ $_state.addAttribute("side_effect",
1995+ SideEffectAttr::get($_builder.getContext(), sideEffect));
19591996 }]>,
19601997 ];
19611998}
0 commit comments