Skip to content

Commit

Permalink
[x86] Adding support for some missing intrinsics: _castf32_u32, _cas…
Browse files Browse the repository at this point in the history
…tf64_u64, _castu32_f32, _castu64_f64

Summary:
Adding support for some missing intrinsics:
_castf32_u32, _castf64_u64, _castu32_f32, _castu64_f64

Reviewers: craig.topper, LuoYuanke, RKSimon, pengfei

Reviewed By: RKSimon

Subscribers: llvm-commits

Patch by yubing (Bing Yu)

Differential Revision: https://reviews.llvm.org/D67212

llvm-svn: 372802
  • Loading branch information
phoebewang committed Sep 25, 2019
1 parent 03f2a11 commit 1f3a15c
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
68 changes: 68 additions & 0 deletions clang/lib/Headers/ia32intrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,74 @@ __writeeflags(unsigned int __f)
}
#endif /* !__x86_64__ */

/** Cast a 32-bit float value to a 32-bit unsigned integer value
*
* \headerfile <x86intrin.h>
* This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction in x86_64,
* and corresponds to the <c> VMOVL / MOVL </c> instruction in ia32.
*
* \param __A
* A 32-bit float value.
* \returns a 32-bit unsigned integer containing the converted value.
*/
static __inline__ unsigned int __attribute__((__always_inline__))
_castf32_u32(float __A) {
unsigned int D;
__builtin_memcpy(&D, &__A, sizeof(__A));
return D;
}

/** Cast a 64-bit float value to a 64-bit unsigned integer value
*
* \headerfile <x86intrin.h>
* This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction in x86_64,
* and corresponds to the <c> VMOVL / MOVL </c> instruction in ia32.
*
* \param __A
* A 64-bit float value.
* \returns a 64-bit unsigned integer containing the converted value.
*/
static __inline__ unsigned long long __attribute__((__always_inline__))
_castf64_u64(double __A) {
unsigned long long D;
__builtin_memcpy(&D, &__A, sizeof(__A));
return D;
}

/** Cast a 32-bit unsigned integer value to a 32-bit float value
*
* \headerfile <x86intrin.h>
* This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction in x86_64,
* and corresponds to the <c> FLDS </c> instruction in ia32.
*
* \param __A
* A 32-bit unsigned integer value.
* \returns a 32-bit float value containing the converted value.
*/
static __inline__ float __attribute__((__always_inline__))
_castu32_f32(unsigned int __A) {
float D;
__builtin_memcpy(&D, &__A, sizeof(__A));
return D;
}

/** Cast a 64-bit unsigned integer value to a 64-bit float value
*
* \headerfile <x86intrin.h>
* This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction in x86_64,
* and corresponds to the <c> FLDL </c> instruction in ia32.
*
* \param __A
* A 64-bit unsigned integer value.
* \returns a 64-bit float value containing the converted value.
*/
static __inline__ double __attribute__((__always_inline__))
_castu64_f64(unsigned long long __A) {
double D;
__builtin_memcpy(&D, &__A, sizeof(__A));
return D;
}

/** Adds the unsigned integer operand to the CRC-32C checksum of the
* unsigned char operand.
*
Expand Down
45 changes: 45 additions & 0 deletions clang/test/CodeGen/x86-builtins.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-unknown-unknown -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=CHECK-64
// RUN: %clang_cc1 -ffreestanding %s -triple=i386-unknown-unknown -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=CHECK-32

#include <x86intrin.h>

unsigned int test_castf32_u32 (float __A){
// CHECK-64-LABEL: @test_castf32_u32
// CHECK-64: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 4, i1 false)
// CHECK-64: %{{.*}} = load i32, i32* %{{.*}}, align 4
// CHECK-32-LABEL: @test_castf32_u32
// CHECK-32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i32 4, i1 false)
// CHECK-32: %{{.*}} = load i32, i32* %{{.*}}, align 4
return _castf32_u32(__A);
}

unsigned long long test_castf64_u64 (double __A){
// CHECK-64-LABEL: @test_castf64_u64
// CHECK-64: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i64 8, i1 false)
// CHECK-64: %{{.*}} = load i64, i64* %{{.*}}, align 8
// CHECK-32-LABEL: @test_castf64_u64
// CHECK-32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i32 8, i1 false)
// CHECK-32: %{{.*}} = load i64, i64* %{{.*}}, align 8
return _castf64_u64(__A);
}

float test_castu32_f32 (unsigned int __A){
// CHECK-64-LABEL: @test_castu32_f32
// CHECK-64: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i64 4, i1 false)
// CHECK-64: %{{.*}} = load float, float* %{{.*}}, align 4
// CHECK-32-LABEL: @test_castu32_f32
// CHECK-32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i32 4, i1 false)
// CHECK-32: %{{.*}} = load float, float* %{{.*}}, align 4
return _castu32_f32(__A);
}

double test_castu64_f64 (unsigned long long __A){
// CHECK-64-LABEL: @test_castu64_f64
// CHECK-64: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i64 8, i1 false)
// CHECK-64: %{{.*}} = load double, double* %{{.*}}, align 8
// CHECK-32-LABEL: @test_castu64_f64
// CHECK-32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %{{.*}}, i8* align 8 %{{.*}}, i32 8, i1 false)
// CHECK-32: %{{.*}} = load double, double* %{{.*}}, align 8
return _castu64_f64(__A);
}

0 comments on commit 1f3a15c

Please sign in to comment.