https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93806
--- Comment #25 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Alexander Cherepanov from comment #24) > (In reply to Vincent Lefèvre from comment #11) > > But what does "internal consistency" mean? > That's a good question. Here we talk about cases (like > -funsafe-math-optimizations) that are not covered by any standards. Other > PRs (like pr61502 or pr93301) discuss possible changes to the standard. So > we need some basic rules to decide what is good and what is bad. > > pr61502 taught me that discussing which value is the right result for a > particular computation is very interesting but not very conclusive. So now > I'm looking for contradictions. If you can derive a contradiction then you > can derive any statement, so it's an ultimate goal. How to apply this to a > compiler? I thought the following is supposed to always hold: if you > explicitly write a value into a variable (of any type) then you should get > back the same value at every future read no matter how the results of other > reads are used or what control flow happens (without other writes to the > variable, of course). That is, after `int x = 0;` all `printf("x = %d", x);` > should output the same no matter how many `if (x == ...)` there are > in-between -- either `printf` doesn't fire at all or it prints `x = 0`. If > we demonstrated that it's broken then we demonstrated a contradiction > (nonsense). And I hoped that it would be uncontroversial:-( It's at least a very easy to describe and obviously useful thing. I also agree it's a very good QOI goal to target. Just to clarify - this is for a single execution of the abstract machine, not for the single "source" instance when the same two values are involved? So float foo(float x) { return x + 1; } void bar() { float f1 = foo(1.); float f2 = foo(1.); } here x + 1 need not evaluate to the same value? This would make transforms such as loop unrolling or tail duplication "safe" since those do not involve evaluating the same expression more times than in the untransformed abstract machine evaluations. [...] > (In reply to Richard Biener from comment #3) > > But you asked for that. So no "wrong-code" here, just another case > > of "instabilities" or how you call that via conditional equivalence > > propagation. > Just to be sure: you are saying that everything works as intended -- the > testcase doesn't contain UB and the result it prints is one of the allowed? > (It could also be read as implying that this pr is a dup of another bug > about conditional equivalence propagation or something.) Then we just > disagree. I think that -funsafe-optimization makes the result acceptable. I see (and somewhat agree) that this is unfortunate for the QOI design goal of "stable" values. But the instability is just a result of optimizers working as intended. There is no designed mechanism in GCC that avoids "opening up" an expression and recomputing (parts of) it [in different contexts differently]. And I have a hard time coming up with a way to implement such a thing that wouldn't be detrimental to desired optimizations :/ As we see in other testcases "conditional equivalences" and replacing one variable with another under them is a source of various problems, but simply disabling those propagations likely will not address the fundamental issue. > Discussion went to specifics of particular optimizations. IMHO it's not > important at all for deciding whether comment 1 demonstrates a bug or not. > Again, IMHO either the testcase contains UB or it shouldn't print nonsense > (in the sense described above). And it doesn't matter which options are > used, whether it's a standards compliant mode, etc. Overall I'm not sure how to address these bugs (but thanks for raising awareness and for creating those testcases!). It's tempting to paper over the individual issues (like not allow conditional propagation of FP values or disabling forwarding of once computed, many used FP conditionals) but I think there's a more fundametal issue around all this which is not fully understood and which we should try to address in a more coordinated fashion (also given "artificial" wrong-code testcases don't put a very high pressure on finding a workaround for them). Just compare to the very old issue regarding the lack of barriers of FP arithmetic with FP environment access. Would it help if we had some --param no-conditional-propagation to turn off such propagation in the two places I'm aware we do it? That way you could see if you can find testcases not involving such propagation (I think it's most easy to get them there though).