Bug 65810 - powerpc64 alignment of r2 insufficient for loading long-double constants
Summary: powerpc64 alignment of r2 insufficient for loading long-double constants
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: unknown
: P3 normal
Target Milestone: 6.0
Assignee: Alan Modra
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2015-04-20 00:10 UTC by Alan Modra
Modified: 2015-04-28 03:49 UTC (History)
3 users (show)

See Also:
Host:
Target: powerpc*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-04-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alan Modra 2015-04-20 00:10:28 UTC
Testsuite results between two identical powerpc64-linux builds, except for the source path name, differ.

+FAIL: gfortran.dg/fmt_en.f90   -O0  execution test
+FAIL: gfortran.dg/fmt_en.f90   -O0   scan-file All kinds rounded to nearest
+FAIL: gfortran.dg/fmt_en.f90   -O1  execution test
+FAIL: gfortran.dg/fmt_en.f90   -O1   scan-file All kinds rounded to nearest
+FAIL: gfortran.dg/fmt_en.f90   -O2  execution test
+FAIL: gfortran.dg/fmt_en.f90   -O2   scan-file All kinds rounded to nearest
+FAIL: gfortran.dg/fmt_en.f90   -O3 -fomit-frame-pointer  execution test
+FAIL: gfortran.dg/fmt_en.f90   -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions  execution test
+FAIL: gfortran.dg/fmt_en.f90   -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions   scan-file All kinds rounded to nearest
+FAIL: gfortran.dg/fmt_en.f90   -O3 -fomit-frame-pointer -funroll-loops  execution test
+FAIL: gfortran.dg/fmt_en.f90   -O3 -fomit-frame-pointer -funroll-loops   scan-file All kinds rounded to nearest
+FAIL: gfortran.dg/fmt_en.f90   -O3 -fomit-frame-pointer   scan-file All kinds rounded to nearest
+FAIL: gfortran.dg/fmt_en.f90   -O3 -g  execution test
+FAIL: gfortran.dg/fmt_en.f90   -O3 -g   scan-file All kinds rounded to nearest
+FAIL: gfortran.dg/fmt_en.f90   -Os  execution test
+FAIL: gfortran.dg/fmt_en.f90   -Os   scan-file All kinds rounded to nearest
+FAIL: gfortran.dg/large_real_kind_1.f90   -O0  execution test
+FAIL: gfortran.dg/large_real_kind_1.f90   -O1  execution test
+FAIL: gfortran.dg/large_real_kind_1.f90   -O2  execution test
+FAIL: gfortran.dg/large_real_kind_1.f90   -O3 -fomit-frame-pointer  execution test
+FAIL: gfortran.dg/large_real_kind_1.f90   -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions  execution test
+FAIL: gfortran.dg/large_real_kind_1.f90   -O3 -fomit-frame-pointer -funroll-loops  execution test
+FAIL: gfortran.dg/large_real_kind_1.f90   -O3 -g  execution test
+FAIL: gfortran.dg/large_real_kind_1.f90   -Os  execution test
+FAIL: gfortran.dg/quad_2.f90   -O0  execution test
+FAIL: gfortran.dg/quad_2.f90   -O1  execution test
+FAIL: gfortran.dg/quad_2.f90   -O2  execution test
+FAIL: gfortran.dg/quad_2.f90   -O3 -fomit-frame-pointer  execution test
+FAIL: gfortran.dg/quad_2.f90   -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions  execution test
+FAIL: gfortran.dg/quad_2.f90   -O3 -fomit-frame-pointer -funroll-loops  execution test
+FAIL: gfortran.dg/quad_2.f90   -O3 -g  execution test
+FAIL: gfortran.dg/quad_2.f90   -Os  execution test

Both compilers configured with
CC="gcc -m64" CXX="g++ -m64" \
${gcc_src}/configure --build=powerpc64-linux \
--with-cpu=power7 \
--disable-nls --enable-__cxa_atexit --enable-secureplt \
--with-long-double-128 --enable-gnu-indirect-function \
--enable-languages=all,go --enable-lto

In one case gcc_src=/home/amodra/src/gcc-5-virgin
the other gcc_src=/home/amodra/src/gcc-5-vir

Running the testcases by hand with different LD_LIBRARY_PATH show the problem is in libgfortran, not the testcase code.  valgrind doesn't show any uninitialized accesses.  

Looking at quad_2.f90 under gdb, I see the abort is due to str3 having an extra leading space.
Comment 1 Jerry DeLisle 2015-04-20 01:43:12 UTC
Could you post the output of: gfortran -v so we can confirm the version number.

I am not seeing it show up on any of the automatic testers.  I tried to access the Power7 machine I usually use and can't get in (comm problems).
Comment 2 Peter Bergner 2015-04-20 02:15:33 UTC
(In reply to Jerry DeLisle from comment #1)
> I am not seeing it show up on any of the automatic testers.  I tried to
> access the Power7 machine I usually use and can't get in (comm problems).

There is the gcc110 GCC compiler farm power7 system.
Comment 3 Alan Modra 2015-04-20 03:14:11 UTC
amodra@bns:~/build/gcc-5-virgin> gcc/gfortran -v
Using built-in specs.
COLLECT_GCC=gcc/gfortran
Target: powerpc64-linux
Configured with: /home/amodra/src/gcc-5-virgin/configure --build=powerpc64-linux --with-cpu=power7 --disable-nls --enable-__cxa_atexit --enable-secureplt --with-long-double-128 --enable-gnu-indirect-function --enable-languages=all,go --enable-lto
Thread model: posix
gcc version 5.0.1 20150416 (prerelease) (GCC)
Comment 4 Alan Modra 2015-04-20 05:24:21 UTC
Here's the bad code
   0x00000fffb7f6c438 <write_float+3736>:	addis   r9,r2,-2
   0x00000fffb7f6c43c <write_float+3740>:	li      r27,0
   0x00000fffb7f6c440 <write_float+3744>:	lfd     f24,32760(r9)
   0x00000fffb7f6c444 <write_float+3748>:	lfd     f25,-32768(r9)

It's from write_float.def:888
  r *= 10;
so is supposed to be loading up 10.0L but instead gets a completely bogus low double as seen in "d" below.
__gcc_qmul (a=1, b=0, c=10, d=-7.3968712249802237e+209)

So not something odd in libgfortran..

Hmm
p/x $r2
$31 = 0xfffb7fa1bd8

So, gcc emits toc sections with alignment of 8 bytes, which the linker respects, leading to a toc pointer (r2) that can only be assumed to be 8 byte aligned.  This completely breaks rs6000.c:offsettable_ok_by_alignment.
My bug.  Short term fix will be to limit offsettable_ok_by_alignment to 8 byte alignment.  Longer term, modify the linker to increase r2 alignment.
Comment 5 Dominique d'Humieres 2015-04-20 09:45:50 UTC
Why is this not seen on powerpc64-unknown-linux-gnu at
https://gcc.gnu.org/ml/gcc-testresults/2015-04/msg02317.html?
Comment 6 Alan Modra 2015-04-20 13:14:29 UTC
It isn't seen most of the time because the failure happens only when r2 isn't 16-byte aligned (50% chance) and the r2 offset to a long double constant is n*64k+32k-8 (0.012% chance per long double).  libgfortran stores paths for error messages in .rodata, so source path can affect placement of those long double constants.  I'm just lucky.
Comment 7 Alan Modra 2015-04-28 03:47:51 UTC
Author: amodra
Date: Tue Apr 28 03:47:19 2015
New Revision: 222498

URL: https://gcc.gnu.org/viewcvs?rev=222498&root=gcc&view=rev
Log:
	PR target/65810
	* config/rs6000/rs6000.c (POWERPC64_TOC_POINTER_ALIGNMENT): Define.
	(offsettable_ok_by_alignment): Use minimum of decl and toc
	pointer alignment.  Replace dead code with assertion.
	(use_toc_relative_ref): Add mode arg.  Return false in -mcmodel=medium
	case if size exceeds toc pointer alignment.
	(rs6000_legitimize_reload_address): Update use_toc_relative_ref call.
	(rs6000_emit_move): Likewise.
	* configure.ac: Add linker toc pointer alignment check.
	* configure: Regenerate.
	* config.in: Regenerate.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config.in
    trunk/gcc/config/rs6000/rs6000.c
    trunk/gcc/configure
    trunk/gcc/configure.ac
Comment 8 Alan Modra 2015-04-28 03:49:59 UTC
Fixed