From c796245431f9ed6a20399c00fa0f373cfd2b2de1 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Tue, 30 May 2017 11:37:29 +0000 Subject: [PATCH] [PPC] Make altivec conversion function macros. The second argument must be a constant, otherwise instruction selection will fail. always_inline is not enough for isel to always fold everything away at -O0. Sadly the overloading turned this into a big macro mess. Fixes PR33212. llvm-svn: 304205 --- clang/lib/Headers/altivec.h | 106 +++++++++++++++----------------- clang/test/CodeGen/altivec-ct.c | 80 ++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 57 deletions(-) create mode 100644 clang/test/CodeGen/altivec-ct.c diff --git a/clang/lib/Headers/altivec.h b/clang/lib/Headers/altivec.h index 957fd5f65e26..90fd477d9b98 100644 --- a/clang/lib/Headers/altivec.h +++ b/clang/lib/Headers/altivec.h @@ -2887,87 +2887,79 @@ static __inline__ vector double __ATTRS_o_ai vec_cpsgn(vector double __a, /* vec_ctf */ -static __inline__ vector float __ATTRS_o_ai vec_ctf(vector int __a, int __b) { - return __builtin_altivec_vcfsx(__a, __b); -} - -static __inline__ vector float __ATTRS_o_ai vec_ctf(vector unsigned int __a, - int __b) { - return __builtin_altivec_vcfux((vector int)__a, __b); -} - #ifdef __VSX__ -static __inline__ vector double __ATTRS_o_ai -vec_ctf(vector unsigned long long __a, int __b) { - vector double __ret = __builtin_convertvector(__a, vector double); - __ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52); - return __ret; -} - -static __inline__ vector double __ATTRS_o_ai -vec_ctf(vector signed long long __a, int __b) { - vector double __ret = __builtin_convertvector(__a, vector double); - __ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52); - return __ret; -} +#define vec_ctf(__a, __b) \ + _Generic((__a), vector int \ + : (vector float)__builtin_altivec_vcfsx((__a), (__b)), \ + vector unsigned int \ + : (vector float)__builtin_altivec_vcfux((vector int)(__a), (__b)), \ + vector unsigned long long \ + : (__builtin_convertvector((vector unsigned long long)(__a), \ + vector double) * \ + (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \ + << 52)), \ + vector signed long long \ + : (__builtin_convertvector((vector signed long long)(__a), \ + vector double) * \ + (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \ + << 52))) +#else +#define vec_ctf(__a, __b) \ + _Generic((__a), vector int \ + : (vector float)__builtin_altivec_vcfsx((__a), (__b)), \ + vector unsigned int \ + : (vector float)__builtin_altivec_vcfux((vector int)(__a), (__b))) #endif /* vec_vcfsx */ -static __inline__ vector float __attribute__((__always_inline__)) -vec_vcfsx(vector int __a, int __b) { - return __builtin_altivec_vcfsx(__a, __b); -} +#define vec_vcfux __builtin_altivec_vcfux /* vec_vcfux */ -static __inline__ vector float __attribute__((__always_inline__)) -vec_vcfux(vector unsigned int __a, int __b) { - return __builtin_altivec_vcfux((vector int)__a, __b); -} +#define vec_vcfsx(__a, __b) __builtin_altivec_vcfsx((vector int)(__a), (__b)) /* vec_cts */ -static __inline__ vector int __ATTRS_o_ai vec_cts(vector float __a, int __b) { - return __builtin_altivec_vctsxs(__a, __b); -} - #ifdef __VSX__ -static __inline__ vector signed long long __ATTRS_o_ai -vec_cts(vector double __a, int __b) { - __a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52); - return __builtin_convertvector(__a, vector signed long long); -} +#define vec_cts(__a, __b) \ + _Generic((__a), vector float \ + : __builtin_altivec_vctsxs((__a), (__b)), vector double \ + : __extension__({ \ + vector double __ret = \ + (__a) * \ + (vector double)(vector unsigned long long)((0x3ffULL + (__b)) \ + << 52); \ + __builtin_convertvector(__ret, vector signed long long); \ + })) +#else +#define vec_cts __builtin_altivec_vctsxs #endif /* vec_vctsxs */ -static __inline__ vector int __attribute__((__always_inline__)) -vec_vctsxs(vector float __a, int __b) { - return __builtin_altivec_vctsxs(__a, __b); -} +#define vec_vctsxs __builtin_altivec_vctsxs /* vec_ctu */ -static __inline__ vector unsigned int __ATTRS_o_ai vec_ctu(vector float __a, - int __b) { - return __builtin_altivec_vctuxs(__a, __b); -} - #ifdef __VSX__ -static __inline__ vector unsigned long long __ATTRS_o_ai -vec_ctu(vector double __a, int __b) { - __a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52); - return __builtin_convertvector(__a, vector unsigned long long); -} +#define vec_ctu(__a, __b) \ + _Generic((__a), vector float \ + : __builtin_altivec_vctuxs((__a), (__b)), vector double \ + : __extension__({ \ + vector double __ret = \ + (__a) * \ + (vector double)(vector unsigned long long)((0x3ffULL + __b) \ + << 52); \ + __builtin_convertvector(__ret, vector unsigned long long); \ + })) +#else +#define vec_ctu __builtin_altivec_vctuxs #endif /* vec_vctuxs */ -static __inline__ vector unsigned int __attribute__((__always_inline__)) -vec_vctuxs(vector float __a, int __b) { - return __builtin_altivec_vctuxs(__a, __b); -} +#define vec_vctuxs __builtin_altivec_vctuxs /* vec_signed */ diff --git a/clang/test/CodeGen/altivec-ct.c b/clang/test/CodeGen/altivec-ct.c new file mode 100644 index 000000000000..b825d5563312 --- /dev/null +++ b/clang/test/CodeGen/altivec-ct.c @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple powerpc64le-linux-gnu -S -O0 -o - %s -target-feature +altivec -target-feature +vsx | FileCheck %s -check-prefix=CHECK -check-prefix=VSX +// RUN: %clang_cc1 -triple powerpc-linux-gnu -S -O0 -o - %s -target-feature +altivec -target-feature -vsx | FileCheck %s + +#include + +// CHECK-LABEL: test1 +// CHECK: vcfsx +vector float test1(vector int x) { + return vec_ctf(x, 0); +} + +// CHECK-LABEL: test2 +// CHECK: vcfux +vector float test2(vector unsigned int x) { + return vec_ctf(x, 0); +} + +#ifdef __VSX__ +// VSX-LABEL: test3 +vector double test3(vector signed long long x) { + return vec_ctf(x, 0); +} + +// VSX-LABEL: test4 +vector double test4(vector unsigned long long x) { + return vec_ctf(x, 0); +} +#endif + +// CHECK-LABEL: test5 +// CHECK: vcfsx +vector float test5(vector int x) { + return vec_vcfsx(x, 0); +} + +// CHECK-LABEL: test6 +// CHECK: vcfux +vector float test6(vector unsigned int x) { + return vec_vcfux(x, 0); +} + +// CHECK-LABEL: test7 +// CHECK: vctsxs +vector int test7(vector float x) { + return vec_cts(x, 0); +} + +#ifdef __VSX__ +// VSX-LABEL: test8 +vector signed long long test8(vector double x) { + return vec_cts(x, 0); +} + +#endif + +// CHECK-LABEL: test9 +// CHECK: vctsxs +vector int test9(vector float x) { + return vec_vctsxs(x, 0); +} + +// CHECK-LABEL: test10 +// CHECK: vctuxs +vector unsigned test10(vector float x) { + return vec_ctu(x, 0); +} + +#ifdef __VSX__ +// VSX-LABEL: test11 +vector unsigned long long test11(vector double x) { + return vec_ctu(x, 0); +} + +#endif + +// CHECK-LABEL: test12 +// CHECK: vctuxs +vector unsigned test12(vector float x) { + return vec_vctuxs(x, 0); +}