https://github.com/siddu0660 updated https://github.com/llvm/llvm-project/pull/166832
>From 227f9ad624e570353abff8de7a09b276e9c6b4e2 Mon Sep 17 00:00:00 2001 From: spamprx <[email protected]> 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<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 //===----------------------------------------------------------------------===// >From f2d9b64ec396de9a57366fa826284bd652128222 Mon Sep 17 00:00:00 2001 From: siddu0660 <[email protected]> Date: Fri, 7 Nov 2025 01:18:51 +0530 Subject: [PATCH 2/2] feat: updated TableGen code for BinOpOverFlow --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 41 ++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 9765684a1cd72..44b5fb484510a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1702,6 +1702,47 @@ def CIR_BinOp : CIR_Op<"binop", [ }]; } +//===----------------------------------------------------------------------===// +// BinOpOverflow +//===----------------------------------------------------------------------===// + +def CIR_BinOpOverflow : CIR_Op<"binop.overflow", [Pure]> { + let summary = "Binary operations with overflow detection"; + let description = [{ + cir.binop.overflow performs the binary operation according to + the specified opcode kind (add, sub, or mul) and returns both + the result and an overflow flag. + + It requires two input operands and returns two results: + - The result of the operation (same type as operands) + - An overflow flag (boolean type) + + The operation supports both signed and unsigned integer types. + For signed types, overflow is detected when the result cannot + be represented in the result type. For unsigned types, overflow + is detected when the result wraps around. + + ```mlir + %result, %overflow = cir.binop.overflow(add, %1, %2) : !s32i -> (!s32i, !bool) + %result, %overflow = cir.binop.overflow(sub, %3, %4) : !u32i -> (!u32i, !bool) + %result, %overflow = cir.binop.overflow(mul, %5, %6) : !s64i -> (!s64i, !bool) + ``` + }]; + + let arguments = (ins + CIR_BinOpKind:$kind, + CIR_AnyType:$lhs, CIR_AnyType:$rhs + ); + + let results = (outs CIR_AnyType:$result, CIR_BoolType:$overflow); + + let assemblyFormat = [{ + `(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) `->` `(` type($result) `,` type($overflow) `)` attr-dict + }]; + + let hasVerifier = 1; +} + //===----------------------------------------------------------------------===// // ShiftOp //===----------------------------------------------------------------------===// _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
