Skip to content

Commit

Permalink
[CIR][CIRGen] Add CIRGen support for assume statement (#1205)
Browse files Browse the repository at this point in the history
This PR adds CIRGen support for C++23 `[[assume(expr)]]` statement.
  • Loading branch information
Lancern authored Dec 6, 2024
1 parent c566b19 commit 65c857e
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 3 deletions.
11 changes: 10 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
if (E->getArg(0)->HasSideEffects(getContext()))
return RValue::get(nullptr);

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

mlir::Value CIRGenFunction::emitCheckedArgForAssume(const Expr *E) {
mlir::Value argValue = evaluateExprAsBool(E);
if (!SanOpts.has(SanitizerKind::Builtin))
return argValue;

assert(!MissingFeatures::sanitizerBuiltin());
llvm_unreachable("NYI");
}

static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *CGF,
unsigned BuiltinID,
const CallExpr *E,
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1782,6 +1782,10 @@ class CIRGenFunction : public CIRGenTypeCache {
/// enabled, a runtime check specified by \p Kind is also emitted.
mlir::Value emitCheckedArgForBuiltin(const Expr *E, BuiltinCheckKind Kind);

/// Emits an argument for a call to a `__builtin_assume`. If the builtin
/// sanitizer is enabled, a runtime check is also emitted.
mlir::Value emitCheckedArgForAssume(const Expr *E);

/// returns true if aggregate type has a volatile member.
/// TODO(cir): this could be a common AST helper between LLVM / CIR.
bool hasVolatileMember(QualType T) {
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,16 @@ CIRGenFunction::emitAttributedStmt(const AttributedStmt &S) {
case attr::AlwaysInline:
case attr::MustTail:
llvm_unreachable("NIY attributes");
case attr::CXXAssume: {
const Expr *assumption = cast<CXXAssumeAttr>(A)->getAssumption();
if (getLangOpts().CXXAssumptions && builder.getInsertionBlock() &&
!assumption->HasSideEffects(getContext())) {
mlir::Value assumptionValue = emitCheckedArgForAssume(assumption);
builder.create<cir::AssumeOp>(getLoc(S.getSourceRange()),
assumptionValue);
}
break;
}
default:
break;
}
Expand Down
20 changes: 18 additions & 2 deletions clang/test/CIR/CodeGen/builtin-assume.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck %s --check-prefix=CIR --input-file=%t.cir
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -fclangir -emit-llvm %s -o %t.ll
// RUN: FileCheck %s --check-prefix=LLVM --input-file=%t.ll

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

int test_assume_attr(int x) {
[[assume(x > 0)]];
return x;
}

// CIR: cir.func @_Z16test_assume_attri
// CIR: %[[#x:]] = cir.load %{{.+}} : !cir.ptr<!s32i>, !s32i
// CIR-NEXT: %[[#zero:]] = cir.const #cir.int<0> : !s32i
// CIR-NEXT: %[[#cond:]] = cir.cmp(gt, %[[#x]], %[[#zero]]) : !s32i, !cir.bool
// CIR-NEXT: cir.assume %[[#cond]] : !cir.bool
// CIR: }

// LLVM: @_Z16test_assume_attri
// LLVM: %[[#cond:]] = trunc i8 %{{.+}} to i1
// LLVM-NEXT: call void @llvm.assume(i1 %[[#cond]])

int test_assume_aligned(int *ptr) {
int *aligned = (int *)__builtin_assume_aligned(ptr, 8);
return *aligned;
Expand Down

0 comments on commit 65c857e

Please sign in to comment.