Krait enhancements from caf

msm8960: Improve performance of memmove, bcopy, and memmove_words

Change-Id: I62b3da046889387f835da741110d35ffd3c8f806

Conflicts:
	libc/Android.mk

msm8960: Improve performance of memcpy

Change-Id: I0c8355ae5e92060ad5a0811d33937e6913c8b633

Bionic/libm: fast neon pow() for small x,y

Add a fast neon version of pow() suitable for relatively small
positive x and y (between 0 and 4).  Run the standard
implementation in all other cases.  Gives approximately 60%
performance improvement to AnTuTu FPU score.

Change-Id: I9234d37eaa6a815d1e619375f5b049c4ec88f557

msm7627a: Enable neon optimized memove and pow functions.

Define SPARROW_NEON_OPTIMIZATION flag so that neon optimized
memove and pow functions are used. Also add Corresponding
definitions in make files.

Change-Id: I12089fc7002e3ec294e63632bd84e395fbd24936

Bionic/libm: Prefer branches and VFP ABI

For internal functions set gcc attribute "aapcs-vfp" for ARM
and use -fno-if-conversion to prefer branches over predicated
instructions (improves performance on architectures with good
branch prediction).

Change-Id: I365e9508bd3babb0bb06fc5de127c1ae17445bcc

Bionic/libm: add assembly versions of sin/cos

Add assembly versions of sin/cos with integrated remainder pi/2
calculation.  Directly extracted from binary libm.so compiled with
__ieee754_rem_pio2 calls inlined.

Change-Id: I9a999c01cea92aace9df7be9ad8f90f150040375

Conflicts:
	libm/Android.mk

Bionic/libm: Remove extra vmov from sin/cos

Move integer representations of x bits on the integer side rather
than moving them to and from the FP registers.

Change-Id: I1d0800730d7553a47c462ee2a0cc044ffe62eb20

Bionic/libm: Pow optimizations and bug fixes

Use VFP calling convention for pow_neon handoff function by default.
Fix register usage collision between two different polynomial
coefficients in pow_neon.  Remove conditional execution in pow_neon
and replace with branching.

Change-Id: I254617940b2787297aff2ab97dbf45c11e6a2b08

Bionic/libm: Add precision-correct de-serialize sin/cos

Modify sin/cos to improve performance while retaining either
bit-for-bit agreement with previous algorithm or <1 ulp
deviation from arbitrary precision result.

Change-Id: Icbd6d66fb1c0ceb53f43fed6541e0c89cc6e7a63
diff --git a/libm/src/e_pow.c b/libm/src/e_pow.c
index d213132..b0a3f53 100644
--- a/libm/src/e_pow.c
+++ b/libm/src/e_pow.c
@@ -61,6 +61,14 @@
 #include "math.h"
 #include "math_private.h"
 
+#if defined(KRAIT_NEON_OPTIMIZATION) || defined(SPARROW_NEON_OPTIMIZATION)
+#if defined(KRAIT_NO_AAPCS_VFP_MODE)
+double pow_neon(double x, double y);
+#else
+double pow_neon(double x, double y, int32_t lx, int32_t hx) __attribute__((pcs("aapcs-vfp")));
+#endif
+#endif
+
 static const double
 bp[] = {1.0, 1.5,},
 dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
@@ -108,12 +116,32 @@
 	ix = hx&0x7fffffff;  iy = hy&0x7fffffff;
 
     /* y==zero: x**0 = 1 */
-	if((iy|ly)==0) return one; 	
 
-    /* +-NaN return x+y */
-	if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
-	   iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) 
-		return x+y;	
+    if (ly == 0) {
+        if (hy == ly) {
+            /* y==0.0, x**0 = 1 */
+            return one;
+        }
+        else if (iy > 0x7ff00000) {
+            /* y is NaN, return x+y (NaN) */
+            return x+y;
+        }
+    }
+    else if (iy >= 0x7ff00000) {
+        /* y is NaN, return x+y (NaN) */
+        return x+y;
+    }
+
+    if (lx == 0) {
+        if (ix > 0x7ff00000) {
+            /* x is NaN, return x+y (NaN) */
+            return x+y;
+        }
+    }
+    else if (ix >= 0x7ff00000) {
+        /* x is NaN, return x+y (NaN) */
+        return x+y;
+    }
 
     /* determine if y is an odd int when x < 0
      * yisint = 0	... y is not an integer
@@ -201,6 +229,14 @@
 	    t1 = u+v;
 	    SET_LOW_WORD(t1,0);
 	    t2 = v-(t1-u);
+#if defined(KRAIT_NEON_OPTIMIZATION) || defined(SPARROW_NEON_OPTIMIZATION)
+	} else if (ix <= 0x40100000 && iy <= 0x40100000 && hy > 0 && hx > 0) {
+#if defined(KRAIT_NO_AAPCS_VFP_MODE)
+		return pow_neon(x,y);
+#else
+		return pow_neon(x,y,lx,hx);
+#endif
+#endif
 	} else {
 	    double ss,s2,s_h,s_l,t_h,t_l;
 	    n = 0;
diff --git a/libm/src/k_cos.c b/libm/src/k_cos.c
index 00916d7..b8cdf8f 100644
--- a/libm/src/k_cos.c
+++ b/libm/src/k_cos.c
@@ -69,6 +69,17 @@
 double
 __kernel_cos(double x, double y)
 {
+#if defined(KRAIT_NEON_OPTIMIZATION)
+	double hz,z,zz,r,w,k;
+
+	z  = x*x;
+	zz = z*z;
+	k = x*y;
+	hz = (float)0.5*z;
+	r  = z*(z*(C1+z*(C2+z*((C3+z*C4)+zz*(C5+z*C6)))));
+	w  = one-hz;
+	return w + (((one-w)-hz) + (r-k));
+#else
 	double hz,z,r,w;
 
 	z  = x*x;
@@ -76,4 +87,5 @@
 	hz = (float)0.5*z;
 	w  = one-hz;
 	return w + (((one-w)-hz) + (z*r-x*y));
+#endif
 }
diff --git a/libm/src/k_sin.c b/libm/src/k_sin.c
index ae06a9d..ee641d4 100644
--- a/libm/src/k_sin.c
+++ b/libm/src/k_sin.c
@@ -60,6 +60,16 @@
 double
 __kernel_sin(double x, double y, int iy)
 {
+#if defined(KRAIT_NEON_OPTIMIZATION)
+	double z,zz,r,v;
+
+	z	=  x*x;
+	zz  =  z*z;
+	v	=  z*x;
+	r	=  S2+z*((S3+z*S4)+zz*(S5+z*S6));
+	if(iy==0) return x+v*(S1+z*r);
+	else      return x-((z*(half*y-v*r)-y)-v*S1);
+#else
 	double z,r,v;
 
 	z	=  x*x;
@@ -67,4 +77,5 @@
 	r	=  S2+z*(S3+z*(S4+z*(S5+z*S6)));
 	if(iy==0) return x+v*(S1+z*r);
 	else      return x-((z*(half*y-v*r)-y)-v*S1);
+#endif
 }
diff --git a/libm/src/math_private.h b/libm/src/math_private.h
index 5f6e088..7cda2e9 100644
--- a/libm/src/math_private.h
+++ b/libm/src/math_private.h
@@ -257,11 +257,19 @@
 #define __ieee754_ldexpf ldexpf
 
 /* fdlibm kernel function */
+#if defined(KRAIT_NEON_OPTIMIZATION)
+int	__ieee754_rem_pio2(double,double*) __attribute__((pcs("aapcs-vfp")));
+double	__kernel_sin(double,double,int) __attribute__((pcs("aapcs-vfp")));
+double	__kernel_cos(double,double) __attribute__((pcs("aapcs-vfp")));
+double	__kernel_tan(double,double,int) __attribute__((pcs("aapcs-vfp")));
+int	__kernel_rem_pio2(double*,double*,int,int,int,const int*) __attribute__((pcs("aapcs-vfp")));
+#else
 int	__ieee754_rem_pio2(double,double*);
 double	__kernel_sin(double,double,int);
 double	__kernel_cos(double,double);
 double	__kernel_tan(double,double,int);
 int	__kernel_rem_pio2(double*,double*,int,int,int,const int*);
+#endif
 
 /* float versions of fdlibm kernel functions */
 int	__ieee754_rem_pio2f(float,float*);