https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82267
--- Comment #7 from Uroš Bizjak <ubizjak at gmail dot com> --- (In reply to Peter Cordes from comment #6) > (In reply to H.J. Lu from comment #2) > > > Are there still cases where -maddress-mode=long makes worse code? > > > > > > Yes, there are more places where -maddress-mode=long needs to zero-extend > > address to 64 bits where 0x67 prefix does for you. > > So ideally, gcc should use 0x67 opportunistically where it saves a > zero-extension instruction. This is already implemented via: ;; Return true for RTX codes that force SImode address. (define_predicate "SImode_address_operand" (match_code "subreg,zero_extend,and")) and: /* Print SImode register names to force addr32 prefix. */ if (SImode_address_operand (addr, VOIDmode)) { [...] gcc_assert (!code); code = 'k'; } in ix86_print_operand_address. > Using 64-bit address size opportunistically wherever we're sure it's safe > seems like a good idea, but I assume that's not easy to implement. > > Can we teach -maddress-mode=long that a 0x67 prefix is a nearly-free way > to zero-extend as part of an addressing-mode, so it will use that instead of > extra instructions? Please see above. It all boils down to combine being smart enough to combine zero-extensions with the address. LEA also handles these kind of zero-extensions. > Note that %rsp can't be an index register, so you only have to check if it's > the base register. That is true, and this fact slipped out of my mind. I'm testing the following patch: Index: i386.c =================================================================== --- i386.c (revision 253208) +++ i386.c (working copy) @@ -19953,12 +19953,11 @@ code = 'k'; } - /* Since the upper 32 bits of RSP are always zero for x32, we can - encode %esp as %rsp to avoid 0x67 prefix if there is no index or - base register. */ + /* Since the upper 32 bits of RSP are always zero for x32, + we can encode %esp as %rsp to avoid 0x67 prefix if + there is no index register. */ if (TARGET_X32 && Pmode == SImode - && ((!index && base && REG_P (base) && REGNO (base) == SP_REG) - || (!base && index && REGNO (index) == SP_REG))) + && !index && base && REG_P (base) && REGNO (base) == SP_REG) code = 'q'; if (ASSEMBLER_DIALECT == ASM_ATT) > > The SIB encodings that would mean index=RSP actually mean "no index". The > ModRM encoding that would mean base=RSP instead means "there's a SIB byte". > https://stackoverflow.com/a/46263495/224132 > > This means that `(%rsp)` is encodeable, instead of (%rsp, %rsp, scale). Any > other register can be used as a base with no SIB byte (unfortunately for > code-size with -fomit-frame-pointer). > > Can this check be applied to %rbp in functions that use a frame pointer? > > That might be possible even if we can't as easily decide whether other > registers need to be zero or sign extended if we're not sure whether they're > "the pointer" or a signed integer pointer-difference. > > However, simple dereference addressing modes (one register, no displacement) > can always use 64-bit address size when the register is known to be > zero-extended.