+cc.
On 2020/12/11 14:25, Xionghu Luo via Gcc wrote:
Thanks, On 2020/12/10 17:12, Richard Biener wrote:2) From PR90070: double temp1 = (double)r->red; double temp2 = (double)aggregate.red; double temp3 = temp2 + (temp1 * 5.0);temp1 * 5 could be not representable in float but the result of the add could so the transform could result in -+Inf where the original computation was fine (but still very large result). Usually in such cases one could say we should implement some diagnostic hints to the user that he might consider refactoring his code to use float computations because we cannot really say whether it's safe (we do at the moment not implement value-range propagation for floating point types).foo (double x, float y, float z) { return ( fabs (x) * y - z ) ; } int main () { float res = foo (1e38, 5.0, 3e38); printf ("res:%f\n", res); } (1) $ gcc a.c -Ofast -ffp-contract=off: 0000000000000880 <foo>: 880: 10 0a 20 fc fabs f1,f1 884: b2 00 21 fc fmul f1,f1,f2 888: 28 18 21 fc fsub f1,f1,f3 88c: 18 08 20 fc frsp f1,f1 890: 20 00 80 4e blr $ ./a.out res:199999993605713849301312521538346418176.000000 (2) $ gcc_MODIFIED a.c -Ofast -ffp-contract=off: 0000000010000660 <foo>: 10000660: 18 08 00 fc frsp f0,f1 10000664: 10 02 00 fc fabs f0,f0 10000668: b2 00 00 ec fmuls f0,f0,f2 // Inf 1000066c: 28 18 20 ec fsubs f1,f0,f3 10000670: 20 00 80 4e blr $ ./a.out res:inf It's true that if change all double computation to float will result in INF if "fabs (x) * y" is larger than FLT_MAX, though the double result in (1) could get back to a large number smaller than FLT_MAX. But the add/sub could also produces INF similarly, foo (double x, float y, float z) { return ( -fabs (x) + y + z ) ; } int main () { float res = foo (1e38, 1e38, 3e38); printf ("res:%f\n", res); } (3) $ gcc a.c -Ofast: 0000000000000880 <foo>: 880: 10 0a 20 fc fabs f1,f1 884: 28 08 42 fc fsub f2,f2,f1 888: 2a 18 22 fc fadd f1,f2,f3 88c: 18 08 20 fc frsp f1,f1 890: 20 00 80 4e blr $ ./a.out res:300000000549775575777803994281145270272.000000 4) $ gcc_MODIFIED a.c -Ofast: 0000000010000660 <foo>: 10000660: 18 08 20 fc frsp f1,f1 10000664: 2a 18 42 ec fadds f2,f2,f3 10000668: 10 0a 20 fc fabs f1,f1 1000066c: 28 08 22 ec fsubs f1,f2,f1 10000670: 20 00 80 4e blr $ ./a.out res:inf Note that the add/sub sequence is different for (3) and (4) since -funsafe-math-optimizations is implicitly true. "fp-contract=fast" in (1) and (2) could avoid Inf as fmads could handle float overflow (verified it on Power, not sure other targets support this), but without float value-range info, it is unsafe to change computation from double to float even for only add/sub expressions. What's more, It seems also difficult to do computation *partly float and partly double* in backprop pass since all the expressions are chained and strong dependent unlike the sign-changing operations, which could only change expressions partly. Thanks, Xionghu
-- Thanks, Xionghu
