This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Fix address shape in cse.c:find_best_addr
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 2 Mar 2005 22:39:57 +0100
- Subject: [patch] Fix address shape in cse.c:find_best_addr
Hello,
cse.c:find_best_addr tries to fold the address, doing for example
constant propagation in the process -- in situation
reg1 = cst;
(set (mem (plus reg2 reg1)) ...)
we get
(set (mem (plus reg2 cst)) ...)
However if the memory reference contains multiplication
reg1 = cst;
(set (mem (plus (mult reg2 4) reg1)) ...)
find_best_addr fails, because fold_rtx makes
(mem (plus (ashift reg2 2) cst))
Which is not a valid address because of the ashift. This patch
makes find_best_addr to undo this mult --> ashift transformation,
thus making the substitution to succeed.
This patch fixes a minor performance regressions with a patch I am
going to send soon.
Bootstrapped & regtested on ia64 and x86_64.
Zdenek
* cse.c (validize_addr): New function.
(find_best_addr): Use it.
Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.345
diff -c -3 -p -r1.345 cse.c
*** cse.c 25 Feb 2005 03:45:37 -0000 1.345
--- cse.c 2 Mar 2005 15:27:41 -0000
*************** canon_reg (rtx x, rtx insn)
*** 2794,2799 ****
--- 2794,2836 ----
return x;
}
+ /* ADDR comes from fold_rtx, which might have made the address invalid.
+ Try fixing that. */
+
+ static rtx
+ validize_addr (rtx addr)
+ {
+ rtx op0, op1, mby;
+ enum rtx_code code = GET_CODE (addr);
+ enum machine_mode mode = GET_MODE (addr);
+
+ switch (code)
+ {
+ case PLUS:
+ case MINUS:
+ op0 = validize_addr (XEXP (addr, 0));
+ op1 = validize_addr (XEXP (addr, 1));
+
+ if (op0 == XEXP (addr, 0)
+ && op1 == XEXP (addr, 1))
+ return addr;
+
+ return gen_rtx_fmt_ee (code, mode, op0, op1);
+
+ case ASHIFT:
+ /* Replace shift with multiply. */
+ op0 = XEXP (addr, 0);
+ op1 = XEXP (addr, 1);
+ if (GET_CODE (op1) != CONST_INT)
+ return addr;
+ mby = simplify_gen_binary (ASHIFT, mode, const1_rtx, op1);
+ return gen_rtx_MULT (mode, op0, mby);
+
+ default:
+ return addr;
+ }
+ }
+
/* LOC is a location within INSN that is an operand address (the contents of
a MEM). Find the best equivalent address to use that is valid for this
insn.
*************** find_best_addr (rtx insn, rtx *loc, enum
*** 2850,2856 ****
be valid and produce better code. */
if (!REG_P (addr))
{
! rtx folded = fold_rtx (addr, NULL_RTX);
if (folded != addr)
{
int addr_folded_cost = address_cost (folded, mode);
--- 2887,2894 ----
be valid and produce better code. */
if (!REG_P (addr))
{
! rtx folded = validize_addr (fold_rtx (addr, NULL_RTX));
!
if (folded != addr)
{
int addr_folded_cost = address_cost (folded, mode);