Changeset 14969


Ignore:
Timestamp:
Sep 1, 2011, 10:43:41 PM (13 years ago)
Author:
Gary Byers
Message:

Try to speed up some cases involving self-calls where the number
of args is fixed, tail calls where some outgoing args are passed
on the stack, and the combination of those things. We generally
do the calls faster, but we don't really recognize that iteration's
being introduced (and that things are happening in a loop.)

Location:
trunk/source/compiler/X86
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/compiler/X86/X8632/x8632-vinsns.lisp

    r14959 r14969  
    16261626)
    16271627
     1628(define-x8632-vinsn (pass-multiple-values-known-function :jumplr) (((fnreg :lisp))
     1629                                                                    ())
     1630  (pushl (:@ (:apply + (:apply target-nil-value) (x8632::%kernel-global 'x86::ret1valaddr))))
     1631  (jmp (:%l fnreg)))
     1632
    16281633
    16291634(define-x8632-vinsn reserve-outgoing-frame (()
     
    41794184  (movsd (:%xmm val) (:@ (:%l base) (:%l idx) 2)))
    41804185
     4186(define-x8632-vinsn pop-outgoing-arg (((n :u16const))
     4187                                      ())
     4188  (popl (:@ (:apply * n (- x8632::node-size)) (:%l x8632::ebp))))
     4189
     4190(define-x8632-vinsn slide-nth-arg (()
     4191                                   ((n :u16const)
     4192                                    (nstackargs :u16const)
     4193                                    (temp :lisp)))
     4194  (movl (:@ (:apply * (:apply - nstackargs (:apply + 1 n)) x8632::node-size) (:%l x8632::esp)) (:%l temp))
     4195  (movl (:%l temp) (:@ (:apply * (:apply + n 1) (- x8632::node-size)) (:%l x8632::ebp))))
     4196
     4197(define-x8632-vinsn set-tail-vsp (((n :u16const))
     4198                                  ())
     4199  ((:pred = 0 n)
     4200   (movl (:%l x8632::ebp) (:%l x8632::esp)))
     4201  ((:not (:pred = 0 n))
     4202   (leal (:@ (:apply * n (- x8632::node-size)) (:%l x8632::ebp)) (:%l x8632::esp))))
     4203
     4204;;; If we've have outgoing arguments in a tail call and are calling
     4205;;; some function (rather than jumping to an internal entry point), we
     4206;;; need to push the caller's return address and unlink its frame
     4207;;; pointer.
     4208(define-x8632-vinsn prepare-tail-call (()
     4209                                       ())
     4210  (pushl (:@ x8632::node-size (:%l x8632::ebp)))
     4211  (movl (:@ (:% x8632::ebp)) (:% x8632::ebp)))
     4212
    41814213(queue-fixup
    41824214 (fixup-x86-vinsn-templates
  • trunk/source/compiler/X86/X8664/x8664-vinsns.lisp

    r14959 r14969  
    17811781;;; as well as this.
    17821782(define-x8664-vinsn (pass-multiple-values :jumplr) (()
    1783                                                   ()
    1784                                                   ((tag :u8)))
     1783                                                    ()
     1784                                                    ((tag :u8)))
    17851785  :resume
    17861786  (movl (:%l x8664::temp0) (:%l tag))
     
    17971797  (:anchored-uuo (uuo-error-not-callable)))
    17981798
     1799(define-x8664-vinsn (pass-multiple-values-known-function :jumplr) (((fnreg :lisp))
     1800                                                                    ())
     1801  (pushq (:@ (:apply + (:apply target-nil-value) (x8664::%kernel-global 'x86::ret1valaddr))))
     1802  (jmp (:%q fnreg)))
    17991803
    18001804
     
    45984602  (movsd (:%xmm val) (:@ (:%q base) (:%q idx))))
    45994603
     4604
     4605(define-x8664-vinsn pop-outgoing-arg (((n :u16const))
     4606                                      ())
     4607  (popq (:@ (:apply * n (- x8664::node-size)) (:%q x8664::rbp))))
     4608
     4609(define-x8664-vinsn slide-nth-arg (()
     4610                                   ((n :u16const)
     4611                                    (nstackargs :u16const)
     4612                                    (temp :lisp)))
     4613  (movq (:@ (:apply * (:apply - nstackargs (:apply + 1 n)) x8664::node-size) (:%q x8664::rsp)) (:%q temp))
     4614  (movq (:%q temp) (:@ (:apply * (:apply + n 1) (- x8664::node-size)) (:%q x8664::rbp))))
     4615                                   
     4616
     4617(define-x8664-vinsn set-tail-vsp (((nargs :u16const))
     4618                                  ())
     4619  ((:pred = 0 nargs)
     4620   (movq (:%q x8664::rbp) (:%q x8664::rsp)))
     4621  ((:not (:pred = 0 nargs))
     4622   (leaq (:@ (:apply * nargs (- x8664::node-size)) (:%q x8664::rbp)) (:%q x8664::rsp))))
     4623
     4624
     4625;;; If we've used one of the fixed-stack-args !slideN vinsns above
     4626;;; and are calling some function (rather than jumping to an internal
     4627;;; entry point), we need to push the caller's return address and unlink
     4628;;; its frame pointer.
     4629(define-x8664-vinsn prepare-tail-call (()
     4630                                       ())
     4631  (pushq (:@ x8664::node-size (:%q x8664::rbp)))
     4632  (movq (:@ (:%q x8664::rbp)) (:%q x8664::rbp)))
     4633
    46004634(queue-fixup
    46014635 (fixup-x86-vinsn-templates
  • trunk/source/compiler/X86/x862.lisp

    r14967 r14969  
    194194(defvar *x862-entry-vstack* nil)
    195195(defvar *x862-fixed-nargs* nil)
     196(defvar *x862-fixed-self-call-label* nil)
     197(defvar *x862-fixed-self-tail-call-label* nil)
    196198(defvar *x862-need-nargs* t)
    197199
     
    611613           (*x862-entry-vstack* nil)
    612614           (*x862-fixed-nargs* nil)
     615           (*x862-fixed-self-call-label* nil)
     616           (*x862-fixed-self-tail-call-label* nil)         
    613617           (*x862-need-nargs* t)
    614618           (fname (afunc-name afunc))
     
    11761180      (declare (type (unsigned-byte 16) nargs))
    11771181      (unless variable-args-entry
     1182        (setq *x862-fixed-nargs* nargs)
     1183        (@ (setq *x862-fixed-self-call-label* (backend-get-next-label)))
    11781184        (if (<= nargs *x862-target-num-arg-regs*) ; caller didn't vpush anything
    11791185          (! save-lisp-context-no-stack-args)
    11801186          (let* ((offset (* (the fixnum (- nargs *x862-target-num-arg-regs*)) *x862-target-node-size*)))
    11811187            (declare (fixnum offset))
    1182             (! save-lisp-context-offset offset))))
     1188            (! save-lisp-context-offset offset)))
     1189        (@ (setq *x862-fixed-self-tail-call-label* (backend-get-next-label))))
    11831190      (target-arch-case
    11841191       (:x8632
     
    28112818            (x862-vpush-register seg (x862-one-untargeted-reg-form seg fn *x862-arg-z*))
    28122819            (setq fn (x862-vloc-ea vstack)))
    2813           (x862-invoke-fn seg fn (x862-arglist seg arglist mv-return-label) spread-p xfer mv-return-label)
     2820          (x862-invoke-fn seg fn (x862-arglist seg arglist mv-return-label (x862-tailcallok xfer)) spread-p xfer mv-return-label)
    28142821          (if (and (logbitp $backend-mvpass-bit xfer)
    28152822                   (not simple-case))
     
    28492856      (! jump-known-symbol)
    28502857      (! call-known-symbol *x862-arg-z*))))
     2858
     2859(defun x862-self-call (seg nargs tail-p)
     2860  (with-x86-local-vinsn-macros (seg)
     2861    (cond ((and tail-p
     2862                (eql nargs *x862-fixed-nargs*)
     2863                (or *x862-open-code-inline*
     2864                    (<= nargs (+ 3 *x862-target-num-arg-regs*)))
     2865                *x862-fixed-self-tail-call-label*)
     2866           ;; We can probably do better than popping the nvrs
     2867           ;; and then jumping to a point where we push them again ...
     2868           (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* (<= nargs *x862-target-num-arg-regs*))
     2869           (let* ((nstack (- nargs *x862-target-num-arg-regs*)))
     2870             (declare (fixnum nstack))
     2871             (if (< nstack 0) (setq nstack 0))
     2872             (do* ((n nstack (1- n)))
     2873                  ((= n 0) (! set-tail-vsp nstack))
     2874               (declare (fixnum n))
     2875               (! pop-outgoing-arg n))
     2876             (-> *x862-fixed-self-tail-call-label*))
     2877           t)
     2878          ((and (not tail-p)
     2879                (eql nargs *x862-fixed-nargs*)
     2880                *x862-fixed-self-call-label*)
     2881           (! call-label (aref *backend-labels* *x862-fixed-self-call-label*))
     2882           t))))
    28512883
    28522884;;; Nargs = nil -> multiple-value case.
     
    28692901           (destreg (if symp ($ *x862-fname*) (unless label-p ($ *x862-temp0*))))
    28702902           (alternate-tail-call
    2871             (and tail-p label-p *x862-tail-label* (eql nargs *x862-tail-nargs*) (not spread-p))))
    2872       (when expression-p
    2873         ;;Have to do this before spread args, since might be vsp-relative.
    2874         (if nargs
    2875           (x862-do-lexical-reference seg destreg fn)
    2876           (x862-copy-register seg destreg fn)))
    2877       (if (or symp lfunp)
    2878         (setq func (if symp
    2879                      (x862-symbol-entry-locative func)
    2880                      (x862-afunc-lfun-ref func))
    2881               a-reg (x862-register-constant-p func)))
    2882       (when tail-p
    2883         #-no-compiler-bugs
    2884         (unless (or immp symp lfunp (typep fn 'lreg) (fixnump fn)) (compiler-bug "Well, well, well.  How could this have happened ?"))
    2885         (when a-reg
    2886           (x862-copy-register seg destreg a-reg))
    2887         (unless spread-p
    2888           (unless alternate-tail-call
    2889             (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* (and nargs (<= nargs *x862-target-num-arg-regs*))))))
    2890       (if spread-p
    2891         (progn
    2892           (x862-set-nargs seg (%i- nargs 1))
    2893                                         ; .SPspread-lexpr-z & .SPspreadargz preserve temp1
    2894           (target-arch-case
    2895            (:x8632
    2896             (! save-node-register-to-spill-area *x862-temp0*)))
    2897           (if (eq spread-p 0)
    2898             (! spread-lexpr)
    2899             (! spread-list))
    2900           (target-arch-case
    2901            (:x8632
    2902             (! load-node-register-from-spill-area *x862-temp0*)))
    2903 
    2904           (when (and tail-p *x862-register-restore-count*)
    2905             (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* nil)))
    2906         (if nargs
    2907           (unless alternate-tail-call (x862-set-nargs seg nargs))
    2908           (! pop-argument-registers)))
    2909       (if callable
    2910         (if (not tail-p)
    2911           (if (x862-mvpass-p xfer)
    2912             (let* ((call-reg (if symp ($ *x862-fname*) ($ *x862-temp0*))))
    2913               (unless mvpass-label (compiler-bug "no label for mvpass"))
    2914               (if label-p
    2915                 (x862-copy-register seg call-reg ($ *x862-fn*))
    2916                 (if a-reg
    2917                   (x862-copy-register seg call-reg  a-reg)
    2918                   (x862-store-immediate seg func call-reg)))
    2919               (if symp
    2920                 (! pass-multiple-values-symbol)
    2921                 (! pass-multiple-values))
    2922               (when mvpass-label
    2923                 (@= mvpass-label)))
    2924             (progn
    2925               (if label-p
    2926                 (progn
    2927                   (! call-label (aref *backend-labels* 2)))
    2928                 (progn
    2929                   (if a-reg
    2930                     (x862-copy-register seg destreg a-reg)
    2931                     (x862-store-immediate seg func destreg))
    2932                   (if symp
    2933                     (x862-call-symbol seg nil)
    2934                     (! call-known-function))))))
    2935           (if alternate-tail-call
    2936             (progn
    2937               (x862-unwind-stack seg xfer 0 0 *x862-tail-vsp*)
    2938               (! jump (aref *backend-labels* *x862-tail-label*)))
    2939             (progn
    2940               (x862-unwind-stack seg xfer 0 0 #x7fffff)
    2941               (if (and (not spread-p) nargs (%i<= nargs *x862-target-num-arg-regs*))
    2942                 (progn
    2943                   (unless (or label-p a-reg) (x862-store-immediate seg func destreg))
    2944                   (x862-restore-full-lisp-context seg)
    2945                   (if label-p
    2946                     (! jump (aref *backend-labels* 1))
    2947                     (progn
     2903            (and tail-p label-p *x862-tail-label* (eql nargs *x862-tail-nargs*) (not spread-p)))
     2904           (set-nargs-vinsn nil))
     2905      (or (and label-p nargs (not spread-p) (not (x862-mvpass-p xfer))
     2906               (not alternate-tail-call)
     2907               (x862-self-call seg nargs tail-p))
     2908          (progn
     2909            (when expression-p
     2910              ;;Have to do this before spread args, since might be vsp-relative.
     2911              (if nargs
     2912                (x862-do-lexical-reference seg destreg fn)
     2913                (x862-copy-register seg destreg fn)))
     2914            (if (or symp lfunp)
     2915              (setq func (if symp
     2916                           (x862-symbol-entry-locative func)
     2917                           (x862-afunc-lfun-ref func))
     2918                    a-reg (x862-register-constant-p func)))
     2919            (when tail-p
     2920              #-no-compiler-bugs
     2921              (unless (or immp symp lfunp (typep fn 'lreg) (fixnump fn)) (compiler-bug "Well, well, well.  How could this have happened ?"))
     2922              (when a-reg
     2923                (x862-copy-register seg destreg a-reg))
     2924              (unless spread-p
     2925                (unless alternate-tail-call
     2926                  (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* (and nargs (<= nargs *x862-target-num-arg-regs*))))))
     2927            (if spread-p
     2928              (progn
     2929                (x862-set-nargs seg (%i- nargs 1))
     2930                ;; .SPspread-lexpr-z & .SPspreadargz preserve temp1
     2931                (target-arch-case
     2932                 (:x8632
     2933                  (! save-node-register-to-spill-area *x862-temp0*)))
     2934                (if (eq spread-p 0)
     2935                  (! spread-lexpr)
     2936                  (! spread-list))
     2937                (target-arch-case
     2938                 (:x8632
     2939                  (! load-node-register-from-spill-area *x862-temp0*)))
     2940
     2941                (when (and tail-p *x862-register-restore-count*)
     2942                  (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* nil)))
     2943              (if nargs
     2944                (unless alternate-tail-call
     2945                  (setq set-nargs-vinsn (x862-set-nargs seg nargs)))
     2946                (! pop-argument-registers)))
     2947            (if callable
     2948              (if (not tail-p)
     2949                (if (x862-mvpass-p xfer)
     2950                  (let* ((call-reg (if label-p ($ *x862-fn*) (if symp ($ *x862-fname*) ($ *x862-temp0*)))))
     2951                    (unless mvpass-label (compiler-bug "no label for mvpass"))
     2952                    (unless label-p
     2953                      (if a-reg
     2954                        (x862-copy-register seg call-reg  a-reg)
     2955                        (x862-store-immediate seg func call-reg)))
     2956                    (if label-p
     2957                      (! pass-multiple-values-known-function call-reg)
    29482958                      (if symp
    2949                         (x862-call-symbol seg t)
    2950                         (! jump-known-function)))))
    2951                 (progn
    2952                   (unless (or label-p a-reg) (x862-store-immediate seg func destreg))
    2953                   (when label-p
    2954                     (x862-copy-register seg *x862-temp0* *x862-fn*))
    2955 
    2956                   (cond ((or spread-p (null nargs))
    2957                          (if symp
    2958                            (! tail-call-sym-gen)
    2959                            (! tail-call-fn-gen)))
     2959                        (! pass-multiple-values-symbol)
     2960                        (! pass-multiple-values)))
     2961                    (when mvpass-label
     2962                      (@= mvpass-label)))
     2963                  (progn
     2964                    (if label-p
     2965                      (progn
     2966                        (! call-label (aref *backend-labels* 2)))
     2967                      (progn
     2968                        (if a-reg
     2969                          (x862-copy-register seg destreg a-reg)
     2970                          (x862-store-immediate seg func destreg))
     2971                        (if symp
     2972                          (x862-call-symbol seg nil)
     2973                          (! call-known-function))))))
     2974                (if alternate-tail-call
     2975                  (progn
     2976                    (x862-unwind-stack seg xfer 0 0 *x862-tail-vsp*)
     2977                    (! jump (aref *backend-labels* *x862-tail-label*)))
     2978                  (progn
     2979                    (x862-unwind-stack seg xfer 0 0 #x7fffff)
     2980                    (if (and (not spread-p) nargs (%i<= nargs *x862-target-num-arg-regs*))
     2981                      (progn
     2982                        (unless (or label-p a-reg) (x862-store-immediate seg func destreg))
     2983                        (x862-restore-full-lisp-context seg)
     2984                        (if label-p
     2985                          (! jump (aref *backend-labels* 1))
     2986                          (progn
     2987                            (if symp
     2988                              (x862-call-symbol seg t)
     2989                              (! jump-known-function)))))
     2990                      (progn
     2991                        (unless (or label-p a-reg) (x862-store-immediate seg func destreg))
     2992                        (when label-p
     2993                          (x862-copy-register seg *x862-temp0* *x862-fn*))
     2994
     2995                        (cond ((or spread-p (null nargs))
     2996                               (if symp
     2997                                 (! tail-call-sym-gen)
     2998                                 (! tail-call-fn-gen)))
     2999                              ((%i> nargs *x862-target-num-arg-regs*)
     3000                               (let* ((nstackargs (- nargs *x862-target-num-arg-regs*)))
     3001                                 (if (and (or *x862-open-code-inline*
     3002                                         (<= nstackargs 3)))
     3003                                   (let* ((nstackbytes (ash nstackargs *x862-target-node-shift*)))
     3004                                     (unless (= nstackbytes *x862-vstack*)
     3005                                       (if (>= *x862-vstack* (ash nstackbytes 1))
     3006                                         ;; If there's room in the caller's
     3007                                         ;; frame beneath the outgoing args,
     3008                                         ;; pop them.  This avoids the use
     3009                                         ;; of a temp reg, but can't deal
     3010                                         ;; with the overlap situation if
     3011                                         ;; that constraint isn't met.
     3012                                         (do* ((n nstackargs (1- n)))
     3013                                              ((= n 0))
     3014                                           (declare (fixnum n))
     3015                                           (! pop-outgoing-arg n))
     3016                                         (let* ((temp
     3017                                                 (target-arch-case
     3018                                                  (:x8664 ($ x8664::temp2))
     3019                                                  (:x8632 ($ x8632::temp1)))))
     3020
     3021                                           (dotimes (i nstackargs)
     3022                                             (! slide-nth-arg i nstackargs temp))
     3023                                           (target-arch-case
     3024                                            (:x8632
     3025                                             ;; x8632::temp1 = x8632::nargs
     3026                                             (remove-dll-node set-nargs-vinsn)
     3027                                             (! set-nargs nargs)))))
     3028                                       (! set-tail-vsp nstackargs))
     3029                                     (! prepare-tail-call)
     3030                                     (if symp
     3031                                       (! jump-known-symbol)
     3032                                       (! jump-known-function)))
     3033                                   (if symp
     3034                                     (! tail-call-sym-slide)
     3035                                     (! tail-call-fn-slide)))))
     3036                              (t
     3037                               (! restore-full-lisp-context)
     3038                               (if symp
     3039                                 (! jump-known-symbol)
     3040                                 (! jump-known-function)))))))))
     3041              ;; The general (funcall) case: we don't know (at compile-time)
     3042              ;; for sure whether we've got a symbol or a (local, constant)
     3043              ;; function.
     3044              (progn
     3045                (unless (or (fixnump fn) (typep fn 'lreg))
     3046                  (x862-one-targeted-reg-form seg fn destreg))
     3047                (if (not tail-p)
     3048                  (if (x862-mvpass-p xfer)
     3049                    (progn (! pass-multiple-values)
     3050                           (when mvpass-label
     3051                             (@= mvpass-label)))
     3052                    (! funcall))                 
     3053                  (cond ((or (null nargs) spread-p)
     3054                         (! tail-funcall-gen))
    29603055                        ((%i> nargs *x862-target-num-arg-regs*)
    2961                          (if symp
    2962                            (! tail-call-sym-slide)
    2963                            (! tail-call-fn-slide)))
     3056                         (! tail-funcall-slide))
    29643057                        (t
    2965                          (if symp
    2966                            (! tail-call-sym-vsp)
    2967                            (! tail-call-fn-vsp)))))))))
    2968         ;; The general (funcall) case: we don't know (at compile-time)
    2969         ;; for sure whether we've got a symbol or a (local, constant)
    2970         ;; function.
    2971         (progn
    2972           (unless (or (fixnump fn) (typep fn 'lreg))
    2973             (x862-one-targeted-reg-form seg fn destreg))
    2974           (if (not tail-p)
    2975             (if (x862-mvpass-p xfer)
    2976               (progn (! pass-multiple-values)
    2977                      (when mvpass-label
    2978                        (@= mvpass-label)))
    2979               (! funcall))                 
    2980             (cond ((or (null nargs) spread-p)
    2981                    (! tail-funcall-gen))
    2982                   ((%i> nargs *x862-target-num-arg-regs*)
    2983                    (! tail-funcall-slide))
    2984                   (t
    2985                    (! restore-full-lisp-context)
    2986                    (! tail-funcall)))))))
    2987     nil))
     3058                         (! restore-full-lisp-context)
     3059                         (! tail-funcall))))))))
     3060      nil)))
    29883061
    29893062(defun x862-seq-fbind (seg vreg xfer vars afuncs body p2decls)
     
    31943267      n)))
    31953268
    3196 (defun x862-arglist (seg args &optional mv-label)
     3269(defun x862-arglist (seg args &optional mv-label suppress-frame-reservation)
    31973270  (with-x86-local-vinsn-macros (seg)
    31983271    (when mv-label
    31993272      (x862-vpush-label seg (aref *backend-labels* mv-label)))
    3200     (when (car args)
     3273    (when (and (car args) (not suppress-frame-reservation))
    32013274      (! reserve-outgoing-frame)
    32023275      (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil)
Note: See TracChangeset for help on using the changeset viewer.