Optimizing 0-displacement jumps on i386

H. Peter Anvin hpa@zytor.com
Mon Aug 11 18:19:57 GMT 2025


On 2025-08-07 23:41, Jan Beulich wrote:
> On 08.08.2025 01:26, Petr Skočík wrote:
>> Hi. I'm new here. I noticed (1) gas isn't literal and is capable of various
>> optimizations & (2) jumps are effectively variable-length due to how gas
>> iteratively does jmp relaxations and I was wondering why not take (2) all
>> the way and delete sequences like 0eb 00, i.e., jumps to the next
>> instruction?
>>
>> These come up quite a lot (tailcalls to a neighboring function) & might be
>> difficult for compilers to eliminate them.
>> (It might be better if the assembler did it for other reasons anyway--like
>> I'd like to a bit more efficiently tailcall to some asm without the
>> compiler getting too nosy). It might be difficult for gas too, but since
>> the framework for length-adjusting jumps is already there ...?
>>
>> Alternatively, and this seems rather easy, 0-displacement jumps could be
>> turned into 2-byte nops, which are quite a bit faster.
>>
>> I tried doing it by modifying the tail of md_convert_frag like so:
>>
>>   if(extension==1 && 0==(valueT)(displacement_from_opcode_start -
>> extension)){ //new
>>       opcode[0]=0x66; //new
>>       opcode[1]=0x90; //new
>>   }else  //new
>>   {
>>   /* Now put displacement after opcode.  */
>>       md_number_to_chars ((char *) where_to_put_displacement,
>>                   (valueT) (displacement_from_opcode_start - extension),
>>                   DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype));
>>   }
>>   fragP->fr_fix += extension;
>> }
>>
>> and it seems to do the job.
>> Just a thought. Thanks for reading my message.
> 
> Hmm, yes, why not? Would you mind transforming the above into a proper patch?
> 

Arguably this should be merged with subsequent alignment padding if it
fits within one instruction.  However, in order to actually be effective
in any meaningful way, this version of the optimization probably needs
to be performed in the linker, or it will simply never happen if the
code is compiled with linker garbage collection, which is pretty common
these days.

The optimization in gas would still apply to intra-function jumps.

Note that it may very well be necessary to disable this optimization, in
case something expects to be able to create a jump instruction and patch
its target; such code might use a zero-displacement jump to ensure a
two-byte as opposed to a 5/6-byte jump. It should be rare though.

	-hpa





More information about the Binutils mailing list