Pelemay 0.0.10 で生成されるアセンブリコード

今日リリースした Pelemay 0.0.10 から分割コンパイルとアセンブリコードの生成をサポートしました。(代わりに Windows を一旦サポート外としています。すみません)

こんな感じのコードに対し，

```elixir:pelemay_test.ex
defmodule PelemayTest do
  require Pelemay
  import Pelemay

  defpelemay do
    def mult_2(list), do: list |> Enum.map(& &1 * 2)
  end
end
```

Pelemayは次のようなCコードを生成します。(`Application.app_dir(:pelemay, "src")`以下，典型的には`_build/dev/lib/pelemay/src` 以下に置かれます)

```c:libnifelixirpelemaytest.c
// This file was generated by Pelemay.Generator.Native
#pragma clang diagnostic ignored "-Wnullability-completeness"
#pragma clang diagnostic ignored "-Wnullability-extension"

#include <stdbool.h>
#include <erl_nif.h>
#include <string.h>
#include "basic.h"


static int load(ErlNifEnv *env, void **priv, ERL_NIF_TERM info);
static void unload(ErlNifEnv *env, void *priv);
static int reload(ErlNifEnv *env, void **priv, ERL_NIF_TERM info);
static int upgrade(ErlNifEnv *env, void **priv, void **old_priv, ERL_NIF_TERM info);

static int
load(ErlNifEnv *env, void **priv, ERL_NIF_TERM info)
{
  atom_struct = enif_make_atom(env, "__struct__");
  atom_range = enif_make_atom(env, "Elixir.Range");
  atom_first = enif_make_atom(env, "first");
  atom_last = enif_make_atom(env, "last");
  return 0;
}

static void
unload(ErlNifEnv *env, void *priv)
{
}

static int
reload(ErlNifEnv *env, void **priv, ERL_NIF_TERM info)
{
  return 0;
}

static int
upgrade(ErlNifEnv *env, void **priv, void **old_priv, ERL_NIF_TERM info)
{
  return load(env, priv, info);
}
static ERL_NIF_TERM
map_elem1_mult_2_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
  if (__builtin_expect((argc != 1), false)) {
    return enif_make_badarg(env);
  }
  ErlNifSInt64 *vec_long;
  size_t vec_l;
  double *vec_double;
  if (__builtin_expect((enif_get_int64_vec_from_list(env, argv[0], &vec_long, &vec_l) == FAIL), false)) {
    if (__builtin_expect((enif_get_double_vec_from_list(env, argv[0], &vec_double, &vec_l) == FAIL), false)) {
      return enif_make_badarg(env);
    }
#pragma clang loop vectorize_width(LOOP_VECTORIZE_WIDTH)
    for(size_t i = 0; i < vec_l; i++) {
      vec_double[i] = ((vec_double[i])*2);
    }
    return enif_make_list_from_double_vec(env, vec_double, vec_l);
  }
#pragma clang loop vectorize_width(LOOP_VECTORIZE_WIDTH)
  for(size_t i = 0; i < vec_l; i++) {
    vec_long[i] = ((vec_long[i])*2);
  }
  return enif_make_list_from_int64_vec(env, vec_long, vec_l);
}
static
ErlNifFunc nif_funcs[] =
{
  // {erl_function_name, erl_function_arity, c_function}
  {"map_elem1_mult_2_nif", 1, map_elem1_mult_2_nif},
  
};
ERL_NIF_INIT(Elixir.PelemayNifElixirPelemayTest, nif_funcs, &load, &reload, &upgrade, &unload)
```

x86_64 向けのアセンブリコードはこんな感じです。(`Application.app_dir(:pelemay, "obj")`以下，典型的には`_build/dev/lib/pelemay/obj` 以下に置かれます)

x86_64のSIMD命令がしっかり生成されています。(`xmm`レジスタを使う命令)

```libnifelixirpelemaytest.s(一部)
	.p2align	4, 0x90         ## -- Begin function map_elem1_mult_2_nif
_map_elem1_mult_2_nif:                  ## @map_elem1_mult_2_nif
Lfunc_begin5:
	.loc	5 44 0                  ## src/libnifelixirpelemaytest.c:44:0
	.cfi_startproc
## %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	pushq	%r14
	pushq	%rbx
	subq	$32, %rsp
	.cfi_offset %rbx, -32
	.cfi_offset %r14, -24
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $rdi
	##DEBUG_VALUE: map_elem1_mult_2_nif:argc <- $esi
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rdx
	movq	%rdi, %r14
	##DEBUG_VALUE: map_elem1_mult_2_nif:argc <- $esi
Ltmp24:
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 45 30 prologue_end    ## src/libnifelixirpelemaytest.c:45:30
	cmpl	$1, %esi
Ltmp25:
	.loc	5 45 7 is_stmt 0        ## src/libnifelixirpelemaytest.c:45:7
	jne	LBB5_22
Ltmp26:
## %bb.1:
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:argc <- $esi
	.loc	5 0 7                   ## src/libnifelixirpelemaytest.c:0:7
	movq	%rdx, %rbx
Ltmp27:
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	.loc	5 51 59 is_stmt 1       ## src/libnifelixirpelemaytest.c:51:59
	movq	(%rdx), %rsi
Ltmp28:
	.loc	5 0 59 is_stmt 0        ## src/libnifelixirpelemaytest.c:0:59
	leaq	-40(%rbp), %rdx
Ltmp29:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	leaq	-24(%rbp), %rcx
Ltmp30:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- [DW_OP_constu 24, DW_OP_minus, DW_OP_deref] $rbp
	.loc	5 51 25                 ## src/libnifelixirpelemaytest.c:51:25
	movq	%r14, %rdi
	callq	_enif_get_int64_vec_from_list
Ltmp31:
	.loc	5 51 87                 ## src/libnifelixirpelemaytest.c:51:87
	testl	%eax, %eax
Ltmp32:
	.loc	5 51 7                  ## src/libnifelixirpelemaytest.c:51:7
	je	LBB5_4
Ltmp33:
## %bb.2:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- [DW_OP_constu 24, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	##DEBUG_VALUE: i <- 0
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- undef
	.loc	5 62 23 is_stmt 1       ## src/libnifelixirpelemaytest.c:62:23
	cmpq	$0, -24(%rbp)
Ltmp34:
	.loc	5 0 0 is_stmt 0         ## src/libnifelixirpelemaytest.c:0:0
	movq	-40(%rbp), %rsi
Ltmp35:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- $rsi
	##DEBUG_VALUE: i <- 0
	.loc	5 62 3                  ## src/libnifelixirpelemaytest.c:62:3
	je	LBB5_3
Ltmp36:
## %bb.17:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 0 3                   ## src/libnifelixirpelemaytest.c:0:3
	xorl	%eax, %eax
Ltmp37:
	.p2align	4, 0x90
LBB5_18:                                ## =>This Inner Loop Header: Depth=1
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	##DEBUG_VALUE: i <- $rax
	.loc	5 63 17 is_stmt 1       ## src/libnifelixirpelemaytest.c:63:17
	shlq	(%rsi,%rax,8)
Ltmp38:
	.loc	5 62 33                 ## src/libnifelixirpelemaytest.c:62:33
	incq	%rax
Ltmp39:
	##DEBUG_VALUE: i <- $rax
	.loc	5 62 25 is_stmt 0       ## src/libnifelixirpelemaytest.c:62:25
	movq	-24(%rbp), %rdx
Ltmp40:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	.loc	5 62 23                 ## src/libnifelixirpelemaytest.c:62:23
	cmpq	%rdx, %rax
Ltmp41:
	.loc	5 62 3                  ## src/libnifelixirpelemaytest.c:62:3
	jb	LBB5_18
	jmp	LBB5_19
Ltmp42:
LBB5_3:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 0 3                   ## src/libnifelixirpelemaytest.c:0:3
	xorl	%edx, %edx
Ltmp43:
LBB5_19:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 65 10 is_stmt 1       ## src/libnifelixirpelemaytest.c:65:10
	movq	%r14, %rdi
	callq	_enif_make_list_from_int64_vec
Ltmp44:
LBB5_21:
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 66 1                  ## src/libnifelixirpelemaytest.c:66:1
	addq	$32, %rsp
	popq	%rbx
	popq	%r14
Ltmp45:
	popq	%rbp
	retq
LBB5_22:
Ltmp46:
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:argc <- $esi
	.loc	5 46 12                 ## src/libnifelixirpelemaytest.c:46:12
	movq	%r14, %rdi
	addq	$32, %rsp
	popq	%rbx
	popq	%r14
Ltmp47:
	popq	%rbp
	jmp	_enif_make_badarg       ## TAILCALL
Ltmp48:
LBB5_4:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- [DW_OP_constu 24, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 52 62                 ## src/libnifelixirpelemaytest.c:52:62
	movq	(%rbx), %rsi
	leaq	-32(%rbp), %rdx
Ltmp49:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- [DW_OP_constu 32, DW_OP_minus, DW_OP_deref] $rbp
	.loc	5 0 62 is_stmt 0        ## src/libnifelixirpelemaytest.c:0:62
	leaq	-24(%rbp), %rcx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- [DW_OP_constu 24, DW_OP_minus, DW_OP_deref] $rbp
	.loc	5 52 27                 ## src/libnifelixirpelemaytest.c:52:27
	movq	%r14, %rdi
	callq	_enif_get_double_vec_from_list
Ltmp50:
	.loc	5 52 92                 ## src/libnifelixirpelemaytest.c:52:92
	testl	%eax, %eax
Ltmp51:
	.loc	5 52 9                  ## src/libnifelixirpelemaytest.c:52:9
	je	LBB5_20
Ltmp52:
## %bb.5:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- [DW_OP_constu 32, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- [DW_OP_constu 24, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	##DEBUG_VALUE: i <- 0
	.loc	5 56 27 is_stmt 1       ## src/libnifelixirpelemaytest.c:56:27
	movq	-24(%rbp), %rdx
Ltmp53:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	.loc	5 0 0 is_stmt 0         ## src/libnifelixirpelemaytest.c:0:0
	movq	-32(%rbp), %rsi
Ltmp54:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	.loc	5 56 25                 ## src/libnifelixirpelemaytest.c:56:25
	testq	%rdx, %rdx
Ltmp55:
	##DEBUG_VALUE: i <- 0
	.loc	5 56 5                  ## src/libnifelixirpelemaytest.c:56:5
	je	LBB5_16
Ltmp56:
## %bb.6:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 57 25 is_stmt 1       ## src/libnifelixirpelemaytest.c:57:25
	cmpq	$7, %rdx
	ja	LBB5_9
Ltmp57:
## %bb.7:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 0 25 is_stmt 0        ## src/libnifelixirpelemaytest.c:0:25
	xorl	%eax, %eax
	jmp	LBB5_8
Ltmp58:
LBB5_9:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 57 25                 ## src/libnifelixirpelemaytest.c:57:25
	movq	%rdx, %rax
	andq	$-8, %rax
	leaq	-8(%rax), %rbx
Ltmp59:
	movq	%rbx, %rcx
	shrq	$3, %rcx
	incq	%rcx
	movl	%ecx, %edi
	andl	$1, %edi
	testq	%rbx, %rbx
	je	LBB5_10
Ltmp60:
## %bb.11:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 0 25                  ## src/libnifelixirpelemaytest.c:0:25
	movl	$1, %ebx
	.loc	5 57 25                 ## src/libnifelixirpelemaytest.c:57:25
	subq	%rcx, %rbx
	leaq	-1(%rdi,%rbx), %rbx
	xorl	%ecx, %ecx
Ltmp61:
LBB5_12:                                ## =>This Inner Loop Header: Depth=1
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	movupd	(%rsi,%rcx,8), %xmm0
	movupd	16(%rsi,%rcx,8), %xmm1
	movupd	32(%rsi,%rcx,8), %xmm2
	movupd	48(%rsi,%rcx,8), %xmm3
	.loc	5 57 39                 ## src/libnifelixirpelemaytest.c:57:39
	addpd	%xmm0, %xmm0
	addpd	%xmm1, %xmm1
	addpd	%xmm2, %xmm2
	addpd	%xmm3, %xmm3
	.loc	5 57 21                 ## src/libnifelixirpelemaytest.c:57:21
	movupd	%xmm1, 16(%rsi,%rcx,8)
	movupd	%xmm0, (%rsi,%rcx,8)
	movupd	%xmm3, 48(%rsi,%rcx,8)
	movupd	%xmm2, 32(%rsi,%rcx,8)
	.loc	5 57 25                 ## src/libnifelixirpelemaytest.c:57:25
	movupd	80(%rsi,%rcx,8), %xmm0
	movupd	64(%rsi,%rcx,8), %xmm1
	movupd	112(%rsi,%rcx,8), %xmm2
	movupd	96(%rsi,%rcx,8), %xmm3
	.loc	5 57 39                 ## src/libnifelixirpelemaytest.c:57:39
	addpd	%xmm1, %xmm1
	addpd	%xmm0, %xmm0
	addpd	%xmm3, %xmm3
	addpd	%xmm2, %xmm2
	.loc	5 57 21                 ## src/libnifelixirpelemaytest.c:57:21
	movupd	%xmm0, 80(%rsi,%rcx,8)
	movupd	%xmm1, 64(%rsi,%rcx,8)
	movupd	%xmm2, 112(%rsi,%rcx,8)
	movupd	%xmm3, 96(%rsi,%rcx,8)
Ltmp62:
	.loc	5 56 35 is_stmt 1       ## src/libnifelixirpelemaytest.c:56:35
	addq	$16, %rcx
	addq	$2, %rbx
	jne	LBB5_12
	jmp	LBB5_13
Ltmp63:
LBB5_10:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 0 35 is_stmt 0        ## src/libnifelixirpelemaytest.c:0:35
	xorl	%ecx, %ecx
Ltmp64:
LBB5_13:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 56 35                 ## src/libnifelixirpelemaytest.c:56:35
	testq	%rdi, %rdi
	je	LBB5_15
Ltmp65:
## %bb.14:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 57 25 is_stmt 1       ## src/libnifelixirpelemaytest.c:57:25
	movupd	(%rsi,%rcx,8), %xmm0
	movupd	16(%rsi,%rcx,8), %xmm1
	movupd	32(%rsi,%rcx,8), %xmm2
	movupd	48(%rsi,%rcx,8), %xmm3
	.loc	5 57 39 is_stmt 0       ## src/libnifelixirpelemaytest.c:57:39
	addpd	%xmm0, %xmm0
	addpd	%xmm1, %xmm1
	addpd	%xmm2, %xmm2
	addpd	%xmm3, %xmm3
	.loc	5 57 21                 ## src/libnifelixirpelemaytest.c:57:21
	movupd	%xmm1, 16(%rsi,%rcx,8)
	movupd	%xmm0, (%rsi,%rcx,8)
	movupd	%xmm3, 48(%rsi,%rcx,8)
	movupd	%xmm2, 32(%rsi,%rcx,8)
Ltmp66:
LBB5_15:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 56 25 is_stmt 1       ## src/libnifelixirpelemaytest.c:56:25
	cmpq	%rax, %rdx
Ltmp67:
	.loc	5 56 5 is_stmt 0        ## src/libnifelixirpelemaytest.c:56:5
	je	LBB5_16
Ltmp68:
LBB5_8:                                 ## =>This Inner Loop Header: Depth=1
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	##DEBUG_VALUE: i <- $rax
	.loc	5 57 25 is_stmt 1       ## src/libnifelixirpelemaytest.c:57:25
	movsd	(%rsi,%rax,8), %xmm0    ## xmm0 = mem[0],zero
	.loc	5 57 39 is_stmt 0       ## src/libnifelixirpelemaytest.c:57:39
	addsd	%xmm0, %xmm0
	.loc	5 57 21                 ## src/libnifelixirpelemaytest.c:57:21
	movsd	%xmm0, (%rsi,%rax,8)
Ltmp69:
	.loc	5 56 35 is_stmt 1       ## src/libnifelixirpelemaytest.c:56:35
	incq	%rax
Ltmp70:
	##DEBUG_VALUE: i <- $rax
	.loc	5 56 25 is_stmt 0       ## src/libnifelixirpelemaytest.c:56:25
	cmpq	%rdx, %rax
Ltmp71:
	.loc	5 56 5                  ## src/libnifelixirpelemaytest.c:56:5
	jb	LBB5_8
Ltmp72:
LBB5_16:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- $rsi
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- $rdx
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 59 12 is_stmt 1       ## src/libnifelixirpelemaytest.c:59:12
	movq	%r14, %rdi
	callq	_enif_make_list_from_double_vec
Ltmp73:
	.loc	5 0 12 is_stmt 0        ## src/libnifelixirpelemaytest.c:0:12
	jmp	LBB5_21
Ltmp74:
LBB5_20:
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_double <- [DW_OP_constu 32, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_l <- [DW_OP_constu 24, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:vec_long <- [DW_OP_constu 40, DW_OP_minus, DW_OP_deref] $rbp
	##DEBUG_VALUE: map_elem1_mult_2_nif:argv <- $rbx
	##DEBUG_VALUE: map_elem1_mult_2_nif:env <- $r14
	.loc	5 53 14 is_stmt 1       ## src/libnifelixirpelemaytest.c:53:14
	movq	%r14, %rdi
	callq	_enif_make_badarg
Ltmp75:
	.loc	5 0 14 is_stmt 0        ## src/libnifelixirpelemaytest.c:0:14
	jmp	LBB5_21
Ltmp76:
Lfunc_end5:
	.cfi_endproc
```

一方，ARM 向けのアセンブリコードはこんな感じです。(`Application.app_dir(:pelemay, "obj")`以下，Nervesで `MIX_TARGET=rpi3`の場合，典型的には`_build/rpi3_dev/lib/pelemay/obj` 以下に置かれます)

ARM の NEON SIMD 命令がしっかり生成されています。(`vld`, `vadd`など，`v`で始まる命令)

```libnifelixirpelemaytest.s(一部)
	.cpu cortex-a8
	.eabi_attribute 28, 1
	.eabi_attribute 23, 1
	.eabi_attribute 24, 1
	.eabi_attribute 25, 1
	.eabi_attribute 26, 2
	.eabi_attribute 30, 2
	.eabi_attribute 34, 1
	.eabi_attribute 18, 4
	.file	"libnifelixirpelemaytest.c"
	.text
.Ltext0:
	.cfi_sections	.debug_frame
	.align	2
	.arch armv7-a
	.arch_extension sec
	.syntax unified
	.arm
	.fpu neon
	.type	unload, %function
unload:
.LVL0:
.LFB27:
	.file 1 "/Users/zacky/pelemay_test/_build/rpi3_dev/lib/pelemay/src/libnifelixirpelemaytest.c"
	.loc 1 28 1 view -0
	.cfi_startproc
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	@ link register save eliminated.
	.loc 1 29 1 view .LVU1
	bx	lr
	.cfi_endproc
.LFE27:
	.size	unload, .-unload
	.align	2
	.syntax unified
	.arm
	.fpu neon
	.type	reload, %function
reload:
.LVL1:
.LFB28:
	.loc 1 33 1 view -0
	.cfi_startproc
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	@ link register save eliminated.
	.loc 1 34 3 view .LVU3
	.loc 1 35 1 is_stmt 0 view .LVU4
	mov	r0, #0
.LVL2:
	.loc 1 35 1 view .LVU5
	bx	lr
	.cfi_endproc
.LFE28:
	.size	reload, .-reload
	.section	.rodata.str1.4,"aMS",%progbits,1
	.align	2
.LC0:
	.ascii	"__struct__\000"
	.align	2
.LC1:
	.ascii	"Elixir.Range\000"
	.align	2
.LC2:
	.ascii	"first\000"
	.align	2
.LC3:
	.ascii	"last\000"
	.text
	.align	2
	.syntax unified
	.arm
	.fpu neon
	.type	load, %function
load:
.LVL3:
.LFB26:
	.loc 1 18 1 is_stmt 1 view -0
	.cfi_startproc
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	.loc 1 19 3 view .LVU7
	.loc 1 19 17 is_stmt 0 view .LVU8
	ldr	r1, .L6
.LVL4:
	.loc 1 18 1 view .LVU9
	push	{r4, r5, r6, lr}
	.cfi_def_cfa_offset 16
	.cfi_offset 4, -16
	.cfi_offset 5, -12
	.cfi_offset 6, -8
	.cfi_offset 14, -4
	.loc 1 19 17 view .LVU10
.LPIC0:
	add	r1, pc, r1
	.loc 1 18 1 view .LVU11
	mov	r5, r0
	.loc 1 19 17 view .LVU12
	bl	enif_make_atom(PLT)
.LVL5:
	.loc 1 18 1 view .LVU13
	ldr	r4, .L6+4
	.loc 1 19 15 view .LVU14
	ldr	r3, .L6+8
	.loc 1 18 1 view .LVU15
.LPIC1:
	add	r4, pc, r4
	.loc 1 20 16 view .LVU16
	ldr	r1, .L6+12
	.loc 1 19 15 view .LVU17
	ldr	r3, [r4, r3]
	.loc 1 20 16 view .LVU18
.LPIC2:
	add	r1, pc, r1
	.loc 1 19 17 view .LVU19
	mov	r2, r0
	.loc 1 20 16 view .LVU20
	mov	r0, r5
	.loc 1 19 15 view .LVU21
	str	r2, [r3]
	.loc 1 20 3 is_stmt 1 view .LVU22
	.loc 1 20 16 is_stmt 0 view .LVU23
	bl	enif_make_atom(PLT)
.LVL6:
	.loc 1 20 14 view .LVU24
	ldr	r3, .L6+16
	.loc 1 21 16 view .LVU25
	ldr	r1, .L6+20
	.loc 1 20 14 view .LVU26
	ldr	r3, [r4, r3]
	.loc 1 21 16 view .LVU27
.LPIC3:
	add	r1, pc, r1
	.loc 1 20 16 view .LVU28
	mov	r2, r0
	.loc 1 21 16 view .LVU29
	mov	r0, r5
	.loc 1 20 14 view .LVU30
	str	r2, [r3]
	.loc 1 21 3 is_stmt 1 view .LVU31
	.loc 1 21 16 is_stmt 0 view .LVU32
	bl	enif_make_atom(PLT)
.LVL7:
	.loc 1 21 14 view .LVU33
	ldr	r3, .L6+24
	.loc 1 22 15 view .LVU34
	ldr	r1, .L6+28
	.loc 1 21 14 view .LVU35
	ldr	r3, [r4, r3]
	.loc 1 22 15 view .LVU36
.LPIC4:
	add	r1, pc, r1
	.loc 1 21 16 view .LVU37
	mov	r2, r0
	.loc 1 22 15 view .LVU38
	mov	r0, r5
	.loc 1 21 14 view .LVU39
	str	r2, [r3]
	.loc 1 22 3 is_stmt 1 view .LVU40
	.loc 1 22 15 is_stmt 0 view .LVU41
	bl	enif_make_atom(PLT)
.LVL8:
	.loc 1 22 13 view .LVU42
	ldr	r3, .L6+32
	ldr	r3, [r4, r3]
	.loc 1 22 15 view .LVU43
	mov	r2, r0
	.loc 1 24 1 view .LVU44
	mov	r0, #0
	.loc 1 22 13 view .LVU45
	str	r2, [r3]
	.loc 1 23 3 is_stmt 1 view .LVU46
	.loc 1 24 1 is_stmt 0 view .LVU47
	pop	{r4, r5, r6, pc}
.L7:
	.align	2
.L6:
	.word	.LC0-(.LPIC0+8)
	.word	_GLOBAL_OFFSET_TABLE_-(.LPIC1+8)
	.word	atom_struct(GOT)
	.word	.LC1-(.LPIC2+8)
	.word	atom_range(GOT)
	.word	.LC2-(.LPIC3+8)
	.word	atom_first(GOT)
	.word	.LC3-(.LPIC4+8)
	.word	atom_last(GOT)
	.cfi_endproc
.LFE26:
	.size	load, .-load
	.align	2
	.syntax unified
	.arm
	.fpu neon
	.type	map_elem1_mult_2_nif, %function
map_elem1_mult_2_nif:
.LVL9:
.LFB30:
	.loc 1 44 1 is_stmt 1 view -0
	.cfi_startproc
	@ args = 0, pretend = 0, frame = 16
	@ frame_needed = 0, uses_anonymous_args = 0
	.loc 1 45 3 view .LVU49
	.loc 1 45 6 is_stmt 0 view .LVU50
	cmp	r1, #1
	.loc 1 44 1 view .LVU51
	push	{r4, r5, r6, lr}
	.cfi_def_cfa_offset 16
	.cfi_offset 4, -16
	.cfi_offset 5, -12
	.cfi_offset 6, -8
	.cfi_offset 14, -4
	sub	sp, sp, #16
	.cfi_def_cfa_offset 32
	.loc 1 45 6 view .LVU52
	bne	.L26
	.loc 1 48 3 is_stmt 1 view .LVU53
	.loc 1 49 3 view .LVU54
	.loc 1 50 3 view .LVU55
	.loc 1 51 3 view .LVU56
	.loc 1 51 25 is_stmt 0 view .LVU57
	add	r5, sp, #8
	mov	r4, r2
	ldr	r1, [r4]
.LVL10:
	.loc 1 51 25 view .LVU58
	add	r2, sp, #4
.LVL11:
	.loc 1 51 25 view .LVU59
	mov	r3, r5
	mov	r6, r0
	bl	enif_get_int64_vec_from_list(PLT)
.LVL12:
	.loc 1 51 6 view .LVU60
	cmp	r0, #0
	beq	.L11
.LVL13:
.LBB2:
	.loc 1 62 21 is_stmt 1 view .LVU61
	ldmib	sp, {r1, r2}
	.loc 1 62 3 is_stmt 0 view .LVU62
	cmp	r2, #0
	beq	.L13
	cmp	r2, #1
	beq	.L22
	lsr	r0, r2, #1
	mov	r3, r1
	add	r0, r1, r0, lsl #4
.LVL14:
.L19:
	.loc 1 63 5 is_stmt 1 discriminator 3 view .LVU63
	.loc 1 63 29 is_stmt 0 discriminator 3 view .LVU64
	vld1.64	{d16-d17}, [r3:64]
	.loc 1 63 17 discriminator 3 view .LVU65
	vadd.i64	q8, q8, q8
	vst1.64	{d16-d17}, [r3:64]!
	.loc 1 62 32 is_stmt 1 discriminator 3 view .LVU66
	.loc 1 62 21 discriminator 3 view .LVU67
	cmp	r0, r3
	bne	.L19
	tst	r2, #1
	bic	r3, r2, #1
	beq	.L13
.L18:
	.loc 1 63 5 view .LVU68
	.loc 1 63 29 is_stmt 0 view .LVU69
	add	r3, r1, r3, lsl #3
	.loc 1 63 33 view .LVU70
	ldrd	r4, [r3]
.LVL15:
	.loc 1 63 33 view .LVU71
	adds	r4, r4, r4
	adc	r5, r5, r5
	.loc 1 63 17 view .LVU72
	strd	r4, [r3]
	.loc 1 62 32 is_stmt 1 view .LVU73
	.loc 1 62 21 view .LVU74
.L13:
	.loc 1 62 21 is_stmt 0 view .LVU75
.LBE2:
	.loc 1 65 3 is_stmt 1 view .LVU76
	.loc 1 65 10 is_stmt 0 view .LVU77
	mov	r0, r6
	bl	enif_make_list_from_int64_vec(PLT)
.LVL16:
.L8:
	.loc 1 66 1 view .LVU78
	add	sp, sp, #16
	.cfi_remember_state
	.cfi_def_cfa_offset 16
	@ sp needed
	pop	{r4, r5, r6, pc}
.LVL17:
.L14:
	.cfi_restore_state
	.loc 1 53 7 is_stmt 1 view .LVU79
	.loc 1 53 14 is_stmt 0 view .LVU80
	mov	r0, r6
.LVL18:
.L26:
	.loc 1 53 14 view .LVU81
	bl	enif_make_badarg(PLT)
.LVL19:
	.loc 1 66 1 view .LVU82
	add	sp, sp, #16
	.cfi_remember_state
	.cfi_def_cfa_offset 16
	@ sp needed
	pop	{r4, r5, r6, pc}
.LVL20:
.L11:
	.cfi_restore_state
	.loc 1 52 5 is_stmt 1 view .LVU83
	.loc 1 52 27 is_stmt 0 view .LVU84
	ldr	r1, [r4]
	add	r2, sp, #12
	mov	r3, r5
	mov	r0, r6
	bl	enif_get_double_vec_from_list(PLT)
.LVL21:
	.loc 1 52 8 view .LVU85
	cmp	r0, #0
	beq	.L14
.LVL22:
.LBB3:
	.loc 1 56 23 is_stmt 1 view .LVU86
	.loc 1 56 25 is_stmt 0 view .LVU87
	ldr	r2, [sp, #8]
	ldr	r1, [sp, #12]
	.loc 1 56 5 view .LVU88
	cmp	r2, #0
	addne	r0, r1, r2, lsl #3
	movne	r3, r1
	beq	.L16
.LVL23:
.L17:
	.loc 1 57 7 is_stmt 1 discriminator 3 view .LVU89
	.loc 1 57 35 is_stmt 0 discriminator 3 view .LVU90
	vldr.64	d16, [r3]
	.loc 1 57 39 discriminator 3 view .LVU91
	vadd.f64	d16, d16, d16
	.loc 1 57 21 discriminator 3 view .LVU92
	vstmia.64	r3!, {d16}
	.loc 1 56 34 is_stmt 1 discriminator 3 view .LVU93
	.loc 1 56 23 discriminator 3 view .LVU94
	.loc 1 56 5 is_stmt 0 discriminator 3 view .LVU95
	cmp	r3, r0
	bne	.L17
.L16:
.LBE3:
	.loc 1 59 5 is_stmt 1 view .LVU96
	.loc 1 59 12 is_stmt 0 view .LVU97
	mov	r0, r6
	bl	enif_make_list_from_double_vec(PLT)
.LVL24:
	b	.L8
.LVL25:
.L22:
.LBB4:
	.loc 1 62 14 view .LVU98
	mov	r3, #0
	b	.L18
.LBE4:
	.cfi_endproc
.LFE30:
	.size	map_elem1_mult_2_nif, .-map_elem1_mult_2_nif
	.align	2
	.syntax unified
	.arm
	.fpu neon
	.type	upgrade, %function
upgrade:
.LVL26:
.LFB29:
	.loc 1 39 1 is_stmt 1 view -0
	.cfi_startproc
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	.loc 1 40 3 view .LVU100
.LBB7:
.LBB8:
	.loc 1 19 17 is_stmt 0 view .LVU101
	ldr	r1, .L29
.LVL27:
	.loc 1 19 17 view .LVU102
.LBE8:
.LBE7:
	.loc 1 39 1 view .LVU103
	push	{r4, r5, r6, lr}
	.cfi_def_cfa_offset 16
	.cfi_offset 4, -16
	.cfi_offset 5, -12
	.cfi_offset 6, -8
	.cfi_offset 14, -4
.LBB14:
.LBB9:
	.loc 1 19 17 view .LVU104
.LPIC5:
	add	r1, pc, r1
.LBE9:
.LBE14:
	.loc 1 39 1 view .LVU105
	mov	r5, r0
.LVL28:
.LBB15:
.LBI7:
	.loc 1 17 1 is_stmt 1 view .LVU106
.LBB10:
	.loc 1 19 3 view .LVU107
	.loc 1 19 17 is_stmt 0 view .LVU108
	bl	enif_make_atom(PLT)
.LVL29:
	.loc 1 19 17 view .LVU109
.LBE10:
.LBE15:
	.loc 1 39 1 view .LVU110
	ldr	r4, .L29+4
.LBB16:
.LBB11:
	.loc 1 19 15 view .LVU111
	ldr	r3, .L29+8
.LBE11:
.LBE16:
	.loc 1 39 1 view .LVU112
.LPIC6:
	add	r4, pc, r4
.LBB17:
.LBB12:
	.loc 1 20 16 view .LVU113
	ldr	r1, .L29+12
	.loc 1 19 15 view .LVU114
	ldr	r3, [r4, r3]
	.loc 1 20 16 view .LVU115
.LPIC7:
	add	r1, pc, r1
	.loc 1 19 17 view .LVU116
	mov	r2, r0
	.loc 1 20 16 view .LVU117
	mov	r0, r5
	.loc 1 19 15 view .LVU118
	str	r2, [r3]
	.loc 1 20 3 is_stmt 1 view .LVU119
	.loc 1 20 16 is_stmt 0 view .LVU120
	bl	enif_make_atom(PLT)
.LVL30:
	.loc 1 20 14 view .LVU121
	ldr	r3, .L29+16
	.loc 1 21 16 view .LVU122
	ldr	r1, .L29+20
	.loc 1 20 14 view .LVU123
	ldr	r3, [r4, r3]
	.loc 1 21 16 view .LVU124
.LPIC8:
	add	r1, pc, r1
	.loc 1 20 16 view .LVU125
	mov	r2, r0
	.loc 1 21 16 view .LVU126
	mov	r0, r5
	.loc 1 20 14 view .LVU127
	str	r2, [r3]
	.loc 1 21 3 is_stmt 1 view .LVU128
	.loc 1 21 16 is_stmt 0 view .LVU129
	bl	enif_make_atom(PLT)
.LVL31:
	.loc 1 21 14 view .LVU130
	ldr	r3, .L29+24
	.loc 1 22 15 view .LVU131
	ldr	r1, .L29+28
	.loc 1 21 14 view .LVU132
	ldr	r3, [r4, r3]
	.loc 1 22 15 view .LVU133
.LPIC9:
	add	r1, pc, r1
	.loc 1 21 16 view .LVU134
	mov	r2, r0
	.loc 1 22 15 view .LVU135
	mov	r0, r5
	.loc 1 21 14 view .LVU136
	str	r2, [r3]
	.loc 1 22 3 is_stmt 1 view .LVU137
	.loc 1 22 15 is_stmt 0 view .LVU138
	bl	enif_make_atom(PLT)
.LVL32:
	.loc 1 22 13 view .LVU139
	ldr	r3, .L29+32
	ldr	r3, [r4, r3]
	.loc 1 22 15 view .LVU140
	mov	r2, r0
.LBE12:
.LBE17:
	.loc 1 41 1 view .LVU141
	mov	r0, #0
.LBB18:
.LBB13:
	.loc 1 22 13 view .LVU142
	str	r2, [r3]
	.loc 1 23 3 is_stmt 1 view .LVU143
.LVL33:
	.loc 1 23 3 is_stmt 0 view .LVU144
.LBE13:
.LBE18:
	.loc 1 41 1 view .LVU145
	pop	{r4, r5, r6, pc}
.L30:
	.align	2
.L29:
	.word	.LC0-(.LPIC5+8)
	.word	_GLOBAL_OFFSET_TABLE_-(.LPIC6+8)
	.word	atom_struct(GOT)
	.word	.LC1-(.LPIC7+8)
	.word	atom_range(GOT)
	.word	.LC2-(.LPIC8+8)
	.word	atom_first(GOT)
	.word	.LC3-(.LPIC9+8)
	.word	atom_last(GOT)
	.cfi_endproc
.LFE29:
	.size	upgrade, .-upgrade
	.align	2
	.global	nif_init
	.syntax unified
	.arm
	.fpu neon
	.type	nif_init, %function
nif_init:
.LFB31:
	.loc 1 74 1 is_stmt 1 view -0
	.cfi_startproc
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	@ link register save eliminated.
	.loc 1 74 1 view .LVU147
	.loc 1 74 1 view .LVU148
	.loc 1 74 1 view .LVU149
	ldr	r0, .L32
.LPIC10:
	add	r0, pc, r0
	bx	lr
```