<p dir="auto">Compressing our debug info might offer a significant, cheap file size win.</p>
<p dir="auto">Things to do:</p>
<ul dir="auto">
<li>Figure out which targets to compress debug info for by default.</li>
<li>Provide a linker flag to control compression on/off.</li>
<li>Teach the linker to compress debug info.</li>
<li>Teach the Go packages how to read compressed debug info.</li>
</ul>
<p dir="auto"><a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/ianlancetaylor/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/ianlancetaylor">@ianlancetaylor</a> commented off-list:</p>
<blockquote>
<p dir="auto">Compressed debug info is supported by gdb and the GNU binutils.<br>
Yes, we should do it in our toolchain for relevant targets.</p>
</blockquote>
<p dir="auto">Related: <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="95777010" data-permission-text="Title is private" data-url="https://github.com/golang/go/issues/11773" data-hovercard-type="issue" data-hovercard-url="/golang/go/issues/11773/hovercard" href="https://github.com/golang/go/issues/11773">#11773</a></p>
<p dir="auto">by <strong>jeff.allen</strong>:</p>
<pre class="notranslate">What steps will reproduce the problem?
If possible, include a link to a program on play.golang.org.
1. here is a program that makes a call to a predicate:

package main

func eq(a,b string) bool {
    return len(a) == len(b)
}

func main() {
    a := ""
    b := ""
    if eq(a,b) {
        println("ok")
    }
}

Inlining the predicate results in assembly with duplicate initialization of temporaries
on the stack and jumps forward and back. 

Is this really correct behavior? It seems suspiciously ugly.

What is the expected output?

This is the assembly from manually inlining the code (i.e. replacing a call to eq(a,b)
with the expression len(a)==len(b))

--- prog list "main" ---
0010 (streq.go:7) TEXT    main+0(SB),$16-0
0011 (streq.go:8) LEAQ    go.string.""+0(SB),BX
0012 (streq.go:8) MOVQ    (BX),BP
0013 (streq.go:8) MOVQ    8(BX),CX
0014 (streq.go:9) MOVQ    (BX),BP
0015 (streq.go:9) MOVQ    8(BX),AX
0016 (streq.go:10) CMPQ    CX,AX
0017 (streq.go:10) JNE     ,26
0018 (streq.go:11) LEAQ    go.string."ok"+0(SB),BX
0019 (streq.go:11) LEAQ    (SP),BP
0020 (streq.go:11) MOVQ    BP,DI
0021 (streq.go:11) MOVQ    BX,SI
0022 (streq.go:11) MOVSQ   ,
0023 (streq.go:11) MOVSQ   ,
0024 (streq.go:11) CALL    ,runtime.printstring+0(SB)
0025 (streq.go:11) CALL    ,runtime.printnl+0(SB)
0026 (streq.go:13) RET     ,

What do you see instead?

This is the assembly from 6g with inlining. Note the useless MOVB $0,.anon2, which after
two jumps (!), is overwritten by MOV AX,.anon2, then compared to $0.

--- prog list "main" ---
0010 (streq.go:7) TEXT    main+0(SB),$24-0
0011 (streq.go:8) LEAQ    go.string.""+0(SB),BX
0012 (streq.go:8) MOVQ    (BX),SI
0013 (streq.go:8) MOVQ    8(BX),DX
0014 (streq.go:9) MOVQ    (BX),CX
0015 (streq.go:9) MOVQ    8(BX),BP
0016 (streq.go:10) MOVB    $0,.anon2+-1(SP)
0017 (streq.go:10) JMP     ,20
0018 (streq.go:10) MOVQ    $1,AX
0019 (streq.go:10) JMP     ,23
0020 (streq.go:10) CMPQ    DX,BP
0021 (streq.go:10) JEQ     ,18
0022 (streq.go:10) MOVQ    $0,AX
0023 (streq.go:10) MOVB    AX,.anon2+-1(SP)
0024 (streq.go:10) MOVBQZX .anon2+-1(SP),BX
0025 (streq.go:10) CMPB    BX,$0
0026 (streq.go:10) JEQ     ,35
0027 (streq.go:11) LEAQ    go.string."ok"+0(SB),BX
0028 (streq.go:11) LEAQ    (SP),BP
0029 (streq.go:11) MOVQ    BP,DI
0030 (streq.go:11) MOVQ    BX,SI
0031 (streq.go:11) MOVSQ   ,
0032 (streq.go:11) MOVSQ   ,
0033 (streq.go:11) CALL    ,runtime.printstring+0(SB)
0034 (streq.go:11) CALL    ,runtime.printnl+0(SB)
0035 (streq.go:13) RET     ,


Which compiler are you using (5g, 6g, 8g, gccgo)?

6g

Which operating system are you using?

Linux

Which version are you using?  (run 'go version')

14893:591fc8a0131a</pre>