[clang] feat: included support for is_constant builtin (PR #166832)
andykaylor wrote: This was handled by https://github.com/llvm/llvm-project/pull/170354 https://github.com/llvm/llvm-project/pull/166832 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
https://github.com/andykaylor closed https://github.com/llvm/llvm-project/pull/166832 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
@@ -3043,6 +3043,44 @@ def CIR_ArrayDtor : CIR_ArrayInitDestroy<"array.dtor"> {
}];
}
+//===--===//
+// 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.
xlauko wrote:
This is not true, the expected result is bool
https://github.com/llvm/llvm-project/pull/166832
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
@@ -3043,6 +3043,44 @@ def CIR_ArrayDtor : CIR_ArrayInitDestroy<"array.dtor"> {
}];
}
+//===--===//
+// 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 -> !s32i
+```
+ }];
+
+ let arguments = (ins CIR_AnyType:$value);
+ let results = (outs CIR_BoolType:$result);
+
+ let assemblyFormat = [{
+`(` $value `:` type($value) `)` `:` type($result) attr-dict
+ }];
+
+ // let hasFolder = 1;
xlauko wrote:
Remove this or implement folder as well.
https://github.com/llvm/llvm-project/pull/166832
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
@@ -4052,6 +4093,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 -> !s32i
+```
+ }];
+
+ let arguments = (ins CIR_AnyType:$value);
+ let results = (outs CIR_SInt32:$result);
+
+ let assemblyFormat = [{
+$value `:` type($value) `->` type($result) attr-dict
xlauko wrote:
@andykaylor pretty much yes. I am traying us to converge on style `: argument
types -> return types` respectivelly `: type` if the operation can be
determined by a single type. Bit of style guide is in:
https://llvm.github.io/clangir/Dialect/cir-style-guide.html
https://github.com/llvm/llvm-project/pull/166832
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
@@ -199,6 +199,43 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl
&gd, unsigned builtinID,
return RValue::get(
builder.createBitcast(allocaAddr, builder.getVoidPtrTy()));
}
+
+ case Builtin::BI__builtin_constant_p: {
+mlir::Location loc = getLoc(e->getSourceRange());
+mlir::Type ResultType = convertType(e->getType());
+
+const Expr *Arg = e->getArg(0);
+QualType ArgType = Arg->getType();
xlauko wrote:
```suggestion
const Expr *arg = e->getArg(0);
QualType argType = arg->getType();
```
https://github.com/llvm/llvm-project/pull/166832
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
https://github.com/spamprx updated
https://github.com/llvm/llvm-project/pull/166832
>From 227f9ad624e570353abff8de7a09b276e9c6b4e2 Mon Sep 17 00:00:00 2001
From: spamprx
Date: Fri, 7 Nov 2025 00:55:26 +0530
Subject: [PATCH 1/3] 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 -> !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
//===-
[clang] feat: included support for is_constant builtin (PR #166832)
https://github.com/spamprx updated
https://github.com/llvm/llvm-project/pull/166832
>From 227f9ad624e570353abff8de7a09b276e9c6b4e2 Mon Sep 17 00:00:00 2001
From: spamprx
Date: Fri, 7 Nov 2025 00:55:26 +0530
Subject: [PATCH 1/3] 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 -> !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
//===-
[clang] feat: included support for is_constant builtin (PR #166832)
@@ -4052,6 +4093,44 @@ def CIR_ExpectOp : CIR_Op<"expect", [ }]; } +//===--===// +// IsConstantOp siddu0660 wrote: Thanks for mentioning the incubator ! I hadn’t come across that detail earlier, but I appreciate you pointing it out. I’ll go through it and make sure I’m aligned before moving forward. https://github.com/llvm/llvm-project/pull/166832 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
https://github.com/spamprx updated
https://github.com/llvm/llvm-project/pull/166832
>From 227f9ad624e570353abff8de7a09b276e9c6b4e2 Mon Sep 17 00:00:00 2001
From: spamprx
Date: Fri, 7 Nov 2025 00:55:26 +0530
Subject: [PATCH 1/2] 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 -> !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
//===-
[clang] feat: included support for is_constant builtin (PR #166832)
andykaylor wrote: Hi @siddu0660. Thanks for working on this! I appreciate that you were proactive in getting started on this. Unfortunately, that probably resulted in a bit of duplicated effort as @adams381 is also working on this, but I can see that you had probably started before I added the comment in https://github.com/llvm/llvm-project/issues/163889 explaining that. I'll review the PR in a minute, but my first feedback is that the title should begin with `[CIR]` for CIR-related work. This is obviously a minor point, but as this is your first contribution I'm going to point out many small things like this to introduce you to our usual practices. https://github.com/llvm/llvm-project/pull/166832 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
https://github.com/siddu0660 updated
https://github.com/llvm/llvm-project/pull/166832
>From 227f9ad624e570353abff8de7a09b276e9c6b4e2 Mon Sep 17 00:00:00 2001
From: spamprx
Date: Fri, 7 Nov 2025 00:55:26 +0530
Subject: [PATCH 1/2] 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 -> !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
//===---
[clang] feat: included support for is_constant builtin (PR #166832)
llvmbot wrote:
@llvm/pr-subscribers-clangir
Author: Sathwik Kodamarthi (siddu0660)
Changes
---
Full diff: https://github.com/llvm/llvm-project/pull/166832.diff
3 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+38)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+25)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+19)
``diff
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 -> !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
//===--===//
``
https://github.com/llvm/llvm-project/pull/166832
_
[clang] feat: included support for is_constant builtin (PR #166832)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/166832 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] feat: included support for is_constant builtin (PR #166832)
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
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 -> !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
//===-
