https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109086
--- Comment #9 from Xi Ruoyao <xry111 at gcc dot gnu.org> --- (In reply to Richard Biener from comment #4) > > Maybe the expand_binop function does not consider the case of dependency > > with `target` when generating rtx for the case of promote MODE_INT mode, and > > maybe theoretically it does not need to be considered, except that > > builtin_strcmp happens to meet such cases, so I think it is enough to modify > > the processing logic of builtin_strcmp (my humble opinion). > > I'm still missing the obvious? We assign the result to 'result', so it > should be all fine? I see that emit_cmp_and_jump_insns eventually forces > the lowpart to a register but still it should work. The problem here is we are assigning the result (i. e. virtual register number) to 'result', not *moving* the result (i. e. the difference between s[i] and t[i]) into 'result'. When expand_simple_binop is allowed to assign new vreg in the loop, it's possible that loop iteration 1 uses vreg1, iteration 2 use vreg2, ..., iteration N use vregN. When we move the result into 'result', the "moving" will happen only if the execution really reaches the move insn, such a behavior is correct. But we we assign the result into 'result', the assignment will "always" happen (because assignment is a logic in the compiler itself, unlike moving which is a part of target code). I. e. we always return vregN as the result, which is not correct if the loop jumps out early. I'd suggest diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 305c65c29be..0c14a3b52b3 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -7142,8 +7142,11 @@ inline_string_cmp (rtx target, tree var_str, const char *const_str, op0 = convert_modes (mode, unit_mode, op0, 1); op1 = convert_modes (mode, unit_mode, op1, 1); - result = expand_simple_binop (mode, MINUS, op0, op1, - result, 1, OPTAB_WIDEN); + rtx diff = expand_simple_binop (mode, MINUS, op0, op1, + result, 1, OPTAB_WIDEN); + if (diff != result) + emit_move_insn (result, diff); + if (i < length - 1) emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX, mode, true, ne_label);