Bug 59679 - gcc version 4.7.3 and gcc version 4.5.3 cause an unaligned access exception on NetBSD/Alpha
Summary: gcc version 4.7.3 and gcc version 4.5.3 cause an unaligned access exception o...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.7.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-01-05 01:57 UTC by nullnilaki
Modified: 2014-06-12 13:52 UTC (History)
2 users (show)

See Also:
Host:
Target: alpha-netbsd
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-01-05 00:00:00


Attachments
perl.h (48.65 KB, text/x-csrc)
2014-01-05 20:57 UTC, nullnilaki
Details
scope.c (9.45 KB, text/x-csrc)
2014-01-05 20:57 UTC, nullnilaki
Details
preprocess scope.c(NO.1) (52.06 KB, text/plain)
2014-01-06 16:32 UTC, nullnilaki
Details
preprocess scope.c(NO.2) (58.73 KB, text/plain)
2014-01-06 16:56 UTC, nullnilaki
Details
preprocess scope.c(NO.3) (125.05 KB, text/plain)
2014-01-06 16:57 UTC, nullnilaki
Details
Reduced version of scope.c illustrating problem. (665 bytes, text/x-csrc)
2014-01-26 23:00 UTC, Michael Cree
Details
Preprocessed version of scope-reduced.c (74.81 KB, text/x-csrc)
2014-01-26 23:01 UTC, Michael Cree
Details

Note You need to log in before you can comment on or make changes to this bug.
Description nullnilaki 2014-01-05 01:57:21 UTC
Using gcc4.7.3 and gcc4.5.3 to compile a Perl v5.18.1.
Perl cause an unaligned access exception.
----------------------------------------------------------------

Please read the perl-bug
https://rt.perl.org/Public/Bug/Display.html?id=120888

----------------------------------------------------------------

gcc4.5 and gcc4.7 cause this problem.
(I can not compile gcc4.6 and gcc4.8 but I think gcc4.6 and gcc4.8 has some 
kind of similar bug.)

----------------------------------------------------------------

This problem was caused by compiler's bug. -ftree-ter option makes wrong binary. 

----------------------------------------------------------------

-O2 version.

(gdb) break scope.c:1217
No source file named scope.c.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (scope.c:1217) pending.
(gdb) r perl.pl
Starting program: /usr/pkg/bin/perl perl.pl
[Switching to LWP 1]

Breakpoint 1, Perl_leave_scope (my_perl=0x160505000, base=<optimized out>) at 
scope.c:1217
1217                *(I8*)ARG0_PTR = (I8)(uv >> 8);
(gdb) list
1212    
1213            case SAVEt_I16:                         /* I16 reference */
1214                *(I16*)ARG0_PTR = (I16)(uv >> 8);
1215                break;
1216            case SAVEt_I8:                          /* I8 reference */
1217                *(I8*)ARG0_PTR = (I8)(uv >> 8);
1218                break;
1219            case SAVEt_DESTRUCTOR:
1220                (*arg1.any_dptr)(ARG0_PTR);
1221                break;
(gdb) x/10i $pc
=> 0x1601795c0 <Perl_leave_scope+3648>: extbl   t5,0x1,t5
   0x1601795c4 <Perl_leave_scope+3652>: ldl     t0,0(s1)
   0x1601795c8 <Perl_leave_scope+3656>: andnot  t0,0xff,t0
   0x1601795cc <Perl_leave_scope+3660>: or      t5,t0,t5
   0x1601795d0 <Perl_leave_scope+3664>: stl     t5,0(s1)
   0x1601795d4 <Perl_leave_scope+3668>: ldl     t3,48(s0)
   0x1601795d8 <Perl_leave_scope+3672>: ldl     t0,152(s0)
   0x1601795dc <Perl_leave_scope+3676>: br      0x160178800 
<Perl_leave_scope+128>
   0x1601795e0 <Perl_leave_scope+3680>: mov     s0,a0
   0x1601795e4 <Perl_leave_scope+3684>: ldq     t12,-24984(gp)
(gdb) p uv
$1 = 2574
(gdb) ptype uv
type = long unsigned int
(gdb) ptype I8
type = signed char
(gdb) print /a uv
$2 = 0xa0e
(gdb) p arg0
$1 = {any_ptr = 0x1605104ee, any_i32 = 1615922414, any_iv = 5910889710, any_uv 
= 5910889710, any_long = 5910889710, any_bool = 238, 
  any_dptr = 0x1605104ee, any_dxptr = 0x1605104ee}
(gdb) p &arg0
Address requested for identifier "arg0" which is in register $s1
(gdb) n
pid 436 (perl): unaligned access: va=0x1605104ee pc=0x1601795c4 ra=0x160179124 
sp=0x1ffffc698 op=ldl
pid 436 (perl): unaligned access: va=0x1605104ee pc=0x1601795d0 ra=0x160179124 
sp=0x1ffffc698 op=stl
1218                break;
1218                break;
(gdb) p uv
$1 = <optimized out>

-------------------------------------------------------------------

-O2 -fno-tree-ter version.
 
(gdb) break scope.c:1217
No source file named scope.c.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (scope.c:1217) pending.
(gdb) r perl.pl
Starting program: /usr/pkg/bin/perl perl.pl
[Switching to LWP 1]

Breakpoint 1, Perl_leave_scope (my_perl=0x160505000, base=<optimized out>) at 
scope.c:1217
1217                *(I8*)ARG0_PTR = (I8)(uv >> 8);
(gdb) x/10i $pc
=> 0x160177df0 <Perl_leave_scope+3664>: extbl   t5,0x1,t5
   0x160177df4 <Perl_leave_scope+3668>: ldq_u   t0,0(s1)
   0x160177df8 <Perl_leave_scope+3672>: insbl   t5,s1,t5
   0x160177dfc <Perl_leave_scope+3676>: mskbl   t0,s1,t0
   0x160177e00 <Perl_leave_scope+3680>: or      t5,t0,t5
   0x160177e04 <Perl_leave_scope+3684>: stq_u   t5,0(s1)
   0x160177e08 <Perl_leave_scope+3688>: ldl     t3,48(s0)
   0x160177e0c <Perl_leave_scope+3692>: ldl     t0,152(s0)
   0x160177e10 <Perl_leave_scope+3696>: br      0x160177020 
<Perl_leave_scope+128>
   0x160177e14 <Perl_leave_scope+3700>: unop    
(gdb) p uv
$1 = 2574
(gdb) ptype uv
type = long unsigned int
(gdb) ptype I8
type = signed char
(gdb) print /a uv
$2 = 0xa0e
(gdb) p arg0
$1 = {any_ptr = 0x1605104ee, any_i32 = 1615922414, any_iv = 5910889710, any_uv 
= 5910889710, any_long = 5910889710, any_bool = 238, 
  any_dptr = 0x1605104ee, any_dxptr = 0x1605104ee}
(gdb) n
1218                break;
Comment 1 Andrew Pinski 2014-01-05 04:32:56 UTC
This looks more like a bug in perl sources.  Can you attach the preprocessed source for scope.c?

The big question is how is ARG0_PTR defined?  GCC must be assuming the alignment is 64bits for some reason.  This needs the preprocessed source to see why the alignment is being done incorrectly.  Maybe ARG0_PTR was assigned from a long long pointer. 

In C, once you assign it to a pointer of bigger alignment and it is not aligned, the code is undefined.
Comment 2 nullnilaki 2014-01-05 20:57:02 UTC
Created attachment 31576 [details]
perl.h

perl.h
Comment 3 nullnilaki 2014-01-05 20:57:40 UTC
Created attachment 31577 [details]
scope.c

scope.c
Comment 4 nullnilaki 2014-01-05 21:02:27 UTC
(In reply to Andrew Pinski from comment #1)
> This looks more like a bug in perl sources.  Can you attach the preprocessed
> source for scope.c?
> 
> The big question is how is ARG0_PTR defined?  GCC must be assuming the
> alignment is 64bits for some reason.  This needs the preprocessed source to
> see why the alignment is being done incorrectly.  Maybe ARG0_PTR was
> assigned from a long long pointer. 
> 
> In C, once you assign it to a pointer of bigger alignment and it is not
> aligned, the code is undefined.

Thank you for your reply!

ARG0_PTR is defined in scope.c.
#define ARG0_PTR arg0.any_ptr

and

any_ptr is defined in perl.h.

union any {
    void*       any_ptr;
    I32         any_i32;
    IV          any_iv;
    UV          any_uv;
    long        any_long;
    bool        any_bool;
    void        (*any_dptr) (void*);
    void        (*any_dxptr) (pTHX_ void*);
};
Comment 5 Andrew Pinski 2014-01-05 23:08:11 UTC
This is still not the preprocessed source.  We need the preprocessed source and the exact options you used to compile the source and the exact options used to configure gcc with.
Comment 6 nullnilaki 2014-01-06 16:01:42 UTC
(In reply to Andrew Pinski from comment #5)
> This is still not the preprocessed source.  We need the preprocessed source
> and the exact options you used to compile the source and the exact options
> used to configure gcc with.

Thank you for your reply!
>We need the preprocessed source...
I made a mistake.
Sorry...
--------------------------------------------------------------
Compile option.

[*] /usr/pkgsrc/lang/perl5/work/.wrapper/bin/cc /usr/pkgsrc/lang/perl5/work/.wrapper/bin/cc -c -DPERL_CORE -O2 -mieee -pthread -I/usr/include -fno-strict-aliasing -pipe -
I/usr/pkg/include -std=c89 -O2 -mieee -pthread -I/usr/include -Wall -ansi -W -Wextra -Wdeclaration-after-statement -Wendif-labels -Wc++-compat -Wwrite-strings -DPIC -fPIC
 scope.c
WARNING: [transform-gcc] passing unknown option -mieee
WARNING: [transform-gcc] passing unknown option -std=c89
WARNING: [transform-gcc] passing unknown option -mieee
WARNING: [transform-gcc] passing unknown option -ansi
WARNING: [transform-gcc] passing unknown option -Wdeclaration-after-statement
WARNING: [transform-gcc] passing unknown option -Wendif-labels
WARNING: [transform-gcc] passing unknown option -Wc++-compat
<.> /usr/pkgsrc/lang/perl5/work/.gcc/bin/gcc -c -DPERL_CORE -O2 -mieee -pthread -fno-strict-aliasing -pipe -I/usr/pkgsrc/lang/perl5/work/.buildlink/include -std=c89 -O2 -
mieee -pthread -Wall -ansi -W -Wextra -Wdeclaration-after-statement -Wendif-labels -Wc++-compat -Wwrite-strings -DPIC -fPIC scope.c -L/usr/pkgsrc/lang/perl5/work/.buildli
nk/lib

--------------------------------------------------------------
Comment 7 nullnilaki 2014-01-06 16:32:42 UTC
Created attachment 31756 [details]
preprocess scope.c(NO.1)

preprocess scope.c(This source is very large. Please concatenate files.)
Comment 8 nullnilaki 2014-01-06 16:56:13 UTC
Created attachment 31757 [details]
preprocess scope.c(NO.2)

preprocess scope.c(This source is very large. Please concatenate files.)
Comment 9 nullnilaki 2014-01-06 16:57:12 UTC
Created attachment 31758 [details]
preprocess scope.c(NO.3)

preprocess scope.c(This source is very large. Please concatenate files.)
Comment 10 Michael Cree 2014-01-26 22:56:40 UTC
This misaligned access in perl is also seen on Debian Alpha Linux. I have been able to reduce the scope.c file substantially while maintaining the misaligned access.  I will attach that as scope-reduced.c.

The misaligned access occurs in line 60, being the case SAVEt_I8 of the switch statement, and with -O2 compiles to:

        extbl $4,1,$4
$LVL18:
        ldl $1,0($6)
        bic $1,255,$1
        bis $4,$1,$4
        stl $4,0($6)

Thus there is an assumption that ARG0_PTR (which expands to arg0.any_ptr) points to an address at least divisible by four.

If one compiles with -fno-tree-ter as mentioned in the initial bug report then
one gets:

        sll $5,48,$5
$LVL18:
        ldq_u $1,0($4)
        sra $5,56,$5
        mskbl $1,$4,$1
        insbl $5,$4,$5
        bis $5,$1,$5
        stq_u $5,0($4)

which copes with any alignment.

If either of the cases SAVEt_SAVESWITCHSTACK or SAVEt_SET_SVFLAGS is removed from the switch statement then the ldq_u/mskbl/insbl sequence results. Thus there appears to be some interaction between those two cases and the code at the top of the while statement that the compiler is using to determine that ARG0_PTR points to an address at least divisible by four.  I admit that I have so far failed to see how such an inference can be made but look forward to being educated by the erudite gcc maintainers.

Compilation was done with:

cc -DPERL_CORE  -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -D_FORTIFY_SOURCE=2 -g -O2 -v -S scope-reduced.c
Using built-in specs.
COLLECT_GCC=cc
Target: alpha-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.8.2-13' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libssp --disable-libmudflap --disable-libitm --disable-libsanitizer --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-alpha/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-alpha --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-alpha --with-arch-directory=alpha --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-long-double-128 --enable-checking=release --build=alpha-linux-gnu --host=alpha-linux-gnu --target=alpha-linux-gnu
Thread model: posix
gcc version 4.8.2 (Debian 4.8.2-13) 
COLLECT_GCC_OPTIONS='-D' 'PERL_CORE' '-D' '_REENTRANT' '-D' '_GNU_SOURCE' '-D' 'DEBIAN' '-D' '_FORTIFY_SOURCE=2' '-g' '-O2' '-v' '-S'
 /usr/lib/gcc/alpha-linux-gnu/4.8/cc1 -quiet -v -imultilib . -imultiarch alpha-linux-gnu -D PERL_CORE -D _REENTRANT -D _GNU_SOURCE -D DEBIAN -D _FORTIFY_SOURCE=2 scope-reduced.c -quiet -dumpbase scope-reduced.c -auxbase scope-reduced -g -O2 -version -o scope-reduced.s
GNU C (Debian 4.8.2-13) version 4.8.2 (alpha-linux-gnu)
	compiled by GNU C version 4.8.2, GMP version 5.1.3, MPFR version 3.1.2-p3, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/alpha-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/alpha-linux-gnu/4.8/../../../../alpha-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/alpha-linux-gnu/4.8/include
 /usr/local/include
 /usr/lib/gcc/alpha-linux-gnu/4.8/include-fixed
 /usr/include/alpha-linux-gnu
 /usr/include
End of search list.
GNU C (Debian 4.8.2-13) version 4.8.2 (alpha-linux-gnu)
	compiled by GNU C version 4.8.2, GMP version 5.1.3, MPFR version 3.1.2-p3, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 503630c10eca9d1ddabc1e36fce68a5f
COMPILER_PATH=/usr/lib/gcc/alpha-linux-gnu/4.8/:/usr/lib/gcc/alpha-linux-gnu/4.8/:/usr/lib/gcc/alpha-linux-gnu/:/usr/lib/gcc/alpha-linux-gnu/4.8/:/usr/lib/gcc/alpha-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/alpha-linux-gnu/4.8/:/usr/lib/gcc/alpha-linux-gnu/4.8/../../../alpha-linux-gnu/:/usr/lib/gcc/alpha-linux-gnu/4.8/../../../:/lib/alpha-linux-gnu/:/lib/:/usr/lib/alpha-linux-gnu/:/usr/lib/
COLLECT_GCC_OPTIONS='-D' 'PERL_CORE' '-D' '_REENTRANT' '-D' '_GNU_SOURCE' '-D' 'DEBIAN' '-D' '_FORTIFY_SOURCE=2' '-g' '-O2' '-v' '-S'

I will also attach preprocessed source.
Comment 11 Michael Cree 2014-01-26 23:00:06 UTC
Created attachment 31957 [details]
Reduced version of scope.c illustrating problem.
Comment 12 Michael Cree 2014-01-26 23:01:22 UTC
Created attachment 31958 [details]
Preprocessed version of scope-reduced.c
Comment 13 Uroš Bizjak 2014-01-28 16:54:14 UTC
Confirmed as tree-optimization problem on 4.9 branch.

The compiler was build as a crosscompiler from x86_64-linux-gnu to alpha-linux-gnu, configured with "configure --target=alpha-linux-gnu".

The preprocessed source from comment 12 is compiled with:

a) gcc-build-alpha/gcc/cc1 -O2 -fno-tree-ter -fpreprocessed scope-reduced-preprocessed.c
b) gcc-build-alpha/gcc/cc1 -O2 -fpreprocessed scope-reduced-preprocessed.c

where a) creates correct binary (scope-reduced.s) and b) creates wrong binary (scope-reduced_.s).

The difference between scope-reduced.s (correct) and scope-reduced_.s (wrong):

--- scope-reduced.s     2014-01-28 17:45:07.803092987 +0100
+++ scope-reduced_.s    2014-01-28 17:44:50.365312704 +0100
@@ -16,7 +16,7 @@
 $Perl_leave_scope..ng:
        lda $30,-16($30)
        cpys $f31,$f31,$f31
-       mov $31,$5
+       mov $31,$6
        ldl $1,48($16)
        mov $31,$8
        stq $26,0($30)
@@ -33,10 +33,10 @@
        s8addq $2,$1,$1
        ldq $3,0($1)
        and $3,63,$18
-       cmpule $18,4,$6
-       bne $6,$L3
+       cmpule $18,4,$5
+       bne $5,$L3
        cmpule $18,20,$2
-       ldq $5,-8($1)
+       ldq $6,-8($1)
        beq $2,$L4
        lda $2,-8($1)
 $L5:
@@ -65,14 +65,12 @@
        br $31,$L5
        .align 4
 $L17:
-       sll $3,48,$3
-       ldq_u $1,0($5)
-       sra $3,56,$3
-       mskbl $1,$5,$1
-       insbl $3,$5,$3
+       extbl $3,1,$3
+       ldl $1,0($6)
+       bic $1,255,$1
        cpys $f31,$f31,$f31
        bis $3,$1,$3
-       stq_u $3,0($5)
+       stl $3,0($6)
        ldl $1,48($16)
        cmplt $17,$1,$2
        bne $2,$L12
@@ -84,24 +82,24 @@
 $L9:
        ldl $2,12($8)
        ldl $1,48($16)
-       bis $5,$2,$2
+       bis $6,$2,$2
        stl $2,12($8)
        br $31,$L2
        .align 4
 $L8:
        ldq $3,0($16)
        ldq $22,24($16)
-       ldq $4,0($5)
+       ldq $4,0($6)
        bis $31,$31,$31
        mov $2,$1
-       ldq $6,0($7)
+       ldq $5,0($7)
        subq $3,$22,$2
        cpys $f31,$f31,$f31
        sra $2,3,$2
        stq $2,16($4)
        ldq $4,16($7)
-       ldq $3,24($6)
-       ldq $2,16($6)
+       ldq $3,24($5)
+       ldq $2,16($5)
        stq $4,24($16)
        s8addq $3,$4,$3
        stq $7,184($16)

The problem can be seen just after $L17 label.
Comment 14 Uroš Bizjak 2014-01-28 17:16:58 UTC
There is no differences in .optimized tree dumps.
Comment 15 Uroš Bizjak 2014-01-28 18:25:46 UTC
(In reply to Uroš Bizjak from comment #13)
> Confirmed as tree-optimization problem on 4.9 branch.

Actually, a middle-end problem, if at all. With -ftree-ter, expand creates a couple of unaligned loads to arg0:

(insn 101 100 102 (set (reg:SI 150)
        (mem:SI (reg/v/f:DI 115 [ arg0 ]) [0  S4 A8])) scope-reduced.c:60 -1
     (nil))
...
(insn 105 104 106 17 (set (mem:SI (reg/v/f:DI 115 [ arg0 ]) [0  S4 A8])
        (reg:SI 151)) scope-reduced.c:60 -1
     (nil))
Comment 16 Uroš Bizjak 2014-01-28 18:26:32 UTC
(In reply to Uroš Bizjak from comment #15)
> (In reply to Uroš Bizjak from comment #13)
> > Confirmed as tree-optimization problem on 4.9 branch.
> 
> Actually, a middle-end problem, if at all. With -ftree-ter, expand creates a
> couple of unaligned loads to arg0:

s/loads/moves/
Comment 17 Uroš Bizjak 2014-01-29 16:38:58 UTC
Some more analysis:

The target code expands non-bwx QImode store

;; MEM[(I8 *)_67] = _69;

via alpha_expand_mov_nobwx, where around line 2229 (config/alpha.c) target address gets checked with "aligned_memory_operand" predicate.  The pointer is "reg/v/f:DI 115 [ arg0 ])", and its REGNO_POINTER_ALIGN is 64. This later datum makes aligned_memory_operand predicate to return true.

The pointer alignment for reg 115 is set in mark_reg_pointer from

(insn 68 67 69 (set (reg/f:DI 134)
        (mem/f:DI (reg/v/f:DI 115 [ arg0 ]) [2 MEM[(struct AV *)_p_36].sv_any+0 S8 A64])) scope-reduced.c:53 -1
     (nil))

since reg 115 is used naked to access 64bit aligned value.

The above (insn 68) is defined in BB 11, where the only predecessor is BB 10 (a switch), and the only successor is BB 15.

Hovever (insn 101):

(insn 101 100 102 (set (reg:SI 150)
        (mem:SI (reg/v/f:DI 115 [ arg0 ]) [0  S4 A8])) scope-reduced.c:60 -1
     (nil))

which assumes 64 bit pointer alignment, lives in BB 13. Again, the only predecessor is BB 10, and the only successor is BB 15.

The initialization of reg 115 is in BB 4 from a memory location:

(insn 27 26 0 (set (reg/v:DI 115 [ arg0 ])
        (mem:DI (plus:DI (reg/v/f:DI 76 [ p0 ])
                (const_int -8 [0xfffffffffffffff8])) [27 MEM[(union ANY *)p0_16 + -8B]+0 S8 A64])) scope-reduced.c:37 -1
     (nil))

and since everything is inside a loop, it looks to me there is no way for GCC to assume inheritance of pointer alignments in BB 13 from BB 10.
Comment 18 Uroš Bizjak 2014-01-29 16:44:33 UTC
(In reply to Uroš Bizjak from comment #17)

> and since everything is inside a loop, it looks to me there is no way for
> GCC to assume inheritance of pointer alignments in BB 13 from BB 10.

The last line should read:

GCC to assume inheritance of pointer alignments in BB 13 from BB 11.

This is middle-end infrastructure problem. Adding CC.
Comment 19 Richard Biener 2014-06-12 13:52:30 UTC
Unsetting target milestone of open non-regression bug from version of branch being closed.