[Bug tree-optimization/85446] New: [7/8 Regression] wrong-code on riscv64
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Wed Apr 18 08:28:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85446
Bug ID: 85446
Summary: [7/8 Regression] wrong-code on riscv64
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: jakub at gcc dot gnu.org
Target Milestone: ---
Starting with r238754 we can miscompile narrowing conversion of pointer to
integer compared against constant (unfortunately the only testcase for this I
have is for riscv64 (due to different IVOPTS decisions) which has been
introduced in r245224, so technically this is just latent bug).
Testcase for -O2 -fwrapv -fno-strict-aliasing -mabi=lp64 -march=rv64g
typedef struct
{
void *cdr;
void *car;
} cons_;
typedef cons_ *Cons;
typedef struct
{
union
{
void *_GCself;
unsigned char flags[sizeof (void *) / sizeof (unsigned char)];
} header;
void *symvalue;
void *symfunction;
void *hashcode;
void *proplist;
void *pname;
void *homepackage;
} symbol_;
typedef symbol_ *Symbol;
typedef struct
{
union
{
void *_GCself;
unsigned char flags[sizeof (void *) / sizeof (unsigned char)];
} header;
signed char rectype;
unsigned char recflags;
unsigned char reclength;
unsigned char recxlength;
void *ht_maxcount;
void *ht_kvtable;
void *ht_lookupfn;
void *ht_hashcodefn;
void *ht_testfn;
void *ht_gcinvariantfn;
void *ht_rehash_size;
void *ht_mincount_threshold;
void *ht_mincount;
void *ht_test;
void *ht_hash;
unsigned int ht_size;
} *Hashtable;
typedef struct
{
union
{
void *_GCself;
unsigned char flags[sizeof (void *) / sizeof (unsigned char)];
} header;
unsigned int length;
void *hal_filler;
void *hal_itable;
void *hal_count;
void *hal_freelist;
void *hal_data[0];
} *HashedAlist;
extern void **STACK;
extern struct symbol_tab_
{
symbol_ S_nil;
symbol_ S_t;
} symbol_tab_data;
extern unsigned int mv_count;
extern void *mv_space[127];
void
C_hash_table_iterate (void)
{
void *state = (STACK -= 1, STACK[0]);
if (((unsigned long) state) & (1UL << 62))
{
void *table = ((Cons) ((void *) ((unsigned long) state & ((1UL << 56) -
1))))->car;
while (1)
{
unsigned int index = (unsigned long) ((unsigned long) ((((Cons)
((void *) ((unsigned long) state & ((1UL << 56) - 1))))->cdr)) & ((2UL << 55) -
1));
if (index == 0)
break;
((Cons) ((void *) ((unsigned long) state & ((1UL << 56) - 1))))->cdr
= ((void *) ((unsigned char *) ((((Cons) ((void *) ((unsigned long) state &
((1UL << 56) - 1))))->cdr)) + (long) (-1)));
{
void **KVptr = &((HashedAlist) ((void *) ((unsigned long) table &
((1UL << 56) - 1))))->hal_data[3 * index - 3];
if (!(KVptr[0] == (void *) 0x380000000FFFFFFUL))
{
mv_space[0] = (void *) ((unsigned char *)
(&symbol_tab_data.S_t) + (1UL << 58));
mv_space[1] = KVptr[0];
mv_space[2] = KVptr[1];
mv_count = 3;
return;
}
}
}
}
mv_space[0] = (void *) ((unsigned char *) (&symbol_tab_data.S_nil) + (1UL <<
58));
mv_count = 1;
}
The difference between cddce3 and forwprop4 shows the bug:
unsigned int index;
...
void * prephitmp_40;
...
<bb 4> [local count: 1073741825]:
# prephitmp_40 = PHI <pretmp_35(3), _11(5)>
# ivtmp.14_36 = PHI <ivtmp.14_42(3), ivtmp.14_9(5)>
index_46 = (unsigned int) prephitmp_40;
- if (index_46 == 0)
+ if (prephitmp_40 == 0B)
goto <bb 7>; [5.50%]
else
goto <bb 5>; [94.50%]
The original was comparing only the low 32-bits of the pointer against 0, the
modified code compares the whole pointer against NULL.
More information about the Gcc-bugs
mailing list