Blob Blame History Raw
Description: enable runtime detection of popcnt-enabled CPU
Origin: fedora
Author: Jerry James <loganjerry@gmail.com>
Last-Update: 2021-09-02

--- a/addedgeg.c
+++ b/addedgeg.c
@@ -74,6 +74,23 @@ no4path(graph *g, int m, int n, int v, i
 }
 
 /*************************************************************************/
+STATIC_POPCNTFUNC(int,compute_degree,(const graph *g, int *deg, int m, int n),
+{
+    const setword *gv;
+    int v, actmaxdeg = 0;
+
+    for (v = 0, gv = g; v < n; ++v, gv += m)
+    {
+        int i, degv = 0;
+        for (i = 0; i < m; ++i)
+            degv += POPCOUNT(gv[i]);
+        if (degv > actmaxdeg) actmaxdeg = degv;
+        deg[v] = degv;
+    }
+    return actmaxdeg;
+})
+
+/*************************************************************************/
 
 int
 main(int argc, char *argv[])
@@ -89,7 +106,7 @@ main(int argc, char *argv[])
 	nauty_counter nin,nout;
         char *arg,sw;
 	setword *gv,*gw;
-	int maxdeg,actmaxdeg,degv;
+	int maxdeg,actmaxdeg;
 	double t;
 #if MAXN
 	graph h[MAXN*MAXM];
@@ -208,16 +225,7 @@ main(int argc, char *argv[])
 	    DYNALLOC1(int,dist,dist_sz,n,"addedgeg");
 #endif
 
-	    actmaxdeg = n;
-	    for (v = 0, gv = g; v < n; ++v, gv += m)
-	    {
-		degv = 0;
-		for (i = 0; i < m; ++i)
-		    degv += POPCOUNT(gv[i]);
-		if (degv < actmaxdeg) actmaxdeg = degv;
-		deg[v] = degv;
-	    }
-
+	    actmaxdeg = compute_degree(g, deg, m, n);
 	    if (actmaxdeg > maxdeg) continue;
 
 	    okdist[0] = okdist[1] = FALSE;
--- a/complg.c
+++ b/complg.c
@@ -51,6 +51,17 @@ compl(graph *g, int m, int n, graph *h,
     }
 }
 
+/*************************************************************************/
+STATIC_POPCNTFUNC(size_t __attribute__((pure)),num_edges,
+    (const graph *g, size_t gwords),
+{
+    size_t ii, ned;
+
+    ned = 0;
+    for (ii = 0; ii < gwords; ++ii) ned += POPCOUNT(g[ii]);
+    return ned;
+})
+
 /**************************************************************************/
 
 int
@@ -175,10 +186,10 @@ main(int argc, char *argv[])
 
         if (restricted || Restricted)
         {
-            ned = loops = 0;
+            loops = 0;
             gwords = m * (size_t)n;
             nn = n * (size_t)(n-1);
-            for (ii = 0; ii < gwords; ++ii) ned += POPCOUNT(g[ii]);
+            ned = num_edges(g, gwords);
             for (ii = 0; ii < n; ++ii) if (ISELEMENT(g+m*ii,ii)) ++loops;
             if (Lswitch)
             {
--- a/configure.ac
+++ b/configure.ac
@@ -79,6 +79,9 @@ AC_ARG_ENABLE([popcnt],
    AS_HELP_STRING([--disable-popcnt], [Disable popcnt extensions]),
    [enablearg=given], [enablearg=notgiven])
 AS_IF([test $enablearg = notgiven || test "x$enable_popcnt" = xyes],[allow_popcnt=1],[allow_popcnt=0])
+AC_ARG_ENABLE([runtime-popcnt],
+   AS_HELP_STRING([--enable-runtime-popcnt], [Detect popcnt extensions at runtime]),
+      [runtime_popcnt=1;enable_popcnt=yes], [runtime_popcnt=0])
 
 dnl --disable-clz disallows clz instructions, otherwise they are tested for
 AC_ARG_ENABLE([clz],
@@ -318,7 +321,7 @@ have_popcntll=0
 have_mmpop32=0
 have_mmpop64=0
 
-AS_IF([test $have_hwpopcnt -eq 1],
+AS_IF([test $have_hwpopcnt -eq 1 -a $runtime_popcnt -eq 0],
       [AS_IF([test "$CC" = "icc"],
              [AC_MSG_CHECKING(if _mm_popcnt_u32() is supported)
               AC_LINK_IFELSE([AC_LANG_SOURCE([#include <nmmintrin.h>
@@ -352,6 +355,7 @@ AC_SUBST(have_popcntl)
 AC_SUBST(have_popcntll)
 AC_SUBST(have_mmpop32)
 AC_SUBST(have_mmpop64)
+AC_SUBST(runtime_popcnt)
 
 # Unless --enable-generic is given to configure, we try to use the -march=native compiler
 #   switch.  However, it breaks some versions of gcc on MacOSX due to a compiler bug, so
--- a/deledgeg.c
+++ b/deledgeg.c
@@ -16,6 +16,23 @@
 
 #include "gtools.h" 
 
+/*************************************************************************/
+STATIC_POPCNTFUNC(int,compute_degree,(const graph *g, int *deg, int m, int n),
+{
+    const setword *gv;
+    int v, actmindeg = n;
+
+    for (v = 0, gv = g; v < n; ++v, gv += m)
+    {
+        int i, degv = 0;
+        for (i = 0; i < m; ++i)
+            degv += POPCOUNT(gv[i]);
+        if (degv < actmindeg) actmindeg = degv;
+        deg[v] = degv;
+    }
+    return actmindeg;
+})
+
 /**************************************************************************/
 
 int
@@ -25,13 +42,13 @@ main(int argc, char *argv[])
     FILE *infile,*outfile;
     boolean badargs,dolabel,quiet,dswitch;
     boolean digraph;
-    int i,j,m,n,v,w,argnum;
+    int j,m,n,v,w,argnum;
     int codetype,outcode;
     graph *g,*gq;
     nauty_counter nin,nout;
     char *arg,sw;
     setword *gv,*gw;
-    int mindeg,actmindeg,degv;
+    int mindeg,actmindeg;
     boolean zswitch;
     double t;
 #if MAXN
@@ -136,16 +153,7 @@ main(int argc, char *argv[])
         DYNALLOC1(int,deg,deg_sz,n,"deledgeg");
 #endif
 
-        actmindeg = n;
-        for (v = 0, gv = g; v < n; ++v, gv += m)
-        {
-            degv = 0;
-            for (i = 0; i < m; ++i)
-                degv += POPCOUNT(gv[i]);
-            if (degv < actmindeg) actmindeg = degv;
-            deg[v] = degv;
-        }
-
+        actmindeg = compute_degree(g, deg, m, n);
         if (actmindeg < mindeg) continue;
 
 	if (zswitch || digraph)
--- a/delptg.c
+++ b/delptg.c
@@ -104,6 +104,22 @@ search(int level, int ndel, int *del, gr
         }
 }
 
+/*************************************************************************/
+STATIC_POPCNTFUNC(void,check_degree,
+    (const graph *g, boolean *degok, int m, int n, long mindeg, long maxdeg),
+{
+    const setword *gv;
+    int v;
+
+    for (v = 0, gv = g; v < n; ++v, gv += m)
+    {
+        int i, degv = 0;
+        for (i = 0; i < m; ++i)
+            degv += POPCOUNT(gv[i]);
+        degok[v] = (degv >= mindeg) && (degv <= maxdeg);
+    }
+})
+
 /**************************************************************************/
 
 int
@@ -112,15 +128,13 @@ main(int argc, char *argv[])
     char *infilename,*outfilename;
     FILE *infile;
     boolean badargs,quiet,dswitch,nswitch;
-    int i,j,m,n,v,argnum;
+    int j,m,n,argnum;
     int ndel;
     int codetype;
     graph *g;
     nauty_counter nin;
     char *arg,sw;
-    setword *gv;
     long mindeg,maxdeg;
-    int degv;
     double t;
 #if MAXN
     boolean degok[MAXN];
@@ -239,13 +253,7 @@ main(int argc, char *argv[])
         DYNALLOC1(int,del,del_sz,n,"delptg");
 #endif
 
-        for (v = 0, gv = g; v < n; ++v, gv += m)
-        {
-    	    degv = 0;
-    	    for (i = 0; i < m; ++i)
-    	        degv += POPCOUNT(gv[i]);
-    	    degok[v] = (degv >= mindeg) && (degv <= maxdeg);
-        }
+        check_degree(g, degok, m, n, mindeg, maxdeg);
 
 	search(0,ndel,del,g,m,n,degok);
 
--- a/directg.c
+++ b/directg.c
@@ -383,6 +383,16 @@ scan(int level, int ne, int minarcs, int
     return level-1;
 }
 
+/*************************************************************************/
+STATIC_POPCNTFUNC(int __attribute__((pure)),compute_degree,(const set *s, int m),
+{
+    int i, deg;
+
+    deg = 0;
+    for (i = 0; i < m; ++i) deg += POPCOUNT(s[i]);
+    return deg;
+})
+
 /**************************************************************************/
 
 static void
@@ -409,8 +419,7 @@ direct(graph *g, int nfixed, long minarc
     ne = 0;
     for (i = 0, gi = g; i < n; ++i, gi += m)
     {
-        deg = 0;
-        for (j = 0; j < m; ++j) deg += POPCOUNT(gi[j]);
+        deg = compute_degree(gi, m);
         if (deg == 0)
         {
             lab[++j0] = i;
--- a/genbg.c
+++ b/genbg.c
@@ -475,8 +475,7 @@ isconnected(graph *g, int n)
 
 /**************************************************************************/
 
-static boolean
-distinvar(graph *g, int *invar, int n1, int n2)
+STATIC_POPCNTFUNC(boolean,distinvar,(graph *g, int *invar, int n1, int n2),
  /* make distance invariant/
     exit immediately FALSE if n-1 not maximal else exit TRUE
     Note: only invar[n1..n1+n2-1] set */
@@ -508,7 +507,7 @@ distinvar(graph *g, int *invar, int n1,
         if (v < n-1 && inv > invar[n-1]) return FALSE;
     }
     return TRUE;
-}
+})
 
 /**************************************************************************/
 
@@ -664,10 +663,10 @@ userautomproc(int count, int *p, int *or
 *                                                                            *
 *****************************************************************************/
 
-static void
-refinex(graph *g, int *lab, int *ptn, int level, int *numcells,
+STATIC_POPCNTFUNC(void,refinex,
+   (graph *g, int *lab, int *ptn, int level, int *numcells,
     int *count, set *active, boolean goodret,
-    int *code, int m, int n)
+    int *code, int m, int n),
 {
     int i,c1,c2,labc1;
     setword x;
@@ -800,7 +799,7 @@ refinex(graph *g, int *lab, int *ptn, in
             }
         }
     }
-}
+})
 
 /**************************************************************************/
 
@@ -948,9 +947,28 @@ accept1(graph *g, int n2, int x, graph *
 }
 
 /**************************************************************************/
+#ifdef INSTRUMENT
+#define INSTRUMENT_VAR(var) ++var
+#define INSTRUMENT_UNIQ(var) if (nuniq) ++var
+#else
+#define INSTRUMENT_VAR(var)
+#define INSTRUMENT_UNIQ(var)
+#endif
 
-static boolean
-accept2(graph *g, int n2, int x, graph *gx, int *deg, boolean nuniq)
+#ifdef PRUNE1
+#define DO_PRUNE1(a,b,c,d,e) if (PRUNE1(a,b,c,d,e)) return FALSE
+#else
+#define DO_PRUNE1(a,b,c,d,e)
+#endif
+
+#ifdef PRUNE2
+#define DO_PRUNE2(a,b,c,d,e) if (PRUNE2(a,b,c,d,e)) return FALSE
+#else
+#define DO_PRUNE2(a,b,c,d,e)
+#endif
+
+STATIC_POPCNTFUNC(boolean,accept2,
+    (graph *g, int n2, int x, graph *gx, int *deg, boolean nuniq),
 /* decide if n in theta(g+x) -- version for n+1 == maxn */
 {
     int i,n;
@@ -967,10 +985,8 @@ accept2(graph *g, int n2, int x, graph *
     static DEFAULTOPTIONS_GRAPH(options);
     setword workspace[50];
 
-#ifdef INSTRUMENT
-    ++a2calls;
-    if (nuniq) ++a2uniq;
-#endif
+    INSTRUMENT_VAR(a2calls);
+    INSTRUMENT_UNIQ(a2uniq);
     n = n1 + n2;
     nx = n + 1;
     for (i = 0; i < n; ++i)
@@ -990,18 +1006,12 @@ accept2(graph *g, int n2, int x, graph *
         gx[n] |= bit[i];
         ++degx[i];
     }
-#ifdef PRUNE1
-    if (PRUNE1(gx,degx,n1,n2+1,maxn2)) return FALSE;
-#endif
+    DO_PRUNE1(gx,degx,n1,n2+1,maxn2);
 
     if (nuniq)
     {
-#ifdef INSTRUMENT
-        ++a2succs;
-#endif
-#ifdef PRUNE2
-        if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
-#endif
+        INSTRUMENT_VAR(a2succs);
+        DO_PRUNE2(gx,degx,n1,n2+1,maxn2);
         if (canonise) makecanon(gx,gcan,n1,n2+1);
         return TRUE;
     }
@@ -1050,12 +1060,8 @@ accept2(graph *g, int n2, int x, graph *
         {
             if (j0 == n)
             {
-#ifdef INSTRUMENT
-                ++a2succs;
-#endif
-#ifdef PRUNE2
-                if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
-#endif
+                INSTRUMENT_VAR(a2succs);
+                DO_PRUNE2(gx,degx,n1,n2+1,maxn2);
                 if (canonise) makecanon(gx,gcan,n1,n2+1);
                 return TRUE;
             }
@@ -1106,12 +1112,8 @@ accept2(graph *g, int n2, int x, graph *
         {
             if (j0 == n)
             {
-#ifdef INSTRUMENT
-                ++a2succs;
-#endif
-#ifdef PRUNE2
-                if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
-#endif
+                INSTRUMENT_VAR(a2succs);
+                DO_PRUNE2(gx,degx,n1,n2+1,maxn2);
                 if (canonise) makecanon(gx,gcan,n1,n2+1);
                 return TRUE;
             }
@@ -1127,12 +1129,8 @@ accept2(graph *g, int n2, int x, graph *
         return FALSE;
     else if (code > 0 || numcells >= nx-4)
     {
-#ifdef INSTRUMENT
-        ++a2succs;
-#endif
-#ifdef PRUNE2
-        if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
-#endif
+        INSTRUMENT_VAR(a2succs);
+        DO_PRUNE2(gx,degx,n1,n2+1,maxn2);
         if (canonise) makecanon(gx,gcan,n1,n2+1);
         return TRUE;
     }
@@ -1143,25 +1141,19 @@ accept2(graph *g, int n2, int x, graph *
     options.defaultptn = FALSE;
 
     active[0] = 0;
-#ifdef INSTRUMENT
-    ++a2nauty;
-#endif
+    INSTRUMENT_VAR(a2nauty);
     nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan);
 
     if (orbits[lab[n]] == orbits[n])
     {
-#ifdef INSTRUMENT
-        ++a2succs;
-#endif
-#ifdef PRUNE2
-    if (PRUNE2(gx,degx,n1,n2+1,maxn2)) return FALSE;
-#endif
+        INSTRUMENT_VAR(a2succs);
+        DO_PRUNE2(gx,degx,n1,n2+1,maxn2);
         if (canonise) makecanon(gx,gcan,n1,n2+1);
         return TRUE;
     }
     else
         return FALSE;
-}
+})
 
 /**************************************************************************/
 
--- a/geng.c
+++ b/geng.c
@@ -698,8 +698,7 @@ gcomplement(graph *g, graph *gc, int n)
 
 /**********************************************************************/
 
-static boolean
-distinvar(graph *g, int *invar, int n)
+STATIC_POPCNTFUNC(boolean,distinvar,(graph *g, int *invar, int n),
 /* make distance invariant
    return FALSE if n-1 not maximal else return TRUE */
 {
@@ -729,7 +728,7 @@ distinvar(graph *g, int *invar, int n)
         if (v < n-1 && inv > invar[n-1]) return FALSE;
     }
     return TRUE;
-}
+})
 
 /**************************************************************************/
 
@@ -943,8 +942,7 @@ arith(xword a, xword b, xword c)
 
 /**************************************************************************/  
 
-static void
-makeleveldata(boolean restricted)
+STATIC_POPCNTFUNC(void,makeleveldata,(boolean restricted),
 /* make the level data for each level */
 {
     long h;
@@ -1050,7 +1048,7 @@ makeleveldata(boolean restricted)
             if (xcard[i] > xcard[i-1]) d->xstart[xcard[i]] = i;
         d->xstart[xcard[nxsets-1]+1] = nxsets;
     }
-}
+})
 
 /**************************************************************************/
 
@@ -1101,9 +1099,9 @@ userautomproc(int count, int *p, int *or
 
 /**************************************************************************/
 
-static void
-userautomprocb(int count, int *p, int *orbits,
-          int numorbits, int stabvertex, int n)
+STATIC_POPCNTFUNC(void,
+userautomprocb,(int count, int *p, int *orbits,
+          int numorbits, int stabvertex, int n),
 /* form orbits on powerset of VG
    called by nauty;  operates on data[n] */
 {
@@ -1167,7 +1165,7 @@ userautomprocb(int count, int *p, int *o
         if      (j1 < j2) xorb[j2] = xorb[i] = xorb[pi] = j1;
         else if (j1 > j2) xorb[j1] = xorb[i] = xorb[pi] = j2;
     }
-}
+})
 
 /*****************************************************************************
 *                                                                            *
@@ -1180,9 +1178,9 @@ userautomprocb(int count, int *p, int *o
 *                                                                            *
 *****************************************************************************/
 
-static void
-refinex(graph *g, int *lab, int *ptn, int level, int *numcells,
-     int *count, set *active, boolean goodret, int *code, int m, int n)
+STATIC_POPCNTFUNC(void,refinex,
+    (graph *g, int *lab, int *ptn, int level, int *numcells,
+     int *count, set *active, boolean goodret, int *code, int m, int n),
 {
     int i,c1,c2,labc1;
     setword x,lact;
@@ -1313,7 +1311,7 @@ refinex(graph *g, int *lab, int *ptn, in
             }
         }
     }
-}
+})
 
 /**************************************************************************/
 
@@ -1332,9 +1330,35 @@ makecanon(graph *g, graph *gcan, int n)
 }
 
 /**************************************************************************/
+#ifdef INSTRUMENT
+#define INSTRUMENTED_VAR(var) boolean var = FALSE
+#define INSTRUMENT_TRUE(var) var = TRUE
+#define INSTRUMENT_VAR(var) ++var
+#define INSTRUMENT_VAR_IF(var1,var2) if (var1) ++var2
+#else
+#define INSTRUMENTED_VAR(var)
+#define INSTRUMENT_TRUE(var)
+#define INSTRUMENT_VAR(var)
+#define INSTRUMENT_VAR_IF(var1,var2)
+#endif
 
-static boolean
-accept1(graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid)
+#ifdef PREPRUNE
+#define DO_PREPRUNE(a,b,c) if (PREPRUNE(a,b,c)) return FALSE
+#else
+#define DO_PREPRUNE(a,b,c)
+#endif
+
+#ifdef PRUNE
+#define DO_PRUNE(a,b,c) if (PRUNE(a,b,c)) return
+#define PRUNE_NOT(a,b,c) if (!PRUNE(a,b,c))
+#else
+#define DO_PRUNE(a,b,c)
+#define PRUNE_NOT(a,b,c)
+#endif
+
+
+STATIC_POPCNTFUNC(boolean,accept1,
+    (graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid),
 /* decide if n in theta(g+x) -  version for n+1 < maxn */
 {
     int i;
@@ -1349,9 +1373,7 @@ accept1(graph *g, int n, xword x, graph
     static DEFAULTOPTIONS_GRAPH(options);
     setword workspace[50];
 
-#ifdef INSTRUMENT
-    ++a1calls;
-#endif
+    INSTRUMENT_VAR(a1calls);
 
     nx = n + 1;
     for (i = 0; i < n; ++i) gx[i] = g[i];
@@ -1368,9 +1390,7 @@ accept1(graph *g, int n, xword x, graph
         ++deg[i];
     }
 
-#ifdef PREPRUNE
-    if (PREPRUNE(gx,n+1,maxn)) return FALSE;
-#endif
+    DO_PREPRUNE(gx,n+1,maxn);
 
     i0 = 0;
     i1 = n;
@@ -1399,9 +1419,7 @@ accept1(graph *g, int n, xword x, graph
     if (numcells == nx)
     {
         *rigid = TRUE;
-#ifdef INSTRUMENT
-        ++a1succs;
-#endif
+        INSTRUMENT_VAR(a1succs);
         return TRUE;
     }
 
@@ -1410,28 +1428,24 @@ accept1(graph *g, int n, xword x, graph
     options.userautomproc = userautomproc;
 
     active[0] = 0;
-#ifdef INSTRUMENT
-    ++a1nauty;
-#endif
+    INSTRUMENT_VAR(a1nauty);
     nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,h);
 
     if (orbits[lab[n]] == orbits[n])
     {
         *rigid = stats.numorbits == nx;
-#ifdef INSTRUMENT
-        ++a1succs;
-#endif
+        INSTRUMENT_VAR(a1succs);
         return TRUE;
     }
     else
         return FALSE;
-}
+})
 
 /**************************************************************************/
 
-static boolean
-accept1b(graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid,
-     void (*makeh)(graph*,xword*,int))
+STATIC_POPCNTFUNC(boolean,accept1b,
+    (graph *g, int n, xword x, graph *gx, int *deg, boolean *rigid,
+     void (*makeh)(graph*,xword*,int)),
 /* decide if n in theta(g+x)  --  version for n+1 < maxn */
 {
     int i,v;
@@ -1447,9 +1461,7 @@ accept1b(graph *g, int n, xword x, graph
     static DEFAULTOPTIONS_GRAPH(options);
     setword workspace[50];
 
-#ifdef INSTRUMENT
-    ++a1calls;
-#endif
+    INSTRUMENT_VAR(a1calls);
 
     nx = n + 1;
     for (i = 0; i < n; ++i) gx[i] = g[i];
@@ -1466,9 +1478,7 @@ accept1b(graph *g, int n, xword x, graph
         ++deg[i];
     }
 
-#ifdef PREPRUNE
-    if (PREPRUNE(gx,n+1,maxn)) return FALSE;
-#endif
+    DO_PREPRUNE(gx,n+1,maxn);
 
     i0 = 0;
     i1 = n;
@@ -1517,9 +1527,7 @@ accept1b(graph *g, int n, xword x, graph
     if (numcells == nx)
     {
         *rigid = TRUE;
-#ifdef INSTRUMENT
-        ++a1succs;
-#endif
+	INSTRUMENT_VAR(a1succs);
         return TRUE;
     }
 
@@ -1528,27 +1536,23 @@ accept1b(graph *g, int n, xword x, graph
     options.userautomproc = userautomprocb;
 
     active[0] = 0;
-#ifdef INSTRUMENT
-    ++a1nauty;
-#endif
+    INSTRUMENT_VAR(a1nauty);
     nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gc);
 
     if (orbits[lab[n]] == orbits[n])
     {
         *rigid = stats.numorbits == nx;
-#ifdef INSTRUMENT
-        ++a1succs;
-#endif
+	INSTRUMENT_VAR(a1succs);
         return TRUE;
     }
     else
         return FALSE;
-}
+})
 
 /**************************************************************************/
 
-static boolean
-accept2(graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq)
+STATIC_POPCNTFUNC(boolean,accept2,
+    (graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq),
 /* decide if n in theta(g+x)  --  version for n+1 == maxn */
 {
     int i;
@@ -1566,10 +1570,8 @@ accept2(graph *g, int n, xword x, graph
     setword workspace[50];
     boolean cheapacc;
 
-#ifdef INSTRUMENT
-    ++a2calls;
-    if (nuniq) ++a2uniq;
-#endif
+    INSTRUMENT_VAR(a2calls);
+    INSTRUMENT_VAR_IF(nuniq,a2uniq);
     nx = n + 1;
     for (i = 0; i < n; ++i)
     {
@@ -1589,15 +1591,11 @@ accept2(graph *g, int n, xword x, graph
         ++degx[i];
     }
 
-#ifdef PREPRUNE
-    if (PREPRUNE(gx,n+1,maxn)) return FALSE;
-#endif
+    DO_PREPRUNE(gx,n+1,maxn);
 
     if (nuniq)
     {
-#ifdef INSTRUMENT
-        ++a2succs;
-#endif
+        INSTRUMENT_VAR(a2succs);
         if (canonise) makecanon(gx,gcan,nx);
         return TRUE;
     }
@@ -1637,9 +1635,7 @@ accept2(graph *g, int n, xword x, graph
         {
             if (j0 == n)
             {
-#ifdef INSTRUMENT
-                ++a2succs;
-#endif
+                INSTRUMENT_VAR(a2succs);
                 if (canonise) makecanon(gx,gcan,nx);
                 return TRUE;
             }
@@ -1682,9 +1678,7 @@ accept2(graph *g, int n, xword x, graph
         {
             if (j0 == n)
             {
-#ifdef INSTRUMENT
-                ++a2succs;
-#endif
+                INSTRUMENT_VAR(a2succs);
                 if (canonise) makecanon(gx,gcan,nx);
                 return TRUE;
             }
@@ -1724,9 +1718,7 @@ accept2(graph *g, int n, xword x, graph
     
     if (cheapacc)
     {
-#ifdef INSTRUMENT
-        ++a2succs;
-#endif
+        INSTRUMENT_VAR(a2succs);
         if (canonise) makecanon(gx,gcan,nx);
         return TRUE;
     }
@@ -1735,22 +1727,18 @@ accept2(graph *g, int n, xword x, graph
     options.defaultptn = FALSE;
 
     active[0] = 0;
-#ifdef INSTRUMENT
-    ++a2nauty;
-#endif
+    INSTRUMENT_VAR(a2nauty);
     nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,50,1,nx,gcan);
 
     if (orbits[lab[n]] == orbits[n])
     {
-#ifdef INSTRUMENT
-        ++a2succs;
-#endif
+        INSTRUMENT_VAR(a2succs);
         if (canonise) makecanon(gx,gcan,nx);
         return TRUE;
     }
     else
         return FALSE;
-}
+})
 
 /**************************************************************************/
 
@@ -1795,9 +1783,9 @@ xbnds(int n, int ne, int dmax)
 
 /**************************************************************************/
 
-static void
-spaextend(graph *g, int n, int *deg, int ne, boolean rigid,
-      int xlb, int xub, void (*makeh)(graph*,xword*,int))
+STATIC_POPCNTFUNC(void,spaextend,
+     (graph *g, int n, int *deg, int ne, boolean rigid,
+      int xlb, int xub, void (*makeh)(graph*,xword*,int)),
 /* extend from n to n+1 -- version for restricted graphs */
 {
     xword x,d,dlow;
@@ -1808,12 +1796,8 @@ spaextend(graph *g, int n, int *deg, int
     int degx[MAXN];
     boolean rigidx;
 
-#ifdef INSTRUMENT
-    boolean haschild;
-
-    haschild = FALSE;
-    if (rigid) ++rigidnodes[n];
-#endif
+    INSTRUMENTED_VAR(haschild);
+    INSTRUMENT_VAR_IF(rigid,rigidnodes[n]);
     ++nodes[n];
 
     nx = n + 1;
@@ -1830,9 +1814,7 @@ spaextend(graph *g, int n, int *deg, int
     if (nx == maxn && xlb < mindeg) xlb = mindeg;
     if (xlb > xub) return;
 
-#ifdef PRUNE
-    if (PRUNE(g,n,maxn)) return;
-#endif
+    DO_PRUNE(g,n,maxn);
 
     xorb = data[n].xorb;
     xx = data[n].xx;
@@ -1855,13 +1837,9 @@ spaextend(graph *g, int n, int *deg, int
                           (connec==1 && isconnected(gx,nx)) ||
                           (connec>1 && isbiconnected(gx,nx))))
                 {
-#ifdef PRUNE
-                    if (!PRUNE(gx,nx,maxn))
-#endif
+                    PRUNE_NOT(gx,nx,maxn)
                     {
-#ifdef INSTRUMENT
-                        haschild = TRUE;
-#endif
+                        INSTRUMENT_TRUE(haschild);
                         ++ecount[ne+xc];
                         (*outproc)(outfile,canonise ? gcan : gx,nx);
                     }
@@ -1894,9 +1872,7 @@ spaextend(graph *g, int n, int *deg, int
                 if (xlbx <= xubx
                     && accept1b(g,n,x,gx,degx,&rigidx,makeh))
                 {
-#ifdef INSTRUMENT
-                    haschild = TRUE;
-#endif
+                    INSTRUMENT_TRUE(haschild);
                     spaextend(gx,nx,degx,ne+xc,rigidx,xlbx,xubx,makeh);
                 }
             }
@@ -1905,15 +1881,13 @@ spaextend(graph *g, int n, int *deg, int
                                 && nodes[n] >= multiplicity)
             --splitlevel;
     }
-#ifdef INSTRUMENT
-    if (haschild) ++fertilenodes[n];
-#endif
-}
+    INSTRUMENT_VAR_IF(haschild, fertilenodes[n]);
+})
 
 /**************************************************************************/
 
-static void
-genextend(graph *g, int n, int *deg, int ne, boolean rigid, int xlb, int xub)
+STATIC_POPCNTFUNC(void,genextend,
+    (graph *g, int n, int *deg, int ne, boolean rigid, int xlb, int xub),
 /* extend from n to n+1 -- version for general graphs */
 {
     xword x,d,dlow;
@@ -1925,12 +1899,8 @@ genextend(graph *g, int n, int *deg, int
     int degx[MAXN];
     boolean rigidx;
 
-#ifdef INSTRUMENT
-    boolean haschild;
-
-    haschild = FALSE;
-    if (rigid) ++rigidnodes[n];
-#endif
+    INSTRUMENTED_VAR(haschild);
+    INSTRUMENT_VAR_IF(rigid,rigidnodes[n]);
     ++nodes[n];
 
     nx = n + 1;
@@ -1947,9 +1917,7 @@ genextend(graph *g, int n, int *deg, int
     if (nx == maxn && xlb < mindeg) xlb = mindeg;
     if (xlb > xub) return;
 
-#ifdef PRUNE 
-    if (PRUNE(g,n,maxn)) return; 
-#endif 
+    DO_PRUNE(g,n,maxn);
 
     imin = data[n].xstart[xlb];
     imax = data[n].xstart[xub+1];
@@ -1971,13 +1939,9 @@ genextend(graph *g, int n, int *deg, int
                 if (!connec || (connec==1 && isconnected(gx,nx))
                             || (connec>1 && isbiconnected(gx,nx)))
                 {
-#ifdef PRUNE
-                    if (!PRUNE(gx,nx,maxn))
-#endif
+                    PRUNE_NOT(gx,nx,maxn)
                     {
-#ifdef INSTRUMENT
-                        haschild = TRUE;
-#endif
+                        INSTRUMENT_TRUE(haschild);
                         ++ecount[ne+xc];
                         (*outproc)(outfile,canonise ? gcan : gx,nx);
                     }
@@ -2008,9 +1972,7 @@ genextend(graph *g, int n, int *deg, int
             data[nx].hi = data[nx].xstart[xubx+1];
             if (accept1(g,n,x,gx,degx,&rigidx))
             {
-#ifdef INSTRUMENT
-                haschild = TRUE;
-#endif
+                INSTRUMENT_TRUE(haschild);
                 genextend(gx,nx,degx,ne+xc,rigidx,xlbx,xubx);
             }
         }
@@ -2018,10 +1980,8 @@ genextend(graph *g, int n, int *deg, int
     if (n == splitlevel-1 && n >= min_splitlevel
             && nodes[n] >= multiplicity)
         --splitlevel;
-#ifdef INSTRUMENT
-    if (haschild) ++fertilenodes[n];
-#endif
-}
+    INSTRUMENT_VAR_IF(haschild, fertilenodes[n]);
+})
 
 /**************************************************************************/
 /**************************************************************************/
--- a/genquarticg.c
+++ b/genquarticg.c
@@ -226,9 +226,9 @@ isbiconnected(graph *g, int n)
  *    of the graph reaches nmax after which it is written to outputfile      *
  ****************************************************************************/
 
-static void
-extend(int n, graph *g, edgestruct *edge, pairstruct *epair, int numpair,
-   int *epairorbit, int *multar, setword *zar, int *col00w, boolean connectflag)
+STATIC_POPCNTFUNC(void,extend,
+   (int n, graph *g, edgestruct *edge, pairstruct *epair, int numpair,
+   int *epairorbit, int *multar, setword *zar, int *col00w, boolean connectflag),
 {
     int   vm1, vm2, vm3, vm4, vt1, vt2, vt3, vt4, c, b, mcol1,
           tcol, got_one, i, j, numpair1, numdovi, maxdovi, i1, j1, i2, j2,
@@ -906,7 +906,7 @@ extend(int n, graph *g, edgestruct *edge
 
     } //end for c..
 
-}
+})
 
 /*****************************************************************************
  *                                                                            *
@@ -1150,9 +1150,9 @@ init_refinex( int *clr, int *lb, int *p,
  *  code := -1 for n-1 not max, 0 for maybe, 1 for definite                   *
  *                                                                            *
  *****************************************************************************/
-static void
-refinex(graph *g, int *lab, int *ptn, int level, int *numcells, int *count,
-           set *active, boolean goodret, int *code, int m, int n)
+STATIC_POPCNTFUNC(void,refinex,
+    (graph *g, int *lab, int *ptn, int level, int *numcells, int *count,
+           set *active, boolean goodret, int *code, int m, int n),
 {
     int     i, c1, c2, labc1, split1, split2, cell1, cell2, cnt, bmin, bmax;
     int     workperm[MAXN], bucket[MAXN+2];
@@ -1280,7 +1280,7 @@ refinex(graph *g, int *lab, int *ptn, in
             }
         }
     }
-}
+})
 
 
 /*****************************************************************************/
--- a/gentourng.c
+++ b/gentourng.c
@@ -549,9 +549,9 @@ userautomproc(int count, int *p, int *or
 *                                                                            *
 *****************************************************************************/
 
-static void
-refinex(graph *g, int *lab, int *ptn, int level, int *numcells,
-     int *count, set *active, boolean goodret, int *code, int m, int n)
+STATIC_POPCNTFUNC(void,refinex,
+    (graph *g, int *lab, int *ptn, int level, int *numcells,
+     int *count, set *active, boolean goodret, int *code, int m, int n),
 {
         int i,c1,c2,labc1;
         setword x,lact;
@@ -683,7 +683,7 @@ refinex(graph *g, int *lab, int *ptn, in
                 }
             }
         }
-}
+})
 
 /**************************************************************************/
 
@@ -805,8 +805,7 @@ accept1(graph *g, int n, xword x, graph
 
 /**************************************************************************/
 
-static boolean
-hitinvar(graph *g, int *invar, int n)
+STATIC_POPCNTFUNC(boolean,hitinvar,(graph *g, int *invar, int n),
 /* make hitting invariant
  *    return FALSE if n-1 not maximal else return TRUE */
 {
@@ -829,12 +828,26 @@ hitinvar(graph *g, int *invar, int n)
             if (v < n-1 && inv > invar[n-1]) return FALSE;
         }
         return TRUE;
-}
+})
 
 /**************************************************************************/
 
-static boolean
-accept2(graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq)
+#ifdef INSTRUMENT
+#define INSTRUMENT_VAR(var) ++var
+#define INSTRUMENT_UNIQ(var) if (nuniq) ++var
+#else
+#define INSTRUMENT_VAR(var)
+#define INSTRUMENT_UNIQ(var)
+#endif
+
+#ifdef PREPRUNE
+#define DO_PREPRUNE(a,b,c) if (PREPRUNE(a,b,c)) return FALSE
+#else
+#define DO_PREPRUNE(a,b,c)
+#endif
+
+STATIC_POPCNTFUNC(boolean,accept2,
+    (graph *g, int n, xword x, graph *gx, int *deg, boolean nuniq),
 /* decide if n in theta(g+x)  --  version for n+1 == maxn */
 {
         int i;
@@ -851,10 +864,8 @@ accept2(graph *g, int n, xword x, graph
         setword workspace[200];
 	boolean cheapacc;
 
-#ifdef INSTRUMENT
-        ++a2calls;
-        if (nuniq) ++a2uniq;
-#endif
+        INSTRUMENT_VAR(a2calls);
+        INSTRUMENT_UNIQ(a2uniq);
         nx = n + 1;
         gxn = 0;
 
@@ -875,15 +886,11 @@ accept2(graph *g, int n, xword x, graph
 	gx[n] = gxn;
         degx[n] = degn = XPOPCOUNT(x);
 	    
-#ifdef PREPRUNE
-        if (PREPRUNE(gx,n+1,maxn)) return FALSE;
-#endif
+        DO_PREPRUNE(gx,n+1,maxn);
 
         if (nuniq)
         {
-#ifdef INSTRUMENT
-            ++a2succs;
-#endif
+            INSTRUMENT_VAR(a2succs);
             if (canonise) makecanon(gx,gcan,nx);
             return TRUE;
         }
@@ -922,9 +929,7 @@ accept2(graph *g, int n, xword x, graph
             {
                 if (j0 == n)
                 {
-#ifdef INSTRUMENT
-                    ++a2succs;
-#endif
+                    INSTRUMENT_VAR(a2succs);
                     if (canonise) makecanon(gx,gcan,nx);
                     return TRUE;
                 }
@@ -967,9 +972,7 @@ accept2(graph *g, int n, xword x, graph
             {
                 if (j0 == n)
                 {
-#ifdef INSTRUMENT
-                    ++a2succs;
-#endif
+                    INSTRUMENT_VAR(a2succs);
                     if (canonise) makecanon(gx,gcan,nx);
                     return TRUE;
                 }
@@ -988,9 +991,7 @@ accept2(graph *g, int n, xword x, graph
     
         if (cheapacc)
         {
-#ifdef INSTRUMENT
-            ++a2succs;
-#endif
+            INSTRUMENT_VAR(a2succs);
             if (canonise) makecanon(gx,gcan,nx);
             return TRUE;
         }
@@ -1000,22 +1001,18 @@ accept2(graph *g, int n, xword x, graph
         options.defaultptn = FALSE;
 
         active[0] = 0;
-#ifdef INSTRUMENT
-        ++a2nauty;
-#endif
+        INSTRUMENT_VAR(a2nauty);
         nauty(gx,lab,ptn,active,orbits,&options,&stats,workspace,200,1,nx,gcan);
 
         if (orbits[lab[n]] == orbits[n])
         {
-#ifdef INSTRUMENT
-            ++a2succs;
-#endif
+            INSTRUMENT_VAR(a2succs);
             if (canonise) makecanon(gx,gcan,nx);
             return TRUE;
         }
         else
             return FALSE;
-}
+})
 
 /**************************************************************************/
 
--- a/gutil1.c
+++ b/gutil1.c
@@ -5,9 +5,9 @@
 
 /**************************************************************************/
 
-void
-degstats(graph *g, int m, int n, unsigned long *edges, int *mindeg,
-     int *mincount, int *maxdeg, int *maxcount, boolean *eulerian)
+POPCNTFUNC(void,degstats,
+    (graph *g, int m, int n, unsigned long *edges, int *mindeg,
+     int *mincount, int *maxdeg, int *maxcount, boolean *eulerian),
 /* Compute degree-related graph properties.
    *edges = number of edges
    *mindeg, *mincount = minimum degree and how many there are
@@ -60,13 +60,13 @@ degstats(graph *g, int m, int n, unsigne
     *maxcount = maxdc;
     *edges = ned / 2;
     *eulerian = (dor & 1) == 0;
-}
+})
 
 /**************************************************************************/
 
-void
-degstats3(graph *g, int m, int n, unsigned long *edges, int *mindeg,
-     int *mincount, int *maxdeg, int *maxcount, int *odddeg)
+POPCNTFUNC(void,degstats3,
+    (graph *g, int m, int n, unsigned long *edges, int *mindeg,
+     int *mincount, int *maxdeg, int *maxcount, int *odddeg),
 /* Compute degree-related graph properties.
    *edges = number of edges
    *mindeg, *mincount = minimum degree and how many there are
@@ -119,16 +119,16 @@ degstats3(graph *g, int m, int n, unsign
     *maxcount = maxdc;
     *edges = ned / 2;
     *odddeg = dodd;
-}
+})
 
 /**************************************************************************/
 
-void
-degstats2(graph *g, boolean digraph, int m, int n,
+POPCNTFUNC(void,degstats2,
+    (graph *g, boolean digraph, int m, int n,
      unsigned long *edges, int *loops,
      int *minindeg, int *minincount, int *maxindeg, int *maxincount,
      int *minoutdeg, int *minoutcount, int *maxoutdeg, int *maxoutcount,
-     boolean *eulerian)
+     boolean *eulerian),
 /* Compute degree-related graph properties.
    *edges = number of edges (including loops), directed edges for digraphs
    *loops = number of loops
@@ -300,12 +300,11 @@ degstats2(graph *g, boolean digraph, int
 	    if (indeg[i] != outdeg[i]) break;
 	*eulerian = (i == n);
     }
-}
+})
 
 /*********************************************************************/
 
-boolean
-isconnected1(graph *g, int n)
+POPCNTFUNC(boolean,isconnected1,(graph *g, int n),
 /* test if g is connected (m=1) */
 {
     setword seen,expanded,toexpand;
@@ -324,7 +323,7 @@ isconnected1(graph *g, int n)
     }
 
     return  POPCOUNT(seen) == n;
-}
+})
 
 /**************************************************************************/
 
@@ -375,25 +374,19 @@ isconnected(graph *g, int m, int n)
 
 /**************************************************************************/
  
-boolean
-issubconnected(graph *g, set *sub, int m, int n)
+POPCNTFUNC(boolean,issubconnected,(graph *g, set *sub, int m, int n),
 /* Test if the subset of g induced by sub is connected. Empty is connected. */
 /* Note that the value for empty subgraphs disagrees with isconnected() */
 {
     int i,head,tail,w,subsize;
     set *gw;
-#if MAXN
-    int queue[MAXN],visited[MAXN];
-    setword subw[MAXM];
-#else
-    DYNALLSTAT(int,queue,queue_sz);
-    DYNALLSTAT(int,visited,visited_sz);
-    DYNALLSTAT(set,subw,subw_sz);
+    DCL_DYNINT(queue);
+    DCL_DYNINT(visited);
+    DCL_DYNSET(subw);
  
-    DYNALLOC1(int,queue,queue_sz,n,"issubconnected");
-    DYNALLOC1(int,visited,visited_sz,n,"issubconnected");
-    DYNALLOC1(set,subw,subw_sz,m,"issubconnected");
-#endif
+    DEF_DYNINT(queue,n,"issubconnected");
+    DEF_DYNINT(visited,n,"issubconnected");
+    DEF_DYNSET(subw,m,"issubconnected");
  
     subsize = 0;
     for (i = 0; i < m; ++i) subsize += (sub[i] ? POPCOUNT(sub[i]) : 0);
@@ -425,7 +418,7 @@ issubconnected(graph *g, set *sub, int m
     }
  
     return tail == subsize;
-}
+})
  
 /**********************************************************************/
  
@@ -1007,8 +1000,8 @@ maxcliques(graph *g, int m, int n)
 
 /**************************************************************************/
 
-static void
-maxcsnode1(int *best, graph *g, setword cliq, setword cov, int maxv)
+STATIC_POPCNTFUNC(void,
+maxcsnode1,(int *best, graph *g, setword cliq, setword cov, int maxv),
 /* Internal search node.  cov has all the vertices outside cliq that
  * cover all of cliq.  maxv is the last vertex of cliq.
  * *best is the largest clique known so far.
@@ -1032,7 +1025,7 @@ maxcsnode1(int *best, graph *g, setword
 	    maxcsnode1(best,g,cliq|bit[i],cov&g[i]&~bit[i],i);
         }
     }
-}
+})
 
 int
 maxcliquesize(graph *g, int m, int n)
--- a/gutil2.c
+++ b/gutil2.c
@@ -21,8 +21,7 @@ loopcount(graph *g, int m, int n)
 
 /**************************************************************************/
 
-long
-pathcount1(graph *g, int start, setword body, setword last)
+POPCNTFUNC(long,pathcount1,(graph *g, int start, setword body, setword last),
 /* Number of paths in g starting at start, lying within body and
    ending in last.  {start} and last should be disjoint subsets of body. */
 {
@@ -43,7 +42,7 @@ pathcount1(graph *g, int start, setword
     }
 
     return count;
-}
+})
 
 /**************************************************************************/
 
@@ -87,8 +86,7 @@ cyclecount(graph *g, int m, int n)
 
 /**************************************************************************/
 
-long
-indpathcount1(graph *g, int start, setword body, setword last)
+POPCNTFUNC(long,indpathcount1,(graph *g, int start, setword body, setword last),
 /* Number of induced paths in g starting at start, extravertices within
  * body and ending in last.
  * {start}, body and last should be disjoint. */
@@ -109,7 +107,7 @@ indpathcount1(graph *g, int start, setwo
     }
 
     return count;
-}
+})
 
 /**************************************************************************/
 
@@ -155,8 +153,7 @@ indcyclecount(graph *g, int m, int n)
 
 /**************************************************************************/
 
-long
-numtriangles1(graph *g, int n)
+POPCNTFUNC(long,numtriangles1,(graph *g, int n),
 /* The number of triangles in g; undirected only */
 {
     int i,j;
@@ -176,12 +173,11 @@ numtriangles1(graph *g, int n)
     }
 
     return total;
-}
+})
 
 /**************************************************************************/
 
-long
-numtriangles(graph *g, int m, int n)
+POPCNTFUNC(long,numtriangles,(graph *g, int m, int n),
 /* The number of triangles in g; undirected only */
 {
     int i,j,k,kw;
@@ -206,7 +202,7 @@ numtriangles(graph *g, int m, int n)
 	}
 
     return total;
-}    
+})
 
 /**************************************************************************/
 
@@ -232,9 +228,8 @@ numdirtriangles(graph *g, int m, int n)
 
 /**************************************************************************/
 
-void
-commonnbrs(graph *g, int *minadj, int *maxadj, int *minnon, int *maxnon,
-       int m, int n)
+POPCNTFUNC(void,commonnbrs,
+   (graph *g, int *minadj, int *maxadj, int *minnon, int *maxnon, int m, int n),
 /* Count the common neighbours of pairs of vertices, and give the minimum
    and maximum for adjacent and non-adjacent vertices.  Undirected only.
    Null minimums are n+1 and null maximums are -1.
@@ -281,7 +276,7 @@ commonnbrs(graph *g, int *minadj, int *m
     *maxadj = maxa;
     *minnon = minn;
     *maxnon = maxn;
-}
+})
 
 /**************************************************************************/
 
@@ -350,8 +345,7 @@ contract1(graph *g, graph *h, int v, int
 static TLS_ATTR int knm[18][16];  /* knm[n,m] = conncontent(K_n - m*K_2) */
 static TLS_ATTR boolean knm_computed = FALSE;
 
-int
-conncontent(graph *g, int m, int n)
+POPCNTFUNC(int,conncontent,(graph *g, int m, int n),
 /* number of connected spanning subgraphs with an even number
    of edges minus the number with an odd number of edges */
 {
@@ -411,14 +405,6 @@ conncontent(graph *g, int m, int n)
 
     if (mindeg == 0) return 0;
 
-#if 0
-    if (mindeg == 1 && ne == n-1)
-    {
-	if (isconnected1(g,n)) return ((n&1) ? 1 : -1);
-	else		       return 0;
-    }
-#endif
-
 /* Cases of clique and near-clique */
 
     if (mindeg == n-1)
@@ -502,7 +488,7 @@ conncontent(graph *g, int m, int n)
     v2 = conncontent(h,m,n-1);
 
     return v1 - v2;
-}
+})
 
 boolean
 stronglyconnected(graph *g, int m, int n)
--- a/listg.c
+++ b/listg.c
@@ -252,8 +252,8 @@ putcgraph(FILE *f, graph *g, int linelen
 
 /**************************************************************************/
 
-static void
-putve(FILE *f, unsigned long id, graph *g, boolean digraph, int m, int n)
+STATIC_POPCNTFUNC(void,putve,
+    (FILE *f, unsigned long id, graph *g, boolean digraph, int m, int n),
 /* Write the numbers of vertices and edges */
 {
     unsigned long ne;
@@ -265,7 +265,7 @@ putve(FILE *f, unsigned long id, graph *
 
     fprintf(f,"Graph %lu has %d vertices and %lu edges.\n",id,n,
             (digraph?ne:ne/2));
-}
+})
 
 /**************************************************************************/
 
@@ -325,8 +325,8 @@ putdotty(FILE *f, graph *g, unsigned lon
 
 /**************************************************************************/
 
-static void
-putbliss(FILE *f, unsigned long id, boolean qswitch, graph *g, int m, int n)
+STATIC_POPCNTFUNC(void,putbliss,
+    (FILE *f, unsigned long id, boolean qswitch, graph *g, int m, int n),
 /* Write the graph in Bliss format, according to
  *      http://www.tcs.hut.fi/Software/bliss/fileformat.shtml */
 {
@@ -346,7 +346,7 @@ putbliss(FILE *f, unsigned long id, bool
     for (i = 0, pg = g; i < n; ++i, pg += m)
         for (j = nextelement(pg,m,i); j >= 0; j = nextelement(pg,m,j))
             fprintf(f,"e %d %d\n",i+1,j+1);
-}
+})
 
 /**************************************************************************/
 
@@ -436,9 +436,8 @@ putMaple(FILE *outfile, graph *g, int li
 
 /**************************************************************************/
 
-static void
-putLaplacianMagma(FILE *outfile, graph *g, int linelength,
-         int m, int n, long index)
+STATIC_POPCNTFUNC(void,putLaplacianMagma,
+    (FILE *outfile, graph *g, int linelength, int m, int n, long index),
 {
     int i,j,j0,d;
     set *gi;
@@ -463,13 +462,12 @@ putLaplacianMagma(FILE *outfile, graph *
         if (i < n-1) fprintf(outfile,",\n");
 	else         fprintf(outfile,"]);\n");
     }
-}
+})
 
 /**************************************************************************/
 
-static void
-putLaplacianMaple(FILE *outfile, graph *g, int linelength,
-                                              int m, int n, long index)
+STATIC_POPCNTFUNC(void,putLaplacianMaple,
+    (FILE *outfile, graph *g, int linelength, int m, int n, long index),
 {
     int i,j,d;
     set *gi;
@@ -503,7 +501,7 @@ putLaplacianMaple(FILE *outfile, graph *
         if (i != n-1) fprintf(outfile,",\n");
     }
     fprintf(outfile,"]);\n");
-}
+})
 
 /**************************************************************************/
 /**************************************************************************/
--- a/multig.c
+++ b/multig.c
@@ -450,6 +450,18 @@ scan_reg(int level, int ne, long minedge
 
 /**************************************************************************/
 
+STATIC_POPCNTFUNC(int __attribute__((pure)),compute_degree,
+    (const set *gi, int m),
+{
+    int i, thisdeg;
+
+    thisdeg = 0;
+    for (i = 0; i < m; ++i) thisdeg += POPCOUNT(gi[i]);
+    return thisdeg;
+})
+
+/**************************************************************************/
+
 static void
 multi(graph *g, int nfixed, long minedges, long maxedges, long maxmult,
       int maxdeg, boolean lswitch, int m, int n)
@@ -477,8 +489,7 @@ multi(graph *g, int nfixed, long minedge
     maxd = 0;
     for (i = 0, gi = g; i < n; ++i, gi += m)
     {
-        thisdeg = 0;
-        for (j = 0; j < m; ++j) thisdeg += POPCOUNT(gi[j]);
+        thisdeg = compute_degree(gi, m);
         deg[i] = thisdeg;
         if (thisdeg > maxd) maxd = thisdeg;
         if (thisdeg == 0) lab[++j0] = i;
--- a/naugraph.c
+++ b/naugraph.c
@@ -174,16 +174,17 @@ updatecan(graph *g, graph *canong, int *
 *                                                                            *
 *****************************************************************************/
 
+#if MAXM==1
 void
 refine(graph *g, int *lab, int *ptn, int level, int *numcells,
        int *count, set *active, int *code, int m, int n)
 {
-
-#if MAXM==1
     refine1(g,lab,ptn,level,numcells,count,active,code,m,n);
 }
 #else
-
+POPCNTFUNC(void,refine,(graph *g, int *lab, int *ptn, int level, int *numcells,
+       int *count, set *active, int *code, int m, int n),
+{
     int i,c1,c2,labc1;
     setword x;
     set *set1,*set2;
@@ -193,11 +194,9 @@ refine(graph *g, int *lab, int *ptn, int
     set *gptr;
     int maxcell,maxpos,hint;
 
-#if !MAXN
-    DYNALLOC1(int,workperm,workperm_sz,n,"refine");
-    DYNALLOC1(set,workset,workset_sz,m,"refine");
-    DYNALLOC1(int,bucket,bucket_sz,n+2,"refine");
-#endif
+    DEF_DYNINT(workperm,n,"refine");
+    DEF_DYNSET(workset,m,"refine");
+    DEF_DYNINT(bucket,n+2,"refine");
 
     longcode = *numcells;
     split1 = -1;
@@ -325,7 +324,7 @@ refine(graph *g, int *lab, int *ptn, int
 
     longcode = MASH(longcode,*numcells);
     *code = CLEANUP(longcode);
-}
+})
 #endif /* else case of MAXM==1 */
 
 /*****************************************************************************
@@ -337,9 +336,8 @@ refine(graph *g, int *lab, int *ptn, int
 *                                                                            *
 *****************************************************************************/
 
-void
-refine1(graph *g, int *lab, int *ptn, int level, int *numcells,
-       int *count, set *active, int *code, int m, int n)
+POPCNTFUNC(void,refine1,(graph *g, int *lab, int *ptn, int level,
+    int *numcells, int *count, set *active, int *code, int m, int n),
 {
     int i,c1,c2,labc1;
     setword x;
@@ -349,10 +347,8 @@ refine1(graph *g, int *lab, int *ptn, in
     set *gptr,workset0;
     int maxcell,maxpos,hint;
 
-#if !MAXN 
-    DYNALLOC1(int,workperm,workperm_sz,n,"refine1"); 
-    DYNALLOC1(int,bucket,bucket_sz,n+2,"refine1"); 
-#endif
+    DEF_DYNINT(workperm,n,"refine1");
+    DEF_DYNINT(bucket,n+2,"refine1");
 
     longcode = *numcells;
     split1 = -1;
@@ -475,7 +471,7 @@ refine1(graph *g, int *lab, int *ptn, in
 
     longcode = MASH(longcode,*numcells);
     *code = CLEANUP(longcode);
-}
+})
 
 /*****************************************************************************
 *                                                                            *
--- a/nausparse.c
+++ b/nausparse.c
@@ -1476,8 +1476,7 @@ copy_sg(sparsegraph *sg1, sparsegraph *s
 *                                                                            *
 *****************************************************************************/
 
-sparsegraph*
-nauty_to_sg(graph *g, sparsegraph *sg, int m, int n)
+POPCNTFUNC(sparsegraph*,nauty_to_sg,(graph *g, sparsegraph *sg, int m, int n),
 {
     int *d,*e;
     int i,k;
@@ -1515,7 +1514,7 @@ nauty_to_sg(graph *g, sparsegraph *sg, i
     }
 
     return sg;
-}
+})
 
 /*****************************************************************************
 *                                                                            *
--- a/nautinv.c
+++ b/nautinv.c
@@ -221,6 +221,19 @@ twopaths(graph *g, int *lab, int *ptn, i
         }
 }
 
+STATIC_POPCNTFUNC(int __attribute__((pure)),disjoint_edges,
+    (const set *ws, const set *gw, int m),
+{
+    int i,pc;
+    setword sw;
+
+    pc = 0;
+    for (i = M; --i >= 0;)
+        if ((sw = ws[i] ^ gw[i]) != 0)
+            pc += POPCOUNT(sw);
+    return pc;
+})
+
 /*****************************************************************************
 *                                                                            *
 *  quadruples() assigns to each vertex v a value depending on the set of     *
@@ -236,7 +249,6 @@ quadruples(graph *g, int *lab, int *ptn,
            int *invar, int invararg, boolean digraph, int m, int n)
 {
         int i,pc;
-        setword sw;
         set *gw;
         int wt;
         int v,iv,v1,v2,v3;
@@ -284,9 +296,7 @@ quadruples(graph *g, int *lab, int *ptn,
                         if (wv3 == wv && v3 <= v) continue;
                         wv3 += wv2;
                         gw = GRAPHROW(g,v3,m);
-                        pc = 0;
-                        for (i = M; --i >= 0;)
-                            if ((sw = ws1[i] ^ gw[i]) != 0) pc += POPCOUNT(sw);
+                        pc = disjoint_edges(ws1,gw,m);
                         wt = (FUZZ1(pc)+wv3) & 077777;
                         wt = FUZZ2(wt);
                         ACCUM(invar[v],wt);
@@ -315,7 +325,6 @@ triples(graph *g, int *lab, int *ptn, in
         int *invar, int invararg, boolean digraph, int m, int n)
 {
         int i,pc;
-        setword sw;
         set *gw;
         int wt;
         int v,iv,v1,v2;
@@ -355,9 +364,7 @@ triples(graph *g, int *lab, int *ptn, in
                     if (wv2 == wv && v2 <= v) continue;
                     wv2 += wv1;
                     gw = GRAPHROW(g,v2,m);
-                    pc = 0;
-                    for (i = M; --i >= 0;)
-                        if ((sw = workset[i] ^ gw[i]) != 0) pc += POPCOUNT(sw);
+                    pc = disjoint_edges(workset,gw,m);
                     wt = (FUZZ1(pc)+wv2) & 077777;
                     wt = FUZZ2(wt);
                     ACCUM(invar[v],wt);
@@ -382,8 +389,7 @@ void
 adjtriang(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos,
           int *invar, int invararg, boolean digraph, int m, int n)
 {
-        int j,pc;
-        setword sw;
+        int pc;
         set *gi;
         int wt;
         int i,v1,v2;
@@ -421,10 +427,8 @@ adjtriang(graph *g, int *lab, int *ptn,
                 i = -1;
                 while ((i = nextelement(workset,M,i)) >= 0)
                 {
-                    pc = 0;
                     gi = GRAPHROW(g,i,m);
-                    for (j = M; --j >= 0;)
-                        if ((sw = workset[j] & gi[j]) != 0) pc += POPCOUNT(sw);
+                    pc = disjoint_edges(workset,gi,m);
                     pc = (pc + wt) & 077777;
                     ACCUM(invar[i],pc);
                 }
@@ -509,7 +513,6 @@ celltrips(graph *g, int *lab, int *ptn,
           int *invar, int invararg, boolean digraph, int m, int n)
 {
         int i,pc;
-        setword sw;
         set *gw;
         int wt;
         int v,iv,v1,iv1,v2,iv2;
@@ -545,10 +548,7 @@ celltrips(graph *g, int *lab, int *ptn,
                     {
                         v2 = lab[iv2];
                         gw = GRAPHROW(g,v2,m);
-                        pc = 0;
-                        for (i = M; --i >= 0;)
-                            if ((sw = workset[i] ^ gw[i]) != 0)
-                                pc += POPCOUNT(sw);
+                        pc = disjoint_edges(workset,gw,m);
                         wt = FUZZ1(pc);
                         ACCUM(invar[v],wt);
                         ACCUM(invar[v1],wt);
@@ -577,7 +577,6 @@ cellquads(graph *g, int *lab, int *ptn,
           int *invar, int invararg, boolean digraph, int m, int n)
 {
         int i,pc;
-        setword sw;
         set *gw;
         int wt;
         int v,iv,v1,iv1,v2,iv2,v3,iv3;
@@ -619,10 +618,7 @@ cellquads(graph *g, int *lab, int *ptn,
                         {
                             v3 = lab[iv3];
                             gw = GRAPHROW(g,v3,m);
-                            pc = 0;
-                            for (i = M; --i >= 0;)
-                                if ((sw = ws1[i] ^ gw[i]) != 0)
-                                    pc += POPCOUNT(sw);
+                            pc = disjoint_edges(ws1,gw,m);
                             wt = FUZZ1(pc);
                             ACCUM(invar[v],wt);
                             ACCUM(invar[v1],wt);
@@ -653,7 +649,6 @@ cellquins(graph *g, int *lab, int *ptn,
           int *invar, int invararg, boolean digraph, int m, int n)
 {
         int i,pc;
-        setword sw;
         set *gw;
         int wt;
         int v,iv,v1,iv1,v2,iv2,v3,iv3,v4,iv4;
@@ -701,10 +696,7 @@ cellquins(graph *g, int *lab, int *ptn,
                             {
                                 v4 = lab[iv4];
                                 gw = GRAPHROW(g,v4,m);
-                                pc = 0;
-                                for (i = M; --i >= 0;)
-                                    if ((sw = ws2[i] ^ gw[i]) != 0)
-                                        pc += POPCOUNT(sw);
+                                pc = disjoint_edges(ws2,gw,m);
                                 wt = FUZZ1(pc);
                                 ACCUM(invar[v],wt);
                                 ACCUM(invar[v1],wt);
@@ -749,6 +741,21 @@ uniqinter(set *s1, set *s2, int m)
 	return -1;
 }
 
+STATIC_POPCNTFUNC(int __attribute__((pure)),triedges,
+    (const set *s0, const set *s1, const set *s2, int m),
+{
+    int i,pc;
+    setword sw;
+
+    pc = 0;
+    for (i = M; --i >= 0;)
+    {
+        sw = s0[i] & s1[i] & s2[i];
+        if (sw) pc += POPCOUNT(sw);
+    }
+    return pc;
+})
+
 /*****************************************************************************
 *                                                                            *
 *  cellfano2() assigns to each vertex v a value depending on the set of      *
@@ -765,7 +772,6 @@ cellfano2(graph *g, int *lab, int *ptn,
           int *invar, int invararg, boolean digraph, int m, int n)
 {
         int i,pc;
-        setword sw;
         int wt;
         int v0,v1,v2,v3,iv0,iv1,iv2,iv3;
         int icell,bigcells,cell1,cell2;
@@ -847,12 +853,7 @@ cellfano2(graph *g, int *lab, int *ptn,
 			    gp1 = GRAPHROW(g,pnt1,m);
 			    gp2 = GRAPHROW(g,pnt2,m);
 
-			    pc = 0;
-			    for (i = M; --i >= 0;)
-			    {
-				sw = gp0[i] & gp1[i] & gp2[i];
-				if (sw) pc += POPCOUNT(sw);
-			    }
+			    pc = triedges(gp0,gp1,gp2,m);
 			    wt = FUZZ1(pc);
 			    ACCUM(invar[v0],wt);
 			    ACCUM(invar[v1],wt);
@@ -914,7 +915,6 @@ cellfano(graph *g, int *lab, int *ptn, i
          int *invar, int invararg, boolean digraph, int m, int n)
 {
         int i,pc;
-        setword sw;
         int wt;
         int v0,v1,v2,v3,iv0,iv1,iv2,iv3;
         int icell,bigcells,cell1,cell2;
@@ -989,12 +989,7 @@ cellfano(graph *g, int *lab, int *ptn, i
                             setnbhd(g,m,n,workset,pt1);
                             for (i = M; --i >= 0;) workset[i] = w02[i] & w13[i];
                             setnbhd(g,m,n,workset,pt2);
-			    pc = 0;
-			    for (i = M; --i >= 0;)
-			    {
-				sw = pt0[i] & pt1[i] & pt2[i];
-				if (sw) pc += POPCOUNT(sw);
-			    }
+			    pc = triedges(pt0,pt1,pt2,m);
 			    wt = FUZZ1(pc);
 			    ACCUM(invar[v0],wt);
 			    ACCUM(invar[v1],wt);
@@ -1238,6 +1233,20 @@ cliques(graph *g, int *lab, int *ptn, in
         }
 }
 
+STATIC_POPCNTFUNC(int,common_edges,(set *ns, const set *gv, int m),
+{
+    int i,pc;
+    setword sw;
+
+    pc = 0;
+    for (i = M; --i >= 0;)
+    {
+        ns[i] = gv[i] & workset[i];
+        if ((sw = ns[i]) != 0) pc += POPCOUNT(sw);
+    }
+    return pc;
+})
+
 /*****************************************************************************
 *                                                                            *
 *  cellcliq() assigns to each vertex v a value depending on the number of    *
@@ -1260,7 +1269,6 @@ cellcliq(graph *g, int *lab, int *ptn, i
         int *cellstart,*cellsize;
         int iv,icell,bigcells,cell1,cell2;
         int pc;
-        setword sw;
 
 #if !MAXN
         DYNALLOC1(set,workset,workset_sz,m,"cellcliq");
@@ -1293,13 +1301,7 @@ cellcliq(graph *g, int *lab, int *ptn, i
                 v[0] = lab[iv];
                 gv = GRAPHROW(g,v[0],m);
 		ns = (set*)wss;
-                pc = 0;
-
-                for (i = M; --i >= 0;)
-                {
-                    ns[i] = gv[i] & workset[i];
-                    if ((sw = ns[i]) != 0) pc += POPCOUNT(sw);
-                }
+                pc = common_edges(ns,gv,m);
                 if (pc <= 1 || pc >= cellsize[icell] - 2) continue;
 
                 ss = 1;
@@ -1333,6 +1335,20 @@ cellcliq(graph *g, int *lab, int *ptn, i
         }
 }
 
+STATIC_POPCNTFUNC(int,not_common_edges,(set *ns, const set *gv, int m),
+{
+    int i,pc;
+    setword sw;
+
+    pc = 0;
+    for (i = M; --i >= 0;)
+    {
+        ns[i] = ~gv[i] & workset[i];
+        if ((sw = ns[i]) != 0) pc += POPCOUNT(sw);
+    }
+    return pc;
+})
+
 /*****************************************************************************
 *                                                                            *
 *  cellind() assigns to each vertex v a value depending on the number of     *
@@ -1389,13 +1405,7 @@ cellind(graph *g, int *lab, int *ptn, in
                 v[0] = lab[iv];
                 gv = GRAPHROW(g,v[0],m);
 	 	ns = (set*)wss;
-                pc = 0;
-
-                for (i = M; --i >= 0;)
-                {
-                    ns[i] = ~gv[i] & workset[i];
-                    if ((sw = ns[i]) != 0) pc += POPCOUNT(sw);
-                }
+                pc = not_common_edges(ns,gv,m);
                 if (pc <= 1 || pc >= cellsize[icell] - 2) continue;
 
                 ss = 1;
@@ -1554,9 +1564,9 @@ nautinv_freedyn(void)
 *                                                                            *
 *****************************************************************************/
 
-static int
-semirefine(graph *g, int *lab, int *ptn, int level, int *numcells,
-           int strength, set *active, int m, int n)
+STATIC_POPCNTFUNC(int,semirefine,
+    (graph *g, int *lab, int *ptn, int level, int *numcells,
+           int strength, set *active, int m, int n),
 {
 	int i,c1,c2,labc1;
 	setword x;
@@ -1567,12 +1577,10 @@ semirefine(graph *g, int *lab, int *ptn,
 	set *gptr;
 	int maxcell,maxpos,hint;
 
-#if !MAXN
-	DYNALLOC1(int,workperm,workperm_sz,n,"refine");
-	DYNALLOC1(set,workset,workset_sz,m,"refine");
-	DYNALLOC1(int,bucket,bucket_sz,n+2,"refine");
-	DYNALLOC1(int,count,count_sz,n,"refine");
-#endif
+	DEF_DYNINT(workperm,n,"refine");
+	DEF_DYNSET(workset,m,"refine");
+	DEF_DYNINT(bucket,n+2,"refine");
+	DEF_DYNINT(count,n,"refine");
 
 	longcode = *numcells;
 	split1 = -1;
@@ -1700,7 +1708,7 @@ semirefine(graph *g, int *lab, int *ptn,
 
 	longcode = MASH(longcode,FUZZ2(*numcells));
 	return CLEANUP(longcode);
-}
+})
 
 void 
 refinvar(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos,
--- a/naututil.c
+++ b/naututil.c
@@ -134,15 +134,18 @@ static const long fuzz2[] = {2001381726L
 *                                                                            *
 *****************************************************************************/
 
-int
-setinter(set *set1, set *set2, int m)
+#if MAXM==1
+POPCNTFUNC(int,setinter,(set *set1, set *set2, int m),
 {
     setword x;
 
-#if  MAXM==1
     if ((x = *set1 & *set2) != 0) return POPCOUNT(x);
     else                          return 0;
+})
 #else
+POPCNTFUNC(int,setinter,(set *set1, set *set2, int m),
+{
+    setword x;
     int count,i;
 
     count = 0;
@@ -154,8 +157,8 @@ setinter(set *set1, set *set2, int m)
     }
 
     return count;
+})
 #endif
-}
 
 /*****************************************************************************
 *                                                                            *
@@ -163,14 +166,15 @@ setinter(set *set1, set *set2, int m)
 *                                                                            *
 *****************************************************************************/
 
-int
-setsize(set *set1, int m)
-{
-
 #if  MAXM==1
+POPCNTFUNC(int,setsize,(set *set1, int m),
+{
     if (set1 != 0) return POPCOUNT(*set1);
     else           return 0;
+})
 #else
+POPCNTFUNC(int,setsize,(set *set1, int m),
+{
     int count,i;
     setword x;
 
@@ -179,8 +183,8 @@ setsize(set *set1, int m)
         if ((x = *set1++) != 0) count += POPCOUNT(x);
 
     return count;
+})
 #endif
-}
 
 /*****************************************************************************
 *                                                                            *
--- a/nauty-h.in
+++ b/nauty-h.in
@@ -88,6 +88,7 @@ it is necessary to check they are correc
 #define HAVE_POPCNTLL @have_popcntll@
 #define HAVE_MMPOP32 @have_mmpop32@
 #define HAVE_MMPOP64 @have_mmpop64@
+#define RUNTIME_POPCNT @runtime_popcnt@
 
 /*==================================================================*/
 
@@ -827,6 +828,46 @@ typedef unsigned long nauty_counter;
 
 #ifndef FIRSTBITNZ   /* Can be defined outside */
 
+/* Determine popcount support at runtime */
+#if RUNTIME_POPCNT
+#if !defined(__x86_64__) && !defined(__i386__)
+#error Runtime popcount support is only available on x86 or x86_64.
+#endif
+#ifndef __GNUC__
+#error Runtime popcount support is only available with GCC.
+#endif
+#if !__clang__ && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6))
+#error Runtime popcount support is only available with GCC 4.6 or later.
+#endif
+#include <cpuid.h>
+
+#define SLOWPOPCNT(type,name,params,...)                                \
+    static type slow_##name params __VA_ARGS__
+#define FASTPOPCNT(type,name,params,...)                                \
+    static type __attribute__((target ("popcnt"))) fast_##name params   \
+    __VA_ARGS__
+#define POPCNTHDR(type,name,params,...)                                 \
+    SLOWPOPCNT(type,name,params,__VA_ARGS__)                            \
+    FASTPOPCNT(type,name,params,__VA_ARGS__)                            \
+    static type (*resolve_##name (void)) params {                       \
+        unsigned int eax, ebx, ecx, edx;                                \
+        return (__get_cpuid(1, &eax, &ebx, &ecx, &edx) &&               \
+            (ecx & bit_POPCNT) != 0)                                    \
+            ? &fast_##name                                              \
+            : &slow_##name;                                             \
+    }
+#define POPCNTFUNC(type,name,params,...)                                \
+    type __attribute__((ifunc ("resolve_" #name))) name params;         \
+    POPCNTHDR(type,name,params,__VA_ARGS__)
+#define STATIC_POPCNTFUNC(type,name,params,...)                         \
+    static type __attribute__((ifunc ("resolve_" #name))) name params;  \
+    POPCNTHDR(type,name,params,__VA_ARGS__)
+#else
+#define POPCNTFUNC(type,name,params,...) type name params __VA_ARGS__
+#define STATIC_POPCNTFUNC(type,name,params,...)                         \
+    static type name params __VA_ARGS__
+#endif
+
 #ifdef NAUTY_IN_MAGMA
 #define FIRSTBITNZ(x) bs_firstbit(x)
 
@@ -938,7 +979,7 @@ static int msc_bsr_16(setword x) \
 
 /* Note that, unlike icc, gcc will not use the POPCNT instruction
    without permission, in which case it defines __POPCNT__ . */
-#elif defined(__POPCNT__)
+#elif defined(__POPCNT__) || RUNTIME_POPCNT
 #if defined(SETWORD_LONGLONG) && HAVE_POPCNTLL
 #define POPCOUNT(x) __builtin_popcountll(x)
 #elif defined(SETWORD_LONG) && HAVE_POPCNTL
@@ -1199,6 +1240,18 @@ extern void free(void*);
 #define CONDYNFREE(name,name_sz,minsz) \
  if (name_sz > (size_t)(minsz)) {DYNFREE(name,name_sz);}
 
+#if MAXN
+#define DCL_DYNINT(var) int var[MAXN]
+#define DCL_DYNSET(var) setword var[MAXM]
+#define DEF_DYNINT(var,n,name)
+#define DEF_DYNSET(var,n,name)
+#else
+#define DCL_DYNINT(var) DYNALLSTAT(int,var,var##_sz)
+#define DCL_DYNSET(var) DYNALLSTAT(set,var,var##_sz)
+#define DEF_DYNINT(var,n,name) DYNALLOC1(int,var,var##_sz,n,name)
+#define DEF_DYNSET(var,n,name) DYNALLOC1(set,var,var##_sz,n,name)
+#endif
+
 /* File to write error messages to (used as first argument to fprintf()). */
 #define ERRFILE stderr
 
--- a/vcolg.c
+++ b/vcolg.c
@@ -130,6 +130,22 @@ testmax(int *p, int n, int *abort)
 
 /**************************************************************************/
 
+#ifndef OUTPROC
+STATIC_POPCNTFUNC(size_t __attribute__((pure)),compute_degree,
+(const graph *g, int m, int n),
+{
+    const graph *gi;
+    size_t ne;
+
+    ne = 0;
+    for (gi = g + m*(size_t)n; --gi >= g; )
+        ne += POPCOUNT(*gi);
+    return ne;
+})
+#endif
+
+/**************************************************************************/
+
 static int
 trythisone(grouprec *group, graph *g, boolean digraph, int m, int n)
 /* Try one solution, accept if maximal. */
@@ -174,9 +190,7 @@ trythisone(grouprec *group, graph *g, bo
 #ifdef OUTPROC
             OUTPROC(outfile,g,col,m,n);
 #else
-	    ne = 0;
-	    for (gi = g + m*(size_t)n; --gi >= g; )
-		ne += POPCOUNT(*gi);
+	    ne = compute_degree(g,m,n);
 	    if (!digraph)
 	    {
 		for (i = 0, gi = g; i < n; ++i, gi += m)
--- a/watercluster2.c
+++ b/watercluster2.c
@@ -593,7 +593,7 @@ void decode_to_nauty(unsigned char *code
 
 /****************************************INIT_FOR_G6*****************************/
 
-void init_for_g6(graph g[],int aantal_toppen, int degree[])
+STATIC_POPCNTFUNC(void,init_for_g6,(graph g[],int aantal_toppen, int degree[]),
 {
   int i;
 
@@ -605,7 +605,7 @@ void init_for_g6(graph g[],int aantal_to
   aantal_gerichte_bogen=0;
   return;
 
-}
+})
 
 
 /***************************FILL_EDGELIST**************************/
@@ -1238,7 +1238,8 @@ void construct_operations_in(int list[],
 
 /**********************************CONSTRUCT_EXTENSIONS**************************/
 
-void construct_extensions(int still_open[], int orbit[], graph touched, int first_in_orbit, graph sameorbit)
+STATIC_POPCNTFUNC(void,construct_extensions,
+    (int still_open[], int orbit[], graph touched, int first_in_orbit, graph sameorbit),
 {
   int top, top2, j, end, list[MAXN], decided[MAXN], error, lowerlimit_outdeg, readylist[MAXN], *readyrun, dummy;
   int minout, do_double=0, i, mindouble;
@@ -1398,7 +1399,7 @@ for (number_operations=0; (top=(*still_o
       }
   }
   return; 
-}
+})
 
 int compare_op(unsigned char *op1, unsigned char *op2)
 // returns 0 if operations are the same, something negative if op1
@@ -1525,7 +1526,8 @@ void compute_edgeorbits(int edgelist[][2
 
 /******************************CANONICAL****************************/
 
-int canonical(unsigned char operation[], int vertexorbit[], int *newgroup, int orbitid, graph touched)
+STATIC_POPCNTFUNC(int,canonical,
+    (unsigned char operation[], int vertexorbit[], int *newgroup, int orbitid, graph touched),
 
 // checks whether the operation is canonical in vertexorbit. Returns 1 if yes, 0 otherwise.
 // In newgroup it is stored whether a new group has been computed for this (*newgroup=1) or not
@@ -1822,7 +1824,7 @@ int canonical(unsigned char operation[],
   else { return 0; }
 
 
-}
+})
 
 int all_diff_colours(graph testset, int orbitid)
 // returns 1 if all elements have some different vertex invariant and 0 otherwise
@@ -3764,7 +3766,7 @@ int test_possible(graph globalg[],int gl
 
 
 
-void waterclusters (graph g[], int n)
+STATIC_POPCNTFUNC(void,waterclusters,(graph g[], int n),
 { 
   int i, j, k, orbitsize, start, end, fixed_edge, dummy, maxgraphdeg, biggest_orbit;
   BOOG kleinste_orbit[MAX_BOGEN+1];  /* het is mogelijk dat er maar 1 orbit is */
@@ -3927,7 +3929,7 @@ void waterclusters (graph g[], int n)
 
 
   return;
-}
+})