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.