------- Additional Comments From jakub at redhat dot com 2005-04-13 09:46 ------- Subject: Re: [3.3/3.4/4.0 Regression] Inlined memcmp makes one argument null on entry
On Tue, Apr 12, 2005 at 05:54:58PM -0000, mmitchel at gcc dot gnu dot org wrote: > > ------- Additional Comments From mmitchel at gcc dot gnu dot org 2005-04-12 > 17:54 ------- > I like the simpler approach. If someone would test that for 4.0, I'd be > ecstatic. Here is what I have bootstrapped/regtested on {i386,x86_64,ia64,ppc,ppc64,s390,s390x}-linux. 2005-04-13 Alexandre Oliva <[EMAIL PROTECTED]> Roger Sayle <[EMAIL PROTECTED]> PR target/20126 * loop.c (loop_givs_rescan): If replacement of DEST_ADDR failed, set the original address pseudo to the correct value before the original insn, if possible, and leave the insn alone, otherwise create a new pseudo, set it and replace it in the insn. * recog.c (validate_change_maybe_volatile): New. * recog.h (validate_change_maybe_volatile): Declare. * gcc.dg/pr20126.c: New. --- gcc/loop.c.jj 2005-04-03 10:33:24.000000000 +0200 +++ gcc/loop.c 2005-04-12 23:22:06.000000000 +0200 @@ -5478,9 +5478,20 @@ loop_givs_rescan (struct loop *loop, str mark_reg_pointer (v->new_reg, 0); if (v->giv_type == DEST_ADDR) - /* Store reduced reg as the address in the memref where we found - this giv. */ - validate_change (v->insn, v->location, v->new_reg, 0); + { + /* Store reduced reg as the address in the memref where we found + this giv. */ + if (!validate_change (v->insn, v->location, v->new_reg, 0)) + { + if (loop_dump_stream) + fprintf (loop_dump_stream, + "unable to reduce iv to register in insn %d\n", + INSN_UID (v->insn)); + bl->all_reduced = 0; + v->ignore = 1; + continue; + } + } else if (v->replaceable) { reg_map[REGNO (v->dest_reg)] = v->new_reg; --- gcc/testsuite/gcc.dg/pr20126.c 1 Jan 1970 00:00:00 -0000 +++ gcc/testsuite/gcc.dg/pr20126.c 10 Mar 2005 11:24:16 -0000 @@ -0,0 +1,50 @@ +/* dg-do run */ +/* dg-options "-O2" */ + +/* PR target/20126 was not really target-specific, but rather a loop's + failure to take into account the possibility that a DEST_ADDR giv + replacement might fail, such as when you attempt to replace a REG + with a PLUS in one of the register_operands of cmpstrqi_rex_1. */ + +extern void abort (void); + +typedef struct { int a; char b[3]; } S; +S c = { 2, "aa" }, d = { 2, "aa" }; + +void * +bar (const void *x, int y, int z) +{ + return (void *) 0; +} + +int +foo (S *x, S *y) +{ + const char *e, *f, *g; + int h; + + h = y->a; + f = y->b; + e = x->b; + + if (h == 1) + return bar (e, *f, x->a) != 0; + + g = e + x->a - h; + while (e <= g) + { + const char *t = e + 1; + if (__builtin_memcmp (e, f, h) == 0) + return 1; + e = t; + } + return 0; +} + +int +main (void) +{ + if (foo (&c, &d) != 1) + abort (); + return 0; +} Jakub -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20126