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