emacs-devel
[Top][All Lists]
Advanced

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

Re: Redundant type checking in window.c and w32menu.c


From: Dmitry Antipov
Subject: Re: Redundant type checking in window.c and w32menu.c
Date: Wed, 20 Jun 2007 18:12:26 +0400
User-agent: Thunderbird 1.5.0.7 (X11/20061008)

Ken Raeburn wrote:

On Jun 19, 2007, at 10:44, Dmitry Antipov wrote:
If we pass CHECK_CONS(), we don't need CONSP()s in Fcar() and Fcdr() and may use XCAR()
and XCDR() instead.

Makes sense.

Whoops, probably not for GNU C :-). At least with -O1 and -O2, GCC (I've
tested with 4.1.2) emits an almost identical and optimal (i.e. with the
only branch ends with a call of wrong_type_argument ()) code for both cases

CHECK_CONS (obj);
x = CAR (obj);
y = CDR (obj);

and

CHECK_CONS (obj);
x = XCAR (obj);
y = XCDR (obj);

Have no ideas about other compilers.

You could make Fcar a static inline function in lisp.h (conditional on GCC, or maybe C99). If the optimizer's good at its job, it should eliminate the redundant CONSP checks. Using an inline function avoids having to check all Fcar uses for arguments that have function calls or side effects. (A quick grep shows several of those. In fact, if your test used the simple macro version, inline functions may result in less code size expansion because of this.) And personally, I think inline functions are often more readable than macros, if they're not very simple macros.

I agree, and here is the stuff I'm trying now. Reordering of data.c
looks ugly, but I have no ideas on how to avoid them :-(.

Dmitry
Index: data.c
===================================================================
RCS file: /sources/emacs/emacs/src/data.c,v
retrieving revision 1.271
diff -u -r1.271 data.c
--- data.c      26 May 2007 17:21:14 -0000      1.271
+++ data.c      20 Jun 2007 14:11:00 -0000
@@ -506,49 +506,6 @@
   return Qnil;
 }
 
-
-/* Extract and set components of lists */
-
-DEFUN ("car", Fcar, Scar, 1, 1, 0,
-       doc: /* Return the car of LIST.  If arg is nil, return nil.
-Error if arg is not nil and not a cons cell.  See also `car-safe'.
-
-See Info node `(elisp)Cons Cells' for a discussion of related basic
-Lisp concepts such as car, cdr, cons cell and list.  */)
-     (list)
-     register Lisp_Object list;
-{
-  return CAR (list);
-}
-
-DEFUN ("car-safe", Fcar_safe, Scar_safe, 1, 1, 0,
-       doc: /* Return the car of OBJECT if it is a cons cell, or else nil.  */)
-     (object)
-     Lisp_Object object;
-{
-  return CAR_SAFE (object);
-}
-
-DEFUN ("cdr", Fcdr, Scdr, 1, 1, 0,
-       doc: /* Return the cdr of LIST.  If arg is nil, return nil.
-Error if arg is not nil and not a cons cell.  See also `cdr-safe'.
-
-See Info node `(elisp)Cons Cells' for a discussion of related basic
-Lisp concepts such as cdr, car, cons cell and list.  */)
-     (list)
-     register Lisp_Object list;
-{
-  return CDR (list);
-}
-
-DEFUN ("cdr-safe", Fcdr_safe, Scdr_safe, 1, 1, 0,
-       doc: /* Return the cdr of OBJECT if it is a cons cell, or else nil.  */)
-     (object)
-     Lisp_Object object;
-{
-  return CDR_SAFE (object);
-}
-
 DEFUN ("setcar", Fsetcar, Ssetcar, 2, 2, 0,
        doc: /* Set the car of CELL to be NEWCAR.  Returns NEWCAR.  */)
      (cell, newcar)
@@ -2933,6 +2890,57 @@
   return make_number (order);
 }
 
+#if defined (__GNUC__) && defined (__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__)
+/* If we're optimizing, these are macros, and they will conflict with
+   the definitions below.  */
+#undef Fcar
+#undef Fcar_safe
+#undef Fcdr
+#undef Fcdr_safe
+#endif
+
+
+/* Extract and set components of lists */
+
+DEFUN ("car", Fcar, Scar, 1, 1, 0,
+       doc: /* Return the car of LIST.  If arg is nil, return nil.
+Error if arg is not nil and not a cons cell.  See also `car-safe'.
+
+See Info node `(elisp)Cons Cells' for a discussion of related basic
+Lisp concepts such as car, cdr, cons cell and list.  */)
+     (list)
+     register Lisp_Object list;
+{
+  return CAR (list);
+}
+
+DEFUN ("car-safe", Fcar_safe, Scar_safe, 1, 1, 0,
+       doc: /* Return the car of OBJECT if it is a cons cell, or else nil.  */)
+     (object)
+     Lisp_Object object;
+{
+  return CAR_SAFE (object);
+}
+
+DEFUN ("cdr", Fcdr, Scdr, 1, 1, 0,
+       doc: /* Return the cdr of LIST.  If arg is nil, return nil.
+Error if arg is not nil and not a cons cell.  See also `cdr-safe'.
+
+See Info node `(elisp)Cons Cells' for a discussion of related basic
+Lisp concepts such as cdr, car, cons cell and list.  */)
+     (list)
+     register Lisp_Object list;
+{
+  return CDR (list);
+}
+
+DEFUN ("cdr-safe", Fcdr_safe, Scdr_safe, 1, 1, 0,
+       doc: /* Return the cdr of OBJECT if it is a cons cell, or else nil.  */)
+     (object)
+     Lisp_Object object;
+{
+  return CDR_SAFE (object);
+}
 
 
 void
Index: lisp.h
===================================================================
RCS file: /sources/emacs/emacs/src/lisp.h,v
retrieving revision 1.577
diff -u -r1.577 lisp.h
--- lisp.h      8 Jun 2007 19:56:24 -0000       1.577
+++ lisp.h      20 Jun 2007 14:11:00 -0000
@@ -2206,10 +2206,39 @@
 EXFUN (Finteger_or_floatp, 1);
 EXFUN (Finteger_or_float_or_marker_p, 1);
 
+/* If using GNU and optimizing for speed,
+   inline the most common cons operations.  */
+#if defined (__GNUC__) && defined (__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__)
+
+#define CONSFN(name) \
+  static __inline__ Lisp_Object \
+  _F ## name (obj) \
+       Lisp_Object obj; \
+  { \
+    return name (obj); \
+  }
+
+CONSFN (CAR)
+CONSFN (CAR_SAFE)
+CONSFN (CDR)
+CONSFN (CDR_SAFE)
+
+#define Fcar(c) _FCAR (c)
+#define Fcar_safe(c) _FCAR_SAFE (c)
+#define Fcdr(c) _FCDR (c)
+#define Fcdr_safe(c) _FCDR_SAFE (c)
+
+#undef CONSFN
+
+#else
+
 EXFUN (Fcar, 1);
 EXFUN (Fcar_safe, 1);
 EXFUN (Fcdr, 1);
 EXFUN (Fcdr_safe, 1);
+
+#endif /* __GNUC__ && __OPTIMIZE__ && !__OPTIMIZE_SIZE__ */
+
 EXFUN (Fsetcar, 2);
 EXFUN (Fsetcdr, 2);
 EXFUN (Fboundp, 1);

reply via email to

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