guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Using branch prediction hints (or not)


From: Ludovic Courtès
Subject: Using branch prediction hints (or not)
Date: Tue, 04 Dec 2007 21:35:04 +0100
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux)

Hi,

A long time ago, Aubbrey Jaffer wrote this page about his experiments
with branch prediction in SCM:

  http://www-swiss.ai.mit.edu/~jaffer/CNS/interpreter-branch.html

I played with GCC's `__builtin_expect' (patch attached) to provide GCC
with branch prediction hints in the most obvious situations:
`SCM_ASSERT'-like macros, `scm_wrong_num_args ()' situations in the
evaluator, and a few others.

It provides a little improvement on my x86 machine, less than 5% for
this program:

  (let loop ((x 20000000))
    (and (> x 0)
         (loop (1- x))))

This made me wonder whether it's even worth it.  OTOH, it doesn't hurt.

So, should we apply it?

Thanks,
Ludovic.

--- orig/libguile/__scm.h
+++ mod/libguile/__scm.h
@@ -3,7 +3,7 @@
 #ifndef SCM___SCM_H
 #define SCM___SCM_H
 
-/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003, 2006 Free Software 
Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003, 2006, 2007 Free 
Software Foundation, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -109,6 +109,20 @@
 #endif
 
 
+/* The SCM_EXPECT macros provide branch prediction hints to the compiler.  To
+ * use only in places where the result of the expression under "normal"
+ * circumstances is known.  */
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+# define SCM_EXPECT    __builtin_expect
+#else
+# define SCM_EXPECT(_expr, _value) (_expr)
+#endif
+
+#define SCM_EXPECT_TRUE(_expr)  SCM_EXPECT ((_expr), 1)
+#define SCM_EXPECT_FALSE(_expr) SCM_EXPECT ((_expr), 0)
+
+
+
 /* {Supported Options}
  *
  * These may be defined or undefined.
@@ -500,14 +514,14 @@
 #define SCM_ASSERT_TYPE(_cond, _arg, _pos, _subr, _msg)
 #define SCM_ASRTGO(_cond, _label)
 #else
-#define SCM_ASSERT(_cond, _arg, _pos, _subr) \
-       do { if (!(_cond)) \
+#define SCM_ASSERT(_cond, _arg, _pos, _subr)                   \
+        do { if (SCM_EXPECT_FALSE (!(_cond)))                  \
           scm_wrong_type_arg (_subr, _pos, _arg); } while (0)
-#define SCM_ASSERT_TYPE(_cond, _arg, _pos, _subr, _msg) \
-       do { if (!(_cond)) \
+#define SCM_ASSERT_TYPE(_cond, _arg, _pos, _subr, _msg)                        
\
+        do { if (SCM_EXPECT_FALSE (!(_cond)))                          \
           scm_wrong_type_arg_msg(_subr, _pos, _arg, _msg);  } while (0)
-#define SCM_ASRTGO(_cond, _label) \
-        do {  if (!(_cond)) \
+#define SCM_ASRTGO(_cond, _label)              \
+        do {  if (SCM_EXPECT_FALSE (!(_cond))) \
           goto _label; } while (0)
 #endif
 
@@ -526,8 +540,9 @@
   return (SCM_UNPACK (gf)                                      \
          ? scm_call_generic_0 ((gf))                           \
          : (scm_error_num_args_subr ((subr)), SCM_UNSPECIFIED))
-#define SCM_GASSERT0(cond, gf, subr) \
-  if (!(cond)) SCM_WTA_DISPATCH_0((gf), (subr))
+#define SCM_GASSERT0(cond, gf, subr)           \
+  if (SCM_EXPECT_FALSE(!(cond)))               \
+    SCM_WTA_DISPATCH_0((gf), (subr))
 
 SCM_API SCM scm_call_generic_1 (SCM gf, SCM a1);
 
@@ -535,8 +550,9 @@
   return (SCM_UNPACK (gf)                                      \
          ? scm_call_generic_1 ((gf), (a1))                     \
          : (scm_wrong_type_arg ((subr), (pos), (a1)), SCM_UNSPECIFIED))
-#define SCM_GASSERT1(cond, gf, a1, pos, subr) \
-  if (!(cond)) SCM_WTA_DISPATCH_1((gf), (a1), (pos), (subr))
+#define SCM_GASSERT1(cond, gf, a1, pos, subr)          \
+  if (SCM_EXPECT_FALSE (!(cond)))                      \
+    SCM_WTA_DISPATCH_1((gf), (a1), (pos), (subr))
 
 SCM_API SCM scm_call_generic_2 (SCM gf, SCM a1, SCM a2);
 
@@ -546,8 +562,9 @@
          : (scm_wrong_type_arg ((subr), (pos),                         \
                                 (pos) == SCM_ARG1 ? (a1) : (a2)),      \
             SCM_UNSPECIFIED))
-#define SCM_GASSERT2(cond, gf, a1, a2, pos, subr) \
-  if (!(cond)) SCM_WTA_DISPATCH_2((gf), (a1), (a2), (pos), (subr))
+#define SCM_GASSERT2(cond, gf, a1, a2, pos, subr)      \
+  if (SCM_EXPECT_FALSE (!(cond)))                      \
+    SCM_WTA_DISPATCH_2((gf), (a1), (a2), (pos), (subr))
 
 SCM_API SCM scm_apply_generic (SCM gf, SCM args);
 
@@ -558,8 +575,9 @@
                                 scm_list_ref ((args),                    \
                                               scm_from_int ((pos) - 1))), \
             SCM_UNSPECIFIED))
-#define SCM_GASSERTn(cond, gf, args, pos, subr) \
-  if (!(cond)) SCM_WTA_DISPATCH_n((gf), (args), (pos), (subr))
+#define SCM_GASSERTn(cond, gf, args, pos, subr)                \
+  if (SCM_EXPECT_FALSE (!(cond)))                      \
+    SCM_WTA_DISPATCH_n((gf), (args), (pos), (subr))
 
 #ifndef SCM_MAGIC_SNARFER
 /* Let these macros pass through if


--- orig/libguile/eval.c
+++ mod/libguile/eval.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006
+/* Copyright (C) 
1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007
  * Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
@@ -299,10 +299,12 @@
 
 
 /* Shortcut macros to simplify syntax error handling. */
-#define ASSERT_SYNTAX(cond, message, form) \
-  { if (!(cond)) syntax_error (message, form, SCM_UNDEFINED); }
-#define ASSERT_SYNTAX_2(cond, message, form, expr) \
-  { if (!(cond)) syntax_error (message, form, expr); }
+#define ASSERT_SYNTAX(cond, message, form)             \
+  { if (SCM_EXPECT_FALSE (!(cond)))                    \
+      syntax_error (message, form, SCM_UNDEFINED); }
+#define ASSERT_SYNTAX_2(cond, message, form, expr)     \
+  { if (SCM_EXPECT_FALSE (!(cond)))                    \
+      syntax_error (message, form, expr); }
 
 
 


--- orig/libguile/eval.i.c
+++ mod/libguile/eval.i.c
@@ -681,7 +681,7 @@
 #ifdef DEVAL
               debug.info->a.args = arg1;
 #endif
-              if (scm_badargsp (formals, arg1))
+              if (SCM_EXPECT_FALSE (scm_badargsp (formals, arg1)))
                 scm_wrong_num_args (proc);
               ENTER_APPLY;
               /* Copy argument list */
@@ -1143,7 +1143,7 @@
       case scm_tcs_closures:
         {
           const SCM formals = SCM_CLOSURE_FORMALS (proc);
-          if (scm_is_pair (formals))
+          if (SCM_EXPECT_FALSE (scm_is_pair (formals)))
             goto wrongnumargs;
           x = SCM_CLOSURE_BODY (proc);
           env = SCM_EXTEND_ENV (formals, SCM_EOL, SCM_ENV (proc));
@@ -1187,7 +1187,7 @@
 
   /* must handle macros by here */
   x = SCM_CDR (x);
-  if (scm_is_pair (x))
+  if (SCM_EXPECT_TRUE (scm_is_pair (x)))
     arg1 = EVALCAR (x, env);
   else
     scm_wrong_num_args (proc);
@@ -1316,7 +1316,7 @@
            goto badfun;
          }
       }
-    if (scm_is_pair (x))
+    if (SCM_EXPECT_TRUE (scm_is_pair (x)))
       arg2 = EVALCAR (x, env);
     else
       scm_wrong_num_args (proc);
@@ -1440,7 +1440,7 @@
             }
          }
       }
-      if (!scm_is_pair (x))
+      if (SCM_EXPECT_FALSE (!scm_is_pair (x)))
        scm_wrong_num_args (proc);
 #ifdef DEVAL
       debug.info->a.args = scm_cons2 (arg1, arg2,
@@ -1518,7 +1518,7 @@
           }
 #else /* DEVAL */
        case scm_tc7_subr_3:
-         if (!scm_is_null (SCM_CDR (x)))
+         if (SCM_EXPECT_FALSE (!scm_is_null (SCM_CDR (x))))
            scm_wrong_num_args (proc);
          else
            RETURN (SCM_SUBRF (proc) (arg1, arg2, EVALCAR (x, env)));
@@ -1709,37 +1709,38 @@
   switch (SCM_TYP7 (proc))
     {
     case scm_tc7_subr_2o:
-      if (SCM_UNBNDP (arg1))
+      if (SCM_EXPECT_FALSE (SCM_UNBNDP (arg1)))
        scm_wrong_num_args (proc);
       if (scm_is_null (args))
         args = SCM_UNDEFINED;
       else
         {
-          if (! scm_is_null (SCM_CDR (args)))
+          if (SCM_EXPECT_FALSE (! scm_is_null (SCM_CDR (args))))
             scm_wrong_num_args (proc);
           args = SCM_CAR (args);
         }
       RETURN (SCM_SUBRF (proc) (arg1, args));
     case scm_tc7_subr_2:
-      if (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))
+      if (SCM_EXPECT_FALSE (scm_is_null (args) ||
+                           !scm_is_null (SCM_CDR (args))))
        scm_wrong_num_args (proc);
       args = SCM_CAR (args);
       RETURN (SCM_SUBRF (proc) (arg1, args));
     case scm_tc7_subr_0:
-      if (!SCM_UNBNDP (arg1))
+      if (SCM_EXPECT_FALSE (!SCM_UNBNDP (arg1)))
        scm_wrong_num_args (proc);
       else
        RETURN (SCM_SUBRF (proc) ());
     case scm_tc7_subr_1:
-      if (SCM_UNBNDP (arg1))
+      if (SCM_EXPECT_FALSE (SCM_UNBNDP (arg1)))
        scm_wrong_num_args (proc);
     case scm_tc7_subr_1o:
-      if (!scm_is_null (args))
+      if (SCM_EXPECT_FALSE (!scm_is_null (args)))
        scm_wrong_num_args (proc);
       else
        RETURN (SCM_SUBRF (proc) (arg1));
     case scm_tc7_dsubr:
-      if (SCM_UNBNDP (arg1) || !scm_is_null (args))
+      if (SCM_EXPECT_FALSE (SCM_UNBNDP (arg1) || !scm_is_null (args)))
        scm_wrong_num_args (proc);
       if (SCM_I_INUMP (arg1))
         {
@@ -1760,13 +1761,13 @@
       SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
                           SCM_ARG1, scm_i_symbol_chars (SCM_SNAME (proc)));
     case scm_tc7_cxr:
-      if (SCM_UNBNDP (arg1) || !scm_is_null (args))
+      if (SCM_EXPECT_FALSE (SCM_UNBNDP (arg1) || !scm_is_null (args)))
        scm_wrong_num_args (proc);
       RETURN (scm_i_chase_pairs (arg1, (scm_t_bits) SCM_SUBRF (proc)));
     case scm_tc7_subr_3:
-      if (scm_is_null (args)
-         || scm_is_null (SCM_CDR (args))
-         || !scm_is_null (SCM_CDDR (args)))
+      if (SCM_EXPECT_FALSE (scm_is_null (args)
+                           || scm_is_null (SCM_CDR (args))
+                           || !scm_is_null (SCM_CDDR (args))))
        scm_wrong_num_args (proc);
       else
        RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CADR (args)));
@@ -1777,7 +1778,7 @@
       RETURN (SCM_SUBRF (proc) (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, 
args)));
 #endif
     case scm_tc7_lsubr_2:
-      if (!scm_is_pair (args))
+      if (SCM_EXPECT_FALSE (!scm_is_pair (args)))
        scm_wrong_num_args (proc);
       else
        RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CDR (args)));
@@ -1809,7 +1810,7 @@
 #else
       arg1 = (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args));
 #endif
-      if (scm_badargsp (SCM_CLOSURE_FORMALS (proc), arg1))
+      if (SCM_EXPECT_FALSE (scm_badargsp (SCM_CLOSURE_FORMALS (proc), arg1)))
        scm_wrong_num_args (proc);
       
       /* Copy argument list */


--- orig/libguile/numbers.c
+++ mod/libguile/numbers.c
@@ -3950,16 +3950,16 @@
 SCM
 scm_sum (SCM x, SCM y)
 {
-  if (SCM_UNBNDP (y))
+  if (SCM_EXPECT_FALSE (SCM_UNBNDP (y)))
     {
       if (SCM_NUMBERP (x)) return x;
       if (SCM_UNBNDP (x)) return SCM_INUM0;
       SCM_WTA_DISPATCH_1 (g_sum, x, SCM_ARG1, s_sum);
     }
 
-  if (SCM_I_INUMP (x))
+  if (SCM_EXPECT_TRUE (SCM_I_INUMP (x)))
     {
-      if (SCM_I_INUMP (y))
+      if (SCM_EXPECT_TRUE (SCM_I_INUMP (y)))
         {
           long xx = SCM_I_INUM (x);
           long yy = SCM_I_INUM (y);
@@ -4144,7 +4144,7 @@
 SCM
 scm_difference (SCM x, SCM y)
 {
-  if (SCM_UNBNDP (y))
+  if (SCM_EXPECT_FALSE (SCM_UNBNDP (y)))
     {
       if (SCM_UNBNDP (x))
         SCM_WTA_DISPATCH_0 (g_difference, s_difference);
@@ -4173,9 +4173,9 @@
           SCM_WTA_DISPATCH_1 (g_difference, x, SCM_ARG1, s_difference);
     }
   
-  if (SCM_I_INUMP (x))
+  if (SCM_EXPECT_TRUE (SCM_I_INUMP (x)))
     {
-      if (SCM_I_INUMP (y))
+      if (SCM_EXPECT_TRUE (SCM_I_INUMP (y)))
        {
          long int xx = SCM_I_INUM (x);
          long int yy = SCM_I_INUM (y);
@@ -4388,7 +4388,7 @@
 SCM
 scm_product (SCM x, SCM y)
 {
-  if (SCM_UNBNDP (y))
+  if (SCM_EXPECT_FALSE (SCM_UNBNDP (y)))
     {
       if (SCM_UNBNDP (x))
        return SCM_I_MAKINUM (1L);
@@ -4398,7 +4398,7 @@
        SCM_WTA_DISPATCH_1 (g_product, x, SCM_ARG1, s_product);
     }
   
-  if (SCM_I_INUMP (x))
+  if (SCM_EXPECT_TRUE (SCM_I_INUMP (x)))
     {
       long xx;
 
@@ -4411,7 +4411,7 @@
         case 1: return y; break;
        }
 
-      if (SCM_I_INUMP (y))
+      if (SCM_EXPECT_TRUE (SCM_I_INUMP (y)))
        {
          long yy = SCM_I_INUM (y);
          long kk = xx * yy;
@@ -4611,7 +4611,7 @@
 {
   double a;
 
-  if (SCM_UNBNDP (y))
+  if (SCM_EXPECT_FALSE (SCM_UNBNDP (y)))
     {
       if (SCM_UNBNDP (x))
        SCM_WTA_DISPATCH_0 (g_divide, s_divide);
@@ -4671,10 +4671,10 @@
        SCM_WTA_DISPATCH_1 (g_divide, x, SCM_ARG1, s_divide);
     }
 
-  if (SCM_I_INUMP (x))
+  if (SCM_EXPECT_TRUE (SCM_I_INUMP (x)))
     {
       long xx = SCM_I_INUM (x);
-      if (SCM_I_INUMP (y))
+      if (SCM_EXPECT_TRUE (SCM_I_INUMP (y)))
        {
          long yy = SCM_I_INUM (y);
          if (yy == 0)


--- orig/libguile/validate.h
+++ mod/libguile/validate.h
@@ -3,7 +3,7 @@
 #ifndef SCM_VALIDATE_H
 #define SCM_VALIDATE_H
 
-/* Copyright (C) 1999,2000,2001, 2002, 2004, 2006 Free Software Foundation, 
Inc.
+/* Copyright (C) 1999,2000,2001, 2002, 2004, 2006, 2007 Free Software 
Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -99,8 +99,10 @@
 #define SCM_OUT_OF_RANGE(pos, arg) \
   do { scm_out_of_range_pos (FUNC_NAME, arg, scm_from_int (pos)); } while (0)
 
-#define SCM_ASSERT_RANGE(pos, arg, f) \
-  do { if (!(f)) scm_out_of_range_pos (FUNC_NAME, arg, scm_from_int (pos)); } 
while (0)
+#define SCM_ASSERT_RANGE(pos, arg, f)                                  \
+  do { if (SCM_EXPECT_FALSE (!(f)))                                    \
+         scm_out_of_range_pos (FUNC_NAME, arg, scm_from_int (pos)); }  \
+  while (0)
 
 #define SCM_MUST_MALLOC_TYPE(type) \
   ((type *) scm_must_malloc (sizeof (type), FUNC_NAME))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]