Bug 82333 - [8 Regression] powerpc64le _Float128 ICE in as_a, at machmode.h:345
Summary: [8 Regression] powerpc64le _Float128 ICE in as_a, at machmode.h:345
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: 8.0
Assignee: Michael Meissner
URL:
Keywords:
: 82928 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-09-26 22:02 UTC by Joseph S. Myers
Modified: 2017-11-27 19:50 UTC (History)
4 users (show)

See Also:
Host:
Target: powerpc64le-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-10-27 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Joseph S. Myers 2017-09-26 22:02:18 UTC
The following code, compiled with -O2 for powerpc64le-linux-gnu, produces the following ICE.  This is a regression from GCC 7 (note you need -mfloat128 to build with older compilers), reduced from glibc test-tgmath3, and probably postdates the change to enable _Float128 support by default for powerpc64le (since the glibc test built before then, then glibc build for powerpc64le was broken for a while, and by the time it was fixed this ICE appeared).  Note, you need both the _Complex long double functions and the apparently independent _Complex _Float128 functions for this ICE to appear.

_Complex long double vld;
_Complex _Float128 vf128;

_Complex long double
fld (_Complex long double arg0)
{
  return 0;
}

_Complex _Float128
ff128 (_Complex _Float128 arg0)
{
  return 0;
}

void
tld (void)
{
  vld = fld (vld);
}

void
tf128 (void)
{
  vf128 = ff128 (vf128);
}

during RTL pass: expand
test-tgmath3.i: In function 'tf128':
test-tgmath3.i:25:9: internal compiler error: in as_a, at machmode.h:345
   vf128 = ff128 (vf128);
   ~~~~~~^~~~~~~~~~~~~~~
0x839dec scalar_mode as_a<scalar_mode>(machine_mode)
        /scratch/jmyers/glibc/many8/src/gcc/gcc/machmode.h:345
0x839dec convert_mode_scalar
        /scratch/jmyers/glibc/many8/src/gcc/gcc/expr.c:281
0x839dec convert_move(rtx_def*, rtx_def*, int)
        /scratch/jmyers/glibc/many8/src/gcc/gcc/expr.c:271
0x84091e store_expr_with_bounds(tree_node*, rtx_def*, int, bool, bool, tree_node*)
        /scratch/jmyers/glibc/many8/src/gcc/gcc/expr.c:5628
0x8424f0 expand_assignment(tree_node*, tree_node*, bool)
        /scratch/jmyers/glibc/many8/src/gcc/gcc/expr.c:5319
0x71ff95 expand_gimple_stmt_1
        /scratch/jmyers/glibc/many8/src/gcc/gcc/cfgexpand.c:3655
0x71ff95 expand_gimple_stmt
        /scratch/jmyers/glibc/many8/src/gcc/gcc/cfgexpand.c:3751
0x722796 expand_gimple_basic_block
        /scratch/jmyers/glibc/many8/src/gcc/gcc/cfgexpand.c:5750
0x7281a6 execute
        /scratch/jmyers/glibc/many8/src/gcc/gcc/cfgexpand.c:6357
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
Comment 1 Michael Meissner 2017-10-31 20:47:01 UTC
This occurs because both fld and ff128 return the same constant (0), one using it as a long double and the other as a _Float128.  Having a 0 constant is not important.  If we return 1 in both functions, it will still trap.

If we change the constant so each function (fld and ff128) returns a different value, it works.

If we suppress inlining, it works.
Comment 2 Michael Meissner 2017-11-09 20:02:00 UTC
Author: meissner
Date: Thu Nov  9 20:01:29 2017
New Revision: 254607

URL: https://gcc.gnu.org/viewcvs?rev=254607&root=gcc&view=rev
Log:
fix pr 82333

Added:
    branches/ibm/ieee/gcc/testsuite/gcc.target/powerpc/pr82333.c
Modified:
    branches/ibm/ieee/gcc/ChangeLog.meissner
    branches/ibm/ieee/gcc/builtins.c
    branches/ibm/ieee/gcc/builtins.def
    branches/ibm/ieee/gcc/c/c-decl.c
    branches/ibm/ieee/gcc/config/rs6000/rs6000.md
    branches/ibm/ieee/gcc/convert.c
    branches/ibm/ieee/gcc/fold-const-call.c
    branches/ibm/ieee/gcc/fold-const.c
    branches/ibm/ieee/gcc/internal-fn.def
    branches/ibm/ieee/gcc/testsuite/ChangeLog.meissner
    branches/ibm/ieee/gcc/testsuite/gcc.target/powerpc/float128-hw2.c
    branches/ibm/ieee/gcc/varasm.c
Comment 3 Michael Meissner 2017-11-09 21:47:13 UTC
The bug is due to compare_constant thinking two floating point constants are the same if the floating point size and the internal value are the same.  On the PowerPC, long double and _Float128 both are 128-bits, but they have different internal representations.

The bug shows up when you try to inline two functions, one that returns 0 converted to long double _Complex and the other that returns 0 converted to _Float128 _Complex.

The function compare_constant in varasm.c thinks that these two constants are the same, and assigns them to the same hash.  When inliner tries to replace the inline function (that returns 0) with the constant, it does moves of the real part and the imaginary part.  In the second function, the real/imaginary parts have type KFmode, while the first function (that has the saved constant) the real/imaginary parts have type TFmode.

The fix is to consider the type along with the precision when doing hash of the constants.
Comment 4 Michael Meissner 2017-11-09 21:53:14 UTC
Note the checkin message in note 2 was for a private branch, that included other patches that have been submitted.
Comment 5 Joseph S. Myers 2017-11-10 18:02:08 UTC
*** Bug 82928 has been marked as a duplicate of this bug. ***
Comment 6 Michael Meissner 2017-11-27 19:50:39 UTC
Fixed in subversion id 255177.