aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2023-01-18 18:36:29 +0100
committerMattias EngdegÄrd2023-02-02 14:46:53 +0100
commitbfd338aad9d1e6bf898fc19d23e1a5ca4e696316 (patch)
tree47d30f360c777d747574e48b888ec417a912576a
parentf6955482c2933706229044c04d88b807b63a7095 (diff)
downloademacs-bfd338aad9d1e6bf898fc19d23e1a5ca4e696316.tar.gz
emacs-bfd338aad9d1e6bf898fc19d23e1a5ca4e696316.zip
LAP peephole optimisation improvements
- Since discardN-preserve-tos(1) and stack-set(1) have the same effect, treat them as equivalent in all transformations. - Move the rule discardN-preserve-tos(X) discardN-preserve-tos(Y) --> discardN-preserve-tos(X+Y) from the final pass to the main iteration since it may enable further optimisations. - Don't apply the rule goto(X) ... X: DISCARD --> DISCARD goto(Y) ... X: DISCARD Y: when DISCARD could be merged or deleted instead, which is even better. - Add the rule OP const return -> <deleted> const return where OP is effect-free. - Generalise the push-pop annihilation rule to PUSH(K) discard(N) -> discard(N-K), N>K PUSH(K) discard(N) -> <deleted>, N=K to any N, not just N=1. - Add the rule OP goto(X) Y: OP X: -> <deleted> Y: OP X: for any operation OP. * lisp/emacs-lisp/byte-opt.el (byte-optimize-lapcode): Make the changes described above.
-rw-r--r--lisp/emacs-lisp/byte-opt.el128
1 files changed, 90 insertions, 38 deletions
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 9eb48f5fe0b..861cf95b1ff 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -2042,31 +2042,29 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2042 ;; optimized but sequences like "dup varset TAG1: discard" are not. 2042 ;; optimized but sequences like "dup varset TAG1: discard" are not.
2043 ;; You may be tempted to change this; resist that temptation. 2043 ;; You may be tempted to change this; resist that temptation.
2044 (cond 2044 (cond
2045 ;; <side-effect-free> pop --> <deleted> 2045 ;;
2046 ;; ...including: 2046 ;; PUSH(K) discard(N) --> <deleted> discard(N-K), N>K
2047 ;; const-X pop --> <deleted> 2047 ;; PUSH(K) discard(N) --> <deleted>, N=K
2048 ;; varref-X pop --> <deleted> 2048 ;; where PUSH(K) is a side-effect-free op such as const, varref, dup
2049 ;; dup pop --> <deleted> 2049 ;;
2050 ;; 2050 ((and (memq (car lap1) '(byte-discard byte-discardN))
2051 ((and (eq 'byte-discard (car lap1))
2052 (memq (car lap0) side-effect-free)) 2051 (memq (car lap0) side-effect-free))
2053 (setq keep-going t) 2052 (setq keep-going t)
2054 (setq tmp (aref byte-stack+-info (symbol-value (car lap0)))) 2053 (let* ((pushes (aref byte-stack+-info (symbol-value (car lap0))))
2055 (setq rest (cdr rest)) 2054 (pops (if (eq (car lap1) 'byte-discardN) (cdr lap1) 1))
2056 (cond ((eql tmp 1) 2055 (net-pops (- pops pushes)))
2057 (byte-compile-log-lap 2056 (cond ((= net-pops 0)
2058 " %s discard\t-->\t<deleted>" lap0) 2057 (byte-compile-log-lap " %s %s\t-->\t<deleted>" lap0 lap1)
2059 (setq lap (delq lap0 (delq lap1 lap)))) 2058 (setcdr rest (cddr rest))
2060 ((eql tmp 0) 2059 (setq lap (delq lap0 lap)))
2061 (byte-compile-log-lap 2060 ((> net-pops 0)
2062 " %s discard\t-->\t<deleted> discard" lap0) 2061 (byte-compile-log-lap
2063 (setq lap (delq lap0 lap))) 2062 " %s %s\t-->\t<deleted> discard(%d)" lap0 lap1 net-pops)
2064 ((eql tmp -1) 2063 (setcar rest (if (eql net-pops 1)
2065 (byte-compile-log-lap 2064 (cons 'byte-discard nil)
2066 " %s discard\t-->\tdiscard discard" lap0) 2065 (cons 'byte-discardN net-pops)))
2067 (setcar lap0 'byte-discard) 2066 (setcdr rest (cddr rest)))
2068 (setcdr lap0 0)) 2067 (t (error "Optimizer error: too much on the stack")))))
2069 (t (error "Optimizer error: too much on the stack"))))
2070 ;; 2068 ;;
2071 ;; goto*-X X: --> X: 2069 ;; goto*-X X: --> X:
2072 ;; 2070 ;;
@@ -2353,6 +2351,40 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2353 (setcar lap0 'byte-return)) 2351 (setcar lap0 'byte-return))
2354 (setcdr lap0 (cdr tmp)) 2352 (setcdr lap0 (cdr tmp))
2355 (setq keep-going t)))) 2353 (setq keep-going t))))
2354
2355 ;;
2356 ;; OP goto(X) Y: OP X: -> Y: OP X:
2357 ;;
2358 ((and (eq (car lap1) 'byte-goto)
2359 (eq (car lap2) 'TAG)
2360 (let ((lap3 (nth 3 rest)))
2361 (and (eq (car lap0) (car lap3))
2362 (eq (cdr lap0) (cdr lap3))
2363 (eq (cdr lap1) (nth 4 rest)))))
2364 (byte-compile-log-lap " %s %s %s %s %s\t-->\t%s %s %s"
2365 lap0 lap1 lap2
2366 (nth 3 rest) (nth 4 rest)
2367 lap2 (nth 3 rest) (nth 4 rest))
2368 (setcdr rest (cddr rest))
2369 (setq lap (delq lap0 lap))
2370 (setq keep-going t))
2371
2372 ;;
2373 ;; OP const return --> const return
2374 ;; where OP is side-effect-free (or mere stack manipulation).
2375 ;;
2376 ((and (eq (car lap1) 'byte-constant)
2377 (eq (car (nth 2 rest)) 'byte-return)
2378 (or (memq (car lap0) '( byte-discard byte-discardN
2379 byte-discardN-preserve-tos
2380 byte-stack-set))
2381 (memq (car lap0) side-effect-free)))
2382 (setq keep-going t)
2383 (setq add-depth 1) ; in case we get rid of too much stack reduction
2384 (setq lap (delq lap0 lap))
2385 (byte-compile-log-lap " %s %s %s\t-->\t%s %s"
2386 lap0 lap1 (nth 2 rest) lap1 (nth 2 rest)))
2387
2356 ;; 2388 ;;
2357 ;; goto-*-else-pop X ... X: goto-if-* --> whatever 2389 ;; goto-*-else-pop X ... X: goto-if-* --> whatever
2358 ;; goto-*-else-pop X ... X: discard --> whatever 2390 ;; goto-*-else-pop X ... X: discard --> whatever
@@ -2491,6 +2523,24 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2491 ) 2523 )
2492 (setq keep-going t)) 2524 (setq keep-going t))
2493 2525
2526 ;;
2527 ;; discardN-preserve-tos(X) discardN-preserve-tos(Y)
2528 ;; --> discardN-preserve-tos(X+Y)
2529 ;; where stack-set(1) is accepted as discardN-preserve-tos(1)
2530 ;;
2531 ((and (or (eq (car lap0) 'byte-discardN-preserve-tos)
2532 (and (eq (car lap0) 'byte-stack-set) (eql (cdr lap0) 1)))
2533 (or (eq (car lap1) 'byte-discardN-preserve-tos)
2534 (and (eq (car lap1) 'byte-stack-set) (eql (cdr lap1) 1))))
2535 (setq keep-going t)
2536 (let ((new-op (cons 'byte-discardN-preserve-tos
2537 ;; This happens to work even when either
2538 ;; op is stack-set(1).
2539 (+ (cdr lap0) (cdr lap1)))))
2540 (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 new-op)
2541 (setcar rest new-op)
2542 (setcdr rest (cddr rest))))
2543
2494 ;; 2544 ;;
2495 ;; stack-set-M [discard/discardN ...] --> discardN-preserve-tos 2545 ;; stack-set-M [discard/discardN ...] --> discardN-preserve-tos
2496 ;; stack-set-M [discard/discardN ...] --> discardN 2546 ;; stack-set-M [discard/discardN ...] --> discardN
@@ -2529,7 +2579,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2529 ;; 2579 ;;
2530 ;; discardN-preserve-tos return --> return 2580 ;; discardN-preserve-tos return --> return
2531 ;; dup return --> return 2581 ;; dup return --> return
2532 ;; stack-set-N return --> return ; where N is TOS-1 2582 ;; stack-set(1) return --> return
2533 ;; 2583 ;;
2534 ((and (eq (car lap1) 'byte-return) 2584 ((and (eq (car lap1) 'byte-return)
2535 (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup)) 2585 (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup))
@@ -2546,8 +2596,15 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2546 ;; 2596 ;;
2547 ((and (eq (car lap0) 'byte-goto) 2597 ((and (eq (car lap0) 'byte-goto)
2548 (setq tmp (cdr (memq (cdr lap0) lap))) 2598 (setq tmp (cdr (memq (cdr lap0) lap)))
2549 (memq (caar tmp) '(byte-discard byte-discardN 2599 (or (memq (caar tmp) '(byte-discard byte-discardN))
2550 byte-discardN-preserve-tos))) 2600 ;; Make sure we don't hoist a discardN-preserve-tos
2601 ;; that really should be merged or deleted instead.
2602 (and (eq (caar tmp) 'byte-discardN-preserve-tos)
2603 (let ((next (cadr tmp)))
2604 (not (or (memq (car next) '(byte-discardN-preserve-tos
2605 byte-return))
2606 (and (eq (car next) 'byte-stack-set)
2607 (eql (cdr next) 1))))))))
2551 (byte-compile-log-lap 2608 (byte-compile-log-lap
2552 " goto-X .. X: \t-->\t%s goto-X.. X: %s Y:" 2609 " goto-X .. X: \t-->\t%s goto-X.. X: %s Y:"
2553 (car tmp) (car tmp)) 2610 (car tmp) (car tmp))
@@ -2562,11 +2619,16 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2562 2619
2563 ;; 2620 ;;
2564 ;; const discardN-preserve-tos ==> discardN const 2621 ;; const discardN-preserve-tos ==> discardN const
2622 ;; const stack-set(1) ==> discard const
2565 ;; 2623 ;;
2566 ((and (eq (car lap0) 'byte-constant) 2624 ((and (eq (car lap0) 'byte-constant)
2567 (eq (car lap1) 'byte-discardN-preserve-tos)) 2625 (or (eq (car lap1) 'byte-discardN-preserve-tos)
2626 (and (eq (car lap1) 'byte-stack-set)
2627 (eql (cdr lap1) 1))))
2568 (setq keep-going t) 2628 (setq keep-going t)
2569 (let ((newdiscard (cons 'byte-discardN (cdr lap1)))) 2629 (let ((newdiscard (if (eql (cdr lap1) 1)
2630 (cons 'byte-discard nil)
2631 (cons 'byte-discardN (cdr lap1)))))
2570 (byte-compile-log-lap 2632 (byte-compile-log-lap
2571 " %s %s\t-->\t%s %s" lap0 lap1 newdiscard lap0) 2633 " %s %s\t-->\t%s %s" lap0 lap1 newdiscard lap0)
2572 (setf (car rest) newdiscard) 2634 (setf (car rest) newdiscard)
@@ -2651,16 +2713,6 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2651 (setcdr lap1 (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0)) 2713 (setcdr lap1 (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0))
2652 (if (eq (car lap1) 'byte-discard) 1 (cdr lap1)))) 2714 (if (eq (car lap1) 'byte-discard) 1 (cdr lap1))))
2653 (setcar lap1 'byte-discardN)) 2715 (setcar lap1 'byte-discardN))
2654
2655 ;;
2656 ;; discardN-preserve-tos-X discardN-preserve-tos-Y -->
2657 ;; discardN-preserve-tos-(X+Y)
2658 ;;
2659 ((and (eq (car lap0) 'byte-discardN-preserve-tos)
2660 (eq (car lap1) 'byte-discardN-preserve-tos))
2661 (setq lap (delq lap0 lap))
2662 (setcdr lap1 (+ (cdr lap0) (cdr lap1)))
2663 (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 (car rest)))
2664 ) 2716 )
2665 (setq rest (cdr rest))) 2717 (setq rest (cdr rest)))
2666 (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth))) 2718 (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth)))