https://github.com/FantasqueX updated https://github.com/llvm/llvm-project/pull/206149
>From 82ba70ea162025cc038d8910edebdbb7c263da00 Mon Sep 17 00:00:00 2001 From: Letu Ren <[email protected]> Date: Sat, 27 Jun 2026 02:42:44 +0800 Subject: [PATCH] [CIR] Support __builtin_nondeterministic_value --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 29 ++++++++ clang/lib/CIR/CodeGen/CIRGenBuilder.h | 4 ++ clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 9 ++- .../builtin-nondeterministic-value.c | 68 +++++++++++++++++++ 4 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 clang/test/CIR/CodeGenBuiltins/builtin-nondeterministic-value.c diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 7d1c48b994b27..1d113df57d784 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2026,6 +2026,35 @@ def CIR_FNegOp : CIR_UnaryOp<"fneg", CIR_AnyFloatOrVecOfFloatType> { let llvmOp = "FNegOp"; } +//===----------------------------------------------------------------------===// +// FreezeOp +//===----------------------------------------------------------------------===// + +def CIR_FreezeOp : CIR_Op<"freeze", [Pure, SameOperandsAndResultType]> { + let summary = "Stop propagation of undef and poison values"; + let description = [{ + The `cir.freeze` operation takes a single operand and returns a value of the + same type. If the operand is a poison or undef value, `cir.freeze` returns + an arbitrary, but fixed, value of the operand type. Otherwise it returns + the operand unchanged. + + Example: + + ```mlir + %1 = cir.freeze %0 : !s32i + ``` + }]; + + let arguments = (ins CIR_AnyType:$input); + let results = (outs CIR_AnyType:$result); + + let assemblyFormat = [{ + $input `:` type($input) attr-dict + }]; + + let llvmOp = "FreezeOp"; +} + //===----------------------------------------------------------------------===// // BrCondOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index cc1ff1e32521f..5547c3b5f579c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -851,6 +851,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return createVecShuffle(loc, vec1, poison, mask); } + mlir::Value createFreeze(mlir::Location loc, mlir::Value value) { + return cir::FreezeOp::create(*this, loc, value); + } + template <typename... Operands> mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str, const mlir::Type &resTy, Operands &&...op) { diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 3b8149411e7c4..d094ea5543f5a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1636,8 +1636,13 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, builder.createIsFPClass(loc, v, cir::FPClassTest(test)), convertType(e->getType()))); } - case Builtin::BI__builtin_nondeterministic_value: - return errorBuiltinNYI(*this, e, builtinID); + case Builtin::BI__builtin_nondeterministic_value: { + mlir::Type ty = convertType(e->getArg(0)->getType()); + mlir::Value result = + cir::ConstantOp::create(builder, loc, ty, cir::PoisonAttr::get(ty)); + result = builder.createFreeze(loc, result); + return RValue::get(result); + } case Builtin::BI__builtin_elementwise_abs: { mlir::Type cirTy = convertType(e->getArg(0)->getType()); bool isIntTy = cir::isIntOrVectorOfIntType(cirTy); diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-nondeterministic-value.c b/clang/test/CIR/CodeGenBuiltins/builtin-nondeterministic-value.c new file mode 100644 index 0000000000000..d7d9224fc0440 --- /dev/null +++ b/clang/test/CIR/CodeGenBuiltins/builtin-nondeterministic-value.c @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM + +typedef float float4 __attribute__((ext_vector_type(4))); + +// TODO: the bool4 (ext_vector_type _Bool) case from the classic CodeGen test is +// omitted here: CIR does not yet implement storing ext-vector-bool types +// (emitStoreOfScalar ExtVectorBoolType is NYI). The cir.freeze lowering itself +// works for <N x !cir.bool>; only the surrounding store is unsupported. + +int clang_nondet_i(int x) { + return __builtin_nondeterministic_value(x); +} + +// CIR-LABEL: cir.func {{.*}}@clang_nondet_i +// CIR: %[[POISON:.*]] = cir.const #cir.poison : !s32i +// CIR: %[[RES:.*]] = cir.freeze %[[POISON]] : !s32i + +// LLVM-LABEL: @clang_nondet_i +// LLVM: %[[RES:.*]] = freeze i32 poison + +float clang_nondet_f(float x) { + return __builtin_nondeterministic_value(x); +} + +// CIR-LABEL: cir.func {{.*}}@clang_nondet_f +// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.float +// CIR: %[[RES:.*]] = cir.freeze %[[POISON]] : !cir.float + +// LLVM-LABEL: @clang_nondet_f +// LLVM: %[[RES:.*]] = freeze float poison + +double clang_nondet_d(double x) { + return __builtin_nondeterministic_value(x); +} + +// CIR-LABEL: cir.func {{.*}}@clang_nondet_d +// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.double +// CIR: %[[RES:.*]] = cir.freeze %[[POISON]] : !cir.double + +// LLVM-LABEL: @clang_nondet_d +// LLVM: %[[RES:.*]] = freeze double poison + +_Bool clang_nondet_b(_Bool x) { + return __builtin_nondeterministic_value(x); +} + +// CIR-LABEL: cir.func {{.*}}@clang_nondet_b +// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.bool +// CIR: %[[RES:.*]] = cir.freeze %[[POISON]] : !cir.bool + +// LLVM-LABEL: @clang_nondet_b +// LLVM: %[[RES:.*]] = freeze i1 poison + +void clang_nondet_fv(void) { + float4 x = __builtin_nondeterministic_value(x); +} + +// CIR-LABEL: cir.func {{.*}}@clang_nondet_fv +// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !cir.float> +// CIR: %[[RES:.*]] = cir.freeze %[[POISON]] : !cir.vector<4 x !cir.float> + +// LLVM-LABEL: @clang_nondet_fv +// LLVM: %[[RES:.*]] = freeze <4 x float> poison _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
