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);

Reply via email to