Skip to content

Commit 712d320

Browse files
committed
[CIR][CIRGen] Implement "if constexpr" code generation
1 parent 00b21e0 commit 712d320

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

clang/lib/CIR/CodeGen/CIRGenStmt.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,16 @@ mlir::LogicalResult CIRGenFunction::buildIfStmt(const IfStmt &S) {
383383
if (buildStmt(S.getInit(), /*useCurrentScope=*/true).failed())
384384
return mlir::failure();
385385

386+
// Handle "if constexpr" explicitly here to avoid generating some
387+
// ill-formed code since in CIR the "if" are no longer simplified
388+
// in this lambda like in Clang but postponed to other MLIR
389+
// passes.
390+
if (S.isConstexpr())
391+
if (auto ndc = S.getNondiscardedCase(getContext())) {
392+
// Replace the "if constexpr" by its non-discarded branch
393+
return buildStmt(ndc.value(), /*useCurrentScope=*/true);
394+
}
395+
386396
if (S.getConditionVariable())
387397
buildDecl(*S.getConditionVariable());
388398

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir-enable -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s
3+
4+
void if0() {
5+
int x = 0;
6+
if constexpr (0 == 0) {
7+
// Declare a variable with same name to be sure we handle the
8+
// scopes correctly
9+
int x = 2;
10+
} else {
11+
int x = 3;
12+
}
13+
if constexpr (0 == 1) {
14+
int x = 4;
15+
} else {
16+
int x = 5;
17+
}
18+
if constexpr (int x = 7; 8 == 8) {
19+
int y = x;
20+
} else {
21+
int y = 2*x;
22+
}
23+
if constexpr (int x = 9; 8 == 10) {
24+
int y = x;
25+
} else {
26+
int y = 3*x;
27+
}
28+
}
29+
30+
// CHECK: cir.func @_Z3if0v() {{.*}}
31+
// CHECK: cir.store %1, %0 : !s32i, cir.ptr <!s32i> loc({{.*}})
32+
// CHECK-NEXT: cir.scope {
33+
// CHECK-NEXT: %2 = cir.alloca !s32i, cir.ptr <!s32i>, ["x", init] {{.*}}
34+
// CHECK-NEXT: %3 = cir.const(#cir.int<2> : !s32i) : !s32i loc({{.*}})
35+
// CHECK-NEXT: cir.store %3, %2 : !s32i, cir.ptr <!s32i> loc({{.*}})
36+
// CHECK-NEXT: } loc({{.*}})
37+
// CHECK-NEXT: cir.scope {
38+
// CHECK-NEXT: %2 = cir.alloca !s32i, cir.ptr <!s32i>, ["x", init] {{.*}}
39+
// CHECK-NEXT: %3 = cir.const(#cir.int<5> : !s32i) : !s32i loc({{.*}})
40+
// CHECK-NEXT: cir.store %3, %2 : !s32i, cir.ptr <!s32i> loc({{.*}})
41+
// CHECK-NEXT: } loc({{.*}})
42+
// CHECK-NEXT: cir.scope {
43+
// CHECK-NEXT: %2 = cir.alloca !s32i, cir.ptr <!s32i>, ["x", init] {{.*}}
44+
// CHECK-NEXT: %3 = cir.alloca !s32i, cir.ptr <!s32i>, ["y", init] {{.*}}
45+
// CHECK-NEXT: %4 = cir.const(#cir.int<7> : !s32i) : !s32i loc({{.*}})
46+
// CHECK-NEXT: cir.store %4, %2 : !s32i, cir.ptr <!s32i> loc({{.*}})
47+
// CHECK-NEXT: %5 = cir.load %2 : cir.ptr <!s32i>, !s32i loc({{.*}})
48+
// CHECK-NEXT: cir.store %5, %3 : !s32i, cir.ptr <!s32i> loc({{.*}})
49+
// CHECK-NEXT: } loc({{.*}})
50+
// CHECK-NEXT: cir.scope {
51+
// CHECK-NEXT: %2 = cir.alloca !s32i, cir.ptr <!s32i>, ["x", init] {{.*}}
52+
// CHECK-NEXT: %3 = cir.alloca !s32i, cir.ptr <!s32i>, ["y", init] {{.*}}
53+
// CHECK-NEXT: %4 = cir.const(#cir.int<9> : !s32i) : !s32i loc({{.*}})
54+
// CHECK-NEXT: cir.store %4, %2 : !s32i, cir.ptr <!s32i> loc({{.*}})
55+
// CHECK-NEXT: %5 = cir.const(#cir.int<3> : !s32i) : !s32i loc({{.*}})
56+
// CHECK-NEXT: %6 = cir.load %2 : cir.ptr <!s32i>, !s32i loc({{.*}})
57+
// CHECK-NEXT: %7 = cir.binop(mul, %5, %6) : !s32i loc({{.*}})
58+
// CHECK-NEXT: cir.store %7, %3 : !s32i, cir.ptr <!s32i> loc({{.*}})
59+
// CHECK-NEXT: } loc({{.*}})
60+
// CHECK-NEXT: cir.return loc({{.*}})

0 commit comments

Comments
 (0)