https://github.com/fileho created 
https://github.com/llvm/llvm-project/pull/175439

Add support for rdrand and rdseed builtins.

Part of #167765 

From 54dd8c6cf38ca5267a7c1665234541542790155d Mon Sep 17 00:00:00 2001
From: Jiri Filek <[email protected]>
Date: Sun, 11 Jan 2026 15:27:22 +0100
Subject: [PATCH] [CIR][X86] Implement rdrand/rdseed builtins

---
 clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp    |  46 +++++-
 .../CIR/CodeGenBuiltins/X86/rdrand-builtins.c | 146 ++++++++++++++++++
 2 files changed, 191 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index eeecc9cdaa741..c6c5eebde1d29 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -1818,7 +1818,51 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_rdrand64_step:
   case X86::BI__builtin_ia32_rdseed16_step:
   case X86::BI__builtin_ia32_rdseed32_step:
-  case X86::BI__builtin_ia32_rdseed64_step:
+  case X86::BI__builtin_ia32_rdseed64_step: {
+    llvm::StringRef intrinsicName;
+    switch (builtinID) {
+    default:
+      llvm_unreachable("Unsupported intrinsic!");
+    case X86::BI__builtin_ia32_rdrand16_step:
+      intrinsicName = "x86.rdrand.16";
+      break;
+    case X86::BI__builtin_ia32_rdrand32_step:
+      intrinsicName = "x86.rdrand.32";
+      break;
+    case X86::BI__builtin_ia32_rdrand64_step:
+      intrinsicName = "x86.rdrand.64";
+      break;
+    case X86::BI__builtin_ia32_rdseed16_step:
+      intrinsicName = "x86.rdseed.16";
+      break;
+    case X86::BI__builtin_ia32_rdseed32_step:
+      intrinsicName = "x86.rdseed.32";
+      break;
+    case X86::BI__builtin_ia32_rdseed64_step:
+      intrinsicName = "x86.rdseed.64";
+      break;
+    }
+
+    mlir::Location loc = getLoc(expr->getExprLoc());
+    mlir::Type randTy = cast<cir::PointerType>(ops[0].getType()).getPointee();
+    llvm::SmallVector<mlir::Type, 2> resultTypes = {randTy,
+                                                    builder.getUInt32Ty()};
+    cir::RecordType resRecord =
+        cir::RecordType::get(&getMLIRContext(), resultTypes, false, false,
+                             cir::RecordType::RecordKind::Struct);
+
+    mlir::Value call =
+        emitIntrinsicCallOp(builder, loc, intrinsicName, resRecord);
+    mlir::Value rand =
+        cir::ExtractMemberOp::create(builder, loc, randTy, call, 0);
+    Address addr =
+        Address(ops[0], clang::CharUnits::fromQuantity(
+                            builder.getCIRIntOrFloatBitWidth(randTy) / 8));
+    builder.createStore(loc, rand, addr);
+
+    return cir::ExtractMemberOp::create(builder, loc, builder.getUInt32Ty(),
+                                        call, 1);
+  }
   case X86::BI__builtin_ia32_addcarryx_u32:
   case X86::BI__builtin_ia32_addcarryx_u64:
   case X86::BI__builtin_ia32_subborrow_u32:
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c 
b/clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c
new file mode 100644
index 0000000000000..bd4c49050477c
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -x c -ffreestanding -triple x86_64-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed 
-Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s
+// RUN: FileCheck --check-prefixes=CIR,CIR-X64 --input-file=%t.cir %s
+// RUN: %clang_cc1 -x c++ -ffreestanding -triple x86_64-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed 
-Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s
+// RUN: FileCheck --check-prefixes=CIR,CIR-X64 --input-file=%t.cir %s
+
+// RUN: %clang_cc1 -x c -ffreestanding -triple x86_64-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed 
-Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s
+// RUN: FileCheck --check-prefixes=LLVM,LLVM-X64 --input-file=%t.ll %s
+// RUN: %clang_cc1 -x c++ -ffreestanding -triple x86_64-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed 
-Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s
+// RUN: FileCheck --check-prefixes=LLVM,LLVM-X64 --input-file=%t.ll %s
+
+// RUN: %clang_cc1 -x c -ffreestanding -triple=x86_64-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed -emit-llvm -Wall -Werror %s -o - 
| FileCheck %s -check-prefixes=OGCG,OGCG-X64
+// RUN: %clang_cc1 -x c++ -ffreestanding -triple=x86_64-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed -emit-llvm -Wall -Werror %s -o - 
| FileCheck %s -check-prefixes=OGCG,OGCG-X64
+
+// 32-bit tests for _rdrand64_step()
+// RUN: %clang_cc1 -x c -ffreestanding -triple i386-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed 
-Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s
+// RUN: FileCheck --check-prefixes=CIR,CIR-X86 --input-file=%t.cir %s
+// RUN: %clang_cc1 -x c -ffreestanding -triple i386-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed 
-Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s
+// RUN: FileCheck --check-prefixes=LLVM,LLVM-X86 --input-file=%t.ll %s
+// RUN: %clang_cc1 -x c -ffreestanding -triple=i386-unknown-linux 
-target-feature +rdrnd -target-feature +rdseed -emit-llvm -Wall -Werror %s -o - 
| FileCheck %s -check-prefixes=OGCG,OGCG-X86
+
+// This test mimics clang/test/CodeGen/X86/rdrand-builtins.c
+
+#include <immintrin.h>
+
+int test_rdrand16(unsigned short *p) {
+  // CIR-LABEL: rdrand16
+  // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.rdrand.16"
+  // CIR: {{%.*}} = cir.extract_member {{%.*}}[0]
+  // CIR: cir.store align(2) {{%.*}}, {{%.*}} : !u16i, !cir.ptr<!u16i>
+  // CIR: {{%.*}} = cir.extract_member {{%.*}}[1]
+  // LLVM-LABEL: rdrand16
+  // LLVM: call { i16, i32 } @llvm.x86.rdrand.16
+  // LLVM: extractvalue { i16, i32 } {{%.*}}, 0
+  // LLVM: store i16
+  // LLVM: extractvalue { i16, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdrand16
+  // OGCG: call { i16, i32 } @llvm.x86.rdrand.16
+  // OGCG: extractvalue { i16, i32 } {{%.*}}, 0
+  // OGCG: store i16
+  // OGCG: extractvalue { i16, i32 } {{%.*}}, 1
+  return _rdrand16_step(p);
+}
+
+int test_rdrand32(unsigned *p) {
+  // CIR-LABEL: rdrand32
+  // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.rdrand.32"
+  // CIR: {{%.*}} = cir.extract_member {{%.*}}[0]
+  // CIR: cir.store align(4) {{%.*}}, {{%.*}} : !u32i, !cir.ptr<!u32i>
+  // CIR: {{%.*}} = cir.extract_member {{%.*}}[1]
+  // LLVM-LABEL: rdrand32
+  // LLVM: call { i32, i32 } @llvm.x86.rdrand.32
+  // LLVM: extractvalue { i32, i32 } {{%.*}}, 0
+  // LLVM: store i32
+  // LLVM: extractvalue { i32, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdrand32
+  // OGCG: call { i32, i32 } @llvm.x86.rdrand.32
+  // OGCG: extractvalue { i32, i32 } {{%.*}}, 0
+  // OGCG: store i32
+  // OGCG: extractvalue { i32, i32 } {{%.*}}, 1
+  return _rdrand32_step(p);
+}
+
+int test_rdrand64(unsigned long long *p) {
+  // CIR-LABEL: rdrand64
+  // CIR-X64: {{%.*}} = cir.call_llvm_intrinsic "x86.rdrand.64"
+  // CIR-X64: {{%.*}} = cir.extract_member {{%.*}}[0]
+  // CIR-X64: cir.store align(8) {{%.*}}, {{%.*}} : !u64i, !cir.ptr<!u64i>
+  // CIR-X64: {{%.*}} = cir.extract_member {{%.*}}[1]
+  // LLVM-LABEL: rdrand64
+  // LLVM-X64: call { i64, i32 } @llvm.x86.rdrand.64
+  // LLVM-X64: extractvalue { i64, i32 } {{%.*}}, 0
+  // LLVM-X64: store i64
+  // LLVM-X64: extractvalue { i64, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdrand64
+  // OGCG-X64: call { i64, i32 } @llvm.x86.rdrand.64
+  // OGCG-X64: extractvalue { i64, i32 } {{%.*}}, 0
+  // OGCG-X64: store i64
+  // OGCG-X64: extractvalue { i64, i32 } {{%.*}}, 1
+
+  // CIR-X86: {{%.*}} = cir.call_llvm_intrinsic "x86.rdrand.32"
+  // CIR-X86: {{%.*}} = cir.call_llvm_intrinsic "x86.rdrand.32"
+  // LLVM-X86: call { i32, i32 } @llvm.x86.rdrand.32
+  // LLVM-X86: call { i32, i32 } @llvm.x86.rdrand.32
+  // OGCG-X86: call { i32, i32 } @llvm.x86.rdrand.32
+  // OGCG-X86: call { i32, i32 } @llvm.x86.rdrand.32
+  return _rdrand64_step(p);
+}
+
+int test_rdseed16(unsigned short *p) {
+  // CIR-LABEL: rdseed16
+  // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.rdseed.16"
+  // CIR: {{%.*}} = cir.extract_member {{%.*}}[0]
+  // CIR: cir.store align(2) {{%.*}}, {{%.*}} : !u16i, !cir.ptr<!u16i>
+  // CIR: {{%.*}} = cir.extract_member {{%.*}}[1]
+  // LLVM-LABEL: rdseed16
+  // LLVM: call { i16, i32 } @llvm.x86.rdseed.16
+  // LLVM: extractvalue { i16, i32 } {{%.*}}, 0
+  // LLVM: store i16
+  // LLVM: extractvalue { i16, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdseed16
+  // OGCG: call { i16, i32 } @llvm.x86.rdseed.16
+  // OGCG: extractvalue { i16, i32 } {{%.*}}, 0
+  // OGCG: store i16
+  // OGCG: extractvalue { i16, i32 } {{%.*}}, 1
+  return _rdseed16_step(p);
+}
+
+int test_rdseed32(unsigned *p) {
+  // CIR-LABEL: rdseed32
+  // CIR: {{%.*}} = cir.call_llvm_intrinsic "x86.rdseed.32"
+  // CIR: {{%.*}} = cir.extract_member {{%.*}}[0]
+  // CIR: cir.store align(4) {{%.*}}, {{%.*}} : !u32i, !cir.ptr<!u32i>
+  // CIR: {{%.*}} = cir.extract_member {{%.*}}[1]
+  // LLVM-LABEL: rdseed32
+  // LLVM: call { i32, i32 } @llvm.x86.rdseed.32
+  // LLVM: extractvalue { i32, i32 } {{%.*}}, 0
+  // LLVM: store i32
+  // LLVM: extractvalue { i32, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdseed32
+  // OGCG: call { i32, i32 } @llvm.x86.rdseed.32
+  // OGCG: extractvalue { i32, i32 } {{%.*}}, 0
+  // OGCG: store i32
+  // OGCG: extractvalue { i32, i32 } {{%.*}}, 1
+  return _rdseed32_step(p);
+}
+
+#if __x86_64__
+int test_rdseed64(unsigned long long *p) {
+  // CIR-X64-LABEL: rdseed64
+  // CIR-X64: {{%.*}} = cir.call_llvm_intrinsic "x86.rdseed.64"
+  // CIR-X64: {{%.*}} = cir.extract_member {{%.*}}[0]
+  // CIR-X64: cir.store align(8) {{%.*}}, {{%.*}} : !u64i, !cir.ptr<!u64i>
+  // CIR-X64: {{%.*}} = cir.extract_member {{%.*}}[1]
+  // LLVM-X64-LABEL: rdseed64
+  // LLVM-X64: call { i64, i32 } @llvm.x86.rdseed.64
+  // LLVM-X64: extractvalue { i64, i32 } {{%.*}}, 0
+  // LLVM-X64: store i64
+  // LLVM-X64: extractvalue { i64, i32 } {{%.*}}, 1
+  // OGCG-X64-LABEL: rdseed64
+  // OGCG-X64: call { i64, i32 } @llvm.x86.rdseed.64
+  // OGCG-X64: extractvalue { i64, i32 } {{%.*}}, 0
+  // OGCG-X64: store i64
+  // OGCG-X64: extractvalue { i64, i32 } {{%.*}}, 1
+  return _rdseed64_step(p);
+}
+#endif

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to