Bug 37698 - optimization compilation error, causing unaligned execptions in the kernel
Summary: optimization compilation error, causing unaligned execptions in the kernel
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Red Hat Raw Hide
Classification: Retired
Component: gcc
Version: 1.0
Hardware: alpha
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: David Lawrence
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2001-04-25 22:02 UTC by George France
Modified: 2007-04-18 16:32 UTC (History)
0 users

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2001-04-27 09:35:28 UTC
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2001:082 0 high SHIPPED_LIVE New version of GCC 2.96-RH available fixing several bugs 2001-06-14 04:00:00 UTC

Description George France 2001-04-25 22:02:49 UTC
Using this compiler: 
Reading specs from /usr/lib/gcc-lib/alpha-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-81)

The optimizer combines two 32-bit stores (stl) in adjacent memory locations
(in a struct, for instance) into one 64-bit store (stq) if you're storing
zeroes. This is fine, unless the two 32-bit locations are not aligned on a
64-bit boundary. This test program shows the problem: 

#include <stdio.h>

struct test {
    char *     a;  /* 8 bytes */
    short int  b;  /* 2 bytes */
    int	     c[2]; /* 8 bytes */
};

int main(int argc, char **argv) {
    struct test t = {argv[0], 0, { 0, 0 } };
    printf("argv[0] is %s\n",t.a);
    return 0;
}

Compiled with the following flags, we get an unaligned access:

gcc -O2 -o test test.c

test(2636): unaligned trap at 00000001200005f8: 000000011ffff8fc 2d 31
argv[0] is ./test

Looking at the assembler source for this program, we see:

	.file	1 "test.c"
	.set noat
	.set noreorder
.section	.rodata
$LC0:
	.ascii "argv[0] is %s\12\0"
.text
	.align 4
	.globl main
	.ent main
main:
	.frame $30,80,$26,0
	.mask 0x4000000,-80
	ldgp $29,0($27)
$main..ng:
	lda $16,$LC0
	lda $30,-80($30)
	ldq $2,0($17)
	ldl $1,56($30)
	stq $31,60($30) ; <---- problem
	fnop
	ldq $3,64($30)
	mov $2,$17
	zapnot $1,252,$1
	stq $26,0($30)
	.prologue 1
	stq $2,48($30)
	stl $1,56($30)
	ldq $1,56($30)
	stq $3,32($30)
	stq $2,16($30)
	stq $1,24($30)
	jsr $26,printf
	ldgp $29,0($26)
	mov $31,$0
	ldq $26,0($30)
	lda $30,80($30)
	ret $31,($26),1
	.end main
	.ident	"GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)"

the line noted above is storing zero ($31) at an offset of 60 from the
stack pointer ($30).
60 is not divisible by 8 and thus not 64-bit aligned, so doing a 64-bit
store (stq) there causes an unaligned memory access exception. This occurs
in the linux kernel in a few places, notably the nfs3 driver.

If the program is changed so that the two 32-bit variables are assigned
separately, the following happens:

#include <stdio.h>

struct test {
    char *     a;  /* 8 bytes */
    short int  b;  /* 2 bytes */
    int      c[2]; /* 8 bytes */
};

int main(int argc, char **argv) {
    struct test t;
    t.a = argv[0];
    t.b = 0;
    t.c[0] = 0;
    t.c[1] = 0;
    printf("argv[0] is %s\n",t.a);
    return 0;
}

Assembler output:
        .file   1 "test_ok.c"
        .set noat
        .set noreorder
.section        .rodata
$LC0:
        .ascii "argv[0] is %s\12\0"
.text
        .align 4
        .globl main
        .ent main
main:
        .frame $30,48,$26,0
        .mask 0x4000000,-48
        ldgp $29,0($27)
$main..ng:
        lda $16,$LC0
        lda $30,-48($30)
        ldq $2,0($17)
        ldl $1,24($30)
        stq $26,0($30)
        .prologue 1
        mov $2,$17
        stl $31,28($30) ; <---- the first 32-bit zero
        zapnot $1,252,$1
        stl $31,32($30) ; <---- the second 32-bit zero
        stq $2,16($30)
        stl $1,24($30)
     jsr $26,printf
        ldgp $29,0($26)
        mov $31,$0
        ldq $26,0($30)
        nop
        lda $30,48($30)
        ret $31,($26),1
        .end main
        .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)"

Now, in the lines above, the stq has been broken into two stl instructions,
and no unaligned accesses occur.

(This report is being sent to jakab and bugzilla instead of gcc.gnu.org's
GNATS because it refers to Red Hat 7.1 in the gcc -v output)

Will Woods was instrumental in finding problem and reporting it. Please
direct any questions, to Will.Woods.

--George

Comment 1 Jakub Jelinek 2001-04-27 09:35:23 UTC
Should be fixed by:
Tue Jan  2 10:47:38 2001  Richard Kenner  <kenner.nyu.edu>

        * expr.c (store_constructor_field): Update ALIGN before calling
        store_constructor.

This patch was actually in the src.rpm, though only as part of one of a few
%ifarch ia64 patches.
I'm moving it into separate patch and applying unconditionally on all arches
for gcc-2.96-82.

Comment 2 Jakub Jelinek 2001-04-28 18:09:13 UTC
Fixed in gcc-2.96-82.


Note You need to log in before you can comment on or make changes to this bug.