optimize direct calls online
This commit is contained in:
		
							parent
							
								
									36b3ec82d2
								
							
						
					
					
						commit
						62b42e8bb8
					
				|  | @ -0,0 +1,58 @@ | |||
| 
 | ||||
| Step1: Optimize direct calls: | ||||
| 
 | ||||
| Suppose we have a case-lambda as follows | ||||
| 
 | ||||
| (case-lambda | ||||
|   [<formals_0> <code_0>] | ||||
|   [<formals_1> <code_1>] | ||||
|   ... | ||||
|   [<formals_n> <code_n>]) | ||||
| 
 | ||||
| First, generate labels for every clause as well as a label for top | ||||
| 
 | ||||
| (case-lambda <label> | ||||
|   [<formals_0> <label_0> <code0_>] | ||||
|   [<formals_1> <label_1> <code1_>] | ||||
|   ... | ||||
|   [<formals_n> <label_n> <coden_>]) | ||||
| 
 | ||||
| Now everywhere there is a call to a closure bound variable: | ||||
|   (funcall x args ...) | ||||
| We match on the labels of x: | ||||
|   * If a matching label is found, we transform the call to | ||||
|     (dircall <label_i> x args ...) | ||||
|   * If no matching label is found, we transform the call to | ||||
|     (dircall <label> x args ...) | ||||
| If we match on a case with ". rest" formals, we emit a call | ||||
| to "list" on the rest arguments because the label will be | ||||
| inside the code (after the rest-args are constructed). | ||||
| 
 | ||||
| 
 | ||||
| Step2: Eliminate passing arg-counts: | ||||
| 
 | ||||
| All direct calls to inner labels do not require passing an argument | ||||
| count since it will not be used by the procedure. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| Step3:  Eliminate useless case-lambda cases. (not important) | ||||
| 
 | ||||
| For every label generated, determine whether it is actually used or | ||||
| not.   | ||||
| 
 | ||||
| We assume the main label unused until we find: | ||||
|   * A reference to it in a closure that's not a dircall operator. | ||||
|   * A reference to it as the target label to a dircall. | ||||
| 
 | ||||
| We assume an inner label unused until we find: | ||||
|   * A direct call to it. | ||||
|   * The main label used. | ||||
| 
 | ||||
| If a case-lambda has unused clauses, they can be eliminated. | ||||
| 
 | ||||
| If a case-lambda has an unused main label, the dispatch can be | ||||
| eliminated. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/ikarus.boot
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/ikarus.boot
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -221,8 +221,8 @@ | |||
| (define-record eval-cp (check body)) | ||||
| (define-record return (value)) | ||||
| (define-record call-cp | ||||
|   (call-convention rp-convention base-idx arg-count live-mask)) | ||||
| (define-record tailcall-cp (convention arg-count)) | ||||
|   (call-convention label rp-convention base-idx arg-count live-mask)) | ||||
| (define-record tailcall-cp (convention label arg-count)) | ||||
| (define-record primcall (op arg*)) | ||||
| (define-record primref (name)) | ||||
| (define-record conditional (test conseq altern)) | ||||
|  | @ -236,6 +236,7 @@ | |||
| (define-record clambda (label cases free)) | ||||
| (define-record closure (code free*)) | ||||
| (define-record funcall (op rand*)) | ||||
| (define-record jmpcall (label op rand*)) | ||||
| (define-record appcall (op rand*)) | ||||
| (define-record forcall (op rand*)) | ||||
| (define-record codes (list body)) | ||||
|  | @ -448,6 +449,8 @@ | |||
|        `(codes ,(map E list) | ||||
|           ,(E body))] | ||||
|       [(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))] | ||||
|       [(jmpcall label rator rand*) | ||||
|        `(jmpcall ,label ,(E rator) . ,(map E rand*))] | ||||
|       [(appcall rator rand*) `(appcall ,(E rator) . ,(map E rand*))] | ||||
|       [(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))] | ||||
|       [(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))] | ||||
|  | @ -464,8 +467,9 @@ | |||
|        `(save-cp ,(E expr))] | ||||
|       [(eval-cp check body) | ||||
|        `(eval-cp ,check ,(E body))] | ||||
|       [(call-cp call-convention rp-convention base-idx arg-count live-mask) | ||||
|       [(call-cp call-convention label rp-convention base-idx arg-count live-mask) | ||||
|        `(call-cp [conv: ,call-convention] | ||||
|                  [label: ,label] | ||||
|                  [rpconv: ,rp-convention] | ||||
|                  [base-idx: ,base-idx] | ||||
|                  [arg-count: ,arg-count] | ||||
|  | @ -1088,6 +1092,90 @@ | |||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (Expr x)) | ||||
| 
 | ||||
| (define (optimize-for-direct-jumps x) | ||||
|   (define who 'optimize-for-direct-jumps) | ||||
|   (define (init-var x) | ||||
|     (set-var-referenced! x #f)) | ||||
|   (define (set-var x v) | ||||
|     (record-case v | ||||
|       [(clambda) (set-var-referenced! x v)] | ||||
|       [(var)  | ||||
|        (cond | ||||
|          [(bound-var v) => (lambda (v) (set-var-referenced! x v))] | ||||
|          [else (void)])] | ||||
|       [else (void)])) | ||||
|   (define (bound-var x) | ||||
|     (var-referenced x)) | ||||
|   (define (optimize c rator rand*) | ||||
|     (let ([n (length rand*)]) | ||||
|       (record-case c | ||||
|         [(clambda main-label cls*) | ||||
|          (let f ([cls* cls*]) | ||||
|            (cond | ||||
|              [(null? cls*)  | ||||
|               ;;; none matching? | ||||
|               (make-funcall rator rand*)] | ||||
|              [else | ||||
|               (record-case (clambda-case-info (car cls*)) | ||||
|                 [(case-info label fml* proper) | ||||
|                  (cond | ||||
|                    [proper | ||||
|                     (if (fx= n (length fml*)) | ||||
|                         (make-jmpcall label rator rand*) | ||||
|                         (f (cdr cls*)))] | ||||
|                    [else | ||||
|                     (if (fx<= (length (cdr fml*)) n) | ||||
|                         (make-jmpcall label rator | ||||
|                            (let f ([fml* (cdr fml*)] [rand* rand*]) | ||||
|                              (cond | ||||
|                                [(null? fml*)  | ||||
|                                 (list (make-primcall 'list rand*))] | ||||
|                                [else | ||||
|                                 (cons (car rand*) | ||||
|                                       (f (cdr fml*) (cdr rand*)))]))) | ||||
|                         (f (cdr cls*)))])])]))]))) | ||||
|   (define (Expr x) | ||||
|     (record-case x | ||||
|       [(constant) x] | ||||
|       [(var)      x] | ||||
|       [(primref)  x] | ||||
|       [(bind lhs* rhs* body) | ||||
|        (for-each init-var lhs*) | ||||
|        (let ([rhs* (map Expr rhs*)]) | ||||
|          (for-each set-var lhs* rhs*) | ||||
|          (make-bind lhs* rhs* (Expr body)))] | ||||
|       [(fix lhs* rhs* body) | ||||
|        (for-each set-var lhs* rhs*) | ||||
|        (make-fix lhs* (map Expr rhs*) (Expr body))] | ||||
|       [(conditional test conseq altern) | ||||
|        (make-conditional (Expr test) (Expr conseq) (Expr altern))] | ||||
|       [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] | ||||
|       [(clambda g cls*)  | ||||
|        (make-clambda g | ||||
|          (map (lambda (cls) | ||||
|                 (record-case cls | ||||
|                   [(clambda-case info body) | ||||
|                    (for-each init-var (case-info-args info)) | ||||
|                    (make-clambda-case info (Expr body))])) | ||||
|               cls*) | ||||
|          #f)] | ||||
|       [(primcall op rand*) | ||||
|        (make-primcall op (map Expr rand*))] | ||||
|       [(forcall op rand*) | ||||
|        (make-forcall op (map Expr rand*))] | ||||
|       [(funcall rator rand*) | ||||
|        (let ([rator (Expr rator)]) | ||||
|          (cond | ||||
|            [(and (var? rator) (bound-var rator)) => | ||||
|             (lambda (c) | ||||
|               (optimize c rator (map Expr rand*)))] | ||||
|            [else | ||||
|             (make-funcall rator (map Expr rand*))]))] | ||||
|       [(appcall rator rand*) | ||||
|        (make-appcall (Expr rator) (map Expr rand*))] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (Expr x)) | ||||
| 
 | ||||
| (define (convert-closures prog) | ||||
|   (define who 'convert-closures) | ||||
|   (define (Expr* x*) | ||||
|  | @ -1160,6 +1248,11 @@ | |||
|                     [(rand* rand*-free) (Expr* rand*)]) | ||||
|          (values (make-funcall rator rand*)  | ||||
|                  (union rat-free rand*-free)))] | ||||
|       [(jmpcall label rator rand*) | ||||
|        (let-values ([(rator rat-free) (Expr rator)] | ||||
|                     [(rand* rand*-free) (Expr* rand*)]) | ||||
|          (values (make-jmpcall label rator rand*)  | ||||
|                  (union rat-free rand*-free)))]  | ||||
|       [(appcall rator rand*) | ||||
|        (let-values ([(rator rat-free) (Expr rator)] | ||||
|                     [(rand* rand*-free) (Expr* rand*)]) | ||||
|  | @ -1301,6 +1394,7 @@ | |||
|       [(primcall op rand*)   (make-primcall op (map E rand*))] | ||||
|       [(forcall op rand*)    (make-forcall op (map E rand*))] | ||||
|       [(funcall rator rand*) (make-funcall (E rator) (map E rand*))] | ||||
|       [(jmpcall label rator rand*) (make-jmpcall label (E rator) (map E rand*))] | ||||
|       [(appcall rator rand*) (make-appcall (E rator) (map E rand*))] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (let ([x (E x)]) | ||||
|  | @ -1503,6 +1597,8 @@ | |||
|           (when (primref? rator) | ||||
|             (mark-uninlined (primref-name rator))) | ||||
|           (make-funcall (Expr rator) (map Expr rand*))])] | ||||
|       [(jmpcall label op arg*) | ||||
|        (make-jmpcall label (Expr op) (map Expr arg*))] | ||||
|       [(appcall op arg*) | ||||
|        (make-appcall (Expr op) (map Expr arg*))] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|  | @ -1537,6 +1633,8 @@ | |||
|           (Tail (make-primcall (primref-name rator) rand*))] | ||||
|          [else | ||||
|           (make-funcall (Expr rator) (map Expr rand*))])] | ||||
|       [(jmpcall label op arg*) | ||||
|        (make-jmpcall label (Expr op) (map Expr arg*))] | ||||
|       [(appcall op arg*) | ||||
|        (make-appcall (Expr op) (map Expr arg*))] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|  | @ -1605,6 +1703,8 @@ | |||
|        (make-funcall (Expr rator) (map Expr rand*))] | ||||
|       [(appcall op arg*) | ||||
|        (make-appcall (Expr op) (map Expr arg*))] | ||||
|       [(jmpcall label op arg*) | ||||
|        (make-jmpcall label (Expr op) (map Expr arg*))] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (define (Tail x) | ||||
|     (record-case x | ||||
|  | @ -1620,6 +1720,8 @@ | |||
|        (make-funcall (Expr rator) (map Expr rand*))] | ||||
|       [(appcall op arg*) | ||||
|        (make-appcall (Expr op) (map Expr arg*))] | ||||
|       [(jmpcall label op arg*) | ||||
|        (make-jmpcall label (Expr op) (map Expr arg*))] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (define (CaseExpr x) | ||||
|     (record-case x  | ||||
|  | @ -1660,6 +1762,7 @@ | |||
|       [(forcall op arg*)  (ormap Expr arg*)] | ||||
|       [(funcall rator arg*) #t]  | ||||
|       [(appcall rator arg*)    #t] | ||||
|       [(jmpcall label rator arg*)    #t] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (define (Tail x) | ||||
|     (record-case x | ||||
|  | @ -1672,6 +1775,7 @@ | |||
|       [(seq e0 e1) (or (Expr e0) (Tail e1))] | ||||
|       [(funcall rator arg*) (or (Expr rator) (ormap Expr arg*))]  | ||||
|       [(appcall rator arg*) (or (Expr rator) (ormap Expr arg*))] | ||||
|       [(jmpcall label rator arg*) (or (Expr rator) (ormap Expr arg*))] | ||||
|       [else (error who "invalid tail expression ~s" (unparse x))])) | ||||
|   (define (CaseExpr x) | ||||
|     (record-case x  | ||||
|  | @ -1801,6 +1905,8 @@ | |||
|        (make-funcall (Expr rator) (map Expr rand*))] | ||||
|       [(appcall op arg*) | ||||
|        (make-appcall (Expr op) (map Expr arg*))] | ||||
|       [(jmpcall label op arg*) | ||||
|        (make-jmpcall label (Expr op) (map Expr arg*))] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (define (Tail x) | ||||
|     (record-case x | ||||
|  | @ -1818,6 +1924,8 @@ | |||
|       [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] | ||||
|       [(funcall rator rand*) | ||||
|        (make-funcall (Expr rator) (map Expr rand*))] | ||||
|       [(jmpcall label op arg*) | ||||
|        (make-jmpcall label (Expr op) (map Expr arg*))] | ||||
|       [(appcall op arg*) | ||||
|        (make-appcall (Expr op) (map Expr arg*))] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|  | @ -1860,7 +1968,7 @@ | |||
|       [(primref? x) #f]  ;;;; PRIMREF CHECK | ||||
|       [(closure? x) #f] | ||||
|       [else         #t])) | ||||
|   (define (do-new-frame op rand* si r call-convention rp-convention orig-live) | ||||
|   (define (do-new-frame label op rand* si r call-convention rp-convention orig-live) | ||||
|     (make-new-frame (fxadd1 si) (fx+ (length rand*) 2) | ||||
|       (let f ([r* rand*] [nsi (fx+ si 2)] [live orig-live]) | ||||
|         (cond | ||||
|  | @ -1869,12 +1977,12 @@ | |||
|              (make-seq  | ||||
|                (make-save-cp (make-frame-var si)) | ||||
|                (case call-convention | ||||
|                  [(normal apply) | ||||
|                  [(normal apply direct) | ||||
|                   (make-eval-cp (check? op) (Expr op nsi r (cons si live)))] | ||||
|                  [(foreign) | ||||
|                   (make-eval-cp #f (make-foreign-label op))] | ||||
|                  [else (error who "invalid convention ~s" call-convention)])) | ||||
|              (make-call-cp call-convention  | ||||
|              (make-call-cp call-convention label | ||||
|                 rp-convention | ||||
|                 (fxadd1 si)    ; frame size | ||||
|                 (length rand*) ; argc | ||||
|  | @ -1914,7 +2022,7 @@ | |||
|            (f (cdr l*) (cons v nlhs*) (fxadd1 si)  | ||||
|               (cons (cons (car l*) v) r) | ||||
|               (cons si live)))]))) | ||||
|   (define (do-tail-frame op rand* si r call-conv live) | ||||
|   (define (do-tail-frame label op rand* si r call-conv live) | ||||
|     (define (const? x) | ||||
|       (record-case x | ||||
|         [(constant) #t] | ||||
|  | @ -1955,7 +2063,7 @@ | |||
|                     (make-assign (make-frame-var i) vsi))))]))])) | ||||
|     (make-seq | ||||
|       (evalrand* rand* 1 si r live (make-primcall 'void '())) | ||||
|       (make-tailcall-cp call-conv (length rand*)))) | ||||
|       (make-tailcall-cp call-conv label (length rand*)))) | ||||
|   (define (Tail x si r live) | ||||
|     (record-case x | ||||
|       [(return v) (make-return (Expr v si r live))] | ||||
|  | @ -1975,13 +2083,11 @@ | |||
|            (map (lambda (x) (Expr x si r live)) arg*)))] | ||||
|                                    | ||||
|       [(funcall op rand*) | ||||
|        (do-tail-frame op rand* si r 'normal live)] | ||||
|        (do-tail-frame #f op rand* si r 'normal live)] | ||||
|       [(appcall op rand*) | ||||
|        (do-tail-frame op rand* si r 'apply live)] | ||||
| ;;;      [(funcall op rand*) | ||||
| ;;;       (do-new-frame op rand* si r 'normal 'tail live)] | ||||
| ;;;      [(appcall op rand*) | ||||
| ;;;       (do-new-frame op rand* si r 'apply 'tail live)] | ||||
|        (do-tail-frame #f op rand* si r 'apply live)] | ||||
|       [(jmpcall label op rand*) | ||||
|        (do-tail-frame label op rand* si r 'direct live)] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (define (Effect x si r live) | ||||
|     (record-case x | ||||
|  | @ -2003,11 +2109,13 @@ | |||
|        (make-primcall op  | ||||
|          (map (lambda (x) (Expr x si r live)) arg*))] | ||||
|       [(forcall op rand*) | ||||
|        (do-new-frame op rand* si r 'foreign 'effect live)] | ||||
|        (do-new-frame #f op rand* si r 'foreign 'effect live)] | ||||
|       [(funcall op rand*) | ||||
|        (do-new-frame op rand* si r 'normal 'effect live)] | ||||
|        (do-new-frame #f op rand* si r 'normal 'effect live)] | ||||
|       [(jmpcall label op rand*) | ||||
|        (do-new-frame label op rand* si r 'direct 'effect live)] | ||||
|       [(appcall op rand*) | ||||
|        (do-new-frame op rand* si r 'apply 'effect live)] | ||||
|        (do-new-frame #f op rand* si r 'apply 'effect live)] | ||||
|       [else (error who "invalid effect expression ~s" (unparse x))])) | ||||
|   (define (Expr x si r live) | ||||
|     (record-case x | ||||
|  | @ -2033,11 +2141,13 @@ | |||
|        (make-primcall op  | ||||
|          (map (lambda (x) (Expr x si r live)) arg*))] | ||||
|       [(forcall op rand*) | ||||
|        (do-new-frame op rand* si r 'foreign 'value live)] | ||||
|        (do-new-frame #f op rand* si r 'foreign 'value live)] | ||||
|       [(funcall op rand*) | ||||
|        (do-new-frame op rand* si r 'normal 'value live)] | ||||
|        (do-new-frame #f op rand* si r 'normal 'value live)] | ||||
|       [(jmpcall label op rand*) | ||||
|        (do-new-frame label op rand* si r 'direct 'value live)] | ||||
|       [(appcall op rand*) | ||||
|        (do-new-frame op rand* si r 'apply 'value live)] | ||||
|        (do-new-frame #f op rand* si r 'apply 'value live)] | ||||
|       [else (error who "invalid expression ~s" (unparse x))])) | ||||
|   (define (bind-fml* fml* r) | ||||
|     (let f ([si 1] [fml* fml*]) | ||||
|  | @ -3509,7 +3619,7 @@ | |||
|        (do-value-prim op rand* ac)] | ||||
|       [(new-frame base-idx size body) | ||||
|        (NonTail body ac)] | ||||
|       [(call-cp call-convention rp-convention offset size mask) | ||||
|       [(call-cp call-convention direct-label rp-convention offset size mask) | ||||
|        (let ([L_CALL (unique-label)]) | ||||
|          (case call-convention | ||||
|            [(normal) | ||||
|  | @ -3528,6 +3638,20 @@ | |||
|                    (movl (mem 0 fpr) cpr) | ||||
|                    (subl (int (frame-adjustment offset)) fpr) | ||||
|                    ac)] | ||||
|            [(direct) | ||||
|             (list* (addl (int (frame-adjustment offset)) fpr) | ||||
|                    ;(movl (int (argc-convention size)) eax) | ||||
|                    (jmp L_CALL) | ||||
|                    ; NEW FRAME | ||||
|                    `(byte-vector ,mask) | ||||
|                    `(int ,(fx* offset wordsize)) | ||||
|                    `(current-frame-offset) | ||||
|                    (rp-label rp-convention) | ||||
|                    L_CALL | ||||
|                    (call (label direct-label)) | ||||
|                    (movl (mem 0 fpr) cpr) | ||||
|                    (subl (int (frame-adjustment offset)) fpr) | ||||
|                    ac)]  | ||||
|            [(foreign)  | ||||
|             (list* (addl (int (frame-adjustment offset)) fpr) | ||||
|                    (movl (int (argc-convention size)) eax) | ||||
|  | @ -3669,15 +3793,23 @@ | |||
|       (do-fix lhs* rhs* (Tail body ac))] | ||||
|      [(new-frame idx size body) | ||||
|       (Tail body ac)] | ||||
|      [(tailcall-cp call-convention argc) | ||||
|       (list*  | ||||
|         (movl (int (argc-convention argc)) eax) | ||||
|         (case call-convention | ||||
|           [(normal) (tail-indirect-cpr-call)] | ||||
|           [(apply)  (jmp (label SL_apply))] | ||||
|           [else  | ||||
|            (error who "invalid tail-call convention ~s" call-convention)]) | ||||
|         ac)] | ||||
|      [(tailcall-cp call-convention direct-label argc) | ||||
|       (case call-convention | ||||
|         [(normal)  | ||||
|          (list* | ||||
|            (movl (int (argc-convention argc)) eax) | ||||
|            (tail-indirect-cpr-call) | ||||
|            ac)] | ||||
|         [(apply)   | ||||
|          (list* | ||||
|            (movl (int (argc-convention argc)) eax) | ||||
|            (jmp (label SL_apply)) | ||||
|            ac)] | ||||
|         [(direct)  | ||||
|          (list* (jmp (label direct-label)) ac)] | ||||
|         [else  | ||||
|          (error who "invalid tail-call convention ~s" | ||||
|                 call-convention)])] | ||||
|       [else (error 'Tail "invalid expression ~s" x)])) | ||||
|   (define (handle-vararg fml-count ac) | ||||
|     (define CONTINUE_LABEL (unique-label)) | ||||
|  | @ -4028,6 +4160,7 @@ | |||
|          [p (uncover-assigned/referenced p)] | ||||
|          [p (copy-propagate p)] | ||||
|          [p (rewrite-assignments p)] | ||||
|          [p (optimize-for-direct-jumps p)] | ||||
|          [p (convert-closures p)] | ||||
|          [p (optimize-closures/lift-codes p)] | ||||
|          [p (introduce-primcalls p)] | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Abdulaziz Ghuloum
						Abdulaziz Ghuloum