From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19724 invoked by alias); 13 Nov 2013 02:20:09 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 19676 invoked by uid 48); 13 Nov 2013 02:20:04 -0000 From: "ian at airs dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug rtl-optimization/59099] New: Erroneous register allocation on 32-bit x86 using regparm Date: Wed, 13 Nov 2013 02:20:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: rtl-optimization X-Bugzilla-Version: 4.8.0 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: ian at airs dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status keywords bug_severity priority component assigned_to reporter cc Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2013-11/txt/msg01180.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59099 Bug ID: 59099 Summary: Erroneous register allocation on 32-bit x86 using regparm Product: gcc Version: 4.8.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: ian at airs dot com CC: vmakarov at redhat dot com The appended test case should run without error and return 0. When I compile it with -O2 -fPIC -m32 for 32-bit x86, it crashes at runtime with a segmentation violation. The generated code is incorrect. The loop is entered like this: movl 12(%esp), %eax leal 4(%esi), %ecx movl %edi, 64(%esp) xorl %esi, %esi subl $1, %eax movl %eax, 20(%esp) jmp .L7 Note that %eax holds a value stored in 20(%esp), which as we will see is used to terminate the loop. At .L7 we see this: .L7: movl 4(%esp), %edi testl %edi, %edi jne .L5 cmpl %edx, 20(%esp) jne .L5 Note that nothing changes %eax. Note the comparison with 20(%esp). At .L5 we see this: .L5: movl 64(%esp), %edi movl (%eax), %eax Note that we are loading a value from %eax. But at this point it still holds the value it was given before the loop, which is a counter, not a pointer. I have not tried to track down the problem, but superficially it appears that the register allocator has decided to rematerialize the pointer p from the register parameter, without realizing that the register has changed since the start of the function. This is reduced from code in the libgo library. The libgo code does not use regparm, but the function in question is a static function and the optimizers assign it regparm ((1)). void (*pfn)(void); struct s { void** q; int h; int t; int s; }; void* f (struct s *, struct s *) __attribute__ ((noinline, regparm(1))); void* __attribute__ ((regparm(1))) f (struct s *p, struct s *p2) { void *gp, *gp1; int t, h, s, t2, h2, c, i; if (p2->h == p2->t) return 0; (*pfn) (); h = p->h; t = p->t; s = p->s; h2 = p2->h; t2 = p2->t; gp = p2->q[h2++]; c = (t2 - h2) / 2; for (i = 0; i != c; i++) { if (t == h || (h == 0 && t == s - 1)) break; gp1 = p2->q[h2++]; p->q[t++] = gp1; if (t == s) t = 0; } p2->h = h2; return gp; } static void fn () { } int main() { struct s s1, s2; void *q[10]; pfn = fn; s1.q = q; s1.h = 0; s1.t = 2; s1.s = 4; s2.q = q; s2.h = 0; s2.t = 4; s2.s = 2; f (&s1, &s2); return 0; }