LoginSignup
0
0

More than 3 years have passed since last update.

quadsortでコンパイルしたバイナリも確認してみる

Posted at

メモ。quadsortのバイナリも見てみよう。

実験環境

kmtr@ubuntu:~/work/2020/0217_quad$ clang --version
clang version 9.0.0-2 (tags/RELEASE_900/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

kmtr@ubuntu:~/work/2020/0217_quad$ clang a.c -o a.o -c -O3 -pg -g
kmtr@ubuntu:~/work/2020/0217_quad$ objdump -S -d a.o

まとめ

・quadsortをコンパイルした結果は、レジスタ割り当てがうまくいくと、メモリへの書き込みがかなり減らせそうに見えた。
・「何もしない」がきちんと「何もしない」結果にできた。これはコンパイラが偉い、たぶん。

普通のSWAPを使った実装

なお、普通のSWAPは、
{a,b,c,d} と要素があったら、

sort{a,b} -> sort{b,c} ->sort{c,d} 
sort{b,c} -> sort{c,d}

で、ソートできる前提で。

ソースコード

ソースコードはこの部分。

サンプルコード
#define SWAPBY2(val,a,b) \
{\
        if ( val[a] > val[b] ) { \
                tmp = val[a]; \
                val[a] = val[b]; \
                val[b] = tmp; \
        } \
} \

void stdswap(int *val)
{
        int tmp; // shared
        SWAPBY2(val,0,1);
        SWAPBY2(val,1,2);
        SWAPBY2(val,2,3);

        SWAPBY2(val,1,2);
        SWAPBY2(val,2,3);
}

コンパイル結果

void stdswap(int *val)
{
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   53                      push   %rbx
   5:   50                      push   %rax
   6:   48 89 fb                mov    %rdi,%rbx
   9:   e8 00 00 00 00          callq  e <stdswap+0xe>
        int tmp; // shared
        SWAPBY2(val,0,1);
   e:   8b 0b                   mov    (%rbx),%ecx
  10:   8b 43 04                mov    0x4(%rbx),%eax
  13:   39 c1                   cmp    %eax,%ecx
  15:   7e 27                   jle    3e <stdswap+0x3e>
  17:   89 03                   mov    %eax,(%rbx)
  19:   89 4b 04                mov    %ecx,0x4(%rbx)
        SWAPBY2(val,1,2);
  1c:   8b 53 08                mov    0x8(%rbx),%edx
  1f:   39 d1                   cmp    %edx,%ecx
  21:   7f 24                   jg     47 <stdswap+0x47>
  23:   89 c8                   mov    %ecx,%eax
        SWAPBY2(val,2,3);
  25:   89 d1                   mov    %edx,%ecx
  27:   8b 73 0c                mov    0xc(%rbx),%esi
  2a:   39 f1                   cmp    %esi,%ecx
  2c:   7f 28                   jg     56 <stdswap+0x56>
  2e:   89 f2                   mov    %esi,%edx

        SWAPBY2(val,1,2);
  30:   89 ce                   mov    %ecx,%esi
  32:   39 f0                   cmp    %esi,%eax
  34:   7f 2c                   jg     62 <stdswap+0x62>
        SWAPBY2(val,2,3);
  36:   89 f0                   mov    %esi,%eax
  38:   39 d0                   cmp    %edx,%eax
  3a:   7f 30                   jg     6c <stdswap+0x6c>
  3c:   eb 34                   jmp    72 <stdswap+0x72>
        SWAPBY2(val,1,2);
  3e:   89 c1                   mov    %eax,%ecx
  40:   8b 53 08                mov    0x8(%rbx),%edx
  43:   39 d1                   cmp    %edx,%ecx
  45:   7e dc                   jle    23 <stdswap+0x23>
  47:   89 53 04                mov    %edx,0x4(%rbx)
  4a:   89 4b 08                mov    %ecx,0x8(%rbx)
  4d:   89 d0                   mov    %edx,%eax
        SWAPBY2(val,2,3);
  4f:   8b 73 0c                mov    0xc(%rbx),%esi
  52:   39 f1                   cmp    %esi,%ecx
  54:   7e d8                   jle    2e <stdswap+0x2e>
  56:   89 73 08                mov    %esi,0x8(%rbx)
  59:   89 4b 0c                mov    %ecx,0xc(%rbx)
  5c:   89 ca                   mov    %ecx,%edx
        SWAPBY2(val,1,2);
  5e:   39 f0                   cmp    %esi,%eax
  60:   7e d4                   jle    36 <stdswap+0x36>
  62:   89 73 04                mov    %esi,0x4(%rbx)
  65:   89 43 08                mov    %eax,0x8(%rbx)
        SWAPBY2(val,2,3);
  68:   39 d0                   cmp    %edx,%eax
  6a:   7e 06                   jle    72 <stdswap+0x72>
  6c:   89 53 08                mov    %edx,0x8(%rbx)
  6f:   89 43 0c                mov    %eax,0xc(%rbx)
}
  72:   48 83 c4 08             add    $0x8,%rsp
  76:   5b                      pop    %rbx
  77:   5d                      pop    %rbp
  78:   c3                      retq
  79:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

ポイント

まじめにvalへの書き込みしすぎなのでは?という気がする。
下記のように、ebxレジスタのオフセット位置にデータを書き込む命令がいっぱいある…

  47:   89 53 04                mov    %edx,0x4(%rbx)
  4a:   89 4b 08                mov    %ecx,0x8(%rbx)

quadsortを使った実装

ソースコード

ソースコード
void quadswap(int *val)
{
    int tmp[4];

    if (val[0] > val[1]) {
        tmp[0] = val[1];
        tmp[1] = val[0];
    } else {
        tmp[0] = val[0];
        tmp[1] = val[1];
    }

    if (val[2] > val[3]) {
        tmp[2] = val[3];
        tmp[3] = val[2];
    } else {
        tmp[2] = val[2];
        tmp[3] = val[3];
    }

    if (tmp[1] <= tmp[2]) {
        val[0] = tmp[0];
        val[1] = tmp[1];
        val[2] = tmp[2];
        val[3] = tmp[3];
    } else if (tmp[0] > tmp[3]) {
        val[0] = tmp[2];
        val[1] = tmp[3];
        val[2] = tmp[0];
        val[3] = tmp[1];
    } else {
        if (tmp[0] <= tmp[2]) {
            val[0] = tmp[0];
            val[1] = tmp[2];
        } else {
            val[0] = tmp[2];
            val[1] = tmp[0];
        }

        if (tmp[1] <= tmp[3]) {
            val[2] = tmp[1];
            val[3] = tmp[3];
        } else {
            val[2] = tmp[3];
            val[3] = tmp[1];
        }
    }
}

コンパイル結果

0000000000000080 <quadswap>:

void quadswap(int *val)
{
  80:   55                      push   %rbp
  81:   48 89 e5                mov    %rsp,%rbp
  84:   53                      push   %rbx
  85:   50                      push   %rax
  86:   48 89 fb                mov    %rdi,%rbx
  89:   e8 00 00 00 00          callq  8e <quadswap+0xe>
    int tmp[4];

    if (val[0] > val[1]) {
  8e:   8b 33                   mov    (%rbx),%esi
  90:   8b 43 04                mov    0x4(%rbx),%eax
  93:   39 c6                   cmp    %eax,%esi
  95:   89 c2                   mov    %eax,%edx
  97:   0f 4d d6                cmovge %esi,%edx
  9a:   0f 4f f0                cmovg  %eax,%esi
    } else {
        tmp[0] = val[0];
        tmp[1] = val[1];
    }

    if (val[2] > val[3]) {
  9d:   8b 43 08                mov    0x8(%rbx),%eax
  a0:   8b 7b 0c                mov    0xc(%rbx),%edi
  a3:   39 f8                   cmp    %edi,%eax
  a5:   89 f9                   mov    %edi,%ecx
  a7:   0f 4d c8                cmovge %eax,%ecx
  aa:   0f 4f c7                cmovg  %edi,%eax
    } else {
        tmp[2] = val[2];
        tmp[3] = val[3];
    }

    if (tmp[1] <= tmp[2]) {
  ad:   39 c2                   cmp    %eax,%edx
  af:   7e 0f                   jle    c0 <quadswap+0x40>
        val[0] = tmp[0];
        val[1] = tmp[1];
        val[2] = tmp[2];
        val[3] = tmp[3];
    } else if (tmp[0] > tmp[3]) {
  b1:   39 ce                   cmp    %ecx,%esi
  b3:   7e 12                   jle    c7 <quadswap+0x47>
        val[0] = tmp[2];
  b5:   89 03                   mov    %eax,(%rbx)
        val[1] = tmp[3];
  b7:   89 4b 04                mov    %ecx,0x4(%rbx)
  ba:   89 f0                   mov    %esi,%eax
  bc:   89 d1                   mov    %edx,%ecx
  be:   eb 20                   jmp    e0 <quadswap+0x60>
        val[0] = tmp[0];
  c0:   89 33                   mov    %esi,(%rbx)
        val[1] = tmp[1];
  c2:   89 53 04                mov    %edx,0x4(%rbx)
  c5:   eb 19                   jmp    e0 <quadswap+0x60>
        val[2] = tmp[0];
        val[3] = tmp[1];
    } else {
        if (tmp[0] <= tmp[2]) {
  c7:   39 c6                   cmp    %eax,%esi
  c9:   89 f7                   mov    %esi,%edi
  cb:   0f 4f f8                cmovg  %eax,%edi
  ce:   0f 4d c6                cmovge %esi,%eax
  d1:   89 3b                   mov    %edi,(%rbx)
  d3:   89 43 04                mov    %eax,0x4(%rbx)
        } else {
            val[0] = tmp[2];
            val[1] = tmp[0];
        }

        if (tmp[1] <= tmp[3]) {
  d6:   39 ca                   cmp    %ecx,%edx
  d8:   89 d0                   mov    %edx,%eax
  da:   0f 4f c1                cmovg  %ecx,%eax
  dd:   0f 4d ca                cmovge %edx,%ecx
  e0:   89 43 08                mov    %eax,0x8(%rbx)
  e3:   89 4b 0c                mov    %ecx,0xc(%rbx)
        } else {
            val[2] = tmp[3];
            val[3] = tmp[1];
        }
    }
}
  e6:   48 83 c4 08             add    $0x8,%rsp
  ea:   5b                      pop    %rbx
  eb:   5d                      pop    %rbp
  ec:   c3                      retq

ポイント

メモリへの書き出しが少ない!

tmp[4]を導入し、それがレジスタに割り当てられることで、val[0..3]への書き出しが少なくなったような!

        if (tmp[0] <= tmp[2]) {
  c7:   39 c6                   cmp    %eax,%esi
  c9:   89 f7                   mov    %esi,%edi
  cb:   0f 4f f8                cmovg  %eax,%edi
  ce:   0f 4d c6                cmovge %esi,%eax
  d1:   89 3b                   mov    %edi,(%rbx)  val[0] = tmp[2]
  d3:   89 43 04                mov    %eax,0x4(%rbx)  val[1] = tmp[0]
        } else {
            val[0] = tmp[2];
            val[1] = tmp[0];
        }

何もしないが、何もしない!

Beautiful!! 並びかえを実行しない、という部分は本当になにも実行しないようになっている。

    if (tmp[1] <= tmp[2]) {
  ad:   39 c2                   cmp    %eax,%edx
  af:   7e 0f                   jle    c0 <quadswap+0x40>
        val[0] = tmp[0];
        val[1] = tmp[1];
        val[2] = tmp[2];
        val[3] = tmp[3];
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0