Hi all,

I've been playing around a little bit with "perf" and Valgrind's
cachegrind tool, and I noticed that the number of branch prediction
misses can be reduced if the argvector reusing check can be hardcoded
for cases where we know the size of the calling function's argvector.

Here's a simple patch to make this happen (works on both the master
and chicken-5 branches).

I also noticed that for some benchmarks, the number of branches
went up, and missed branches too, compared to current master.  I'm
not sure what to make of that.  Perhaps this is due to inlining
differences.

Cheers,
Peter
From 1e6685d0fb9580a34a407ef8fa62f42eb1266268 Mon Sep 17 00:00:00 2001
From: Peter Bex <pe...@more-magic.net>
Date: Thu, 15 Dec 2016 23:44:35 +0100
Subject: [PATCH] Statically determine if av can be reused or not.

This is faster due to avoiding branch prediction misses.
---
 c-backend.scm | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/c-backend.scm b/c-backend.scm
index 2479986..02b3393 100644
--- a/c-backend.scm
+++ b/c-backend.scm
@@ -477,19 +477,27 @@
 	(let* ((n (length args))
 	       (avl (+ n (if selfarg 1 0)))
 	       (caller-has-av? (not (or (lambda-literal-customizable ll)
-					(lambda-literal-direct ll)))))
+					(lambda-literal-direct ll))))
+	       (caller-argcount (lambda-literal-argument-count ll))
+	       (caller-rest-mode (lambda-literal-rest-argument-mode ll)))
 	  ;; Try to re-use argvector from current function if it is
 	  ;; large enough.  push-args gets used only for functions in
 	  ;; CPS context, so callee never returns to current function.
 	  ;; And even so, av[] is already copied into temporaries.
-	  (cond (caller-has-av?
-		 (gen #t "C_word *av2;")
-		 (gen #t "if(c >= " avl ") {")
-		 (gen #t "  av2=av; /* Re-use our own argvector */")
-		 (gen #t "} else {")
-		 (gen #t "  av2=C_alloc(" avl ");")
-		 (gen #t "}"))
-		(else (gen #t "C_word av2[" avl "];")))
+	  (cond
+	   ((or (not caller-has-av?)	     ; Argvec missing or
+		(and (< caller-argcount avl) ; known to be too small?
+		     (eq? caller-rest-mode 'none)))
+	    (gen #t "C_word av2[" avl "];"))
+	   ((>= caller-argcount avl)   ; Argvec known to be re-usable?
+	    (gen #t "C_word *av2=av; /* Re-use our own argvector */"))
+	   (else      ; Need to determine dynamically. This is slower.
+	    (gen #t "C_word *av2;")
+	    (gen #t "if(c >= " avl ") {")
+	    (gen #t "  av2=av; /* Re-use our own argvector */")
+	    (gen #t "} else {")
+	    (gen #t "  av2=C_alloc(" avl ");")
+	    (gen #t "}")))
 	  (when selfarg (gen #t "av2[0]=" selfarg ";"))
 	  (do ((j (if selfarg 1 0) (add1 j))
 	       (args args (cdr args)))
-- 
2.1.4

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers

Reply via email to