Skip to content

Commit 65c857e

Browse files
authored
[CIR][CIRGen] Add CIRGen support for assume statement (#1205)
This PR adds CIRGen support for C++23 `[[assume(expr)]]` statement.
1 parent c566b19 commit 65c857e

File tree

4 files changed

+42
-3
lines changed

4 files changed

+42
-3
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
11101110
if (E->getArg(0)->HasSideEffects(getContext()))
11111111
return RValue::get(nullptr);
11121112

1113-
mlir::Value argValue = emitScalarExpr(E->getArg(0));
1113+
mlir::Value argValue = emitCheckedArgForAssume(E->getArg(0));
11141114
builder.create<cir::AssumeOp>(getLoc(E->getExprLoc()), argValue);
11151115
return RValue::get(nullptr);
11161116
}
@@ -2478,6 +2478,15 @@ mlir::Value CIRGenFunction::emitCheckedArgForBuiltin(const Expr *E,
24782478
llvm_unreachable("NYI");
24792479
}
24802480

2481+
mlir::Value CIRGenFunction::emitCheckedArgForAssume(const Expr *E) {
2482+
mlir::Value argValue = evaluateExprAsBool(E);
2483+
if (!SanOpts.has(SanitizerKind::Builtin))
2484+
return argValue;
2485+
2486+
assert(!MissingFeatures::sanitizerBuiltin());
2487+
llvm_unreachable("NYI");
2488+
}
2489+
24812490
static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *CGF,
24822491
unsigned BuiltinID,
24832492
const CallExpr *E,

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,6 +1782,10 @@ class CIRGenFunction : public CIRGenTypeCache {
17821782
/// enabled, a runtime check specified by \p Kind is also emitted.
17831783
mlir::Value emitCheckedArgForBuiltin(const Expr *E, BuiltinCheckKind Kind);
17841784

1785+
/// Emits an argument for a call to a `__builtin_assume`. If the builtin
1786+
/// sanitizer is enabled, a runtime check is also emitted.
1787+
mlir::Value emitCheckedArgForAssume(const Expr *E);
1788+
17851789
/// returns true if aggregate type has a volatile member.
17861790
/// TODO(cir): this could be a common AST helper between LLVM / CIR.
17871791
bool hasVolatileMember(QualType T) {

clang/lib/CIR/CodeGen/CIRGenStmt.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,16 @@ CIRGenFunction::emitAttributedStmt(const AttributedStmt &S) {
346346
case attr::AlwaysInline:
347347
case attr::MustTail:
348348
llvm_unreachable("NIY attributes");
349+
case attr::CXXAssume: {
350+
const Expr *assumption = cast<CXXAssumeAttr>(A)->getAssumption();
351+
if (getLangOpts().CXXAssumptions && builder.getInsertionBlock() &&
352+
!assumption->HasSideEffects(getContext())) {
353+
mlir::Value assumptionValue = emitCheckedArgForAssume(assumption);
354+
builder.create<cir::AssumeOp>(getLoc(S.getSourceRange()),
355+
assumptionValue);
356+
}
357+
break;
358+
}
349359
default:
350360
break;
351361
}

clang/test/CIR/CodeGen/builtin-assume.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -fclangir -emit-cir %s -o %t.cir
22
// RUN: FileCheck %s --check-prefix=CIR --input-file=%t.cir
3-
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -fclangir -emit-llvm %s -o %t.ll
44
// RUN: FileCheck %s --check-prefix=LLVM --input-file=%t.ll
55

66
int test_assume(int x) {
@@ -19,6 +19,22 @@ int test_assume(int x) {
1919
// LLVM: %[[#cond:]] = trunc i8 %{{.+}} to i1
2020
// LLVM-NEXT: call void @llvm.assume(i1 %[[#cond]])
2121

22+
int test_assume_attr(int x) {
23+
[[assume(x > 0)]];
24+
return x;
25+
}
26+
27+
// CIR: cir.func @_Z16test_assume_attri
28+
// CIR: %[[#x:]] = cir.load %{{.+}} : !cir.ptr<!s32i>, !s32i
29+
// CIR-NEXT: %[[#zero:]] = cir.const #cir.int<0> : !s32i
30+
// CIR-NEXT: %[[#cond:]] = cir.cmp(gt, %[[#x]], %[[#zero]]) : !s32i, !cir.bool
31+
// CIR-NEXT: cir.assume %[[#cond]] : !cir.bool
32+
// CIR: }
33+
34+
// LLVM: @_Z16test_assume_attri
35+
// LLVM: %[[#cond:]] = trunc i8 %{{.+}} to i1
36+
// LLVM-NEXT: call void @llvm.assume(i1 %[[#cond]])
37+
2238
int test_assume_aligned(int *ptr) {
2339
int *aligned = (int *)__builtin_assume_aligned(ptr, 8);
2440
return *aligned;

0 commit comments

Comments
 (0)