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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2024-12-17
             Status|UNCONFIRMED                 |NEW
     Ever confirmed|0                           |1
           Priority|P3                          |P2

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I think the problem is cp_fold_immediate_r now being done from cp_fold_r.
If there is e.g. a cast that can't be optimized right away as useless ((int)
for foo call returning int is useless, but (int) for foo returning unsigned
char is not), or any other expression, say
typedef float V __attribute__((vector_size (32)));

consteval int
baz (int x)
{
  return x;
}

V
qux (V x, V y)
{
  return __builtin_ia32_blendps256 (x, y, baz (0x23) + 1);
}
then cp_fold_r first sees the cast (NOP_EXPR, PLUS_EXPR above etc.), calls
cp_fold on it, but that doesn't really do anything on it, because the operand
of it is still a CALL_EXPR to the immediate function.  Then we walk into the
operand, do cp_fold_r on it, do cp_fold_immediate_r on that and that turns the
CALL_EXPR into INTEGER_CST.
But nothing will do the NOP_EXPR or PLUS_EXPR cp_fold on it anymore.
So, either cp_fold_immediate_r would need to be done in a separate cp_walk_tree
on the whole function (or whole initializer etc.) rather than from within
cp_fold_r, i.e. first fold immediates, then everything else, or it would need
to be done from cp_fold rather than cp_fold_r, so that e.g. when we see a
NOP_EXPR the cp_fold handling of it can do:
      op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops, flags);

      if (...)
        x = fold (convert (TREE_TYPE (x), op0));
      else if (op0 != TREE_OPERAND (x, 0))
        {
          if (op0 == error_mark_node)
            x = error_mark_node;
          else
            x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
where cp_fold_maybe_rvalue which does cp_fold inside of it would turn the
immediate call into INTEGER_CST and the last fold_buil1_loc would fold the cast
of INTEGER_CST into INTEGER_CST with another type.  Or similarly for
PLUS_EXPR/whatever else.

Right now, the immediate folding is done after the outer trees are folded.
Note, if it is done from cp_fold, the question is how to ensure it isn't
diagnosed multiple times if constant evaluation of the call fails, whether we
turn those into error_mark_node or some special form on which we don't diagnose
it again, ...

Reply via email to