[clang] [CIR] Add if statement support (PR #134333)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 4 12:12:31 PDT 2025
================
@@ -462,6 +462,58 @@ def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp", "DoWhileOp",
let hasVerifier = 1;
}
+//===----------------------------------------------------------------------===//
+// IfOp
+//===----------------------------------------------------------------------===//
+
+def IfOp : CIR_Op<"if",
+ [DeclareOpInterfaceMethods<RegionBranchOpInterface>,
+ RecursivelySpeculatable, AutomaticAllocationScope, NoRegionArguments]>{
+
+ let summary = "the if-then-else operation";
+ let description = [{
+ The `cir.if` operation represents an if-then-else construct for
+ conditionally executing two regions of code. The operand is a `cir.bool`
+ type.
+
+ Examples:
+
+ ```mlir
+ cir.if %b {
----------------
andykaylor wrote:
I'm guessing the reason for the difference is that the condition only needs to be executed once for if statements. Any operations needed to evaluate the condition will appear in the lexical scope enclosing the if operation, similar to how the init section of for loops are handled.
I think it would be good to change for consistency (and maybe also revisit the init section of for loops).
Consider:
```
if (int x = *p)
n += x;
```
Gives us:
```
cir.scope {
%3 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
%4 = cir.load deref %0 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
%5 = cir.load %4 : !cir.ptr<!s32i>, !s32i
cir.store %5, %3 : !s32i, !cir.ptr<!s32i>
%6 = cir.load %3 : !cir.ptr<!s32i>, !s32i
%7 = cir.cast(int_to_bool, %6 : !s32i), !cir.bool
cir.if %7 {
%8 = cir.load %3 : !cir.ptr<!s32i>, !s32i
%9 = cir.load %1 : !cir.ptr<!s32i>, !s32i
%10 = cir.binop(add, %9, %8) nsw : !s32i
cir.store %10, %1 : !s32i, !cir.ptr<!s32i>
}
}
```
But
```
while (int x = *p)
n += x;
```
Gives us:
```
cir.scope {
%3 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
cir.while {
%4 = cir.load deref %0 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
%5 = cir.load %4 : !cir.ptr<!s32i>, !s32i
cir.store %5, %3 : !s32i, !cir.ptr<!s32i>
%6 = cir.load %3 : !cir.ptr<!s32i>, !s32i
%7 = cir.cast(int_to_bool, %6 : !s32i), !cir.bool
cir.condition(%7)
} do {
%4 = cir.load %3 : !cir.ptr<!s32i>, !s32i
%5 = cir.load %1 : !cir.ptr<!s32i>, !s32i
%6 = cir.binop(add, %5, %4) nsw : !s32i
cir.store %6, %1 : !s32i, !cir.ptr<!s32i>
cir.yield
}
}
```
Maybe the if representation should be:
```
cir.scope {
%3 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
cir.if {
%4 = cir.load deref %0 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
%5 = cir.load %4 : !cir.ptr<!s32i>, !s32i
cir.store %5, %3 : !s32i, !cir.ptr<!s32i>
%6 = cir.load %3 : !cir.ptr<!s32i>, !s32i
%7 = cir.cast(int_to_bool, %6 : !s32i), !cir.bool
cir.condition(%7)
} then {
%8 = cir.load %3 : !cir.ptr<!s32i>, !s32i
%9 = cir.load %1 : !cir.ptr<!s32i>, !s32i
%10 = cir.binop(add, %9, %8) nsw : !s32i
cir.store %10, %1 : !s32i, !cir.ptr<!s32i>
}
}
```
@bcardosolopes What do you think?
https://github.com/llvm/llvm-project/pull/134333
More information about the cfe-commits
mailing list