https://github.com/Lancern created https://github.com/llvm/llvm-project/pull/144376
This patch adds support for the `__builtin_assume` builtin function. >From 886097329c486b48ceb32ea7ea807e561ad8abdd Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Mon, 16 Jun 2025 23:38:47 +0800 Subject: [PATCH] [CIR] Add support for __builtin_assume This patch adds support for the __builtin_assume builtin function. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 22 +++++++++++ clang/include/clang/CIR/MissingFeatures.h | 1 + clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 39 +++++++++++++++++++ clang/lib/CIR/CodeGen/CIRGenFunction.h | 4 ++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 9 +++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 10 +++++ clang/test/CIR/CodeGen/builtin_call.cpp | 16 ++++++++ 7 files changed, 101 insertions(+) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index bd36d228578b7..60fbce646da9b 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2385,4 +2385,26 @@ def ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> { let hasFolder = 1; } +//===----------------------------------------------------------------------===// +// Assume Operations +//===----------------------------------------------------------------------===// + +def AssumeOp : CIR_Op<"assume"> { + let summary = "Tell the optimizer that a boolean value is true"; + let description = [{ + The `cir.assume` operation takes a single boolean prediate as its only + argument and does not have any results. The operation tells the optimizer + that the predicate is always true. + + This operation corresponds to the `__assume` and the `__builtin_assume` + builtin function. + }]; + + let arguments = (ins CIR_BoolType:$predicate); + + let assemblyFormat = [{ + $predicate `:` type($predicate) attr-dict + }]; +} + #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 13ddc77835fbc..ca9eef36e0d78 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -90,6 +90,7 @@ struct MissingFeatures { static bool opCallABIExtendArg() { return false; } static bool opCallABIIndirectArg() { return false; } static bool opCallWidenArg() { return false; } + static bool opCallBuiltin() { return false; } static bool opCallBitcastArg() { return false; } static bool opCallImplicitObjectSizeArgs() { return false; } static bool opCallReturn() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index c59ac78210f81..6e4d38bd6f051 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CIRGenCall.h" +#include "CIRGenConstantEmitter.h" #include "CIRGenFunction.h" #include "CIRGenModule.h" #include "CIRGenValue.h" @@ -28,6 +29,8 @@ using namespace clang::CIRGen; RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, const CallExpr *e, ReturnValueSlot returnValue) { + const FunctionDecl *fd = gd.getDecl()->getAsFunction(); + // See if we can constant fold this builtin. If so, don't emit it at all. // TODO: Extend this handling to all builtin calls that we can constant-fold. Expr::EvalResult result; @@ -49,7 +52,43 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, } } + assert(!cir::MissingFeatures::opCallBuiltin()); + + // If the builtin has been declared explicitly with an assembler label, + // disable the specialized emitting below. Ideally we should communicate the + // rename in IR, or at least avoid generating the intrinsic calls that are + // likely to get lowered to the renamed library functions. + unsigned builtinIDIfNoAsmLabel = fd->hasAttr<AsmLabelAttr>() ? 0 : builtinID; + + assert(!cir::MissingFeatures::opCallBuiltin()); + + switch (builtinIDIfNoAsmLabel) { + default: + break; + + case Builtin::BI__assume: + case Builtin::BI__builtin_assume: { + if (e->getArg(0)->HasSideEffects(getContext())) + return RValue::get(nullptr); + + mlir::Value argValue = emitCheckedArgForAssume(e->getArg(0)); + builder.create<cir::AssumeOp>(getLoc(e->getExprLoc()), argValue); + return RValue::get(nullptr); + } + } + mlir::Location loc = getLoc(e->getExprLoc()); cgm.errorNYI(loc, "non constant foldable builtin calls"); return getUndefRValue(e->getType()); } + +mlir::Value CIRGenFunction::emitCheckedArgForAssume(const Expr *e) { + mlir::Value argValue = evaluateExprAsBool(e); + if (!sanOpts.has(SanitizerKind::Builtin)) + return argValue; + + assert(!cir::MissingFeatures::sanitizers()); + cgm.errorNYI(e->getSourceRange(), + "emitCheckedArgForAssume: sanitizers are NYI"); + return {}; +} diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index de6ef2a69faf1..6c490a72b2e93 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -772,6 +772,10 @@ class CIRGenFunction : public CIRGenTypeCache { LValue emitCastLValue(const CastExpr *e); + /// 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); + LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e); void emitConstructorBody(FunctionArgList &args); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 6a4e4e4a7df3b..a96501ab2c384 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -407,6 +407,14 @@ struct ConvertCIRToLLVMPass StringRef getArgument() const override { return "cir-flat-to-llvm"; } }; +mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite( + cir::AssumeOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + auto cond = adaptor.getPredicate(); + rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(op, cond); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMBrCondOpLowering::matchAndRewrite( cir::BrCondOp brOp, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { @@ -1811,6 +1819,7 @@ void ConvertCIRToLLVMPass::runOnOperation() { dl); patterns.add< // clang-format off + CIRToLLVMAssumeOpLowering, CIRToLLVMBaseClassAddrOpLowering, CIRToLLVMBinOpLowering, CIRToLLVMBrCondOpLowering, diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index a809818063547..a80c66ac1abf2 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -29,6 +29,16 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute attr, mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage); +class CIRToLLVMAssumeOpLowering + : public mlir::OpConversionPattern<cir::AssumeOp> { +public: + using mlir::OpConversionPattern<cir::AssumeOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::AssumeOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + class CIRToLLVMBrCondOpLowering : public mlir::OpConversionPattern<cir::BrCondOp> { public: diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp index 2706ea7f8f857..c5ad08740ea3c 100644 --- a/clang/test/CIR/CodeGen/builtin_call.cpp +++ b/clang/test/CIR/CodeGen/builtin_call.cpp @@ -76,3 +76,19 @@ float constant_fp_builtin_single() { // OGCG: define {{.*}}float @_Z26constant_fp_builtin_singlev() // OGCG: ret float 0x3FB99999A0000000 // OGCG: } + +void assume(bool arg) { + __builtin_assume(arg); +} + +// CIR: cir.func @_Z6assumeb +// CIR: cir.assume %{{.+}} : !cir.bool +// CIR: } + +// LLVM: define void @_Z6assumeb +// LLVM: call void @llvm.assume(i1 %{{.+}}) +// LLVM: } + +// OGCG: define {{.*}}void @_Z6assumeb +// OGCG: call void @llvm.assume(i1 %{{.+}}) +// OGCG: } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits