[clang] feat: included support for is_constant builtin (PR #166832)
Sathwik Kodamarthi via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 6 11:30:01 PST 2025
https://github.com/siddu0660 created https://github.com/llvm/llvm-project/pull/166832
None
>From 227f9ad624e570353abff8de7a09b276e9c6b4e2 Mon Sep 17 00:00:00 2001
From: spamprx <cs23btech11012 at iith.ac.in>
Date: Fri, 7 Nov 2025 00:55:26 +0530
Subject: [PATCH] feat: included support for is_constant builtin
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 38 ++++++++++++++++++++
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 25 +++++++++++++
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 19 ++++++++++
3 files changed, 82 insertions(+)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 2b361ed0982c6..9765684a1cd72 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4052,6 +4052,44 @@ def CIR_ExpectOp : CIR_Op<"expect", [
}];
}
+//===----------------------------------------------------------------------===//
+// IsConstantOp
+//===----------------------------------------------------------------------===//
+
+def CIR_IsConstantOp : CIR_Op<"is_constant", [Pure]> {
+ let summary = "Check if a value is a compile-time constant";
+ let description = [{
+ The `cir.is_constant` operation checks whether its input value is a
+ compile-time constant. This operation models the `__builtin_constant_p`
+ builtin function.
+
+ The operation takes a single operand of any CIR type and returns a signed
+ 32-bit integer. The result is 1 if the operand is a compile-time constant,
+ and 0 otherwise.
+
+ If the value can be determined to be constant at compile time, this
+ operation may be folded to a constant value. Otherwise, it will be lowered
+ to the `llvm.is.constant` intrinsic.
+
+ Example:
+
+ ```mlir
+ %0 = cir.is_constant %expr : i32 -> !s32i
+ %1 = cir.is_constant %ptr : !cir.ptr<i32> -> !s32i
+ ```
+ }];
+
+ let arguments = (ins CIR_AnyType:$value);
+ let results = (outs CIR_SInt32:$result);
+
+ let assemblyFormat = [{
+ $value `:` type($value) `->` type($result) attr-dict
+ }];
+
+ let hasFolder = 1;
+ let hasLLVMLowering = false;
+}
+
//===----------------------------------------------------------------------===//
// PrefetchOp
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index e35100ffe4b6b..8777ff16f068f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -199,6 +199,31 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
return RValue::get(
builder.createBitcast(allocaAddr, builder.getVoidPtrTy()));
}
+
+ case Builtin::BI__builtin_constant_p: {
+ auto loc = getLoc(e->getSourceRange());
+
+ Expr::EvalResult evalResult;
+
+ // Try to evaluate at compile time first
+ if (e->getArg(0)->EvaluateAsRValue(evalResult, getContext()) &&
+ !evalResult.hasSideEffects()) {
+ // Expression is a compile-time constant, return 1
+ llvm::APInt apInt(32, 1);
+ llvm::APSInt apSInt(apInt, /*isUnsigned=*/false);
+ return RValue::get(builder.getConstInt(loc, apSInt));
+ }
+
+ // Expression cannot be evaluated at compile time, emit runtime check
+ mlir::Value argValue = emitScalarExpr(e->getArg(0));
+ mlir::Type resultType = builder.getSInt32Ty();
+ auto isConstantOp = cir::IsConstantOp::create(builder, loc, resultType, argValue);
+ mlir::Value resultValue = isConstantOp.getResult();
+ mlir::Type exprTy = convertType(e->getType());
+ if (exprTy != resultValue.getType())
+ resultValue = builder.createIntCast(resultValue, exprTy);
+ return RValue::get(resultValue);
+ }
case Builtin::BIcos:
case Builtin::BIcosf:
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 7ba03ce40140c..de23514cf5a79 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2117,6 +2117,25 @@ OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) {
return {};
}
+//===----------------------------------------------------------------------===//
+// IsConstantOp Definitions
+//===----------------------------------------------------------------------===//
+
+OpFoldResult cir::IsConstantOp::fold(FoldAdaptor adaptor) {
+ // If the input value is a constant attribute, return 1 (true)
+ mlir::Attribute value = adaptor.getValue();
+ if (value) {
+ // The value is a compile-time constant, so return 1
+ mlir::Type resultType = getResult().getType();
+ llvm::APInt apInt(32, 1);
+ llvm::APSInt apSInt(apInt, /*isUnsigned=*/false);
+ return cir::IntAttr::get(resultType, apSInt);
+ }
+
+ // If the input is not a constant, we cannot fold
+ return {};
+}
+
//===----------------------------------------------------------------------===//
// CopyOp Definitions
//===----------------------------------------------------------------------===//
More information about the cfe-commits
mailing list