From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2140) id 823253857B82; Fri, 8 Dec 2023 01:06:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 823253857B82 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1701997563; bh=uYR0gThWeCi9IGH7yBK11vmvrXDSosbzy/jrmY3GcpI=; h=From:To:Subject:Date:From; b=mK/Z1LBRcdr25voPrfvXyJjDgEFca4WJm6vKgYXmwMBpvJoCucK1/usFo4oFUX3Fj iPy/p1ha5GRnBPa1dO4SFaroRb0DCtbkhUYPPC6Lbq/Mc3xo7IIdvsrxZSNCtvEQSD JKVAb7BuN+wB8aR91Mmu3a+PcMq8j5zHXK15k3Yg= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Alexandre Oliva To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/aoliva/heads/testme)] -finline-stringops: check base blksize for memset [PR112784] X-Act-Checkin: gcc X-Git-Author: Alexandre Oliva X-Git-Refname: refs/users/aoliva/heads/testme X-Git-Oldrev: 9527fd37a4ae7a8fec0ae66e665235f53bce15b5 X-Git-Newrev: d81f3c5282b3a811a249b15aced023d75ae40486 Message-Id: <20231208010603.823253857B82@sourceware.org> Date: Fri, 8 Dec 2023 01:06:03 +0000 (GMT) List-Id: https://gcc.gnu.org/g:d81f3c5282b3a811a249b15aced023d75ae40486 commit d81f3c5282b3a811a249b15aced023d75ae40486 Author: Alexandre Oliva Date: Thu Dec 7 20:12:02 2023 -0300 -finline-stringops: check base blksize for memset [PR112784] Diff: --- gcc/builtins.cc | 46 +++++++++++++++++++++----- gcc/testsuite/gcc.dg/inline-mem-cmp-pr112778.c | 10 ++++++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/gcc/builtins.cc b/gcc/builtins.cc index afa9be51443..40bb4016317 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -4284,6 +4284,31 @@ expand_builtin_memset (tree exp, rtx target, machine_mode mode) return expand_builtin_memset_args (dest, val, len, target, mode, exp); } +/* Check that store_by_pieces allows BITS + LEN (so that we don't + expand something too unreasonably long), and every power of 2 in + BITS. */ +static bool +can_store_by_multiple_pieces (unsigned HOST_WIDE_INT bits, + by_pieces_constfn constfun, + void *constfundata, unsigned int align, + bool memsetp, + unsigned HOST_WIDE_INT len) +{ + if (!can_store_by_pieces (bits + len, constfun, constfundata, align, memsetp)) + return false; + + /* We start at 2 because we can manage single byte stores even if + can_store_by_pieces rejects it. */ + for (unsigned HOST_WIDE_INT bit = 2; + bit && bit < bits; + bit <<= 1) + if ((bit & bits) != 0 + && !can_store_by_pieces (bit, constfun, constfundata, align, memsetp)) + return false; + + return true; +} + /* Try to store VAL (or, if NULL_RTX, VALC) in LEN bytes starting at TO. Return TRUE if successful, FALSE otherwise. TO is assumed to be aligned at an ALIGN-bits boundary. LEN must be a multiple of @@ -4341,7 +4366,9 @@ try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len, else /* Huh, max_len < min_len? Punt. See pr100843.c. */ return false; - if (min_len >= blksize) + if (min_len >= blksize + && can_store_by_pieces (blksize, builtin_memset_read_str, + &valc, align, true)) { min_len -= blksize; min_bits = floor_log2 (min_len); @@ -4367,8 +4394,9 @@ try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len, happen because of the way max_bits and blksize are related, but it doesn't hurt to test. */ if (blksize > xlenest - || !can_store_by_pieces (xlenest, builtin_memset_read_str, - &valc, align, true)) + || !can_store_by_multiple_pieces (xlenest - blksize, + builtin_memset_read_str, + &valc, align, true, blksize)) { if (!(flag_inline_stringops & ILSOP_MEMSET)) return false; @@ -4386,17 +4414,17 @@ try_store_by_multiple_pieces (rtx to, rtx len, unsigned int ctz_len, of overflow. */ if (max_bits < orig_max_bits && xlenest + blksize >= xlenest - && can_store_by_pieces (xlenest + blksize, - builtin_memset_read_str, - &valc, align, true)) + && can_store_by_multiple_pieces (xlenest, + builtin_memset_read_str, + &valc, align, true, blksize)) { max_loop = true; break; } if (blksize - && can_store_by_pieces (xlenest, - builtin_memset_read_str, - &valc, align, true)) + && can_store_by_multiple_pieces (xlenest, + builtin_memset_read_str, + &valc, align, true, 0)) { max_len += blksize; min_len += blksize; diff --git a/gcc/testsuite/gcc.dg/inline-mem-cmp-pr112778.c b/gcc/testsuite/gcc.dg/inline-mem-cmp-pr112778.c new file mode 100644 index 00000000000..fdfc5b6f28c --- /dev/null +++ b/gcc/testsuite/gcc.dg/inline-mem-cmp-pr112778.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-finline-stringops" } */ + +char buf[3]; + +int +f () +{ + __builtin_memset (buf, 'v', 3); +}