From 3f718330636cc3d8b05670ea29253c3c70d1b297 Mon Sep 17 00:00:00 2001 From: Stas Boukarev Date: Sat, 20 Feb 2016 23:16:43 +0300 Subject: [PATCH] Micro-optimize verify-arg-count on x86oids and ARM64. When MIN is 1 it only needs to be checked for zero, using TEST instead of CMP on x86 saves one byte. Using CBZ on ARM64 saves one instruction. --- src/compiler/arm64/call.lisp | 27 ++++++++++++++------------- src/compiler/x86-64/call.lisp | 35 ++++++++++++++++++++--------------- src/compiler/x86/call.lisp | 34 +++++++++++++++++++--------------- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/compiler/arm64/call.lisp b/src/compiler/arm64/call.lisp index d69b3f0b4..b1d6148eb 100644 --- a/src/compiler/arm64/call.lisp +++ b/src/compiler/arm64/call.lisp @@ -541,24 +541,25 @@ (:generator 3 (let ((err-lab (generate-error-code vop 'invalid-arg-count-error))) - (flet ((load-immediate (x) - (add-sub-immediate (fixnumize x)))) + (labels ((load-immediate (x) + (add-sub-immediate (fixnumize x))) + (check-min () + (cond ((= min 1) + (inst cbz nargs err-lab)) + ((plusp min) + (inst cmp nargs (load-immediate min)) + (inst b :lo err-lab))))) (cond ((eql max 0) (inst cbnz nargs err-lab)) ((not min) (inst cmp nargs (load-immediate max)) (inst b :ne err-lab)) - (max - (when (plusp min) - (inst cmp nargs (load-immediate min)) - (inst b :lo err-lab)) - (inst cmp nargs (load-immediate max)) - (inst b :hi err-lab)) - ((eql min 1) - (inst cbz nargs err-lab)) - ((plusp min) - (inst cmp nargs (load-immediate min)) - (inst b :lo err-lab))))))) + (max + (check-min) + (inst cmp nargs (load-immediate max)) + (inst b :hi err-lab)) + (t + (check-min))))))) ;;;; Local call with unknown values convention return: diff --git a/src/compiler/x86-64/call.lisp b/src/compiler/x86-64/call.lisp index 30b2dab3f..60f4b6946 100644 --- a/src/compiler/x86-64/call.lisp +++ b/src/compiler/x86-64/call.lisp @@ -1311,21 +1311,26 @@ (:vop-var vop) (:save-p :compute-only) (:generator 3 - (let ((err-lab (generate-error-code vop 'invalid-arg-count-error))) - (cond ((not min) - (if (zerop max) - (inst test nargs nargs) - (inst cmp nargs (fixnumize max))) - (inst jmp :ne err-lab)) - (max - (when (plusp min) - (inst cmp nargs (fixnumize min)) - (inst jmp :b err-lab)) - (inst cmp nargs (fixnumize max)) - (inst jmp :a err-lab)) - ((plusp min) - (inst cmp nargs (fixnumize min)) - (inst jmp :b err-lab)))))) + (let ((err-lab + (generate-error-code vop 'invalid-arg-count-error nargs))) + (flet ((check-min () + (cond ((= min 1) + (inst test nargs nargs) + (inst jmp :e err-lab)) + ((plusp min) + (inst cmp nargs (fixnumize min)) + (inst jmp :b err-lab))))) + (cond ((not min) + (if (zerop max) + (inst test nargs nargs) + (inst cmp nargs (fixnumize max))) + (inst jmp :ne err-lab)) + (max + (check-min) + (inst cmp nargs (fixnumize max)) + (inst jmp :a err-lab)) + (t + (check-min))))))) ;; Signal an error about an untagged number. ;; These are pretty much boilerplate and could be generic except: diff --git a/src/compiler/x86/call.lisp b/src/compiler/x86/call.lisp index e3d396eb4..bc341bf9a 100644 --- a/src/compiler/x86/call.lisp +++ b/src/compiler/x86/call.lisp @@ -1394,21 +1394,25 @@ (:save-p :compute-only) (:generator 3 (let ((err-lab - (generate-error-code vop 'invalid-arg-count-error nargs))) - (cond ((not min) - (if (zerop max) - (inst test nargs nargs) - (inst cmp nargs (fixnumize max))) - (inst jmp :ne err-lab)) - (max - (when (plusp min) - (inst cmp nargs (fixnumize min)) - (inst jmp :b err-lab)) - (inst cmp nargs (fixnumize max)) - (inst jmp :a err-lab)) - ((plusp min) - (inst cmp nargs (fixnumize min)) - (inst jmp :b err-lab)))))) + (generate-error-code vop 'invalid-arg-count-error nargs))) + (flet ((check-min () + (cond ((= min 1) + (inst test nargs nargs) + (inst jmp :e err-lab)) + ((plusp min) + (inst cmp nargs (fixnumize min)) + (inst jmp :b err-lab))))) + (cond ((not min) + (if (zerop max) + (inst test nargs nargs) + (inst cmp nargs (fixnumize max))) + (inst jmp :ne err-lab)) + (max + (check-min) + (inst cmp nargs (fixnumize max)) + (inst jmp :a err-lab)) + (t + (check-min))))))) ;;; Single-stepping (defun emit-single-step-test () -- 2.11.4.GIT