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

Reply via email to