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