Bug 84309 - [8 Regression] Wrong-code with -ffast-math
Summary: [8 Regression] Wrong-code with -ffast-math
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: Jakub Jelinek
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2018-02-09 12:35 UTC by Marek Polacek
Modified: 2018-02-13 20:23 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-02-09 00:00:00


Attachments
gcc8-pr84309.patch (966 bytes, patch)
2018-02-09 18:10 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Marek Polacek 2018-02-09 12:35:53 UTC
Target: x86_64-pc-linux-gnu

typedef __SIZE_TYPE__ size_t;
double pow (double x, double y);
double log2 (double x);

int
main ()
{
  size_t a = 1024;
  size_t b = 16 * 1024;
  size_t c = pow (2, (log2 (a) + log2 (b)) / 2);
  if (c != 4 * 1024)
    __builtin_abort ();
  return 0;
}

$ xgcc x.c -lm; ./a.out
$ xgcc x.c -lm -ffast-math; ./a.out
Aborted (core dumped)
Comment 1 Marek Polacek 2018-02-09 12:36:09 UTC
Started with r251230.
Comment 2 Jakub Jelinek 2018-02-09 16:36:49 UTC
Isn't this just an invalid test?  I mean, when working with floating point, especially when using -ffast-math, one needs to accept some inaccuracy.
Here we compute
0x1.ffffffffffff9p+11
which is 7ulps from the correct result, I'd say for -ffast-math that is within the acceptability limit.
Comment 3 Jakub Jelinek 2018-02-09 18:10:53 UTC
Created attachment 43387 [details]
gcc8-pr84309.patch

That said, if the target has c99 runtime and the constant is a power of 2, I can't imagine why exp2 (log2 (C) * x) wouldn't be faster and more precise than
exp (log (C) * x).
Comment 4 Eric Gallager 2018-02-09 18:22:31 UTC
(In reply to Jakub Jelinek from comment #2)
> Isn't this just an invalid test?  I mean, when working with floating point,
> especially when using -ffast-math, one needs to accept some inaccuracy.
> Here we compute
> 0x1.ffffffffffff9p+11
> which is 7ulps from the correct result, I'd say for -ffast-math that is
> within the acceptability limit.

There's some warnings for it:

$ /usr/local/bin/gcc -o 84309.exe -ffast-math -Wall -Wextra -pedantic -Wconversion -Wfloat-equal -Wdouble-promotion -Wtraditional-conversion -Wunsuffixed-float-constants 84309.c
84309.c: In function 'main':
84309.c:10:29: warning: passing argument 1 of 'log2' as floating rather than integer due to prototype [-Wtraditional-conversion]
   size_t c = pow (2, (log2 (a) + log2 (b)) / 2);
                             ^
84309.c:10:40: warning: passing argument 1 of 'log2' as floating rather than integer due to prototype [-Wtraditional-conversion]
   size_t c = pow (2, (log2 (a) + log2 (b)) / 2);
                                        ^
84309.c:10:19: warning: passing argument 1 of 'pow' as floating rather than integer due to prototype [-Wtraditional-conversion]
   size_t c = pow (2, (log2 (a) + log2 (b)) / 2);
                   ^
84309.c:10:14: warning: conversion from 'double' to 'size_t' {aka 'long unsigned int'} may change value [-Wfloat-conversion]
   size_t c = pow (2, (log2 (a) + log2 (b)) / 2);
              ^~~
$

Often times -Wconversion warnings are just noise, but in this case it seems as if they might actually be relevant.
Comment 5 Jakub Jelinek 2018-02-09 18:26:17 UTC
(In reply to Eric Gallager from comment #4)
> (In reply to Jakub Jelinek from comment #2)
> > Isn't this just an invalid test?  I mean, when working with floating point,
> > especially when using -ffast-math, one needs to accept some inaccuracy.
> > Here we compute
> > 0x1.ffffffffffff9p+11
> > which is 7ulps from the correct result, I'd say for -ffast-math that is
> > within the acceptability limit.
> 
> There's some warnings for it:

The warnings are completely useless.
Comment 6 Jakub Jelinek 2018-02-13 08:35:13 UTC
Author: jakub
Date: Tue Feb 13 08:34:42 2018
New Revision: 257617

URL: https://gcc.gnu.org/viewcvs?rev=257617&root=gcc&view=rev
Log:
	PR middle-end/84309
	* match.pd (pow(C,x) -> exp(log(C)*x)): Optimize instead into
	exp2(log2(C)*x) if C is a power of 2 and c99 runtime is available.
	* generic-match-head.c (canonicalize_math_after_vectorization_p): New
	inline function.
	* gimple-match-head.c (canonicalize_math_after_vectorization_p): New
	inline function.
	* omp-simd-clone.h: New file.
	* omp-simd-clone.c: Include omp-simd-clone.h.
	(expand_simd_clones): No longer static.
	* tree-vect-patterns.c: Include fold-const-call.h, attribs.h,
	cgraph.h and omp-simd-clone.h.
	(vect_recog_pow_pattern): Optimize pow(C,x) to exp(log(C)*x).
	(vect_recog_widen_shift_pattern): Formatting fix.
	(vect_pattern_recog_1): Don't check optab for calls.

	* gcc.dg/pr84309.c: New test.
	* gcc.target/i386/pr84309.c: New test.

Added:
    trunk/gcc/omp-simd-clone.h
    trunk/gcc/testsuite/gcc.dg/pr84309.c
    trunk/gcc/testsuite/gcc.target/i386/pr84309.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/generic-match-head.c
    trunk/gcc/gimple-match-head.c
    trunk/gcc/match.pd
    trunk/gcc/omp-simd-clone.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-vect-patterns.c
Comment 7 Jakub Jelinek 2018-02-13 08:37:13 UTC
Fixed.
Comment 8 Jakub Jelinek 2018-02-13 20:23:22 UTC
Author: jakub
Date: Tue Feb 13 20:22:50 2018
New Revision: 257634

URL: https://gcc.gnu.org/viewcvs?rev=257634&root=gcc&view=rev
Log:
	PR middle-end/84309
	* match.pd (pow(C,x) -> exp(log(C)*x)): Use exp2s and log2s instead
	of exps and logs in the use_exp2 case.

	* gcc.dg/pr84309-2.c: New test.

Added:
    trunk/gcc/testsuite/gcc.dg/pr84309-2.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/match.pd
    trunk/gcc/testsuite/ChangeLog