Hi, When combine tries to combine:
(insn 37 35 39 3 (set (reg:SI 90) (plus:SI (mult:SI (reg/v:SI 84 [ i ]) (const_int 4 [0x4])) (reg:SI 106))) x.i:11 247 {*leasi_2} (nil)) (insn 39 37 41 3 (set (mem:SI (zero_extend:DI (reg:SI 90)) [3 MEM[symbol: x, index: D.2741_12, step: 4, offset: 4294967292B]+0 S4 A32]) (reg/v:SI 84 [ i ])) x.i:11 64 {*movsi_internal} (expr_list:REG_DEAD (reg:SI 90) (nil))) it optimizes (zero_extend:DI (plus:SI (mult:SI (reg/v:SI 84 [ i ]) (const_int 4 [0x4])) (reg:SI 106))) into (and:DI (plus:DI (subreg:DI (mult:SI (reg/v:SI 85 [ i ]) (const_int 4 [0x4])) 0) (subreg:DI (reg:SI 106) 0)) (const_int 4294967292 [0xfffffffc])) in make_compound_operation. X86 backend doesn't accept the new expression as valid address while (zero_extend:DI) works just fine. This patches keeps ZERO_EXTEND when zero-extending address to Pmode. It reduces number of lea from 24173 to 21428 in x32 libgfortran.so. Does it make any senses? Thanks. H.J. --- 2011-10-12 H.J. Lu <hongjiu...@intel.com> PR rtl-optimization/50696 * combine.c (subst): If an address is zero-extended to Pmode, replace FROM with while keeping ZERO_EXTEND. diff --git a/gcc/combine.c b/gcc/combine.c index 6c3b17c..45180e5 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -5078,6 +5078,23 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy) } } } +#ifdef POINTERS_EXTEND_UNSIGNED + else if (POINTERS_EXTEND_UNSIGNED > 0 + && code == MEM + && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND + && GET_MODE (XEXP (x, 0)) == Pmode) + { + /* If an address is zero-extended to Pmode, replace FROM with + TO while keeping ZERO_EXTEND. */ + new_rtx = subst (XEXP (XEXP (x, 0), 0), from, to, 0, 0, + unique_copy); + /* Drop ZERO_EXTEND on constant. */ + if (CONST_INT_P (new_rtx)) + SUBST (XEXP (x, 0), new_rtx); + else + SUBST (XEXP (XEXP (x, 0), 0), new_rtx); + } +#endif else { len = GET_RTX_LENGTH (code);