This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/16028] New: Bad code gen for vector code with -O3 (caused by GRA/reload)
- From: "fjahanian at apple dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 16 Jun 2004 21:51:40 -0000
- Subject: [Bug c/16028] New: Bad code gen for vector code with -O3 (caused by GRA/reload)
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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