[CIR] Add support for __builtin_assume (#144376)
This patch adds support for the `__builtin_assume` builtin function.
This commit is contained in:
@@ -2387,4 +2387,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 functions.
|
||||
}];
|
||||
|
||||
let arguments = (ins CIR_BoolType:$predicate);
|
||||
|
||||
let assemblyFormat = [{
|
||||
$predicate `:` type($predicate) attr-dict
|
||||
}];
|
||||
}
|
||||
|
||||
#endif // CLANG_CIR_DIALECT_IR_CIROPS_TD
|
||||
|
||||
@@ -237,6 +237,9 @@ struct MissingFeatures {
|
||||
static bool lowerAggregateLoadStore() { return false; }
|
||||
static bool dataLayoutTypeAllocSize() { return false; }
|
||||
static bool asmLabelAttr() { return false; }
|
||||
static bool builtinCall() { return false; }
|
||||
static bool builtinCallF128() { return false; }
|
||||
static bool builtinCallMathErrno() { return false; }
|
||||
|
||||
// Missing types
|
||||
static bool dataMemberType() { return false; }
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CIRGenCall.h"
|
||||
#include "CIRGenConstantEmitter.h"
|
||||
#include "CIRGenFunction.h"
|
||||
#include "CIRGenModule.h"
|
||||
#include "CIRGenValue.h"
|
||||
@@ -66,6 +67,32 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
|
||||
return emitLibraryCall(*this, fd, e,
|
||||
cgm.getBuiltinLibFunction(fd, builtinID));
|
||||
|
||||
assert(!cir::MissingFeatures::builtinCallF128());
|
||||
|
||||
// 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::builtinCallMathErrno());
|
||||
assert(!cir::MissingFeatures::builtinCall());
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
cgm.errorNYI(e->getSourceRange(), "unimplemented builtin call");
|
||||
return getUndefRValue(e->getType());
|
||||
}
|
||||
@@ -88,3 +115,14 @@ cir::FuncOp CIRGenModule::getBuiltinLibFunction(const FunctionDecl *fd,
|
||||
mlir::Type type = convertType(fd->getType());
|
||||
return getOrCreateCIRFunction(name, type, d, /*forVTable=*/false);
|
||||
}
|
||||
|
||||
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 {};
|
||||
}
|
||||
|
||||
@@ -772,6 +772,10 @@ public:
|
||||
|
||||
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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -94,3 +94,19 @@ void library_builtins() {
|
||||
// OGCG: define dso_local void @_Z16library_builtinsv()
|
||||
// OGCG: call i32 (ptr, ...) @printf(ptr noundef null)
|
||||
// OGCG: call void @abort()
|
||||
|
||||
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: }
|
||||
|
||||
Reference in New Issue
Block a user