Move interrupt branch from start to end of block, on i386.
authorTaylor R Campbell <campbell@mumble.net>
Sun, 26 Jun 2011 19:39:09 +0000 (19:39 +0000)
committerTaylor R Campbell <campbell@mumble.net>
Sun, 26 Jun 2011 19:39:09 +0000 (19:39 +0000)
This makes it a forward branch rather than a reverse branch, so that
the CPU's branch predictor will predict it not taken rather than taken
by default.

Reduces time to compile the whole system by about 20%.  This
performance increase will apply to any compiled code, independent of
what sort of computation it does.

src/compiler/machines/i386/rules3.scm

index a6da4e2daeb68a51355a4fd14d2d1b8da0f465df..c9da18f50b2a80391a9da218377962d666d6d65d 100644 (file)
@@ -398,14 +398,23 @@ USA.
 
 (define (interrupt-check interrupt-label checks)
   ;; This always does interrupt checks in line.
-  (LAP ,@(if (or (memq 'INTERRUPT checks) (memq 'HEAP checks))
-            (LAP (CMP W (R ,regnum:free-pointer) ,reg:compiled-memtop)
-                 (JGE (@PCR ,interrupt-label)))
-            (LAP))
-       ,@(if (memq 'STACK checks)
-            (LAP (CMP W (R ,regnum:stack-pointer) ,reg:stack-guard)
-                 (JL (@PCR ,interrupt-label)))
-            (LAP))))
+  (let ((branch-target (generate-label 'INTERRUPT)))
+    ;; Put the interrupt check branch target after the branch so that
+    ;; it is a forward branch, which Intel and AMD CPUs will predict
+    ;; not taken by default, in the absence of dynamic branch
+    ;; prediction profile data.
+    (add-end-of-block-code!
+     (lambda ()
+       (LAP (LABEL ,branch-target)
+           (JMP (@PCR ,interrupt-label)))))
+    (LAP ,@(if (or (memq 'INTERRUPT checks) (memq 'HEAP checks))
+              (LAP (CMP W (R ,regnum:free-pointer) ,reg:compiled-memtop)
+                   (JGE (@PCR ,branch-target)))
+              (LAP))
+        ,@(if (memq 'STACK checks)
+              (LAP (CMP W (R ,regnum:stack-pointer) ,reg:stack-guard)
+                   (JL (@PCR ,branch-target)))
+              (LAP)))))
 
 (define (simple-procedure-header code-word label entry)
   (let ((checks (get-entry-interrupt-checks)))