This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c/16028] New: Bad code gen for vector code with -O3 (caused by GRA/reload)


Following test case when compiled with -O3 shows a bug in reload, used by GRA. 
Test case:

typedef short __attribute__ ((vector_size (16))) vecint;

vecint i = { 150, 100, 150, 200, 0, 0, 0, 0 };vecint j = { 10, 13, 20, 30, 1, 1, 1, 1 };
vecint k;

union {
  vecint v;
  short i[8];
} res;
void
verify (int a1, int b1)
{
  if (a1 != b1)
    abort ();}

int
main ()
{  k = i + j;
  res.v = k;

  verify (res.i[0], 160);

  k = i & j; /* bad code gen for this statement causes the abort. */
  res.v = k;
  verify (res.i[0], 2);

  k = i * j;
  res.v = k;
  verify (res.i[0], 1500);

  exit (0);
}

Assembly code for powerpc darwin shows the bug:

        lhz r16,78(r1)  ! Only half-word is loaded
        ...
        lhz r20,94(r1)  ! Only half-word is loaded
        ...
        and r28,r16,r20 ! expects full 32bit values in r16 and r20 here
        and r29,r17,r21
        ...

Followin is the relevant RTL generated after LRA and before GRA.

From: b.c.25.lreg 

(insn:HI 11 18 29 0 (set (subreg:SI (reg:V8HI 118 [ i.0 ]) 0)
        (mem:SI (lo_sum:SI (reg/f:SI 125)
                (symbol_ref:SI ("!D__i") [flags 0x2] <var_decl 0x41700480 i>)) [0 i+0 S4 A128])) 303 
{movsi_low} (insn_list 8 (insn_list 18 (nil)))
    (nil))
...

(insn:HI 13 301 24 0 (set (subreg:SI (reg:V8HI 118 [ i.0 ]) 4)
        (mem:SI (plus:SI (reg/f:SI 124)
                (const_int 4 [0x4])) [0 i+4 S4 A32])) 309 {*movsi_internal1} (insn_list 9 (insn_list 11 (nil)))
    (nil))
...

(insn:HI 30 307 33 0 (set (reg:TI 136 [ i.0 ])
        (subreg:TI (reg:V8HI 118 [ i.0 ]) 0)) 331 {*movti_string} (insn_list 17 (nil))
    (nil))
...

(insn:HI 40 38 41 0 (set (reg:HI 145)
        (subreg:HI (reg:V8HI 118 [ i.0 ]) 2)) 311 {*movhi_internal} (insn_list 17 (nil))
    (nil))
...

(insn:HI 54 52 55 0 (set (reg:HI 157)
        (subreg:HI (reg:V8HI 118 [ i.0 ]) 6)) 311 {*movhi_internal} (insn_list 17 (nil))
    (nil))
...

(insn:HI 68 66 69 0 (set (reg:HI 169)
        (subreg:HI (reg:V8HI 118 [ i.0 ]) 10)) 311 {*movhi_internal} (insn_list 17 (nil))
    (nil))

...

(insn:HI 82 80 83 0 (set (reg:HI 181 [ i.0 ])
        (subreg:HI (reg:V8HI 118 [ i.0 ]) 14)) 311 {*movhi_internal} (insn_list 17 (nil))
    (nil))

...

(insn:HI 121 152 122 2 (parallel [
            (set (subreg:SI (reg:V8HI 121 [ T.6 ]) 0)
                (and:SI (subreg:SI (reg:V8HI 118 [ i.0 ]) 0)
                    (subreg:SI (reg:V8HI 119 [ j.1 ]) 0)))
            (clobber (scratch:CC))
        ]) 81 {andsi3} (nil)
    (expr_list:REG_UNUSED (scratch:CC)
        (nil)))

===========================================================

During reload (which implements greg) after call to emit_reload_insns,
this is how the rtl tree looks like:

(insn:HI 11 18 29 0 (set (subreg:SI (reg:V8HI 16 r16 [orig:118 i.0 ] [118]) 0)
        (mem:SI (lo_sum:SI (reg/f:SI 9 r9 [125])
                (symbol_ref:SI ("!D__i") [flags 0x2] <var_decl 0x41714480 i>)) [0 i+0 S4 A128])) 303 
{movsi_low} (insn_list 8 (ins\
n_list 18 (nil)))
    (nil))
...

r16 is set to a 16bit value here.

(insn 340 39 341 0 (set (reg:HI 16 r16)
        (reg:HI 145)) -1 (nil)
    (nil))
...


(insn:HI 82 80 83 0 (set (reg:HI 13 r13 [orig:181 i.0 ] [181])
        (subreg:HI (reg:V8HI 16 r16 [orig:118 i.0 ] [118]) 14)) 311 {*movhi_internal} (insn_list 17 (nil))
    (nil))
...

(insn:HI 121 152 122 2 (parallel [
            (set (subreg:SI (reg:V8HI 28 r28 [orig:121 T.6 ] [121]) 0)
                (and:SI (subreg:SI (reg:V8HI 16 r16 [orig:118 i.0 ] [118]) 0)
                    (subreg:SI (reg:V8HI 20 r20 [orig:119 j.1 ] [119]) 0)))
            (clobber (scratch:CC))
        ]) 81 {andsi3} (nil)
    (expr_list:REG_UNUSED (scratch:CC)
        (nil)))
==============================================

Later on insn 340 in above is changed to a load:

(insn 340 39 341 0 (set (reg:HI 16 r16)
        (mem:HI (plus:SI (reg/f:SI 1 r1)
                (const_int 78 [0x4e])) [0 S2 A8])) 311 {*movhi_internal} (nil)
    (nil))

....

Note that r16 expects the full 32-bit value. It only gets the 16bit value now.

(insn:HI 121 152 122 2 (parallel [
            (set (subreg:SI (reg:V8HI 28 r28 [orig:121 T.6 ] [121]) 0)
                (and:SI (subreg:SI (reg:V8HI 16 r16 [orig:118 i.0 ] [118]) 0)
                    (subreg:SI (reg:V8HI 20 r20 [orig:119 j.1 ] [119]) 0)))
            (clobber (scratch:CC))
        ]) 81 {andsi3} (nil)
    (expr_list:REG_UNUSED (scratch:CC)
        (nil)))
===============================================

Problem seems to originate in routine find_equiv_reg which decides that reg:HI r16 holds
the same value as reg:HI 145. But reg:SI r16 is referenced in and and:SI instruction later on.

-- 
           Summary: Bad code gen for vector code with -O3 (caused by
                    GRA/reload)
           Product: gcc
           Version: 3.5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: fjahanian at apple dot com
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: powerpc-apple-darwin7.2.0
  GCC host triplet: powerpc-apple-darwin7.2.0
GCC target triplet: powerpc-apple-darwin7.2.0


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16028


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]