X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Floop.lisp;h=9ffa2c0b55e48f21d42134ea408fc834f31cdd32;hb=b1a20dc4dee1a14c9b11eabf4130187227b9b2a7;hp=68f1741f44306e03cbd66e8edbd98ad45ee69585;hpb=4898ef32c639b1c7f4ee13a5ba566ce6debd03e6;p=sbcl.git diff --git a/src/code/loop.lisp b/src/code/loop.lisp index 68f1741..9ffa2c0 100644 --- a/src/code/loop.lisp +++ b/src/code/loop.lisp @@ -503,27 +503,21 @@ code to be loaded. ;;;; code analysis stuff (defun loop-constant-fold-if-possible (form &optional expected-type) - (let ((new-form form) (constantp nil) (constant-value nil)) - (when (setq constantp (constantp new-form)) - (setq constant-value (eval new-form))) + (let* ((constantp (sb!xc:constantp form)) + (value (and constantp (sb!int:constant-form-value form)))) (when (and constantp expected-type) - (unless (sb!xc:typep constant-value expected-type) + (unless (sb!xc:typep value expected-type) (loop-warn "~@" - form constant-value expected-type) - (setq constantp nil constant-value nil))) - (values new-form constantp constant-value))) - -(defun loop-constantp (form) - (constantp form)) + form value expected-type) + (setq constantp nil value nil))) + (values form constantp value))) ;;;; LOOP iteration optimization -(defvar *loop-duplicate-code* - nil) +(defvar *loop-duplicate-code* nil) -(defvar *loop-iteration-flag-var* - (make-symbol "LOOP-NOT-FIRST-TIME")) +(defvar *loop-iteration-flag-var* (make-symbol "LOOP-NOT-FIRST-TIME")) (defun loop-code-duplication-threshold (env) (declare (ignore env)) @@ -1067,7 +1061,7 @@ code to be loaded. (t (error "invalid LOOP variable passed in: ~S" name)))) (defun loop-maybe-bind-form (form data-type) - (if (loop-constantp form) + (if (constantp form) form (loop-make-var (gensym "LOOP-BIND-") form data-type))) @@ -1795,6 +1789,27 @@ code to be loaded. (setq step-hack `(,variable ,step-hack))) (let ((first-test test) (remaining-tests test)) + ;; As far as I can tell, the effect of the following code is + ;; to detect cases where we know statically whether the first + ;; iteration of the loop will be executed. Depending on the + ;; situation, we can either: + ;; a) save one jump and one comparison per loop (not per iteration) + ;; when it will get executed + ;; b) remove the loop body completely when it won't be executed + ;; + ;; Noble goals. However, the code generated in case a) will + ;; fool the loop induction variable detection, and cause + ;; code like (LOOP FOR I TO 10 ...) to use generic addition + ;; (bug #278a). + ;; + ;; Since the gain in case a) is rather minimal and Python is + ;; generally smart enough to handle b) without any extra + ;; support from the loop macro, I've disabled this code for + ;; now. The code and the comment left here in case somebody + ;; extends the induction variable bound detection to work + ;; with code where the stepping precedes the test. + ;; -- JES 2005-11-30 + #+nil (when (and stepby-constantp start-constantp limit-constantp (realp start-value) (realp limit-value)) (when (setq first-test @@ -1815,22 +1830,6 @@ code to be loaded. '((:from :upfrom :downfrom) (:to :upto :downto :above :below) (:by)) nil (list (list kwd val))))) -(defun loop-sequence-elements-path (variable data-type prep-phrases - &key - fetch-function - size-function - sequence-type - element-type) - (multiple-value-bind (indexv) (loop-named-var 'index) - (let ((sequencev (loop-named-var 'sequence))) - (list* nil nil ; dummy bindings and prologue - (loop-sequencer - indexv 'fixnum - variable (or data-type element-type) - sequencev sequence-type - `(,fetch-function ,sequencev ,indexv) - `(,size-function ,sequencev) - prep-phrases))))) ;;;; builtin LOOP iteration paths