[Committed] PR middle-end/18548: RTL expansion of MAX_EXPR
Roger Sayle
roger@eyesopen.com
Sat Dec 18 14:38:00 GMT 2004
This patch resolves PR middle-end/18548 which is a wrong-code regression
on mainline. The problem is that the RTL sequences generated for MIN_EXPR
and MAX_EXPR generated can clobber "target" which may still be required
to evaluate op0 and/or op1.
Consider the problematic case of "a = MAX(b, a+1)", where we expand_expr
ends up with target = (reg A), op0 = (reg B) and op1 = (plus (reg A) 1).
Although we use safe_from_p in expand_operands which ensures that we
don't overwrite target when evaluating op0 and op1, the later code
doesn't test for this interaction. So instead we generate
target = op0 (set (reg A) (reg B))
if (target < op1) (compare (reg A) (plus (reg A) 1))
target = op1 (set (reg A) (plus (reg A) 1))
My first thoughts on a solution were to use reg_overlap_mentioned_p
to ensure that register "target" is mentioned in "op1". However,
although we're sure that target isn't a MEM at this point, we're not
certain it's a register. However thinking about forcing things to
be registers revealed the real problem above, that we should be
forcing op1 into a register, rather than performing the addition
twice. If target, op0 and op1 are all registers (or op0/op1 are
constants), is impossible to clobber op1 with an assignment to
target in this part of the code.
The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages, and regression tested with a
top-level "make -k check" with no new failures.
Committed to mainline CVS.
2004-12-18 Roger Sayle <roger@eyesopen.com>
PR middle-end/18548
* expr.c (expand_expr_real_1) <MAX_EXPR>: Ensure that target, op0
and op1 are all registers (or constants) before expanding the RTL
comparison sequence [to avoid reg_overlap_mentioned (target, op1)].
* gcc.dg/max-1.c: New test case.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.760
diff -c -3 -p -r1.760 expr.c
*** expr.c 12 Dec 2004 21:12:43 -0000 1.760
--- expr.c 18 Dec 2004 04:48:47 -0000
*************** expand_expr_real_1 (tree exp, rtx target
*** 7671,7677 ****
/* At this point, a MEM target is no longer useful; we will get better
code without it. */
! if (MEM_P (target))
target = gen_reg_rtx (mode);
/* If op1 was placed in target, swap op0 and op1. */
--- 7671,7677 ----
/* At this point, a MEM target is no longer useful; we will get better
code without it. */
! if (! REG_P (target))
target = gen_reg_rtx (mode);
/* If op1 was placed in target, swap op0 and op1. */
*************** expand_expr_real_1 (tree exp, rtx target
*** 7682,7687 ****
--- 7682,7692 ----
op1 = tem;
}
+ /* We generate better code and avoid problems with op1 mentioning
+ target by forcing op1 into a pseudo if it isn't a constant. */
+ if (! CONSTANT_P (op1))
+ op1 = force_reg (mode, op1);
+
if (target != op0)
emit_move_insn (target, op0);
/* PR middle-end/18548 */
/* Test case reduced by Andrew Pinski <pinskia@physics.uc.edu> */
/* { dg-do run } */
/* { dg-options "-O1 -fno-tree-lrs" } */
extern void abort (void);
long fff[10];
void f(long a, long b)
{
long crcc = b;
long d = *((long*)(a+1));
int i;
a = d >= b? d:b;
for(i=0;i<10;i++)
fff[i] = a;
}
int main(void)
{
int i;
long a = 10;
f((long)(&a)-1,0);
for(i = 0;i<10;i++)
if (fff[i]!=10)
abort ();
return 0;
}
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833
More information about the Gcc-patches
mailing list