@@ -3574,6 +3574,39 @@ def DeleteArrayOp : CIR_Op<"delete.array">,
3574
3574
// CallOp and TryCallOp
3575
3575
//===----------------------------------------------------------------------===//
3576
3576
3577
+ def SE_All : I32EnumAttrCase<"All", 1, "all">;
3578
+ def SE_Pure : I32EnumAttrCase<"Pure", 2, "pure">;
3579
+ def SE_Const : I32EnumAttrCase<"Const", 3, "const">;
3580
+
3581
+ def SideEffect : I32EnumAttr<
3582
+ "SideEffect", "allowed side effects of a function",
3583
+ [SE_All, SE_Pure, SE_Const]> {
3584
+ let description = [{
3585
+ The side effect attribute specifies the possible side effects of the callee
3586
+ of a call operation. This is an enumeration attribute and all possible
3587
+ enumerators are:
3588
+
3589
+ - all: The callee can have any side effects. This is the default if no side
3590
+ effects are explicitly listed.
3591
+ - pure: The callee may read data from memory, but it cannot write data to
3592
+ memory. This has the same effect as the GNU C/C++ attribute
3593
+ `__attribute__((pure))`.
3594
+ - const: The callee may not read or write data from memory. This has the
3595
+ same effect as the GNU C/C++ attribute `__attribute__((const))`.
3596
+
3597
+ Examples:
3598
+
3599
+ ```mlir
3600
+ %0 = cir.const #cir.int<0> : !s32i
3601
+ %1 = cir.const #cir.int<1> : !s32i
3602
+ %2 = cir.call @add(%0, %1) : (!s32i, !s32i) -> !s32i side_effect(all)
3603
+ %2 = cir.call @add(%0, %1) : (!s32i, !s32i) -> !s32i side_effect(pure)
3604
+ %2 = cir.call @add(%0, %1) : (!s32i, !s32i) -> !s32i side_effect(const)
3605
+ ```
3606
+ }];
3607
+ let cppNamespace = "::cir";
3608
+ }
3609
+
3577
3610
class CIR_CallOp<string mnemonic, list<Trait> extra_traits = []> :
3578
3611
Op<CIR_Dialect, mnemonic,
3579
3612
!listconcat(extra_traits,
@@ -3633,6 +3666,7 @@ class CIR_CallOp<string mnemonic, list<Trait> extra_traits = []> :
3633
3666
OptionalAttr<FlatSymbolRefAttr>:$callee,
3634
3667
Variadic<CIR_AnyType>:$arg_ops,
3635
3668
DefaultValuedAttr<CallingConv, "CallingConv::C">:$calling_conv,
3669
+ DefaultValuedAttr<SideEffect, "SideEffect::All">:$side_effect,
3636
3670
ExtraFuncAttr:$extra_attrs,
3637
3671
OptionalAttr<ASTCallExprInterface>:$ast
3638
3672
);
@@ -3685,12 +3719,15 @@ def CallOp : CIR_CallOp<"call", [NoRegionArguments]> {
3685
3719
OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType,
3686
3720
CArg<"mlir::ValueRange", "{}">:$operands,
3687
3721
CArg<"CallingConv", "CallingConv::C">:$callingConv,
3722
+ CArg<"SideEffect", "SideEffect::All">:$sideEffect,
3688
3723
CArg<"mlir::UnitAttr", "{}">:$exception), [{
3689
3724
$_state.addOperands(operands);
3690
3725
if (callee)
3691
3726
$_state.addAttribute("callee", callee);
3692
3727
$_state.addAttribute("calling_conv",
3693
3728
CallingConvAttr::get($_builder.getContext(), callingConv));
3729
+ $_state.addAttribute("side_effect",
3730
+ SideEffectAttr::get($_builder.getContext(), sideEffect));
3694
3731
if (exception)
3695
3732
$_state.addAttribute("exception", exception);
3696
3733
if (resType && !isa<VoidType>(resType))
@@ -3702,13 +3739,16 @@ def CallOp : CIR_CallOp<"call", [NoRegionArguments]> {
3702
3739
"FuncType":$fn_type,
3703
3740
CArg<"mlir::ValueRange", "{}">:$operands,
3704
3741
CArg<"CallingConv", "CallingConv::C">:$callingConv,
3742
+ CArg<"SideEffect", "SideEffect::All">:$sideEffect,
3705
3743
CArg<"mlir::UnitAttr", "{}">:$exception), [{
3706
3744
$_state.addOperands(ValueRange{ind_target});
3707
3745
$_state.addOperands(operands);
3708
3746
if (!fn_type.isVoid())
3709
3747
$_state.addTypes(fn_type.getReturnType());
3710
3748
$_state.addAttribute("calling_conv",
3711
3749
CallingConvAttr::get($_builder.getContext(), callingConv));
3750
+ $_state.addAttribute("side_effect",
3751
+ SideEffectAttr::get($_builder.getContext(), sideEffect));
3712
3752
if (exception)
3713
3753
$_state.addAttribute("exception", exception);
3714
3754
// Create region placeholder for potential cleanups.
@@ -3751,7 +3791,8 @@ def TryCallOp : CIR_CallOp<"try_call",
3751
3791
CArg<"mlir::ValueRange", "{}">:$operands,
3752
3792
CArg<"mlir::ValueRange", "{}">:$contOperands,
3753
3793
CArg<"mlir::ValueRange", "{}">:$landingPadOperands,
3754
- CArg<"CallingConv", "CallingConv::C">:$callingConv), [{
3794
+ CArg<"CallingConv", "CallingConv::C">:$callingConv,
3795
+ CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{
3755
3796
$_state.addOperands(operands);
3756
3797
if (callee)
3757
3798
$_state.addAttribute("callee", callee);
@@ -3760,6 +3801,8 @@ def TryCallOp : CIR_CallOp<"try_call",
3760
3801
3761
3802
$_state.addAttribute("calling_conv",
3762
3803
CallingConvAttr::get($_builder.getContext(), callingConv));
3804
+ $_state.addAttribute("side_effect",
3805
+ SideEffectAttr::get($_builder.getContext(), sideEffect));
3763
3806
3764
3807
// Handle branches
3765
3808
$_state.addOperands(contOperands);
@@ -3780,7 +3823,8 @@ def TryCallOp : CIR_CallOp<"try_call",
3780
3823
CArg<"mlir::ValueRange", "{}">:$operands,
3781
3824
CArg<"mlir::ValueRange", "{}">:$contOperands,
3782
3825
CArg<"mlir::ValueRange", "{}">:$landingPadOperands,
3783
- CArg<"CallingConv", "CallingConv::C">:$callingConv), [{
3826
+ CArg<"CallingConv", "CallingConv::C">:$callingConv,
3827
+ CArg<"SideEffect", "SideEffect::All">:$sideEffect), [{
3784
3828
::llvm::SmallVector<mlir::Value, 4> finalCallOperands({ind_target});
3785
3829
finalCallOperands.append(operands.begin(), operands.end());
3786
3830
$_state.addOperands(finalCallOperands);
@@ -3790,6 +3834,8 @@ def TryCallOp : CIR_CallOp<"try_call",
3790
3834
3791
3835
$_state.addAttribute("calling_conv",
3792
3836
CallingConvAttr::get($_builder.getContext(), callingConv));
3837
+ $_state.addAttribute("side_effect",
3838
+ SideEffectAttr::get($_builder.getContext(), sideEffect));
3793
3839
3794
3840
// Handle branches
3795
3841
$_state.addOperands(contOperands);
@@ -4196,7 +4242,7 @@ def MemCpyInlineOp : CIR_MemOp<"memcpy_inline"> {
4196
4242
Given two CIR pointers, `src` and `dst`, `memcpy_inline` will copy `len`
4197
4243
bytes from the memory pointed by `src` to the memory pointed by `dst`.
4198
4244
4199
- Unlike `cir.libc.memcpy`, this Op guarantees that no external functions
4245
+ Unlike `cir.libc.memcpy`, this Op guarantees that no external functions
4200
4246
are called, and length of copied bytes is a constant.
4201
4247
4202
4248
Examples:
0 commit comments