https://github.com/fileho updated https://github.com/llvm/llvm-project/pull/175439
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 1/2] [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 From d7d3620911c7328bb00eec2770ab20647c4affd8 Mon Sep 17 00:00:00 2001 From: Jiri Filek <[email protected]> Date: Fri, 16 Jan 2026 20:20:18 +0100 Subject: [PATCH 2/2] [CIR][X86] rdrand - simplify store alignment --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 5 +-- .../CIR/CodeGenBuiltins/X86/rdrand-builtins.c | 36 +++++++++---------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index c6c5eebde1d29..ade73cd1f5f19 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -1855,10 +1855,7 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { 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); + builder.CIRBaseBuilderTy::createStore(loc, rand, ops[0]); return cir::ExtractMemberOp::create(builder, loc, builder.getUInt32Ty(), call, 1); diff --git a/clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c index bd4c49050477c..224e82a7dd416 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/rdrand-builtins.c @@ -26,17 +26,17 @@ 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.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 + // 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 + // OGCG: store i16 {{%.*}}, ptr {{%.*}}, align 2 // OGCG: extractvalue { i16, i32 } {{%.*}}, 1 return _rdrand16_step(p); } @@ -45,17 +45,17 @@ 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.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 + // 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 + // OGCG: store i32 {{%.*}}, ptr {{%.*}}, align 4 // OGCG: extractvalue { i32, i32 } {{%.*}}, 1 return _rdrand32_step(p); } @@ -64,17 +64,17 @@ 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.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 + // 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 + // OGCG-X64: store i64 {{%.*}}, ptr {{%.*}}, align 8 // OGCG-X64: extractvalue { i64, i32 } {{%.*}}, 1 // CIR-X86: {{%.*}} = cir.call_llvm_intrinsic "x86.rdrand.32" @@ -90,17 +90,17 @@ 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.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 + // 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 + // OGCG: store i16 {{%.*}}, ptr {{%.*}}, align 2 // OGCG: extractvalue { i16, i32 } {{%.*}}, 1 return _rdseed16_step(p); } @@ -109,17 +109,17 @@ 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.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 + // 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 + // OGCG: store i32 {{%.*}}, ptr {{%.*}}, align 4 // OGCG: extractvalue { i32, i32 } {{%.*}}, 1 return _rdseed32_step(p); } @@ -129,17 +129,17 @@ 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.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 + // 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 + // OGCG-X64: store i64 {{%.*}}, ptr {{%.*}}, align 8 // OGCG-X64: extractvalue { i64, i32 } {{%.*}}, 1 return _rdseed64_step(p); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
