https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69888
--- Comment #2 from Uroš Bizjak <ubizjak at gmail dot com> --- (In reply to Jakub Jelinek from comment #1) > Untested fix. Looks OK, but please introduce a temporary variable, something like: --cut here-- diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a1c87ab..6457293 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -26152,20 +26152,23 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, || !alg_usable_p (algs->unknown_size, memset, have_as))) { enum stringop_alg alg; + HOST_WIDE_INT new_size; - /* If there aren't any usable algorithms, then recursing on - smaller sizes isn't going to find anything. Just return the - simple byte-at-a-time copy loop. */ - if (!any_alg_usable_p) + if (max <= 0) + max = 4096; + /* If there aren't any usable algorithms or if recursing with the + same arguments as before, then recursing on smaller sizes or + same size isn't going to find anything. Just return the simple + byte-at-a-time copy loop. */ + new_size = max / 2; + if (!any_alg_usable_p || new_size == orig_expected_size) { /* Pick something reasonable. */ if (TARGET_INLINE_STRINGOPS_DYNAMICALLY) *dynamic_check = 128; return loop_1_byte; } - if (max <= 0) - max = 4096; - alg = decide_alg (count, max / 2, min_size, max_size, memset, + alg = decide_alg (count, new_size, min_size, max_size, memset, zero_memset, have_as, dynamic_check, noalign); gcc_assert (*dynamic_check == -1); if (TARGET_INLINE_STRINGOPS_DYNAMICALLY) --cut here--