-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[CIR] Add support for __builtin_assume #144376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Sirui Mu (Lancern) ChangesThis patch adds support for the Full diff: https://github.com/llvm/llvm-project/pull/144376.diff 7 Files Affected:
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: }
|
andykaylor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good except for the vague MissingFeatures assertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this meant to represent? I know there's a lot of handling missing here, but for this to appear in emitBuiltinExpr is a bit confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced it with several more fine-grained missing feature flags.
This patch adds support for the __builtin_assume builtin function.
bcardosolopes
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, LGTM
This patch adds support for the
__builtin_assumebuiltin function.