[libmath-prime-util-perl] 73/181: various XSUB optimizations

Partha P. Mukherjee ppm-guest at moszumanska.debian.org
Thu May 21 18:51:08 UTC 2015


This is an automated email from the git hooks/post-receive script.

ppm-guest pushed a commit to annotated tag v0.36
in repository libmath-prime-util-perl.

commit 4e0e6abf4b193a8f51bf8d01609856ec183adf4b
Author: bulk88 <bulk88 at hotmail.com>
Date:   Mon Dec 30 21:15:59 2013 -0500

    various XSUB optimizations
    
    in prime_memfree convert _XS_prime_maxbitsm from alias to pure perl
    possibly constant folding const sub
    
    in _XS_prime_count, if G_VOID, don't alloc or fetch any SVs if returning
    nothing, use TARG to return a UV, PUSHu unrolled for locality to
    put XSprePUSH near PUSHs and PUTBACK into a 3 statement function call free
    area of stack manipulation
    
    in _XS_miller_rabin, XSRETURN_IV would generate a new mortal SVIV,
    instead of using the TARG SV* already allocated and set to IV on one
    particular execution path, TARG is more efficient since it often is a
    pad SV of the caller pure perl sub, and takes a shortcut through sv_setsv
    if both src and dest SV*s are identical
    
    in _XS_ExponentialIntegral factor out the SvNV and SvUV, teach compiler to
    optimize out the default and not complain about it on < 4 branch (in
    theory, var ix could be negative since its an I32), MPUASSUME code is from
    Perl 5.19
    
    in _validate_num read my_perl->Istack_base less often (inside ST macro)
---
 XS.xs    | 67 +++++++++++++++++++++++++++++++++++++++++++++++-----------------
 ptypes.h | 19 ++++++++++++++++++
 2 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/XS.xs b/XS.xs
index 851142f..7b5578d 100644
--- a/XS.xs
+++ b/XS.xs
@@ -146,6 +146,12 @@ MODULE = Math::Prime::Util	PACKAGE = Math::Prime::Util
 
 PROTOTYPES: ENABLE
 
+BOOT:
+{
+    SV * sv = newSViv(BITS_PER_WORD);
+    HV * stash = gv_stashpv("Math::Prime::Util", TRUE);
+    newCONSTSUB(stash, "_XS_prime_maxbits", sv);
+}
 
 void
 prime_memfree()
@@ -154,7 +160,6 @@ prime_memfree()
     _XS_get_verbose = 2
     _XS_get_callgmp = 3
     _get_prime_cache_size = 4
-    _XS_prime_maxbits = 5
   PPCODE:
     UV ret = 0;
     switch (ix) {
@@ -163,7 +168,6 @@ prime_memfree()
       case 2:  ret = _XS_get_verbose(); break;
       case 3:  ret = _XS_get_callgmp(); break;
       case 4:  ret = get_prime_cache(0,0); break;
-      case 5:  ret = BITS_PER_WORD;     break;
     }
     if (ix > 1) XSRETURN_UV(ret);
 
@@ -182,16 +186,30 @@ prime_precalc(IN UV n)
 
 void
 _XS_prime_count(IN UV low, IN UV high = 0)
-  PPCODE:
+  CODE:
     if (high == 0) {   /* Without a Perl layer in front of this, we'll have */
       high = low;      /* the pathological case of a-0 turning into 0-a.    */
       low = 0;
     }
     if (GIMME_V == G_VOID) {
       prime_precalc(high);
+      /* doing PPCODE: (implied XSprePUSH) and jumping to the PUTBACK was less
+      efficient machine code wise than these 2 return paths*/
+      XSRETURN(0);
     } else {
-      PUSHs(sv_2mortal(newSVuv( _XS_prime_count(low, high) )));
+      UV RETVAL;
+      RETVAL = _XS_prime_count(low, high);
+      {
+        dXSTARG;
+        sv_setuv(TARG, RETVAL);
+        SvSETMAGIC(TARG);
+        XSprePUSH;
+        PUSHs(TARG);
+        PUTBACK;
+        return;
+      }
     }
+    /*unreachable*/
 
 UV
 _XS_nth_prime(IN UV n)
@@ -367,9 +385,9 @@ _XS_miller_rabin(IN UV n, ...)
   CODE:
     if (items < 2)
       croak("No bases given to miller_rabin");
-    if ( (n == 0) || (n == 1) ) XSRETURN_IV(0);   /* 0 and 1 are composite */
-    if ( (n == 2) || (n == 3) ) XSRETURN_IV(1);   /* 2 and 3 are prime */
-    if (( n % 2 ) == 0)  XSRETURN_IV(0);          /* MR works with odd n */
+    if ( (n == 0) || (n == 1) ) {RETVAL = 0; goto return_iv;}   /* 0 and 1 are composite */
+    if ( (n == 2) || (n == 3) ) {RETVAL = 1; goto return_iv;}   /* 2 and 3 are prime */
+    if (( n % 2 ) == 0) {RETVAL = 0; goto return_iv;}          /* MR works with odd n */
     while (c < items) {
       int b = 0;
       while (c < items) {
@@ -382,6 +400,7 @@ _XS_miller_rabin(IN UV n, ...)
         break;
     }
     RETVAL = prob_prime;
+    return_iv:
   OUTPUT:
     RETVAL
 
@@ -568,13 +587,22 @@ _XS_ExponentialIntegral(IN SV* x)
   PREINIT:
     double ret;
   CODE:
-    switch (ix) {
-      case 0: ret = _XS_ExponentialIntegral(SvNV(x)); break;
-      case 1: ret = _XS_LogarithmicIntegral(SvNV(x)); break;
-      case 2: ret = (double) ld_riemann_zeta(SvNV(x)); break;
-      case 3: ret = _XS_RiemannR(SvNV(x)); break;
-      case 4: ret = _XS_chebyshev_theta(SvUV(x)); break;
-      default:ret = _XS_chebyshev_psi(SvUV(x)); break;
+    if(ix < 4 ) {
+      NV nv = SvNV(x);
+      switch (ix) {
+        case 0: ret = _XS_ExponentialIntegral(nv); break;
+        case 1: ret = _XS_LogarithmicIntegral(nv); break;
+        case 2: ret = (double) ld_riemann_zeta(nv); break;
+        case 3: ret = _XS_RiemannR(nv); break;
+        default: MPUNOT_REACHED; break; /* CC thinks ix is negative */
+      }
+    } else {
+      UV uv = SvUV(x);
+      switch (ix) {
+        case 4: ret = _XS_chebyshev_theta(uv); break;
+        case 5:
+        default: ret = _XS_chebyshev_psi(uv); break;
+      }
     }
     RETVAL = ret;
   OUTPUT:
@@ -687,6 +715,9 @@ carmichael_lambda(IN SV* svn)
 
 int
 _validate_num(SV* svn, ...)
+  PREINIT:
+    SV* sv1;
+    SV* sv2;
   CODE:
     RETVAL = 0;
     if (_validate_int(aTHX_ svn, 0)) {
@@ -694,13 +725,13 @@ _validate_num(SV* svn, ...)
         UV n = my_svuv(svn);
         sv_setuv(svn, n);
       }
-      if (items > 1 && SvOK(ST(1))) {
+      if (items > 1 && ((sv1 = ST(1)), SvOK(sv1))) {
         UV n = my_svuv(svn);
-        UV min = my_svuv(ST(1));
+        UV min = my_svuv(sv1);
         if (n < min)
           croak("Parameter '%"UVuf"' must be >= %"UVuf, n, min);
-        if (items > 2 && SvOK(ST(2))) {
-          UV max = my_svuv(ST(2));
+        if (items > 2 && ((sv2 = ST(2)), SvOK(sv2))) {
+          UV max = my_svuv(sv2);
           if (n > max)
             croak("Parameter '%"UVuf"' must be <= %"UVuf, n, max);
           MPUassert( items <= 3, "_validate_num takes at most 3 parameters");
diff --git a/ptypes.h b/ptypes.h
index 1259198..6c51e4d 100644
--- a/ptypes.h
+++ b/ptypes.h
@@ -102,4 +102,23 @@ typedef __int8 int8_t;
 
 #define MPUassert(c,text) if (!(c)) { croak("Math::Prime::Util internal error: " text); }
 
+#ifndef DEBUGGING
+#  if __has_builtin(__builtin_unreachable) \
+     || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5 || __GNUC__ > 5) /* 4.5 -> */
+#    define MPUASSUME(x) ((x) ? (void) 0 : __builtin_unreachable())
+#  elif defined(_MSC_VER)
+#    define MPUASSUME(x) __assume(x)
+#  elif defined(__ARMCC_VERSION) /* untested */
+#    define MPUASSUME(x) __promise(x)
+#  else
+/* a random compiler might define assert to its own special optimization token
+   so pass it through to C lib as a last resort */
+#    define MPUASSUME(x) assert(x)
+#  endif
+#else
+#  define MPUASSUME(x) assert(x)
+#endif
+
+#define MPUNOT_REACHED MPUASSUME(0)
+
 #endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git



More information about the Pkg-perl-cvs-commits mailing list