Native Compilation in Emacs

by HP on at DFNconf
This meeting will be online. Please join us with the following link: https://conf.dfn.de/webapp/conference/979117107
tl;dr: How, and why the Emacs OS finally grew a native code compiler
Slides (auto generated)

Abstract

The next version of Emacs will include an optimizing compiler from Elisp to native code, thanks to the work by Andrea Corallo et.al. This will facilitate performance increases between 2.3x and 42x¹ and a generally smoother editing experience².

In this talk, I will discuss the design and implementation of this new feature and demonstrate some of its implications for day-to-day use.

Introduction

Current State of the Gnunion

Motivation for Performance Improvements

Now: Native Code 🎉

Demo

Interpreter

(defun silly-loop1 (n)
  "Return the time, in seconds, to run N iterations of a loop."
  (let ((t1 (float-time)))
    (while (> (setq n (1- n)) 0))
    (- (float-time) t1)))
(silly-loop1 50000000)

Byte Code

(defun silly-loop2 (n)
  "Return the time, in seconds, to run N iterations of a loop."
  (let ((t1 (float-time)))
    (while (> (setq n (1- n)) 0))
    (- (float-time) t1)))
(byte-compile 'silly-loop2)
(silly-loop2 50000000)
(with-temp-buffer
  (disassemble 'silly-loop2 (current-buffer))
  (buffer-string))

Native Code

(defun silly-loop3 (n)
  "Return the time, in seconds, to run N iterations of a loop."
  (let ((t1 (float-time)))
    (while (> (setq n (1- n)) 0))
    (- (float-time) t1)))
(native-compile 'silly-loop3)
(silly-loop3 50000000)
(with-temp-buffer
  (disassemble 'silly-loop3 (current-buffer))
  (buffer-string))

Implementation Details

LAP Generation

(defun simple1 (n)
  (+ n 1))
(with-temp-buffer
  (disassemble 'simple1 (current-buffer))
  (buffer-string))

LAP to LIMPLE

LIMPLE

Motivation:

(defun simple2 (n)
  (+ n 1))
(let ((native-comp-verbose 2))
  (native-compile 'simple2))

LIMPLE -> SSA

Data flow analysis

Propagation of

Call Optimization

Dead Code Elimination

Tail Recursion Elimination

Code Layout

(defun simple2 (n)
  (+ n 1))
(native-compile 'simple2)
(with-temp-buffer
  (disassemble 'simple2 (current-buffer))
  (buffer-string))

Usage

Sources