From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.devel Subject: Native compilation - specific optimisation surely possible? Date: Sun, 2 Jan 2022 10:20:02 +0000 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="2543"; mail-complaints-to="usenet@ciao.gmane.io" To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Jan 02 11:21:13 2022 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1n3xzF-0000a8-Nu for ged-emacs-devel@m.gmane-mx.org; Sun, 02 Jan 2022 11:21:13 +0100 Original-Received: from localhost ([::1]:48696 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1n3xzE-00063l-OS for ged-emacs-devel@m.gmane-mx.org; Sun, 02 Jan 2022 05:21:12 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:57804) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1n3xyC-0005Ip-G6 for emacs-devel@gnu.org; Sun, 02 Jan 2022 05:20:10 -0500 Original-Received: from colin.muc.de ([193.149.48.1]:33196 helo=mail.muc.de) by eggs.gnu.org with smtp (Exim 4.90_1) (envelope-from ) id 1n3xyA-0007oR-6H for emacs-devel@gnu.org; Sun, 02 Jan 2022 05:20:08 -0500 Original-Received: (qmail 41014 invoked by uid 3782); 2 Jan 2022 10:20:03 -0000 Original-Received: from acm.muc.de (p4fe15593.dip0.t-ipconnect.de [79.225.85.147]) (using STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP; Sun, 02 Jan 2022 11:20:03 +0100 Original-Received: (qmail 4648 invoked by uid 1000); 2 Jan 2022 10:20:02 -0000 Content-Disposition: inline X-Submission-Agent: TMDA/1.3.x (Ph3nix) X-Primary-Address: acm@muc.de Received-SPF: pass client-ip=193.149.48.1; envelope-from=acm@muc.de; helo=mail.muc.de X-Spam_score_int: 0 X-Spam_score: 0.0 X-Spam_bar: / X-Spam_report: (0.0 / 5.0 requ) SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:283877 Archived-At: Hello, Emacs. The following very short function: ;; -*- lexical-binding: t -*- (defun comp-test-55 (x) (unless (integerp x) x)) byte compiles to: byte code for comp-test-55: doc: ... args: (arg1) 0 dup 1 integerp 2 not 3 goto-if-nil-else-pop 1 6 dup 7:1 return , then on an amd-64 machine, native compiles to (annotation added by me): 00000000000012c0 : Setup of the function: 12c0: 55 push %rbp 12c1: 53 push %rbx 12c2: 48 89 fb mov %rdi,%rbx 12c5: 48 83 ec 08 sub $0x8,%rsp 12c9: 48 8b 05 18 2d 00 00 mov 0x2d18(%rip),%rax # 3fe8 12d0: 48 8b 28 mov (%rax),%rbp fixnump: 12d3: 8d 47 fe lea -0x2(%rdi),%eax 12d6: a8 03 test $0x3,%al 12d8: 75 26 jne 1300 12da: 48 8b 05 ff 2c 00 00 mov 0x2cff(%rip),%rax # 3fe0 12e1: 48 8b 78 10 mov 0x10(%rax),%rdi Nil in %rdi?: 12e5: 31 f6 xor %esi,%esi 12e7: ff 95 c0 27 00 00 call *0x27c0(%rbp) `eq' <======================== 12ed: 48 85 c0 test %rax,%rax 12f0: 48 0f 45 c3 cmovne %rbx,%rax Tear down of the function: 12f4: 48 83 c4 08 add $0x8,%rsp 12f8: 5b pop %rbx 12f9: 5d pop %rbp 12fa: c3 ret 12fb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) bignump: 1300: 8d 47 fb lea -0x5(%rdi),%eax 1303: a8 07 test $0x7,%al 1305: 74 09 je 1310 1307: 31 ff xor %edi,%edi 1309: eb da jmp 12e5 130b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) pseudovectorp: 1310: be 02 00 00 00 mov $0x2,%esi 1315: ff 55 08 call *0x8(%rbp) 1318: 84 c0 test %al,%al 131a: 75 be jne 12da 131c: 31 ff xor %edi,%edi 131e: eb c5 jmp 12e5 .. The input parameter x (or arg1) is passed into the function in the register %rdi. integerp is coded successively as fixnump followed (if necessary) by bignump. The fixnump is coded beautifully in three instructions. I don't understand what's happening at 12da. It seems that the address of a stack pointer is being loaded into %rax, from which the result of `fixnump' (which was already in %rax) is loaded into %rdi. But my main point is the compilation of the `not' instruction at 12e5. The operand to `not' is in %rdi. It is coded up as (eq %rdi nil) by loading 0 (nil) into %rsi at 12e5, then making a function call to `eq' at 12e7. Surely the overhead of the function call for `eq' makes this a candidate for optimisation? `not' could be coded up in two instructions (test %rdi,%rdi followed by a conditional jump or (faster) the cmovne which is %already there). `not' is presumably a common opcode in byte compiled functions. `eq' surely more so. So why are we coding these up as function calls? Andrea? -- Alan Mackenzie (Nuremberg, Germany).