re PR target/20126 (Inlined memcmp makes one argument null on entry)
gcc/ChangeLog: 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/testsuite/ChangeLog: * gcc.dg/pr20126.c: New. From-SVN: r97939
This commit is contained in:
parent
f7d7d3b779
commit
46382283d5
@ -1,3 +1,13 @@
|
||||
2005-04-09 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
2005-04-09 Caroline Tice <ctice@apple.com>
|
||||
|
||||
* bb-reorder.c (find_rarely_executed_basic_blocks_and_crossing_edges):
|
||||
|
28
gcc/loop.c
28
gcc/loop.c
@ -5476,9 +5476,31 @@ loop_givs_rescan (struct loop *loop, struct iv_class *bl, rtx *reg_map)
|
||||
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_maybe_volatile (v->insn, v->location,
|
||||
v->new_reg))
|
||||
/* Yay, it worked! */;
|
||||
/* Not replaceable; emit an insn to set the original
|
||||
giv reg from the reduced giv. */
|
||||
else if (REG_P (*v->location))
|
||||
loop_insn_emit_before (loop, 0, v->insn,
|
||||
gen_move_insn (*v->location,
|
||||
v->new_reg));
|
||||
else
|
||||
{
|
||||
/* If it wasn't a reg, create a pseudo and use that. */
|
||||
rtx reg, seq;
|
||||
start_sequence ();
|
||||
reg = force_reg (v->mode, *v->location);
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
loop_insn_emit_before (loop, 0, v->insn, seq);
|
||||
if (!validate_change_maybe_volatile (v->insn, v->location, reg))
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
else if (v->replaceable)
|
||||
{
|
||||
reg_map[REGNO (v->dest_reg)] = v->new_reg;
|
||||
|
40
gcc/recog.c
40
gcc/recog.c
@ -235,6 +235,46 @@ validate_change (rtx object, rtx *loc, rtx new, int in_group)
|
||||
return apply_change_group ();
|
||||
}
|
||||
|
||||
|
||||
/* Function to be passed to for_each_rtx to test whether a piece of
|
||||
RTL contains any mem/v. */
|
||||
static int
|
||||
volatile_mem_p (rtx *x, void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return (MEM_P (*x) && MEM_VOLATILE_P (*x));
|
||||
}
|
||||
|
||||
/* Same as validate_change, but doesn't support groups, and it accepts
|
||||
volatile mems if they're already present in the original insn. */
|
||||
|
||||
int
|
||||
validate_change_maybe_volatile (rtx object, rtx *loc, rtx new)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (validate_change (object, loc, new, 0))
|
||||
return 1;
|
||||
|
||||
if (volatile_ok
|
||||
/* If there isn't a volatile MEM, there's nothing we can do. */
|
||||
|| !for_each_rtx (&PATTERN (object), volatile_mem_p, 0)
|
||||
/* Make sure we're not adding or removing volatile MEMs. */
|
||||
|| for_each_rtx (loc, volatile_mem_p, 0)
|
||||
|| for_each_rtx (&new, volatile_mem_p, 0)
|
||||
|| !insn_invalid_p (object))
|
||||
return 0;
|
||||
|
||||
volatile_ok = 1;
|
||||
|
||||
gcc_assert (!insn_invalid_p (object));
|
||||
|
||||
result = validate_change (object, loc, new, 0);
|
||||
|
||||
volatile_ok = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This subroutine of apply_change_group verifies whether the changes to INSN
|
||||
were valid; i.e. whether INSN can still be recognized. */
|
||||
|
||||
|
@ -74,6 +74,7 @@ extern void init_recog_no_volatile (void);
|
||||
extern int check_asm_operands (rtx);
|
||||
extern int asm_operand_ok (rtx, const char *);
|
||||
extern int validate_change (rtx, rtx *, rtx, int);
|
||||
extern int validate_change_maybe_volatile (rtx, rtx *, rtx);
|
||||
extern int insn_invalid_p (rtx);
|
||||
extern void confirm_change_group (void);
|
||||
extern int apply_change_group (void);
|
||||
|
@ -1,3 +1,7 @@
|
||||
2005-04-09 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* gcc.dg/pr20126.c: New.
|
||||
|
||||
2005-04-09 Bud Davis <bdavis@gfortran.org>
|
||||
Steven G. Kargl <kargls@comcast.net>
|
||||
|
||||
|
50
gcc/testsuite/gcc.dg/pr20126.c
Normal file
50
gcc/testsuite/gcc.dg/pr20126.c
Normal file
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user