From: Bill Schmidt Date: Sat, 7 Jun 2014 02:20:52 +0000 (+0000) Subject: [PPC64LE] Implement little-endian semantics for vec_unpack[hl] X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=61d8772216d8e932b08ed0eb4fa3542592e8f4cb;p=clang [PPC64LE] Implement little-endian semantics for vec_unpack[hl] The PowerPC vector-unpack-high and vector-unpack-low instructions are defined architecturally with a big-endian bias, in that the vector element numbering is assumed to be "left to right" regardless of whether the processor is in big-endian or little-endian mode. This effectively reverses the meaning of "high" and "low." Such a definition is unnatural for little-endian code generation. To facilitate ease of porting, the vec_unpackh and vec_unpackl interfaces are designed to use natural element ordering, so that elements are numbered according to little-endian design principles when code is generated for a little-endian target. The desired semantics can be achieved by using the opposite instruction for little-endian mode. That is, when a call to vec_unpackh appears in the code, a vector-unpack-low is generated, and when a call to vec_unpackl appears in the code, a vector-unpack-high is generated. The correctness of this code is tested by the new unpack.c test added in a previous patch, as well as the modifications to builtins-ppc-altivec.c in the present patch. Note that these interfaces were originally incorrectly implemented when they take a vector pixel argument. This patch corrects this implementation for both big- and little-endian code generation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210391 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Headers/altivec.h b/lib/Headers/altivec.h index 7dfb74e069..65990e0db4 100644 --- a/lib/Headers/altivec.h +++ b/lib/Headers/altivec.h @@ -8430,34 +8430,57 @@ vec_vrfiz(vector float __a) /* vec_unpackh */ +/* The vector unpack instructions all have a big-endian bias, so for + little endian we must reverse the meanings of "high" and "low." */ + static vector short __ATTRS_o_ai vec_unpackh(vector signed char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vupklsb((vector char)__a); +#else return __builtin_altivec_vupkhsb((vector char)__a); +#endif } static vector bool short __ATTRS_o_ai vec_unpackh(vector bool char __a) { +#ifdef __LITTLE_ENDIAN__ + return (vector bool short)__builtin_altivec_vupklsb((vector char)__a); +#else return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a); +#endif } static vector int __ATTRS_o_ai vec_unpackh(vector short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vupklsh(__a); +#else return __builtin_altivec_vupkhsh(__a); +#endif } static vector bool int __ATTRS_o_ai vec_unpackh(vector bool short __a) { +#ifdef __LITTLE_ENDIAN__ + return (vector bool int)__builtin_altivec_vupklsh((vector short)__a); +#else return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a); +#endif } static vector unsigned int __ATTRS_o_ai vec_unpackh(vector pixel __a) { - return (vector unsigned int)__builtin_altivec_vupkhsh((vector short)__a); +#ifdef __LITTLE_ENDIAN__ + return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a); +#else + return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a); +#endif } /* vec_vupkhsb */ @@ -8465,13 +8488,21 @@ vec_unpackh(vector pixel __a) static vector short __ATTRS_o_ai vec_vupkhsb(vector signed char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vupklsb((vector char)__a); +#else return __builtin_altivec_vupkhsb((vector char)__a); +#endif } static vector bool short __ATTRS_o_ai vec_vupkhsb(vector bool char __a) { +#ifdef __LITTLE_ENDIAN__ + return (vector bool short)__builtin_altivec_vupklsb((vector char)__a); +#else return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a); +#endif } /* vec_vupkhsh */ @@ -8479,19 +8510,31 @@ vec_vupkhsb(vector bool char __a) static vector int __ATTRS_o_ai vec_vupkhsh(vector short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vupklsh(__a); +#else return __builtin_altivec_vupkhsh(__a); +#endif } static vector bool int __ATTRS_o_ai vec_vupkhsh(vector bool short __a) { +#ifdef __LITTLE_ENDIAN__ + return (vector bool int)__builtin_altivec_vupklsh((vector short)__a); +#else return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a); +#endif } static vector unsigned int __ATTRS_o_ai vec_vupkhsh(vector pixel __a) { - return (vector unsigned int)__builtin_altivec_vupkhsh((vector short)__a); +#ifdef __LITTLE_ENDIAN__ + return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a); +#else + return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a); +#endif } /* vec_unpackl */ @@ -8499,31 +8542,51 @@ vec_vupkhsh(vector pixel __a) static vector short __ATTRS_o_ai vec_unpackl(vector signed char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vupkhsb((vector char)__a); +#else return __builtin_altivec_vupklsb((vector char)__a); +#endif } static vector bool short __ATTRS_o_ai vec_unpackl(vector bool char __a) { +#ifdef __LITTLE_ENDIAN__ + return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a); +#else return (vector bool short)__builtin_altivec_vupklsb((vector char)__a); +#endif } static vector int __ATTRS_o_ai vec_unpackl(vector short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vupkhsh(__a); +#else return __builtin_altivec_vupklsh(__a); +#endif } static vector bool int __ATTRS_o_ai vec_unpackl(vector bool short __a) { +#ifdef __LITTLE_ENDIAN__ + return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a); +#else return (vector bool int)__builtin_altivec_vupklsh((vector short)__a); +#endif } static vector unsigned int __ATTRS_o_ai vec_unpackl(vector pixel __a) { - return (vector unsigned int)__builtin_altivec_vupklsh((vector short)__a); +#ifdef __LITTLE_ENDIAN__ + return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a); +#else + return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a); +#endif } /* vec_vupklsb */ @@ -8531,13 +8594,21 @@ vec_unpackl(vector pixel __a) static vector short __ATTRS_o_ai vec_vupklsb(vector signed char __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vupkhsb((vector char)__a); +#else return __builtin_altivec_vupklsb((vector char)__a); +#endif } static vector bool short __ATTRS_o_ai vec_vupklsb(vector bool char __a) { +#ifdef __LITTLE_ENDIAN__ + return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a); +#else return (vector bool short)__builtin_altivec_vupklsb((vector char)__a); +#endif } /* vec_vupklsh */ @@ -8545,19 +8616,31 @@ vec_vupklsb(vector bool char __a) static vector int __ATTRS_o_ai vec_vupklsh(vector short __a) { +#ifdef __LITTLE_ENDIAN__ + return __builtin_altivec_vupkhsh(__a); +#else return __builtin_altivec_vupklsh(__a); +#endif } static vector bool int __ATTRS_o_ai vec_vupklsh(vector bool short __a) { +#ifdef __LITTLE_ENDIAN__ + return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a); +#else return (vector bool int)__builtin_altivec_vupklsh((vector short)__a); +#endif } static vector unsigned int __ATTRS_o_ai vec_vupklsh(vector pixel __a) { - return (vector unsigned int)__builtin_altivec_vupklsh((vector short)__a); +#ifdef __LITTLE_ENDIAN__ + return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a); +#else + return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a); +#endif } /* vec_xor */ diff --git a/test/CodeGen/builtins-ppc-altivec.c b/test/CodeGen/builtins-ppc-altivec.c index 8a846bdec8..8277f5dda7 100644 --- a/test/CodeGen/builtins-ppc-altivec.c +++ b/test/CodeGen/builtins-ppc-altivec.c @@ -5173,84 +5173,84 @@ void test6() { /* vec_unpackh */ res_vs = vec_unpackh(vsc); // CHECK: @llvm.ppc.altivec.vupkhsb -// CHECK-LE: @llvm.ppc.altivec.vupkhsb +// CHECK-LE: @llvm.ppc.altivec.vupklsb res_vbs = vec_unpackh(vbc); // CHECK: @llvm.ppc.altivec.vupkhsb -// CHECK-LE: @llvm.ppc.altivec.vupkhsb +// CHECK-LE: @llvm.ppc.altivec.vupklsb res_vi = vec_unpackh(vs); // CHECK: @llvm.ppc.altivec.vupkhsh -// CHECK-LE: @llvm.ppc.altivec.vupkhsh +// CHECK-LE: @llvm.ppc.altivec.vupklsh res_vbi = vec_unpackh(vbs); // CHECK: @llvm.ppc.altivec.vupkhsh -// CHECK-LE: @llvm.ppc.altivec.vupkhsh +// CHECK-LE: @llvm.ppc.altivec.vupklsh res_vui = vec_unpackh(vp); -// CHECK: @llvm.ppc.altivec.vupkhsh -// CHECK-LE: @llvm.ppc.altivec.vupkhsh +// CHECK: @llvm.ppc.altivec.vupkhpx +// CHECK-LE: @llvm.ppc.altivec.vupklpx res_vs = vec_vupkhsb(vsc); // CHECK: @llvm.ppc.altivec.vupkhsb -// CHECK-LE: @llvm.ppc.altivec.vupkhsb +// CHECK-LE: @llvm.ppc.altivec.vupklsb res_vbs = vec_vupkhsb(vbc); // CHECK: @llvm.ppc.altivec.vupkhsb -// CHECK-LE: @llvm.ppc.altivec.vupkhsb +// CHECK-LE: @llvm.ppc.altivec.vupklsb res_vi = vec_vupkhsh(vs); // CHECK: @llvm.ppc.altivec.vupkhsh -// CHECK-LE: @llvm.ppc.altivec.vupkhsh +// CHECK-LE: @llvm.ppc.altivec.vupklsh res_vbi = vec_vupkhsh(vbs); // CHECK: @llvm.ppc.altivec.vupkhsh -// CHECK-LE: @llvm.ppc.altivec.vupkhsh +// CHECK-LE: @llvm.ppc.altivec.vupklsh res_vui = vec_vupkhsh(vp); -// CHECK: @llvm.ppc.altivec.vupkhsh -// CHECK-LE: @llvm.ppc.altivec.vupkhsh +// CHECK: @llvm.ppc.altivec.vupkhpx +// CHECK-LE: @llvm.ppc.altivec.vupklpx /* vec_unpackl */ res_vs = vec_unpackl(vsc); // CHECK: @llvm.ppc.altivec.vupklsb -// CHECK-LE: @llvm.ppc.altivec.vupklsb +// CHECK-LE: @llvm.ppc.altivec.vupkhsb res_vbs = vec_unpackl(vbc); // CHECK: @llvm.ppc.altivec.vupklsb -// CHECK-LE: @llvm.ppc.altivec.vupklsb +// CHECK-LE: @llvm.ppc.altivec.vupkhsb res_vi = vec_unpackl(vs); // CHECK: @llvm.ppc.altivec.vupklsh -// CHECK-LE: @llvm.ppc.altivec.vupklsh +// CHECK-LE: @llvm.ppc.altivec.vupkhsh res_vbi = vec_unpackl(vbs); // CHECK: @llvm.ppc.altivec.vupklsh -// CHECK-LE: @llvm.ppc.altivec.vupklsh +// CHECK-LE: @llvm.ppc.altivec.vupkhsh res_vui = vec_unpackl(vp); -// CHECK: @llvm.ppc.altivec.vupklsh -// CHECK-LE: @llvm.ppc.altivec.vupklsh +// CHECK: @llvm.ppc.altivec.vupklpx +// CHECK-LE: @llvm.ppc.altivec.vupkhpx res_vs = vec_vupklsb(vsc); // CHECK: @llvm.ppc.altivec.vupklsb -// CHECK-LE: @llvm.ppc.altivec.vupklsb +// CHECK-LE: @llvm.ppc.altivec.vupkhsb res_vbs = vec_vupklsb(vbc); // CHECK: @llvm.ppc.altivec.vupklsb -// CHECK-LE: @llvm.ppc.altivec.vupklsb +// CHECK-LE: @llvm.ppc.altivec.vupkhsb res_vi = vec_vupklsh(vs); // CHECK: @llvm.ppc.altivec.vupklsh -// CHECK-LE: @llvm.ppc.altivec.vupklsh +// CHECK-LE: @llvm.ppc.altivec.vupkhsh res_vbi = vec_vupklsh(vbs); // CHECK: @llvm.ppc.altivec.vupklsh -// CHECK-LE: @llvm.ppc.altivec.vupklsh +// CHECK-LE: @llvm.ppc.altivec.vupkhsh res_vui = vec_vupklsh(vp); -// CHECK: @llvm.ppc.altivec.vupklsh -// CHECK-LE: @llvm.ppc.altivec.vupklsh +// CHECK: @llvm.ppc.altivec.vupklpx +// CHECK-LE: @llvm.ppc.altivec.vupkhpx /* vec_xor */ res_vsc = vec_xor(vsc, vsc);