So while modifying phi-opt, I ran into pr85213.c testcase failing with the C++ front-end. BUT the problem is not related at all to PHI-OPT changes as the IR coming out of the front-end is hugely different with and without debug information turned on. Without debug info turned on we start with: NON_LVALUE_EXPR <SAVE_EXPR <-(__builtin_expect ((long int) (x == 0), 3) == 0)> >; But with: NON_LVALUE_EXPR <SAVE_EXPR <-(__builtin_expect (# DEBUG BEGIN STMT; x != 0; ? 0 : 1, 3) == 0)>> It just happens with the PHI-OPT, by the time we get to expand, the IR is very similar BUT the difference comes from SSA names are different. You can reproduce the failure on the trunk without any patches to PHI-OPT by doing: g++ -O1 -fsanitize=undefined -fcompare-debug -fdisable-tree-phiopt2 c-c++-common/ubsan/pr85213.c
Note in older versions of GCC (8.x), disabling phiopt1 is needed instead of phiopt2.
I think this is another -gstatement-frontiers issue. Without -g, during folding we are folding a COND_EXPR with x != 0, 0 and 1 arguments, but with -g it has a STATEMENT_LIST with DEBUG_BEGIN_STMT and x != 0 And that one e.g. in fold_ternary_loc doesn't satisfy truth_value_p, so the /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR over COND_EXPR in cases such as floating point comparisons. */ if (integer_zerop (op1) && code == COND_EXPR && integer_onep (op2) && !VECTOR_TYPE_P (type) && truth_value_p (TREE_CODE (arg0))) return fold_convert_loc (loc, type, invert_truthvalue_loc (loc, arg0)); folding doesn't happen. In the past, most of the -gstatement-frontiers related -fdebug-compare bugfixes were about making sure we gimplify it the same (and we still have some unresolved (almost unresolvable) ones). But this shows whole new category of bugs, the folders aren't really prepared for it, guess neither generic-match.c (or its callers) or fold-const.c. E.g. fold_ternary_loc starts with if (op0) { arg0 = op0; STRIP_NOPS (arg0); } shouldn't we use expr_single in that code somehow? Like after the STRIP_NOPS add do { tree narg0 = expr_single (arg0); if (narg0 == arg0) break; arg0 = narg0; STRIP_NOPS (arg0); } while (1); perhaps in some macro/inline fn? Or reconsider the DEBUG_BEGIN_STMT stuff.
-gstatement-frontiers has been introduced in r8-5241-g8697bf9f46f36168ddba5752db582e673e3cbe8c or so.
Meh. I wonder if we can make expr_single cheaper by setting a tree flag on the STATEMENT_LIST at least?
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
GCC 9 branch is being closed
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
GCC 10 branch is being closed.
GCC 11 branch is being closed.