https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61578
Dominik Vogt <vogt at linux dot vnet.ibm.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |vogt at linux dot vnet.ibm.com --- Comment #27 from Dominik Vogt <vogt at linux dot vnet.ibm.com> --- The patch in comment 22 that was applied on 2015-09-01 with the git commit id 0af99ebfea26293fc900fe9050c5dd514005e4e5 breaks the S/390 compiler (and maybe other platforms too): tt.c: -- snip -- struct t { int i; void *p; void *q; }; void foo (t **g) { (*g)->p = &((*g)->p); } -- snip -- This code should set "p" to "&p", but actually sets "q" to "&p". Before the patch, compiling with "g++ -O2" resulted in this assembly code: tt.s: lg %r1,0(%r2) # r1 := *g la %r2,8(%r1) # r2 := &((*g)->p) stg %r2,8(%r1) # *r2 := (*g) + 8 <--- GOOD with the patch it uses r1 for both, effectively doubling the store target's offset into the structure: tt.s: lg %r1,0(%r2) # r1 := *g la %r1,8(%r1) # r1 := &((*g)->p) stg %r1,8(%r1) # *(r1 + 8) := (*g) + 8 <--- BAD RTL details: ============ tt.c.232r.reload (BAD, with patch): -- snip -- (insn 6 3 7 2 (set (reg/f:DI 1 %r1 [orig:61 *g_2(D) ] [61]) (mem/f:DI (reg:DI 2 %r2 [ g ]) [1 *g_2(D)+0 S8 A64])) tt.c:9 900 {*movdi_64} (nil)) (insn 7 6 13 2 (parallel [ (set (reg/f:DI 1 %r1 [orig:61 *g_2(D) ] [61]) (plus:DI (reg/f:DI 1 %r1 [orig:61 *g_2(D) ] [61]) (const_int 8 [0x8]))) (clobber (reg:CC 33 %cc)) ]) tt.c:9 1171 {*adddi3} (nil)) (insn 13 7 10 2 (set (mem/f:DI (plus:DI (reg/f:DI 1 %r1 [orig:61 *g_2(D) ] [61]) (const_int 8 [0x8])) [2 _3->p+0 S8 A64]) (reg/f:DI 1 %r1 [orig:61 *g_2(D) ] [61])) tt.c:9 900 {*movdi_64} (nil)) -- snip -- tt.c.232r.reload (GOOD, without patch): -- snip -- (insn 6 3 12 2 (set (reg/f:DI 1 %r1 [orig:61 *g_2(D) ] [61]) (mem/f:DI (reg:DI 2 %r2 [ g ]) [1 *g_2(D)+0 S8 A64])) tt.c:9 900 {*movdi_64} (nil)) (insn 12 6 7 2 (set (reg:DI 2 %r2 [63]) (reg/f:DI 1 %r1 [orig:61 *g_2(D) ] [61])) tt.c:9 900 {*movdi_64} (nil)) (insn 7 12 13 2 (parallel [ (set (reg:DI 2 %r2 [63]) (plus:DI (reg:DI 2 %r2 [63]) (const_int 8 [0x8]))) (clobber (reg:CC 33 %cc)) ]) tt.c:9 1171 {*adddi3} (nil)) (insn 13 7 10 2 (set (mem/f:DI (plus:DI (reg/f:DI 1 %r1 [orig:61 *g_2(D) ] [61]) (const_int 8 [0x8])) [2 _3->p+0 S8 A64]) (reg:DI 2 %r2 [63])) tt.c:9 900 {*movdi_64} (nil)) -- snip -- tt.c.231r.ira (GOOD): -- snip -- (insn 6 3 7 2 (set (reg/f:DI 61 [ *g_2(D) ]) (mem/f:DI (reg:DI 2 %r2 [ g ]) [1 *g_2(D)+0 S8 A64])) tt.c:9 900 {*movdi_64} (expr_list:REG_DEAD (reg:DI 2 %r2 [ g ]) (nil))) (insn 7 6 10 2 (parallel [ (set (mem/f:DI (plus:DI (reg/f:DI 61 [ *g_2(D) ]) (const_int 8 [0x8])) [2 _3->p+0 S8 A64]) (plus:DI (reg/f:DI 61 [ *g_2(D) ]) (const_int 8 [0x8]))) (clobber (reg:CC 33 %cc)) ]) tt.c:9 1171 {*adddi3} (expr_list:REG_DEAD (reg/f:DI 61 [ *g_2(D) ]) (expr_list:REG_UNUSED (reg:CC 33 %cc) (nil)))) -- snip --