From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1039) id 0953F3894421; Tue, 27 Apr 2021 15:23:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0953F3894421 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: H.J. Lu To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-162] op_by_pieces_d::run: Change a while loop to a do-while loop X-Act-Checkin: gcc X-Git-Author: H.J. Lu X-Git-Refname: refs/heads/master X-Git-Oldrev: 42a10bb884c0d5af2583b8bfe4d239ce95bf9e43 X-Git-Newrev: 3bb41228d76b3a3cbd9923d57388f0903f7683de Message-Id: <20210427152338.0953F3894421@sourceware.org> Date: Tue, 27 Apr 2021 15:23:38 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Apr 2021 15:23:38 -0000 https://gcc.gnu.org/g:3bb41228d76b3a3cbd9923d57388f0903f7683de commit r12-162-g3bb41228d76b3a3cbd9923d57388f0903f7683de Author: H.J. Lu Date: Mon Apr 26 15:36:18 2021 -0700 op_by_pieces_d::run: Change a while loop to a do-while loop Change a while loop in op_by_pieces_d::run to a do-while loop to prepare for offset adjusted operation for the remaining bytes on the last piece operation of a memory region. PR middle-end/90773 * expr.c (op_by_pieces_d::get_usable_mode): New member function. (op_by_pieces_d::run): Cange a while loop to a do-while loop. Diff: --- gcc/expr.c | 76 +++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/gcc/expr.c b/gcc/expr.c index 5a1fda7e3e8..a4a004dd177 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1041,6 +1041,9 @@ pieces_addr::maybe_postinc (HOST_WIDE_INT size) class op_by_pieces_d { + private: + scalar_int_mode get_usable_mode (scalar_int_mode mode, unsigned int); + protected: pieces_addr m_to, m_from; unsigned HOST_WIDE_INT m_len; @@ -1108,6 +1111,25 @@ op_by_pieces_d::op_by_pieces_d (rtx to, bool to_load, m_align = align; } +/* This function returns the largest usable integer mode for LEN bytes + whose size is no bigger than size of MODE. */ + +scalar_int_mode +op_by_pieces_d::get_usable_mode (scalar_int_mode mode, unsigned int len) +{ + unsigned int size; + do + { + size = GET_MODE_SIZE (mode); + if (len >= size && prepare_mode (mode, m_align)) + break; + /* NB: widest_int_mode_for_size checks SIZE > 1. */ + mode = widest_int_mode_for_size (size); + } + while (1); + return mode; +} + /* This function contains the main loop used for expanding a block operation. First move what we can in the largest integer mode, then go to successively smaller modes. For every access, call @@ -1116,42 +1138,50 @@ op_by_pieces_d::op_by_pieces_d (rtx to, bool to_load, void op_by_pieces_d::run () { - while (m_max_size > 1 && m_len > 0) + if (m_len == 0) + return; + + /* NB: widest_int_mode_for_size checks M_MAX_SIZE > 1. */ + scalar_int_mode mode = widest_int_mode_for_size (m_max_size); + mode = get_usable_mode (mode, m_len); + + do { - scalar_int_mode mode = widest_int_mode_for_size (m_max_size); + unsigned int size = GET_MODE_SIZE (mode); + rtx to1 = NULL_RTX, from1; - if (prepare_mode (mode, m_align)) + while (m_len >= size) { - unsigned int size = GET_MODE_SIZE (mode); - rtx to1 = NULL_RTX, from1; + if (m_reverse) + m_offset -= size; - while (m_len >= size) - { - if (m_reverse) - m_offset -= size; + to1 = m_to.adjust (mode, m_offset); + from1 = m_from.adjust (mode, m_offset); - to1 = m_to.adjust (mode, m_offset); - from1 = m_from.adjust (mode, m_offset); + m_to.maybe_predec (-(HOST_WIDE_INT)size); + m_from.maybe_predec (-(HOST_WIDE_INT)size); - m_to.maybe_predec (-(HOST_WIDE_INT)size); - m_from.maybe_predec (-(HOST_WIDE_INT)size); + generate (to1, from1, mode); - generate (to1, from1, mode); + m_to.maybe_postinc (size); + m_from.maybe_postinc (size); - m_to.maybe_postinc (size); - m_from.maybe_postinc (size); + if (!m_reverse) + m_offset += size; - if (!m_reverse) - m_offset += size; + m_len -= size; + } - m_len -= size; - } + finish_mode (mode); - finish_mode (mode); - } + if (m_len == 0) + return; - m_max_size = GET_MODE_SIZE (mode); + /* NB: widest_int_mode_for_size checks SIZE > 1. */ + mode = widest_int_mode_for_size (size); + mode = get_usable_mode (mode, m_len); } + while (1); /* The code above should have handled everything. */ gcc_assert (!m_len);