Bug 37698 - optimization compilation error, causing unaligned execptions in the kernel
optimization compilation error, causing unaligned execptions in the kernel
Status: CLOSED RAWHIDE
Product: Red Hat Raw Hide
Classification: Retired
Component: gcc (Show other bugs)
1.0
alpha Linux
medium Severity medium
: ---
: ---
Assigned To: Jakub Jelinek
David Lawrence
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2001-04-25 18:02 EDT by George France
Modified: 2007-04-18 12:32 EDT (History)
0 users

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2001-04-27 05:35:28 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description George France 2001-04-25 18:02:49 EDT
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@compaq.com.

--George
Comment 1 Jakub Jelinek 2001-04-27 05:35:23 EDT
Should be fixed by:
Tue Jan  2 10:47:38 2001  Richard Kenner  <kenner@vlsi1.ultra.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 14:09:13 EDT
Fixed in gcc-2.96-82.

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