diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 6138fbc10ccd..82787e41132c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -383,6 +383,16 @@ mlir::LogicalResult CIRGenFunction::buildIfStmt(const IfStmt &S) { if (buildStmt(S.getInit(), /*useCurrentScope=*/true).failed()) return mlir::failure(); + // Handle "if constexpr" explicitly here to avoid generating some + // ill-formed code since in CIR the "if" are no longer simplified + // in this lambda like in Clang but postponed to other MLIR + // passes. + if (S.isConstexpr()) + if (auto ndc = S.getNondiscardedCase(getContext())) { + // Replace the "if constexpr" by its non-discarded branch + return buildStmt(ndc.value(), /*useCurrentScope=*/true); + } + if (S.getConditionVariable()) buildDecl(*S.getConditionVariable()); diff --git a/clang/test/CIR/CodeGen/if-constexpr.cpp b/clang/test/CIR/CodeGen/if-constexpr.cpp new file mode 100644 index 000000000000..1e53c681c3cc --- /dev/null +++ b/clang/test/CIR/CodeGen/if-constexpr.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir-enable -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +void if0() { + int x = 0; + if constexpr (0 == 0) { + // Declare a variable with same name to be sure we handle the + // scopes correctly + int x = 2; + } else { + int x = 3; + } + if constexpr (0 == 1) { + int x = 4; + } else { + int x = 5; + } + if constexpr (int x = 7; 8 == 8) { + int y = x; + } else { + int y = 2*x; + } + if constexpr (int x = 9; 8 == 10) { + int y = x; + } else { + int y = 3*x; + } +} + +// CHECK: cir.func @_Z3if0v() {{.*}} +// CHECK: cir.store %1, %0 : !s32i, cir.ptr loc({{.*}}) +// CHECK-NEXT: cir.scope { +// CHECK-NEXT: %2 = cir.alloca !s32i, cir.ptr , ["x", init] {{.*}} +// CHECK-NEXT: %3 = cir.const(#cir.int<2> : !s32i) : !s32i loc({{.*}}) +// CHECK-NEXT: cir.store %3, %2 : !s32i, cir.ptr loc({{.*}}) +// CHECK-NEXT: } loc({{.*}}) +// CHECK-NEXT: cir.scope { +// CHECK-NEXT: %2 = cir.alloca !s32i, cir.ptr , ["x", init] {{.*}} +// CHECK-NEXT: %3 = cir.const(#cir.int<5> : !s32i) : !s32i loc({{.*}}) +// CHECK-NEXT: cir.store %3, %2 : !s32i, cir.ptr loc({{.*}}) +// CHECK-NEXT: } loc({{.*}}) +// CHECK-NEXT: cir.scope { +// CHECK-NEXT: %2 = cir.alloca !s32i, cir.ptr , ["x", init] {{.*}} +// CHECK-NEXT: %3 = cir.alloca !s32i, cir.ptr , ["y", init] {{.*}} +// CHECK-NEXT: %4 = cir.const(#cir.int<7> : !s32i) : !s32i loc({{.*}}) +// CHECK-NEXT: cir.store %4, %2 : !s32i, cir.ptr loc({{.*}}) +// CHECK-NEXT: %5 = cir.load %2 : cir.ptr , !s32i loc({{.*}}) +// CHECK-NEXT: cir.store %5, %3 : !s32i, cir.ptr loc({{.*}}) +// CHECK-NEXT: } loc({{.*}}) +// CHECK-NEXT: cir.scope { +// CHECK-NEXT: %2 = cir.alloca !s32i, cir.ptr , ["x", init] {{.*}} +// CHECK-NEXT: %3 = cir.alloca !s32i, cir.ptr , ["y", init] {{.*}} +// CHECK-NEXT: %4 = cir.const(#cir.int<9> : !s32i) : !s32i loc({{.*}}) +// CHECK-NEXT: cir.store %4, %2 : !s32i, cir.ptr loc({{.*}}) +// CHECK-NEXT: %5 = cir.const(#cir.int<3> : !s32i) : !s32i loc({{.*}}) +// CHECK-NEXT: %6 = cir.load %2 : cir.ptr , !s32i loc({{.*}}) +// CHECK-NEXT: %7 = cir.binop(mul, %5, %6) : !s32i loc({{.*}}) +// CHECK-NEXT: cir.store %7, %3 : !s32i, cir.ptr loc({{.*}}) +// CHECK-NEXT: } loc({{.*}}) +// CHECK-NEXT: cir.return loc({{.*}})