This is the mail archive of the gcc-prs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

optimization/8746: gcc-3 miscompiles Linux kernel ppa driver on x86


>Number:         8746
>Category:       optimization
>Synopsis:       gcc-3 miscompiles Linux kernel ppa driver on x86
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Thu Nov 28 08:26:06 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Carsten Haustein
>Release:        gcc releases since 3.1.1 (at least)
>Organization:
>Environment:
i586-linux-gnu; kernel 2.4.19-SMP
>Description:
This bug affects the ppa driver (used by Iomega Zip drive connected to parallel port) taken from Linux kernel 2.4.19 source tree (drivers/scsi/ppa.c) when compiled with optimization turned on.

I can reproduce it with gcc versions 3.1.1, 3.2, 3.2.1 but not with version 2.95.3. I haven't tested other versions of gcc but I think any version newer than 2.95.3 is affected.
 
Close to the end of function int ppa_completion(...) there is a check whether the zip drive is ready. This test fails always due to wrong code generation and causes the driver to spend a lot of time on waiting. Transfer rate drops down from >450 kB/s to ~50 kB/s.

The affected code is:
   ...
   unsigned char r;
   ...
   /* Now check to see if the drive is ready to communicate */
   r = (r_str(ppb) & 0xf0);
   /* If not, drop back down to the scheduler and wait a timer tick */
   if (!(r & 0x80))
      return 0;
   ...

What actually happens is:
1.) Read state byte from parport.
2.) Mask out lower nibble.
3.) Check the MSB (ready bit) of the byte read.

gcc translates this to:
1.) Read state byte into register al (8 bit).
2.) Apply bit-mask to register eax (32 bit, supersetting al).
3.) Check whether the processors sign-flag (which corresponds to the MSB) is set. Code generation for (r & 0x80) is omitted.

But since 0xf0 is applied to eax the sign-flag depends on bit 31 (which will always be cleared) rather than on bit 7 (the bit of interest).
>How-To-Repeat:

>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]