summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Schmidt <wschmidt@linux.vnet.ibm.com>2014-06-06 14:45:06 +0000
committerBill Schmidt <wschmidt@linux.vnet.ibm.com>2014-06-06 14:45:06 +0000
commit7c0114f6e373497855844a063e9c2d9c4966da58 (patch)
tree90c90552593c65e7ad788480466c0cd34a348b78
parent4aedff8995d3e0788fd2e84079e5b19fcdf899c5 (diff)
downloadbcm5719-llvm-7c0114f6e373497855844a063e9c2d9c4966da58.tar.gz
bcm5719-llvm-7c0114f6e373497855844a063e9c2d9c4966da58.zip
[PPC64LE] Implement little-endian semantics for vec_mul[eo]
The PowerPC vector-multiply-even and vector-multiply-odd 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 definition is unnatural for little-endian code generation. To facilitate ease of porting, the vec_mule and vec_mulo interfacs 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_mule appears in the code, a vector-multiply-odd is generated, and when a call to vec_mulo appears in the code, a vector-multiply-even is generated. The correctness of this code is tested by the new mult-even-odd.c test added in a previous patch. I plan to later make the existing ppc32 Altivec compile-time tests work for ppc64 and ppc64le as well. llvm-svn: 210337
-rw-r--r--clang/lib/Headers/altivec.h67
1 files changed, 67 insertions, 0 deletions
diff --git a/clang/lib/Headers/altivec.h b/clang/lib/Headers/altivec.h
index 252d3fbba6d..9995415c010 100644
--- a/clang/lib/Headers/altivec.h
+++ b/clang/lib/Headers/altivec.h
@@ -3488,30 +3488,49 @@ vec_mtvscr(vector float __a)
__builtin_altivec_mtvscr((vector int)__a);
}
+/* The vmulos* and vmules* instructions have a big endian bias, so
+ we must reverse the meaning of "even" and "odd" for little endian. */
+
/* vec_mule */
static vector short __ATTRS_o_ai
vec_mule(vector signed char __a, vector signed char __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulosb(__a, __b);
+#else
return __builtin_altivec_vmulesb(__a, __b);
+#endif
}
static vector unsigned short __ATTRS_o_ai
vec_mule(vector unsigned char __a, vector unsigned char __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmuloub(__a, __b);
+#else
return __builtin_altivec_vmuleub(__a, __b);
+#endif
}
static vector int __ATTRS_o_ai
vec_mule(vector short __a, vector short __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulosh(__a, __b);
+#else
return __builtin_altivec_vmulesh(__a, __b);
+#endif
}
static vector unsigned int __ATTRS_o_ai
vec_mule(vector unsigned short __a, vector unsigned short __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulouh(__a, __b);
+#else
return __builtin_altivec_vmuleuh(__a, __b);
+#endif
}
/* vec_vmulesb */
@@ -3519,7 +3538,11 @@ vec_mule(vector unsigned short __a, vector unsigned short __b)
static vector short __attribute__((__always_inline__))
vec_vmulesb(vector signed char __a, vector signed char __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulosb(__a, __b);
+#else
return __builtin_altivec_vmulesb(__a, __b);
+#endif
}
/* vec_vmuleub */
@@ -3527,7 +3550,11 @@ vec_vmulesb(vector signed char __a, vector signed char __b)
static vector unsigned short __attribute__((__always_inline__))
vec_vmuleub(vector unsigned char __a, vector unsigned char __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmuloub(__a, __b);
+#else
return __builtin_altivec_vmuleub(__a, __b);
+#endif
}
/* vec_vmulesh */
@@ -3535,7 +3562,11 @@ vec_vmuleub(vector unsigned char __a, vector unsigned char __b)
static vector int __attribute__((__always_inline__))
vec_vmulesh(vector short __a, vector short __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulosh(__a, __b);
+#else
return __builtin_altivec_vmulesh(__a, __b);
+#endif
}
/* vec_vmuleuh */
@@ -3543,7 +3574,11 @@ vec_vmulesh(vector short __a, vector short __b)
static vector unsigned int __attribute__((__always_inline__))
vec_vmuleuh(vector unsigned short __a, vector unsigned short __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulouh(__a, __b);
+#else
return __builtin_altivec_vmuleuh(__a, __b);
+#endif
}
/* vec_mulo */
@@ -3551,25 +3586,41 @@ vec_vmuleuh(vector unsigned short __a, vector unsigned short __b)
static vector short __ATTRS_o_ai
vec_mulo(vector signed char __a, vector signed char __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulesb(__a, __b);
+#else
return __builtin_altivec_vmulosb(__a, __b);
+#endif
}
static vector unsigned short __ATTRS_o_ai
vec_mulo(vector unsigned char __a, vector unsigned char __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmuleub(__a, __b);
+#else
return __builtin_altivec_vmuloub(__a, __b);
+#endif
}
static vector int __ATTRS_o_ai
vec_mulo(vector short __a, vector short __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulesh(__a, __b);
+#else
return __builtin_altivec_vmulosh(__a, __b);
+#endif
}
static vector unsigned int __ATTRS_o_ai
vec_mulo(vector unsigned short __a, vector unsigned short __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmuleuh(__a, __b);
+#else
return __builtin_altivec_vmulouh(__a, __b);
+#endif
}
/* vec_vmulosb */
@@ -3577,7 +3628,11 @@ vec_mulo(vector unsigned short __a, vector unsigned short __b)
static vector short __attribute__((__always_inline__))
vec_vmulosb(vector signed char __a, vector signed char __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulesb(__a, __b);
+#else
return __builtin_altivec_vmulosb(__a, __b);
+#endif
}
/* vec_vmuloub */
@@ -3585,7 +3640,11 @@ vec_vmulosb(vector signed char __a, vector signed char __b)
static vector unsigned short __attribute__((__always_inline__))
vec_vmuloub(vector unsigned char __a, vector unsigned char __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmuleub(__a, __b);
+#else
return __builtin_altivec_vmuloub(__a, __b);
+#endif
}
/* vec_vmulosh */
@@ -3593,7 +3652,11 @@ vec_vmuloub(vector unsigned char __a, vector unsigned char __b)
static vector int __attribute__((__always_inline__))
vec_vmulosh(vector short __a, vector short __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmulesh(__a, __b);
+#else
return __builtin_altivec_vmulosh(__a, __b);
+#endif
}
/* vec_vmulouh */
@@ -3601,7 +3664,11 @@ vec_vmulosh(vector short __a, vector short __b)
static vector unsigned int __attribute__((__always_inline__))
vec_vmulouh(vector unsigned short __a, vector unsigned short __b)
{
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vmuleuh(__a, __b);
+#else
return __builtin_altivec_vmulouh(__a, __b);
+#endif
}
/* vec_nmsub */
OpenPOWER on IntegriCloud