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
