New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: make UNDEF into a pseudo-instruction #16291

josharian opened this Issue Jul 7, 2016 · 3 comments


None yet
4 participants

josharian commented Jul 7, 2016

The compiler inserts obj.AUNDEF instructions into exit blocks without a return instruction, so that liveness analysis understands the control flow. However, obj.UNDEF is assembled into a two byte UD2 instruction (0f 0b). Something similar occurs on arm, and presumably on other architectures. Since that instruction is unreachable, we may as well omit it entirely, much like we do with obj.NOP. (Savings are small, approx 0.15% binary size, but might help a bit in small, hot, cache-sensitive functions.)

One easy fix is to change the assemblers to treat obj.AUNDEF the same as obj.NOP. However, this will break any hand-written assembly that uses UNDEF and wants it to mean UD2.

Another fix is to add obj.AUNDEFNOP, which plive.go would treat as the same as obj.AUNDEF, but which would be converted to obj.NOP at assembly time.

Opinions? I'd rather do the former.


@josharian josharian added this to the Go1.8 milestone Jul 7, 2016

@josharian josharian self-assigned this Jul 7, 2016


This comment has been minimized.


randall77 commented Jul 13, 2016

I think treating UNDEF as NOP (no generated code) would be fine. I'm not worried about people depending on it generating real code; assembly isn't under the go1 guarantee.

I remember there being a case where we need a nop that generated real code - maybe before deferreturn so we get correct line numbers? Just make sure we don't break that.


This comment has been minimized.


josharian commented Aug 26, 2016

The nop that generates real code is inserted via ginsnop (per arch). On x86, it uses XCHGL AX, AX.

@quentinmit quentinmit added the NeedsFix label Oct 11, 2016


This comment has been minimized.


rsc commented Oct 21, 2016

Missed Go 1.8. Doesn't really seem worth it at all, at least not without more motivation. You'll probably spend more time debugging it than all the CPU saved ever.

@rsc rsc modified the milestones: Go1.9, Go1.8 Oct 21, 2016

@josharian josharian modified the milestones: Unplanned, Go1.9 May 3, 2017

josharian added a commit to josharian/go that referenced this issue May 23, 2017

cmd/compile: stop emitting AUNDEF for BlockExit

[Breaks profiling. It appears the undef is also needed to provide
a pc for tracebacks?]

It was used by liveness analysis.
Now that liveness works directly on SSA, it is unnecessary.

Fixes golang#16291

name        old object-bytes  new object-bytes  delta
Template           386k ± 0%         386k ± 0%  -0.07%  (p=0.008 n=5+5)
Unicode            202k ± 0%         202k ± 0%  -0.02%  (p=0.008 n=5+5)
GoTypes           1.16M ± 0%        1.16M ± 0%  -0.07%  (p=0.008 n=5+5)
Compiler          3.91M ± 0%        3.91M ± 0%  -0.06%  (p=0.008 n=5+5)
SSA               7.91M ± 0%        7.86M ± 0%  -0.53%  (p=0.008 n=5+5)
Flate              227k ± 0%         227k ± 0%  -0.19%  (p=0.008 n=5+5)
GoParser           283k ± 0%         283k ± 0%  -0.03%  (p=0.008 n=5+5)
Reflect            951k ± 0%         950k ± 0%  -0.09%  (p=0.008 n=5+5)
Tar                187k ± 0%         187k ± 0%  -0.05%  (p=0.008 n=5+5)
XML                406k ± 0%         406k ± 0%  -0.04%  (p=0.008 n=5+5)
[Geo mean]         648k              647k       -0.11%

name        old text-bytes    new text-bytes    delta
HelloSize          684k ± 0%         680k ± 0%  -0.60%  (p=0.008 n=5+5)

Change-Id: I7e026d06a33265481f73754bd3867e80b1d129ec
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment