> -----Original Message----- > From: Eric Botcazou [mailto:ebotca...@adacore.com] > Sent: Saturday, June 15, 2013 5:37 PM > To: Bin Cheng > Cc: gcc-patches@gcc.gnu.org > Subject: Re: [PATCH GCC]Fix PR57540, try to choose scaled_offset address mode > when expanding array reference > > > As reported in pr57540, gcc chooses bad address mode, resulting in A) > > invariant part of address expression is not kept or hoisted; b) > > additional computation which should be encoded in address expression. > > The reason is when gcc runs into "addr+offset" (which is invalid) > > during expanding, it pre-computes the entire address and accesses memory > unit using "MEM[reg]". > > Yet we can force addr into register and try to generate "reg+offset" > > which is valid for targets like ARM. By doing this, we can: > > 1) keep addr in loop invariant form and hoist it later; > > 2) saving additional computation by taking advantage of scaled > > addressing mode; > > Does the invalid address not go through arm_legitimize_address from here? > > /* Perform machine-dependent transformations on X > in certain cases. This is not necessary since the code > below can handle all possible cases, but machine-dependent > transformations can make better code. */ > { > rtx orig_x = x; > x = targetm.addr_space.legitimize_address (x, oldx, mode, as); > if (orig_x != x && memory_address_addr_space_p (mode, x, as)) > goto done; > } >
Hi Eric, The problem occurs when accessing local array element. For example, # VUSE <.MEM_27> k_8 = parent[k_29]; GCC calculates the address in three steps: 1) addr is calculated as "r105 + (-2064)". 2) offset is calculated as "r165*4". 3) calls offset_address to combine the address into "r105+ r165*4 + (-2064)". Since ADDR is valid and there is no call to memory_address_addr_space in offset_address, the invalid address expression has no chance to go through target dependent legitimization function. Even there is a chance, the current implementation of memory_address_addr_space prevents the scaled address expression from being generated because of below code: if (! cse_not_expected && !REG_P (x)) x = break_out_memory_refs (x); Thanks. bin