re PR tree-optimization/38051 (Miscompilation of glibc's memcmp)
2008-11-15 Richard Guenther <rguenther@suse.de> PR tree-optimization/38051 * tree-ssa-alias.c (update_alias_info_1): Manually find written variables. * gcc.c-torture/execute/pr38051.c: New testcase. Co-Authored-By: Jakub Jelinek <jakub@redhat.com> From-SVN: r141887
This commit is contained in:
parent
ee9a72e50c
commit
6389463779
@ -1,3 +1,9 @@
|
||||
2008-11-15 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/38051
|
||||
* tree-ssa-alias.c (update_alias_info_1): Manually find
|
||||
written variables.
|
||||
|
||||
2008-11-15 Joshua Kinard <kumba@gentoo.org>
|
||||
|
||||
* doc/invoke.texi (-mfix-r10000): Document.
|
||||
|
@ -1,3 +1,9 @@
|
||||
2008-11-15 Richard Guenther <rguenther@suse.de>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/38051
|
||||
* gcc.c-torture/execute/pr38051.c: New testcase.
|
||||
|
||||
2008-11-15 Joshua Kinard <kumba@gentoo.org>
|
||||
Richard Sandiford <rdsandiford@goolemail.com>
|
||||
|
||||
|
205
gcc/testsuite/gcc.c-torture/execute/pr38051.c
Normal file
205
gcc/testsuite/gcc.c-torture/execute/pr38051.c
Normal file
@ -0,0 +1,205 @@
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
static int mymemcmp1 (unsigned long int, unsigned long int)
|
||||
__attribute__ ((__nothrow__));
|
||||
|
||||
__inline static int
|
||||
mymemcmp1 (unsigned long int a, unsigned long int b)
|
||||
{
|
||||
long int srcp1 = (long int) &a;
|
||||
long int srcp2 = (long int) &b;
|
||||
unsigned long int a0, b0;
|
||||
do
|
||||
{
|
||||
a0 = ((unsigned char *) srcp1)[0];
|
||||
b0 = ((unsigned char *) srcp2)[0];
|
||||
srcp1 += 1;
|
||||
srcp2 += 1;
|
||||
}
|
||||
while (a0 == b0);
|
||||
return a0 - b0;
|
||||
}
|
||||
|
||||
static int mymemcmp2 (long, long, size_t) __attribute__ ((__nothrow__));
|
||||
|
||||
static int
|
||||
mymemcmp2 (long int srcp1, long int srcp2, size_t len)
|
||||
{
|
||||
unsigned long int a0, a1;
|
||||
unsigned long int b0, b1;
|
||||
switch (len % 4)
|
||||
{
|
||||
default:
|
||||
case 2:
|
||||
a0 = ((unsigned long int *) srcp1)[0];
|
||||
b0 = ((unsigned long int *) srcp2)[0];
|
||||
srcp1 -= 2 * (sizeof (unsigned long int));
|
||||
srcp2 -= 2 * (sizeof (unsigned long int));
|
||||
len += 2;
|
||||
goto do1;
|
||||
case 3:
|
||||
a1 = ((unsigned long int *) srcp1)[0];
|
||||
b1 = ((unsigned long int *) srcp2)[0];
|
||||
srcp1 -= (sizeof (unsigned long int));
|
||||
srcp2 -= (sizeof (unsigned long int));
|
||||
len += 1;
|
||||
goto do2;
|
||||
case 0:
|
||||
if (16 <= 3 * (sizeof (unsigned long int)) && len == 0)
|
||||
return 0;
|
||||
a0 = ((unsigned long int *) srcp1)[0];
|
||||
b0 = ((unsigned long int *) srcp2)[0];
|
||||
goto do3;
|
||||
case 1:
|
||||
a1 = ((unsigned long int *) srcp1)[0];
|
||||
b1 = ((unsigned long int *) srcp2)[0];
|
||||
srcp1 += (sizeof (unsigned long int));
|
||||
srcp2 += (sizeof (unsigned long int));
|
||||
len -= 1;
|
||||
if (16 <= 3 * (sizeof (unsigned long int)) && len == 0)
|
||||
goto do0;
|
||||
}
|
||||
do
|
||||
{
|
||||
a0 = ((unsigned long int *) srcp1)[0];
|
||||
b0 = ((unsigned long int *) srcp2)[0];
|
||||
if (a1 != b1)
|
||||
return mymemcmp1 ((a1), (b1));
|
||||
do3:
|
||||
a1 = ((unsigned long int *) srcp1)[1];
|
||||
b1 = ((unsigned long int *) srcp2)[1];
|
||||
if (a0 != b0)
|
||||
return mymemcmp1 ((a0), (b0));
|
||||
do2:
|
||||
a0 = ((unsigned long int *) srcp1)[2];
|
||||
b0 = ((unsigned long int *) srcp2)[2];
|
||||
if (a1 != b1)
|
||||
return mymemcmp1 ((a1), (b1));
|
||||
do1:
|
||||
a1 = ((unsigned long int *) srcp1)[3];
|
||||
b1 = ((unsigned long int *) srcp2)[3];
|
||||
if (a0 != b0)
|
||||
return mymemcmp1 ((a0), (b0));
|
||||
srcp1 += 4 * (sizeof (unsigned long int));
|
||||
srcp2 += 4 * (sizeof (unsigned long int));
|
||||
len -= 4;
|
||||
}
|
||||
while (len != 0);
|
||||
do0:
|
||||
if (a1 != b1)
|
||||
return mymemcmp1 ((a1), (b1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mymemcmp3 (long, long, size_t) __attribute__ ((__nothrow__));
|
||||
|
||||
static int
|
||||
mymemcmp3 (long int srcp1, long int srcp2, size_t len)
|
||||
{
|
||||
unsigned long int a0, a1, a2, a3;
|
||||
unsigned long int b0, b1, b2, b3;
|
||||
unsigned long int x;
|
||||
int shl, shr;
|
||||
shl = 8 * (srcp1 % (sizeof (unsigned long int)));
|
||||
shr = 8 * (sizeof (unsigned long int)) - shl;
|
||||
srcp1 &= -(sizeof (unsigned long int));
|
||||
switch (len % 4)
|
||||
{
|
||||
default:
|
||||
case 2:
|
||||
a1 = ((unsigned long int *) srcp1)[0];
|
||||
a2 = ((unsigned long int *) srcp1)[1];
|
||||
b2 = ((unsigned long int *) srcp2)[0];
|
||||
srcp1 -= 1 * (sizeof (unsigned long int));
|
||||
srcp2 -= 2 * (sizeof (unsigned long int));
|
||||
len += 2;
|
||||
goto do1;
|
||||
case 3:
|
||||
a0 = ((unsigned long int *) srcp1)[0];
|
||||
a1 = ((unsigned long int *) srcp1)[1];
|
||||
b1 = ((unsigned long int *) srcp2)[0];
|
||||
srcp2 -= 1 * (sizeof (unsigned long int));
|
||||
len += 1;
|
||||
goto do2;
|
||||
case 0:
|
||||
if (16 <= 3 * (sizeof (unsigned long int)) && len == 0)
|
||||
return 0;
|
||||
a3 = ((unsigned long int *) srcp1)[0];
|
||||
a0 = ((unsigned long int *) srcp1)[1];
|
||||
b0 = ((unsigned long int *) srcp2)[0];
|
||||
srcp1 += 1 * (sizeof (unsigned long int));
|
||||
goto do3;
|
||||
case 1:
|
||||
a2 = ((unsigned long int *) srcp1)[0];
|
||||
a3 = ((unsigned long int *) srcp1)[1];
|
||||
b3 = ((unsigned long int *) srcp2)[0];
|
||||
srcp1 += 2 * (sizeof (unsigned long int));
|
||||
srcp2 += 1 * (sizeof (unsigned long int));
|
||||
len -= 1;
|
||||
if (16 <= 3 * (sizeof (unsigned long int)) && len == 0)
|
||||
goto do0;
|
||||
}
|
||||
do
|
||||
{
|
||||
a0 = ((unsigned long int *) srcp1)[0];
|
||||
b0 = ((unsigned long int *) srcp2)[0];
|
||||
x = (((a2) >> (shl)) | ((a3) << (shr)));
|
||||
if (x != b3)
|
||||
return mymemcmp1 ((x), (b3));
|
||||
do3:
|
||||
a1 = ((unsigned long int *) srcp1)[1];
|
||||
b1 = ((unsigned long int *) srcp2)[1];
|
||||
x = (((a3) >> (shl)) | ((a0) << (shr)));
|
||||
if (x != b0)
|
||||
return mymemcmp1 ((x), (b0));
|
||||
do2:
|
||||
a2 = ((unsigned long int *) srcp1)[2];
|
||||
b2 = ((unsigned long int *) srcp2)[2];
|
||||
x = (((a0) >> (shl)) | ((a1) << (shr)));
|
||||
if (x != b1)
|
||||
return mymemcmp1 ((x), (b1));
|
||||
do1:
|
||||
a3 = ((unsigned long int *) srcp1)[3];
|
||||
b3 = ((unsigned long int *) srcp2)[3];
|
||||
x = (((a1) >> (shl)) | ((a2) << (shr)));
|
||||
if (x != b2)
|
||||
return mymemcmp1 ((x), (b2));
|
||||
srcp1 += 4 * (sizeof (unsigned long int));
|
||||
srcp2 += 4 * (sizeof (unsigned long int));
|
||||
len -= 4;
|
||||
}
|
||||
while (len != 0);
|
||||
do0:
|
||||
x = (((a2) >> (shl)) | ((a3) << (shr)));
|
||||
if (x != b3)
|
||||
return mymemcmp1 ((x), (b3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__ ((noinline))
|
||||
int mymemcmp (const void *s1, const void *s2, size_t len)
|
||||
{
|
||||
unsigned long int a0;
|
||||
unsigned long int b0;
|
||||
long int srcp1 = (long int) s1;
|
||||
long int srcp2 = (long int) s2;
|
||||
if (srcp1 % (sizeof (unsigned long int)) == 0)
|
||||
return mymemcmp2 (srcp1, srcp2, len / (sizeof (unsigned long int)));
|
||||
else
|
||||
return mymemcmp3 (srcp1, srcp2, len / (sizeof (unsigned long int)));
|
||||
}
|
||||
|
||||
char buf[256] __attribute__((aligned (16)));
|
||||
char buf2[256] __attribute__((aligned (16)));
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
__builtin_memcpy (buf + 9,
|
||||
"\x1\x37\x82\xa7\x55\x49\x9d\xbf\xf8\x44\xb6\x55\x17\x8e\xf9", 15);
|
||||
__builtin_memcpy (buf2 + 24,
|
||||
"\x1\x37\x82\xa7\x55\x49\xd0\xf3\xb7\x2a\x6d\x23\x71\x49\x6a", 15);
|
||||
if (mymemcmp (buf + 9, buf2 + 24, 33) != -51)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
||||
|
@ -2667,6 +2667,17 @@ update_alias_info_1 (gimple stmt, struct alias_info *ai)
|
||||
|
||||
mem_ref_stats->num_mem_stmts++;
|
||||
|
||||
/* Add all decls written to to the list of written variables. */
|
||||
if (gimple_has_lhs (stmt)
|
||||
&& TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME)
|
||||
{
|
||||
tree lhs = gimple_get_lhs (stmt);
|
||||
while (handled_component_p (lhs))
|
||||
lhs = TREE_OPERAND (lhs, 0);
|
||||
if (DECL_P (lhs))
|
||||
pointer_set_insert (ai->written_vars, lhs);
|
||||
}
|
||||
|
||||
/* Notice that we only update memory reference stats for symbols
|
||||
loaded and stored by the statement if the statement does not
|
||||
contain pointer dereferences and it is not a call/asm site.
|
||||
@ -2689,25 +2700,19 @@ update_alias_info_1 (gimple stmt, struct alias_info *ai)
|
||||
dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
|
||||
memory symbols in its argument list, but these cases do not
|
||||
occur so frequently as to constitute a serious problem. */
|
||||
if (gimple_stored_syms (stmt))
|
||||
EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
|
||||
{
|
||||
tree sym = referenced_var (i);
|
||||
pointer_set_insert (ai->written_vars, sym);
|
||||
if (!stmt_dereferences_ptr_p
|
||||
&& stmt_escape_type != ESCAPE_TO_CALL
|
||||
&& stmt_escape_type != ESCAPE_TO_PURE_CONST
|
||||
&& stmt_escape_type != ESCAPE_TO_ASM)
|
||||
update_mem_sym_stats_from_stmt (sym, stmt, 0, 1);
|
||||
}
|
||||
|
||||
if (!stmt_dereferences_ptr_p
|
||||
&& gimple_loaded_syms (stmt)
|
||||
&& stmt_escape_type != ESCAPE_TO_CALL
|
||||
&& stmt_escape_type != ESCAPE_TO_PURE_CONST
|
||||
&& stmt_escape_type != ESCAPE_TO_ASM)
|
||||
EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
|
||||
update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
|
||||
{
|
||||
if (gimple_stored_syms (stmt))
|
||||
EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
|
||||
update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 0, 1);
|
||||
|
||||
if (gimple_loaded_syms (stmt))
|
||||
EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
|
||||
update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user