Hi,

find_reloads_subreg_address has to get rid of (subreg (mem ...)) RTXs.
In order to do so the full address sometimes gets reloaded. E.g. if
the resulting address is invalid and gets pushed into the literal
pool.  Unfortunately that information is not propagated into
find_reloads.  So find_reloads pushes additional reloads although the
address has already been fixed.


I've found this issue while debugging the optional_dim_3.f90 failure
on S/390 with -march=z196:

(set (reg:HI 1) (mem:HI (symbol_ref:DI ("foo"))))
(set (reg:SI 2) (sign_extend:SI (subreg:QI (reg:HI 1) 1)))

The (subreg:QI (mem:HI (symbol_ref:DI "foo")) 1) is folded into:

(mem:HI (const:DI (plus:DI (symbol_ref:DI ("foo")) (const_int 1))))

Which is an invalid address on S/390 since we cannot cope with odd
addends for symbolic constants.  So the whole thing ends up in the
literal pool and the resulting literal pool address of course is
perfectly valid.  Since this information is not propagated into
find_reloads two additional reloads get issued.

The attached patch introduces the address_reloaded flag also for
find_reloads_subreg_address and sets it accordingly.

This is probably not a correctness issue since reload will anyway be
able to fix up the invalid address.  But since it avoids pointless
reloads I think its a good thing to do and will help to improve
performance.

Bootstrapped and regtested on x86_64, s390 and s390x.

Ok for mainline?

Bye,

-Andreas-


2011-03-23  Andreas Krebbel  <andreas.kreb...@de.ibm.com>

        * reload.c (find_reloads_subreg_address): Add address_reloaded
        parameter and return true there if the full address has been
        reloaded.
        (find_reloads_toplev): Pass address_reloaded flag.
        (find_reloads_address_1): Don't use address_reloaded parameter.


Index: gcc/reload.c
===================================================================
*** gcc/reload.c.orig
--- gcc/reload.c
*************** static void find_reloads_address_part (r
*** 285,291 ****
                                       enum machine_mode, int,
                                       enum reload_type, int);
  static rtx find_reloads_subreg_address (rtx, int, int, enum reload_type,
!                                       int, rtx);
  static void copy_replacements_1 (rtx *, rtx *, int);
  static int find_inc_amount (rtx, rtx);
  static int refers_to_mem_for_reload_p (rtx);
--- 285,291 ----
                                       enum machine_mode, int,
                                       enum reload_type, int);
  static rtx find_reloads_subreg_address (rtx, int, int, enum reload_type,
!                                       int, rtx, int *);
  static void copy_replacements_1 (rtx *, rtx *, int);
  static int find_inc_amount (rtx, rtx);
  static int refers_to_mem_for_reload_p (rtx);
*************** find_reloads_toplev (rtx x, int opnum, e
*** 4759,4765 ****
                           || ! offsettable_memref_p (reg_equiv_mem[regno])
                           || num_not_at_initial_offset))))
        x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
!                                        insn);
      }
  
    for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
--- 4759,4765 ----
                           || ! offsettable_memref_p (reg_equiv_mem[regno])
                           || num_not_at_initial_offset))))
        x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
!                                          insn, address_reloaded);
      }
  
    for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
*************** find_reloads_address_1 (enum machine_mod
*** 5995,6001 ****
                {
                  x = find_reloads_subreg_address (x, 0, opnum,
                                                   ADDR_TYPE (type),
!                                                  ind_levels, insn);
                  push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
                  return 1;
--- 5995,6001 ----
                {
                  x = find_reloads_subreg_address (x, 0, opnum,
                                                   ADDR_TYPE (type),
!                                                  ind_levels, insn, NULL);
                  push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
                  return 1;
*************** find_reloads_address_part (rtx x, rtx *l
*** 6097,6105 ****
  
  static rtx
  find_reloads_subreg_address (rtx x, int force_replace, int opnum,
!                            enum reload_type type, int ind_levels, rtx insn)
  {
    int regno = REGNO (SUBREG_REG (x));
  
    if (reg_equiv_memory_loc[regno])
      {
--- 6097,6107 ----
  
  static rtx
  find_reloads_subreg_address (rtx x, int force_replace, int opnum,
!                            enum reload_type type, int ind_levels, rtx insn,
!                            int *address_reloaded)
  {
    int regno = REGNO (SUBREG_REG (x));
+   int reloaded = 0;
  
    if (reg_equiv_memory_loc[regno])
      {
*************** find_reloads_subreg_address (rtx x, int 
*** 6123,6129 ****
              unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
              int offset;
              rtx orig = tem;
-             int reloaded;
  
              /* For big-endian paradoxical subregs, SUBREG_BYTE does not
                 hold the correct (negative) byte offset.  */
--- 6125,6130 ----
*************** find_reloads_subreg_address (rtx x, int 
*** 6192,6202 ****
                  && !strict_memory_address_addr_space_p
                        (GET_MODE (x), XEXP (reg_equiv_mem[regno], 0),
                         MEM_ADDR_SPACE (reg_equiv_mem[regno])))
!               push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
!                            base_reg_class (GET_MODE (tem), MEM, SCRATCH),
!                            GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
!                            opnum, type);
! 
              /* If this is not a toplevel operand, find_reloads doesn't see
                 this substitution.  We have to emit a USE of the pseudo so
                 that delete_output_reload can see it.  */
--- 6193,6205 ----
                  && !strict_memory_address_addr_space_p
                        (GET_MODE (x), XEXP (reg_equiv_mem[regno], 0),
                         MEM_ADDR_SPACE (reg_equiv_mem[regno])))
!               {
!                 push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 
0,
!                              base_reg_class (GET_MODE (tem), MEM, SCRATCH),
!                              GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
!                              opnum, type);
!                 reloaded = 1;
!               }
              /* If this is not a toplevel operand, find_reloads doesn't see
                 this substitution.  We have to emit a USE of the pseudo so
                 that delete_output_reload can see it.  */
*************** find_reloads_subreg_address (rtx x, int 
*** 6211,6216 ****
--- 6214,6222 ----
            }
        }
      }
+   if (reloaded && address_reloaded)
+     *address_reloaded = 1;
+ 
    return x;
  }
  

Reply via email to