Useless instructions in generated code?

Hi,

This is super minor but I sometimes see seemingly redundant instructions in generated code.

For instance in the following snippet,

Do you guys happen to know the purpose of zeroing eax again on line 9 even though it has already been zeroed on line 6?

(disclaimer : I don't know much about assembly)

1 Like

Intel recommends that jump targets be 16-byte aligned:

3.4.1.5
Assembly/Compiler Coding Rule 12. (M impact, H generality) All branch targets should be 16-
byte aligned.

https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf

In this case, LLVM decided to use xor eax, eax to fill the required space to align .LBB0_2.

8 Likes

Thanks!

1 Like

Unfortunately I don't think that is really what is going on here.
I became suspicious because I have never seen padding filled with anything but nops. This behaviour seemed a bit too clever for no real gain.

Looking a bit more closely at the Compiler Explorer it shows assembly before padding has even been generated. You can turn of filtering of assembly directives to see that there is a .p2align 4, 0x90 right after the xor, that will later be expanded to padding. Looking at generated bytes xor eax, eax is also too short. There are 14 bytes required in this position, this xor only has 2.

Why the xor is really there I don't know. Locally using rustc 1.19 it does not appear, so this might just be a missing/misbehaving optimization in LLVM which has been fixed by now.

3 Likes

Weird! It did seem kind of strange that LLVM would try to be "smart" with its selection of a nop instruction.

The xor instruction is removed if using beta or nightly. See for example Compiler Explorer

There apparently is some kind of optimization between 1.18 and upcoming 1.19.