https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114084

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Bet the associate code is really unprepared to have unfolded trees around,
which hasn't been the case before delayed folding has been introduced to C and
C++ FEs.
Unfortunately it isn't complete, because e.g. convert_to_integer_1 -> do_narrow
-> fold_build2_loc happily folds.

Anyway, quick fix could be not trying to reassociate TREE_CONSTANT parts:
--- gcc/fold-const.cc.jj        2024-01-26 00:07:58.000000000 +0100
+++ gcc/fold-const.cc   2024-02-24 09:38:40.150808529 +0100
@@ -908,6 +908,8 @@ split_tree (tree in, tree type, enum tre
   if (TREE_CODE (in) == INTEGER_CST || TREE_CODE (in) == REAL_CST
       || TREE_CODE (in) == FIXED_CST)
     *litp = in;
+  else if (TREE_CONSTANT (in))
+    *conp = in;
   else if (TREE_CODE (in) == code
           || ((! FLOAT_TYPE_P (TREE_TYPE (in)) || flag_associative_math)
               && ! SAT_FIXED_POINT_TYPE_P (TREE_TYPE (in))
@@ -956,8 +958,6 @@ split_tree (tree in, tree type, enum tre
       if (neg_var_p && var)
        *minus_varp = var, var = 0;
     }
-  else if (TREE_CONSTANT (in))
-    *conp = in;
   else if (TREE_CODE (in) == BIT_NOT_EXPR
           && code == PLUS_EXPR)
     {

So, the problem happens on
typedef unsigned _BitInt (__SIZEOF_INT__ * __CHAR_BIT__ - 1) T;
T a, b;

void
foo (void)
{
  b = (T) ((a | (-1U >> 1)) >> 1 | (a | 5) << 4);
}
when fold_binary_loc is called on (unsigned _BitInt(31)) a << 4 | 80 and
(unsigned _BitInt(31)) (2147483647 >> 1), but the important part is that
the op0 has the unsigned _BitInt(31) type, while op1 is NOP_EXPR to that type
from
RSHIFT_EXPR done on T type (the typedef).
Soon BIT_IOR_EXPR folding is called on
(unsigned _BitInt(31)) a << 4 and 2147483647 >> 1 | 80 where the latter is all
in T type (fold_binary_loc does STRIP_NOPS).  Because split_tree prefers same
code over TREE_CONSTANT, this splits it into the LSHIFT_EXPR var0, RSHIFT_EXPR
con1 (because it is TREE_CONSTANT) and the T type 80 literal in lit1,
everything else is NULL.  As there are 3 objects, it reassociates.  We first
associate_tree the 0 vs. 1 cases, but that just moves the *1 into *0 because
their counterparts are NULL.
Both the RSHIFT_EXPR and INTEGER_CST 80 have T type but atype is the
build_bitint_type
non-typedef type, so
11835                 /* Eliminate lit0 and minus_lit0 to con0 and minus_con0.
*/
11836                 con0 = associate_trees (loc, con0, lit0, code, atype);
returns NOP_EXPR of the RSHIFT_EXPR | INTEGER_CST.
And then we associate_trees the LSHIFT_EXPR with this result and so it recurses
infinitely.

Perhaps my above patch is an improvement, if we know some subtree is
TREE_CONSTANT, all we need is just wait for it to be constant folded (not sure
it would always do e.g. because of division by zero or similar) trying to
reassociate its parts with other expressions might just split the constants to
other spots instead of keeping it together.

Reply via email to