https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67815

            Bug ID: 67815
           Summary: Optimize const1 * copysign (const2, y) into copysign
                    (const1 * const2, y) if const1 > 0 or -copysign
                    (const1 * const2, y) if const1 < 0
           Product: gcc
           Version: 5.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
  Target Milestone: ---

In 481.wrf, I've noticed several occurrences of (1/12.) * copysign (1.0, var)
and likewise with other constants.  This should be optimizable into just
copysign (1/12., var) (or, say for (-1/12.) * copysign (1.0, var) into
-copysign (1/12., var).
As the expressions are actually x * const1 * copysign (const2, y), the const1
and copysign factors might not appear together, and while reassoc1 pass
sometimes puts them together, sometimes it does not:
  _2051 = __builtin_copysignf (1.0e+0, vel_2000);
...
  _2059 = _2051 * _2058;
  _2060 = _2059 * 1.666666753590106964111328125e-2;
is before reassoc1 and
  _2051 = __builtin_copysignf (1.0e+0, vel_2000);
...
  _2047 = _2051 * 1.666666753590106964111328125e-2;
  _2060 = _2047 * _2058;
is after reassoc1, so in this case reassoc1 worked fine, but in another spot
I see
  _2968 = __builtin_copysignf (1.0e+0, vel_2943);
...
  _2973 = _2968 * _2972;
  _2974 = _2973 * 8.3333335816860198974609375e-2;
before reassoc1 and
  _2968 = __builtin_copysignf (1.0e+0, vel_2943);
...
  _3008 = _2972 * 8.3333335816860198974609375e-2;
  _2974 = _3008 * _2968;
after reassoc1.  Thus, supposedly this should be performed either only in
reassoc, or in reassoc and somewhere else.
Testcase for -Ofast:
float
f0 (float x)
{
  return 7.5 * __builtin_copysignf (1.0, x);
}

double
f1 (double x, double y)
{
  return x * ((1.0/12) * __builtin_copysign (1.0, y));
}

double
f2 (double x, double y)
{
  return (x * (-1.0/12)) * __builtin_copysign (1.0, y);
}

double
f3 (double x, double y, double z)
{
  return (x * z) * ((1.0/12) * __builtin_copysign (4.0, y));
}

double
f4 (double x, double y, double z)
{
  return (x * (-1.0/12)) * z * __builtin_copysign (2.0, y);
}

Reply via email to