https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106505
Bug ID: 106505 Summary: DCE depends on whether if or else is used Product: gcc Version: 12.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: tmayerl at student dot ethz.ch Target Milestone: --- In some cases, the compiler's ability to eliminate dead code depends on whether the if expression is left as it is or negated and the body moved to the else block. GCC detects that the if expressions in the following code snippet evaluate to false and thus removes the dead code: #include <stdio.h> #include <stdbool.h> void DCEMarker0_(); void f(bool s, bool c) { if (!c == !s) { if (s && !c) { DCEMarker0_(); } } } In the following snippet, the inner if has been negated and the body has been moved to the else block. However, GCC cannot eliminate the dead code anymore: #include <stdio.h> #include <stdbool.h> void DCEMarker0_(); void f(bool s, bool c) { if (!c == !s) { if (!(s && !c)) {} else { DCEMarker0_(); } } } This can also be seen via the following Compiler Explorer link: https://godbolt.org/z/P4a61nsdq If s and c in the inner if expression are swapped, it is the other way round. Without the else, the compiler cannot eliminate the dead code: #include <stdio.h> #include <stdbool.h> void DCEMarker0_(); void f(bool s, bool c) { if (!c == !s) { if (c && !s) { DCEMarker0_(); } } } However, it suddenly can optimise the code when the if expression is negated and the body is moved to the else: #include <stdio.h> #include <stdbool.h> void DCEMarker0_(); void f(bool s, bool c) { if (!c == !s) { if (!(c && !s)) {} else { DCEMarker0_(); } } } This can also be seen via the following Compiler Explorer link: https://godbolt.org/z/95jo3Gv45 Due to the order issue this might be related to the following bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106379 However, this example only works with C as a source language. With C++, it is fine. Thus, this might be related to the following bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106381 Another example is given below. In this case, only one variable is needed. However, this only works with the datatype unsigned instead of bool. Therefore, it might be related to the following bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106380 Version with dead code eliminated: #include <stdio.h> #include <stdbool.h> void DCEMarker0_(); void f(unsigned s) { if (!s == !!s) { DCEMarker0_(); } } Version with dead code not eliminated: #include <stdio.h> #include <stdbool.h> void DCEMarker0_(); void f(unsigned s) { if (!(!s == !!s)) {} else { DCEMarker0_(); } } This can also be seen via the following Compiler Explorer link: https://godbolt.org/z/zYfoTs3PE