Skip to content

Commit

Permalink
[CIR][CIRGen] Implement "if consteval" code generation (#446)
Browse files Browse the repository at this point in the history
Emit the false-branch of the consteval if statement, if any.
  • Loading branch information
keryell authored and lanza committed Apr 29, 2024
1 parent 0a4b775 commit 5e1db07
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
11 changes: 9 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,16 +371,23 @@ static void terminateBody(CIRGenBuilderTy &builder, mlir::Region &r,
}

mlir::LogicalResult CIRGenFunction::buildIfStmt(const IfStmt &S) {
mlir::LogicalResult res = mlir::success();
// The else branch of a consteval if statement is always the only branch
// that can be runtime evaluated.
const Stmt *ConstevalExecuted;
if (S.isConsteval()) {
llvm_unreachable("consteval nyi");
ConstevalExecuted = S.isNegatedConsteval() ? S.getThen() : S.getElse();
if (!ConstevalExecuted)
// No runtime code execution required
return res;
}
mlir::LogicalResult res = mlir::success();

// C99 6.8.4.1: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
auto ifStmtBuilder = [&]() -> mlir::LogicalResult {
if (S.isConsteval())
return buildStmt(ConstevalExecuted, /*useCurrentScope=*/true);

if (S.getInit())
if (buildStmt(S.getInit(), /*useCurrentScope=*/true).failed())
return mlir::failure();
Expand Down
33 changes: 33 additions & 0 deletions clang/test/CIR/CodeGen/if-consteval.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

void should_be_used_1();
void should_be_used_2();
void should_be_used_3();
constexpr void should_not_be_used() {}

constexpr void f() {
if consteval {
should_not_be_used(); // CHECK-NOT: call {{.*}}should_not_be_used
} else {
should_be_used_1(); // CHECK: call {{.*}}should_be_used_1
}

if !consteval {
should_be_used_2(); // CHECK: call {{.*}}should_be_used_2
} else {
should_not_be_used(); // CHECK-NOT: call {{.*}}should_not_be_used
}

if consteval {
should_not_be_used(); // CHECK-NOT: call {{.*}}should_not_be_used
}

if !consteval {
should_be_used_3(); // CHECK: call {{.*}}should_be_used_3
}
}

void g() {
f();
}

0 comments on commit 5e1db07

Please sign in to comment.