Author: Jiří Filek
Date: 2026-01-16T13:50:48-08:00
New Revision: 37da38eb1ac00c6434d5a62af691cbf679e58c70

URL: 
https://github.com/llvm/llvm-project/commit/37da38eb1ac00c6434d5a62af691cbf679e58c70
DIFF: 
https://github.com/llvm/llvm-project/commit/37da38eb1ac00c6434d5a62af691cbf679e58c70.diff

LOG: [CIR][X86] Implement rdrand/rdseed builtins (#175439)

Add support for rdrand and rdseed builtins.

Part of #167765

Added: 
    clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c

Modified: 
    clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 497462a465145..6c01cbd7f699f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -2011,7 +2011,48 @@ 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);
+    builder.CIRBaseBuilderTy::createStore(loc, rand, ops[0]);
+
+    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..224e82a7dd416
--- /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 {{%.*}}, {{%.*}} : !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 {{%.*}}, ptr {{%.*}}, align 2
+  // LLVM: extractvalue { i16, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdrand16
+  // OGCG: call { i16, i32 } @llvm.x86.rdrand.16
+  // OGCG: extractvalue { i16, i32 } {{%.*}}, 0
+  // OGCG: store i16 {{%.*}}, ptr {{%.*}}, align 2
+  // 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 {{%.*}}, {{%.*}} : !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 {{%.*}}, ptr {{%.*}}, align 4
+  // LLVM: extractvalue { i32, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdrand32
+  // OGCG: call { i32, i32 } @llvm.x86.rdrand.32
+  // OGCG: extractvalue { i32, i32 } {{%.*}}, 0
+  // OGCG: store i32 {{%.*}}, ptr {{%.*}}, align 4
+  // 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 {{%.*}}, {{%.*}} : !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 {{%.*}}, ptr {{%.*}}, align 8
+  // 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 {{%.*}}, ptr {{%.*}}, align 8
+  // 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 {{%.*}}, {{%.*}} : !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 {{%.*}}, ptr {{%.*}}, align 2
+  // LLVM: extractvalue { i16, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdseed16
+  // OGCG: call { i16, i32 } @llvm.x86.rdseed.16
+  // OGCG: extractvalue { i16, i32 } {{%.*}}, 0
+  // OGCG: store i16 {{%.*}}, ptr {{%.*}}, align 2
+  // 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 {{%.*}}, {{%.*}} : !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 {{%.*}}, ptr {{%.*}}, align 4
+  // LLVM: extractvalue { i32, i32 } {{%.*}}, 1
+  // OGCG-LABEL: rdseed32
+  // OGCG: call { i32, i32 } @llvm.x86.rdseed.32
+  // OGCG: extractvalue { i32, i32 } {{%.*}}, 0
+  // OGCG: store i32 {{%.*}}, ptr {{%.*}}, align 4
+  // 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 {{%.*}}, {{%.*}} : !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 {{%.*}}, ptr {{%.*}}, align 8
+  // 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 {{%.*}}, ptr {{%.*}}, align 8
+  // 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