I’m in the process of upgrading a gcc port, but my client is using a gcc 4.4.1
port right now and has run into a scheduler bug. This seems to have been fixed
at some point, as the 8.3.1 code base doesn’t seem to have the bug. But they’d
like a fix on their 4.4.1 base.
Basically, what I see is a block of code where we have
struct pnode * pn = ctx->return_pn;
atomic_write_u32((unsigned int*)&ctx->return_pn, 0);
x = pn-> x;
where the ‘atomic_write_u32’ is an extended asm that is basically
static inline void atomic_write_u32( unsigned int *reg, unsigned int v) {
asm ( "move %[dest], %[src]\n”
: [dest] “=m” (*reg)
: [src] “r” (v));
}
What happens is that the load of the local pn gets motioned AFTER the
assignment of zero to the passed in reference of ctx->return_pn, and we SEGV at
runtime dereferencing a NULL pointer.
I’ve checked the phase dumps and everything’s fine in the RTL until sched1,
where we end up with
;;======================================================
;; -- basic block 2 from 2 to 13 -- before reload
;; ======================================================
;; 0--> 2 r50=d0
:i_pipeline
;; 1--> 7 r51=0x0
:i_pipeline
;; 2--> 8 [r50+0x9c]=asm_operands :nothing
;; 3--> 6 r47=[r50+0x9c]
:i_pipeline <=== moved load of pn after code that zeroes it
;; 4--> 9 d0=r47
:i_pipeline
;; 5--> 10 call [`pnode_ref_dec'] :i_pipeline
;; 6--> 12 {cc=cmp([r50+0xb0],0x0);r49=[r50+0 :i_pipeline
;; 7--> 13 pc={(cc==0x0)?L23:pc} :i_pipeline
;; Ready list (final):
;; total time = 7
;; new head = 2
;; new tail = 13
I grovelled thru Bugzilla, couldn’t find anything that seemed relevant using
search terms like “sched”, “haifa”, “asm”. I’m hoping that someone might
recognize this problem and point me to a relevant Bugzilla report before I dig
into the schedule pass to try and see why it goes wrong.
I’m guessing that the pass is not recognizing the aliasing of &ctx->return_pn
in the caller and *reg in the inline asm results in thinking it’s safe to
motion a reference to ctx->return_pn...