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.
@randall77
The compiler inserts
obj.AUNDEFinstructions into exit blocks without a return instruction, so that liveness analysis understands the control flow. However,obj.UNDEFis 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 withobj.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.AUNDEFthe same asobj.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 asobj.AUNDEF, but which would be converted toobj.NOPat assembly time.Opinions? I'd rather do the former.
@randall77