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); }