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

--- Comment #43 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Robin Dapp from comment #40)
> (In reply to Jakub Jelinek from comment #37)
> [..]
> 
> > The above isn't complete, so one just has to guess what you mean outside of
> > that, but the above doesn't seem to be correct.  There are many internal
> > calls, and most of them shouldn't have the above handling.  Say if there is
> > .MUL_OVERFLOW (op.ops[opi], op.ops[opi]) call, it should count as 2 uses,
> > not one.
> 
> But we would count MUL_OVERFLOW as two uses because its else_pos = -1?
> For clarity we could maybe move the else pos check into the if condition,
> yes.
> 
> One other thing, though.  The else branch checks for is_gimple_debug and
> flow_bb_inside_loop_p.  We could handle this separately and continue.
> Maybe something like this is clearer, replacing the whole loop (and moved
> the else_idx check)?
> 
>       FOR_EACH_IMM_USE_STMT (op_use_stmt, imm_iter, op.ops[opi])
>       {
>         if (is_gimple_debug (op_use_stmt)
>             || (*code == ERROR_MARK
>                 && !flow_bb_inside_loop_p (loop,
>                                            gimple_bb (op_use_stmt))))
>           continue;
> 
>         /* In case of a COND_OP (mask, op1, op2, op1) reduction we might have
>            op1 twice (once as definition, once as else) in the same operation.
>            Allow this.  */
>         gcall *call = dyn_cast<gcall *> (op_use_stmt);
>         internal_fn ifn;
>         if (call && gimple_call_internal_p (call)
>             && (ifn = gimple_call_internal_fn (call))
>                 && internal_fn_else_index (ifn) > -1)
>           {
>             unsigned else_idx = internal_fn_else_index (ifn);
>             for (unsigned int j = 0; j < gimple_call_num_args (call); ++j)
>               {
>                 if (j == else_idx)
>                   continue;
>                 if (gimple_call_arg (call, j) == op.ops[opi])
>                   cnt++;
>               }
>           }
>         else
>           FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
>             cnt++;
>       }

Then
      bool cond_fn_p = op.code.is_internal_fn ()
        && (conditional_internal_fn_code (internal_fn (op.code))
            != ERROR_MARK);
would be unused and would cause bootstrap error.
Anyway, it really depends on what you want to achieve with this code.
My (admittedly limited) understanding of this is that use_stmt ought to be
always
one of the statements among the op_use_stmt statements (I believe it must be a
use statement of op.ops[opi]) and I think should be also inside of the loop and
because after this loop it fails if cnt != 1, I think before your changes it
basically made sure that there is exactly one non-debug use in the loop (the
use_stmt one) and not other, and that on use_stmt there is just one use.
Now, the patch changed it to allow one extra use in certain cases (but I think
only on use_stmt, because there should be one use on use_stmt and if there is
some other in the loop, that would be already too much).  So I think my patch
ought to work and the above would be more expensive (as it would need to check
each op_use_stmt for being suitable internal call).
the code before

Reply via email to