Currently, following test fails on alpha target: FAIL: gfortran.fortran-torture/execute/intrinsic_len.f90 execution, -O2 -fomit-frame-pointer -finline-functions -funroll-loops
This is due to generic scheduler problem, where scheduler doesn't care about conflictig memory alias sets. The problem is in function w. The end of the function is expanded to: ... (insn 27 26 28 intrinsic_len.f90:21 (set (mem/s:DI (and:DI (plus:DI (reg/f:DI 69 [ __result ]) (const_int 7 [0x7])) (const_int -8 [0xfffffffffffffff8])) [0 S8 A64]) (reg:DI 81)) -1 (nil)) (insn 28 27 0 intrinsic_len.f90:21 (set (mem/s:DI (and:DI (reg/f:DI 69 [ __result ]) (const_int -8 [0xfffffffffffffff8])) [0 S8 A64]) (reg:DI 80)) -1 (nil)) ;; *i = 8; (insn 29 28 30 intrinsic_len.f90:22 (set (reg:SI 85) (const_int 8 [0x8])) -1 (nil)) (insn 30 29 0 intrinsic_len.f90:22 (set (mem:SI (reg/v/f:DI 71 [ i ]) [4 (* i) S4 A32]) (reg:SI 85)) -1 (nil)) Please note that alias set of (insn 27) and (insn 28) is set to 0 (in alpha.c, alpha_expand_unaligned_store), "the alias set which aliases everything". All is good until sched2 pass comes along: ;; 0--> 41 $29=unspec/v[$27,0x1] 10 :(ev4_ib0+ev4_ebox) ;; 1--> 42 $29=unspec/v[$29,0x1] 11 :(ev4_ib0+ev4_ebox) ;; 2--> 40 $25=$29+high(`*$LC0') :(ev4_ib0+ev4_ebox) ;; 3--> 9 $22=$25+low(`*$LC0') :(ev4_ib0+ev4_ebox) ;; 3--> 18 $21=[$16+0x7&0xfffffffffffffff8] :(ev4_ib01+ev4_abox) ;; 4--> 13 $20=$22&0x7 :(ev4_ib0+ev4_ebox) ;; 4--> 10 $24=[$25+low(`*$LC0')&0xffffffffff:(ev4_ib01+ev4_abox) ;; 5--> 11 $23=[$22+0x7&0xfffffffffffffff8] :(ev4_ib01+ev4_abox) ;; 6--> 23 $6=unspec[$21,0x40,$16] 3 :(ev4_ib0+ev4_ebox) ;; 6--> 19 $19=[$16&0xfffffffffffffff8] :(ev4_ib01+ev4_abox) ;; 7--> 14 $17=zxt($24,0x40,$22<<0x3) :(ev4_ib0+ev4_ebox) ;; 8--> 15 $8=$23<<0x40-$22&0x7<<0x3 :(ev4_ib0+ev4_ebox) ;; 9--> 24 $2=!0xffffffffffffffff<<$16<<0x3&$:(ev4_ib0+ev4_ebox) ;; 10--> 16 $8={($20==0x0)?0x0:$8} :(ev4_ib0+ev4_ebox) ;; 11--> 29 $1=0x8 :(ev4_ib0+ev4_ebox) ;; 11--> 30 [$18]=$1 :(ev4_ib1+ev4_abox) ;; 12--> 17 $7=$17|$8 :(ev4_ib0+ev4_ebox) ;; 13--> 21 $4=unspec[$7,0x40,$16] 2 :(ev4_ib0+ev4_ebox) ;; 14--> 22 $5=$7<<$16<<0x3 :(ev4_ib0+ev4_ebox) ;; 15--> 25 $3=$6|$4 :(ev4_ib0+ev4_ebox) ;; 15--> 27 [$16+0x7&0xfffffffffffffff8]=$3 :(ev4_ib1+ev4_abox) ;; 16--> 26 $0=$2|$5 :(ev4_ib0+ev4_ebox) ;; 16--> 28 [$16&0xfffffffffffffff8]=$0 :(ev4_ib1+ev4_abox) ;; 17--> 45 return :(ev4_ib1+ev4_bbox),ev4_bbox See where (insn 30) went? Unfortunately, (insn 30) was moved in between of unaligned sequence (involving load, arith ops and store from aligned address). Since the store value surrounds unaligned value, it was overwritten. Resulting code: 0x0000000120000820 <w+0>: ldah gp,2(t12) 0x0000000120000824 <w+4>: lda gp,-30952(gp) 0x0000000120000828 <w+8>: ldah t11,-2(gp) 0x000000012000082c <w+12>: ldq_u a4,7(a0) 0x0000000120000830 <w+16>: lda t8,31800(t11) 0x0000000120000834 <w+20>: ldq_u t10,31800(t11) 0x0000000120000838 <w+24>: ldq_u t9,7(t8) 0x000000012000083c <w+28>: and t8,0x7,a5 0x0000000120000840 <w+32>: extql t10,t8,a1 0x0000000120000844 <w+36>: ldq_u a3,0(a0) 0x0000000120000848 <w+40>: extqh t9,t8,t7 0x000000012000084c <w+44>: lda t0,8 0x0000000120000850 <w+48>: mskqh a4,a0,t5 0x0000000120000854 <w+52>: cmoveq a5,0,t7 0x0000000120000858 <w+56>: mskql a3,a0,t4 0x000000012000085c <w+60>: nop *1* 0x0000000120000860 <w+64>: stl t0,0(a2) 0x0000000120000864 <w+68>: or a1,t7,t6 0x0000000120000868 <w+72>: insqh t6,a0,t3 0x000000012000086c <w+76>: nop 0x0000000120000870 <w+80>: insql t6,a0,v0 0x0000000120000874 <w+84>: or t5,t3,t2 0x0000000120000878 <w+88>: stq_u t2,7(a0) 0x000000012000087c <w+92>: or t4,v0,t1 *2* 0x0000000120000880 <w+96>: stq_u t1,0(a0) 0x0000000120000884 <w+100>: ret 0x0000000120000888: nop 0x000000012000088c: unop *1* (gdb) i r $pc $t0 $a2 pc 0x120000860 0x120000860 <w+64> t0 0x8 8 a2 0x11f2bb450 4817925200 *2* (gdb) i r $pc $t1 $t2 $a0 pc 0x120000880 0x120000880 <w+96> t1 0x333231302516250f 3689065127620257039 t2 0xc30fbedf37363534 -4391081245749660364 a0 0x11f2bb454 4817925204 This happens before and after *2*: (gdb) x $a2 0x11f2bb450: 0x00000008 (gdb) si 22 i = len(w) (gdb) x $a2 0x11f2bb450: 0x2516250f (gdb) x/4 $a2 0x11f2bb450: 0x2516250f 0x33323130 0x37363534 0xc30fbedf -- Summary: scheduler does not look for conflicting alias sets Product: gcc Version: 4.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: ubizjak at gmail dot com GCC build triplet: x86_64-unknown-linux-gnu GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: alpha-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38879