https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112374
--- Comment #40 from Robin Dapp <rdapp at gcc dot gnu.org> --- (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++; }