This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH/RFC] force_reg() doesn't propagate MEM_POINTER flag to REG_POINTER
- From: Peter Bergner <bergner at vnet dot ibm dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: Anton Blanchard <anton at samba dot org>
- Date: Thu, 21 Sep 2006 14:06:47 -0500
- Subject: [PATCH/RFC] force_reg() doesn't propagate MEM_POINTER flag to REG_POINTER
While working on PR28690 in which we use the REG_POINTER flag in
rs6000_legitimize_address() to force "base" pointers to objects
to be the first operand of indexed load/store instructions for
performance reasons, we came across a test case in which the
REG_POINTER flag was being lost. The problem is the call to
force_reg() in break_out_memory_refs(). In this case, we pass
force_reg():
(mem/f:SI (plus:SI (reg/v/f:SI 120 [ base ])
(reg:SI 125)) [0 S4 A32])
and get back a normal:
(reg:SI 126)
when we really wanted:
(reg/f:SI 126)
This is particularly bad for multidimensional arrays like:
int indexedload(int ***base, int idx0, int idx1, int idx2)
{
return base[idx0][idx1][idx2];
}
In this case, we'll generate 3 indexed loads, but we'll only be
able to transform the first since the other two base pointers will
have lost their REG_POINTER flags. Using the patch below propagates
the MEM_POINTER flag to the reg we generate in force_reg(), so that
we're able to transform all of the indexed loads.
Does anyone see any problems with the patch below? If not, I'll
submit it along with the rest of the patch from PR28690. I'll note
that it survived bootstrap and regression tests on powerpc64-linux
(32-bit and 64-bit) using all languages except Ada, which I'm not
setup to handle.
Peter
* explow.c (force_reg): Set REG_POINTER flag according to
MEM_POINTER flag.
Index: explow.c
===================================================================
--- explow.c (revision 116698)
+++ explow.c (working copy)
@@ -710,6 +710,8 @@ force_reg (enum machine_mode mode, rtx x
align = MIN (sa, ca);
}
+ else if (MEM_P (x) && MEM_POINTER (x))
+ align = MEM_ALIGN (x);
if (align)
mark_reg_pointer (temp, align);