diff --git a/clang/lib/Headers/immintrin.h b/clang/lib/Headers/immintrin.h --- a/clang/lib/Headers/immintrin.h +++ b/clang/lib/Headers/immintrin.h @@ -291,6 +291,22 @@ { return (int)__builtin_ia32_rdrand64_step(__p); } +#else +// We need to emulate the functionality of 64-bit rdrand with 2 32-bit +// rdrand instructions. +static __inline__ int __attribute__((__always_inline__, __nodebug__, __target__("rdrnd"))) +_rdrand64_step(unsigned long long *__p) +{ + unsigned long long tmp; + if (__builtin_ia32_rdrand32_step((unsigned int *)&tmp) & + __builtin_ia32_rdrand32_step(((unsigned int *)&tmp) + 1)) { + *__p = tmp; + return 1; + } else { + *__p = 0; + return 0; + } +} #endif #endif /* __RDRND__ */ diff --git a/clang/test/CodeGen/X86/rdrand-builtins.c b/clang/test/CodeGen/X86/rdrand-builtins.c --- a/clang/test/CodeGen/X86/rdrand-builtins.c +++ b/clang/test/CodeGen/X86/rdrand-builtins.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -no-opaque-pointers -ffreestanding %s -triple=x86_64-unknown-unknown -target-feature +rdrnd -target-feature +rdseed -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=CHECK,X64 -// RUN: %clang_cc1 -no-opaque-pointers -ffreestanding %s -triple=i386-unknown-unknown -target-feature +rdrnd -target-feature +rdseed -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=CHECK +// RUN: %clang_cc1 -no-opaque-pointers -ffreestanding %s -triple=i386-unknown-unknown -target-feature +rdrnd -target-feature +rdseed -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=CHECK,X32 #include @@ -24,6 +24,29 @@ // X64: call { i64, i32 } @llvm.x86.rdrand.64 // X64: store i64 } +#else +int rdrand64(unsigned long long *p) { +// X32: @rdrand64 +// X32: [[RETVAL_I:%.*]] = alloca i32, align 4 +// X32: call { i32, i32 } @llvm.x86.rdrand.32 +// X32: store i32 +// X32: call { i32, i32 } @llvm.x86.rdrand.32 +// X32: store i32 +// X32: [[AND_I:%.*]] = and i32 +// X32: [[TOBOOL_I:%.*]] = icmp ne i32 [[AND_I]], 0 +// X32: br i1 [[TOBOOL_I]], label [[IF_THEN_I:%.*]], label [[IF_ELSE_I:%.*]] +// X32: if.then.i: +// X32: store i64 +// X32: store i32 1, i32* [[RETVAL_I]], align 4 +// X32: br label [[_RDRAND64_STEP_EXIT:%.*]] +// X32: if.else.i: +// X32: store i64 0 +// X32: store i32 0, i32* [[RETVAL_I]], align 4 +// X32: br label [[_RDRAND64_STEP_EXIT]] +// X32: _rdrand64_step.exit: +// X32: %{{.*}} = load i32, i32* [[RETVAL_I]], align 4 + return _rdrand64_step(p); +} #endif int rdseed16(unsigned short *p) {