https://github.com/FantasqueX updated 
https://github.com/llvm/llvm-project/pull/206149

>From dc27aefc6adc9637b8b796b2d3a105df32b7e1a9 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/CIRGenBuiltin.cpp       |  9 ++-
 .../builtin-nondeterministic-value.c          | 68 +++++++++++++++++++
 3 files changed, 104 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/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 3b8149411e7c4..174a69efc191e 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 = cir::FreezeOp::create(builder, 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

Reply via email to