Bug 20432 - complex reciprocal has too many operations
Summary: complex reciprocal has too many operations
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.1.0
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2005-03-11 21:17 UTC by Thomas Koenig
Modified: 2021-08-15 00:53 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-08-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Koenig 2005-03-11 21:17:24 UTC
#include <math.h>
#include <complex.h>

int main()
{
    float complex c,d;
    foo(&c);
    d=1.0/c;
    return creal(d)+cimag(d)<0;
}
$ gcc -S -O -fdump-tree-optimized recip.c
$ tail -25 recip.c.t66.optimized
<bb 0>:
  foo (&c);
  SR.24 = (double) REALPART_EXPR <c>;
  SR.23 = (double) IMAGPART_EXPR <c>;
  if (ABS_EXPR <SR.24> < ABS_EXPR <SR.23>) goto <L1>; else goto <L2>;

<L1>:;
  D.2387 = SR.24 / SR.23;
  D.2389 = SR.23 + SR.24 * D.2387;
  SR.25 = (D.2387 + 0.0) / D.2389;
  SR.26 = (D.2387 * 0.0 - 1.0e+0) / D.2389;
  goto <bb 3>;

<L2>:;
  D.2395 = SR.23 / SR.24;
  D.2397 = SR.24 + SR.23 * D.2395;
  SR.25 = (D.2395 * 0.0 + 1.0e+0) / D.2397;
  SR.26 = (0.0 - D.2395) / D.2397;

<bb 3>:
  return (double) (float) SR.25 + (double) (float) SR.26 < 0.0;

}

$ gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: ../gcc-4.1/configure --prefix=/home/ig25 --enable-languages=c,f95
Thread model: posix
gcc version 4.1.0 20050311 (experimental)

I can't see a reason why the +0 and *0 operations should
be necessary.  

Thomas
Comment 1 Andrew Pinski 2005-03-11 21:25:06 UTC
D.2395 * 0.0
Can trap if D.2395 is a non quiet NAN.
Likewise for "D.2387 + 0.0"
Though in this case it does not matter because we are going to trap later on.
Comment 2 Thomas Koenig 2005-03-11 21:36:39 UTC
(In reply to comment #1)
> D.2395 * 0.0
> Can trap if D.2395 is a non quiet NAN.

D.2395 gets its value from

  D.2395 = SR.23 / SR.24;

two lines earlier.  Is there anything that would generate
a signaling NaN for this case and not trap immediately?

> Likewise for "D.2387 + 0.0"

Same argument.

> Though in this case it does not matter because we are going to trap later on.

.. which is true, and which is why I think this is missed-optimization.
Comment 3 Andrew Pinski 2005-03-12 17:35:06 UTC
I cannot remember the rules but -0.0 * 0.0 could be -0.0 (and not 0.0), someone needs to help me 
here.
Comment 4 Thomas Koenig 2005-03-17 13:41:17 UTC
(In reply to comment #3)
> I cannot remember the rules but -0.0 * 0.0 could be -0.0 (and not 0.0),
someone needs to help me 
> here.

I'm trying to see what input could apply to, but I can't think of one.
What were you referring to?
Comment 5 Thomas Koenig 2008-12-11 21:22:45 UTC
This is still active with gcc -cx-complex-rules:

<bb 2>:
  foo (&c);
  D.2256 = (double) REALPART_EXPR <c>;
  D.2258 = (double) IMAGPART_EXPR <c>;
  if (ABS_EXPR <D.2256> < ABS_EXPR <D.2258> != 0)
    goto <bb 3>;
  else
    goto <bb 4>;

<bb 3>:
Invalid sum of outgoing probabilities 0.0%
Invalid sum of incoming frequencies 10000, should be 0
  D.2292 = D.2256 / D.2258;
  D.2294 = D.2258 + D.2256 * D.2292;
  CR.13 = D.2292 + 0.0 / D.2294;
  CI.14 = D.2292 * 0.0 - 1.0e+0 / D.2294;
  goto <bb 5>;

<bb 4>:
Invalid sum of outgoing probabilities 0.0%
  D.2300 = D.2258 / D.2256;
  D.2302 = D.2256 + D.2258 * D.2300;
  CR.13 = D.2300 * 0.0 + 1.0e+0 / D.2302;
  CI.14 = 0.0 - D.2300 / D.2302;

Maybe time to confirm this bug after more than three years :-)
Comment 6 Thomas Koenig 2016-08-30 18:23:15 UTC
Still an issue:

#include <math.h>
#include <complex.h>

int main()
{
    float complex c,d;
    foo(&c);
    d=1.0f/c;
    return creal(d)+cimag(d)<0;
}

Using -fcx-fortran-rules yields (from the optimized dump)

  _13 = REALPART_EXPR <c>;
  _14 = IMAGPART_EXPR <c>;
  _15 = ABS_EXPR <_13>;
  _16 = ABS_EXPR <_14>;
  if (_15 < _16)
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 3>:
  _18 = _13 / _14;
  _19 = _13 * _18;
  _20 = _14 + _19;
  _21 = _18 + 0.0;
  _22 = _18 * 0.0;
  _23 = _22 - 1.0e+0;
  _24 = _21 / _20;
  _25 = _23 / _20;
  goto <bb 5>;

  <bb 4>:
  _26 = _14 / _13;
  _27 = _14 * _26;
  _28 = _13 + _27;
  _29 = _26 * 0.0;
  _30 = _29 + 1.0e+0;
  _31 = 0.0 - _26;
  _32 = _30 / _28;
  _33 = _31 / _28;


I do not think it is possible to create a NaN/Inf situation here
where just ignoring the imaginary zero is wrong.