We've been looking recently at some object code from an Ada compiler for the PowerPC e500v2 core. As part of this, we examined the distribution of instruction mnemonics in the code generated by this particular use of the compiler on a suite of example programs.
The split by type of instruction is roughly as follows:
Interestingly, there aren't as many compare operations as we might otherwise expect. This is because xor
tends to be used for this instead.
As is usually the case, there are some opcodes that are favoured and some that are never used, and as is also usually the case, the interesting stuff is in between.
Below is a list of instructions that were only used once in the generated output (out of over 100k instructions).
- lhzx (Load Half Word and Zero Indexed)
- This came up on the first assignment in a loop assigning record components in an array of records.
- nand
- We saw this on the one instance of
v := not( a and b )
where the operation was on a modular type with 32 bits of storage. - evxor (Vector XOR)
- This was used as a 64-bit "load immediate zero" by performing
evxor %r10,%r10,%r10
. In this case the registerr10
was then used for initialising an array of 5 bytes. - rlwinm. (Rotate Left Word Immediate, then AND with Mask)
- This was used in a binary-search of different case-branches for an enumeration type. The line
rlwinm. %r9,%r3,0,11,16
was used, which works if the decision to be made happens to be something that can be decided by masking bits. - addze. (Add to Zero Extended)
- This was a puzzler, it turns out it was from doing an integer division that needed to be rounded, and then using that for the Ada "mod" operator. The division was implemented as a shift, so the rounding compensation can be picked up from the carry flag using
addze
; the value needs to be tested to implement "mod" so the flags can be set directly from that add. - efsnabs (Floating point negative absolute value)
- Normally this compiler tries to rearrange expressions to a simplified form, and this often results in a "-abs" operation getting split up. This one time, it happened to be in a place where the compiler couldn't rearrange things as much, so it opted for a "negative abs" instruction.
- adde. (Add Extended)
- A curious combination of events here, where we are explicitly testing for membership of a range of values, but the range is all negative values going up to -1; the compiler spotted that it would have done an
addze.
on a register that's already zero in this case, and switched to anadde.
instruction instead.