The following testcase distilled from ggc-common.c in GCC 3.3.4 is miscompiled on ppc64. It loads a floating point value (70.0) into the pic register and dereferences it, thus the testcase segfaults. /* { dg-do run } */ /* { dg-options "-O2" } */ /* { dg-options "-mminimal-toc" { target powerpc64-*-* } } */ extern void abort (void); extern void exit (int); double __attribute__((noinline)) foo (void) { return 16441577472.0; } double __attribute__((noinline)) bar (double x) { return x; } int __attribute__((noinline)) test (void) { double x = foo (); x = bar (x); x /= 1024 * 1024 * 1024; x *= 70; x = x < 70 ? x : 70; x += 30; return x; } int main (void) { if (test () != 100) abort (); exit (0); }
At lreg time there is: (insn 38 66 39 3 (set (reg:DF 127 [ x ]) (mem/u/f:DF (plus:DI (reg:DI 30 30) (const:DI (minus:DI (symbol_ref/u:DI ("*.LC1") [flags 0x2]) (symbol_ref:DI ("*.LCTOC1"))))) [0 S8 A64])) 312 {*movdf_hardfloat64} (nil) (expr_list:REG_DEAD (reg:DI 30 30) (expr_list:REG_EQUAL (const_double:DF 7.0e+1 [0x0.8cp+7]) (nil)))) ... (insn 40 67 42 4 (set (mem/f:DF (plus:DI (reg/f:DI 31 31) (const_int 112 [0x70])) [0 x+0 S8 A64]) (reg:DF 127 [ x ])) 312 {*movdf_hardfloat64} (nil) (expr_list:REG_DEAD (reg:DF 127 [ x ]) (nil))) ... (insn 43 42 44 4 (set (reg:DF 132) (const_double:DF 3.0e+1 [0x0.fp+5])) 312 {*movdf_hardfloat64} (nil) (nil)) As insn 38 is the last one which uses the PIC register at lreg time, global alloc decides to put DF 127 into DF 30: Reloads for insn # 38 Reload 0: reload_out (DF) = (reg:DF 127 [ x ]) GENERAL_REGS, RELOAD_FOR_OUTPUT (opnum = 0) reload_out_reg: (reg:DF 127 [ x ]) reload_reg_rtx: (reg:DF 30 30) which would be fine if insn 43 was not reloaded into: (insn 43 42 44 4 (set (reg:DF 32 0 [132]) (mem/u/f:DF (plus:DI (reg:DI 30 30) (const:DI (minus:DI (symbol_ref/u:DI ("*.LC3") [flags 0x2]) (symbol_ref:DI ("*.LCTOC1"))))) [0 S8 A64])) 312 {*movdf_hardfloat64} (nil) (nil)) RS6000_PIC_OFFSET_TABLE_REGNUM is not a fixed reg on ppc64 and insn 43 at lreg time has no (use (reg:DI 30 30)) or something similar, so there is nothing that prevents this. In GCC 3.3.4 the situation is the same, but the testcase works, as register f0 is chosen instead of r30. In 3.4 without -mminimal-toc, but with -fpic or -fPIC the situation is very similar, s/r30/r2/, but r0 is chosen instead of r2 and thus the testcase doesn't fail, still I don't see what would prevent under bigger register preasure using that register. Given that rs6000_legitimize_reload_address on TARGET_TOC architectures can reference TOC_REGISTER at any time (call create_TOC_reference ()), I don't see other solution than to: if (TARGET_TOC) { fixed_regs[TOC_REGISTER] = call_used_regs[TOC_REGISTER] = 1; } in CONDITIONAL_REGISTER_USAGE (resp. rs6000_conditional_register_usage in 3.5), do you agree? Dunno if it should be call_really_used_regs[TOC_REGISTER] = 1 as well or not.
*** Bug 16197 has been marked as a duplicate of this bug. ***
*** Bug 16198 has been marked as a duplicate of this bug. ***
Confirmed, patch here: <http://gcc.gnu.org/ml/gcc-patches/2004-06/msg02060.html>.
Subject: Bug 16195 CVSROOT: /cvs/gcc Module name: gcc Changes by: jakub@gcc.gnu.org 2004-06-29 19:27:07 Modified files: gcc : ChangeLog gcc/testsuite : ChangeLog gcc/config/rs6000: rs6000.c Added files: gcc/testsuite/gcc.dg: 20040625-1.c Log message: PR target/16195 * config/rs6000/rs6000.c (rs6000_conditional_register_usage): Make r30 fixed if TARGET_TOC && TARGET_MINIMAL_TOC. (first_reg_to_save): Pretend call_used_regs[30] is 0 if TARGET_TOC && TARGET_MINIMAL_TOC. (rs6000_emit_prologue, rs6000_emit_epilogue): Likewise. * gcc.dg/20040625-1.c: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.4196&r2=2.4197 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3917&r2=1.3918 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/rs6000.c.diff?cvsroot=gcc&r1=1.654&r2=1.655 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/20040625-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
Subject: Bug 16195 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-rhl-branch Changes by: jakub@gcc.gnu.org 2004-07-03 12:11:31 Modified files: gcc : ChangeLog gcc/config/rs6000: rs6000.c rs6000.h gcc/testsuite : ChangeLog Added files: gcc/testsuite/gcc.dg: 20040625-1.c Log message: PR target/16195 * config/rs6000/rs6000.h (CONDITIONAL_REGISTER_USAGE): Make r30 fixed if TARGET_TOC && TARGET_MINIMAL_TOC. * config/rs6000/rs6000.c (first_reg_to_save): Pretend call_used_regs[30] is 0 if TARGET_TOC && TARGET_MINIMAL_TOC. (rs6000_emit_prologue, rs6000_emit_epilogue): Likewise. * gcc.dg/20040625-1.c: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=2.2326.2.399.2.22&r2=2.2326.2.399.2.23 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/rs6000.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.576.2.15.2.4&r2=1.576.2.15.2.5 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/rs6000.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.306.4.3.2.4&r2=1.306.4.3.2.5 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=1.3389.2.170.2.9&r2=1.3389.2.170.2.10 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/20040625-1.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-rhl-branch&r1=NONE&r2=1.1.2.1
Since this patch went in on the mainline, may we please also have the 3.4 backport applied?
Subject: Bug 16195 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: jakub@gcc.gnu.org 2004-08-19 22:38:59 Modified files: gcc : ChangeLog gcc/testsuite : ChangeLog gcc/config/rs6000: rs6000.c rs6000.h Added files: gcc/testsuite/gcc.dg: 20040625-1.c Log message: PR target/16195 * config/rs6000/rs6000.h (CONDITIONAL_REGISTER_USAGE): Make r30 fixed if TARGET_TOC && TARGET_MINIMAL_TOC. * config/rs6000/rs6000.c (first_reg_to_save): Pretend call_used_regs[30] is 0 if TARGET_TOC && TARGET_MINIMAL_TOC. (rs6000_emit_prologue, rs6000_emit_epilogue): Likewise. * gcc.dg/20040625-1.c: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=2.2326.2.585&r2=2.2326.2.586 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.252&r2=1.3389.2.253 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/20040625-1.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.16.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/rs6000.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.576.2.29&r2=1.576.2.30 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/rs6000.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.306.4.10&r2=1.306.4.11
Fixed.