From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1285) id 196493858C55; Thu, 13 Oct 2022 16:44:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 196493858C55 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1665679483; bh=NYT9eKlwhI7Y9MBne0nh7RbWccpb0fTcQJlGNp1w338=; h=From:To:Subject:Date:From; b=yUSZNZOwkv+D/F7EGH+7s5Lno3JPYTQhQ09cnQFWAXfpVos1Yg5cltkr06ZmFZRIj uRGT8153wfKh/mlcPMyGk0ESxfitMdWBMcDTI9x6KODfPQ8LF62F1eNwuoZDE9yrwE I/MmL8IimsZfnO8itDe21vnI8YA9XNY4ZMAs7E8g= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Eric Botcazou To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-3283] Fix emit_group_store regression on big-endian X-Act-Checkin: gcc X-Git-Author: Eric Botcazou X-Git-Refname: refs/heads/master X-Git-Oldrev: fc748d47e95dd612f4a0ef408851df0293173fd8 X-Git-Newrev: c853d655ab27d288b9dcadb2920f7cd28dc1390d Message-Id: <20221013164443.196493858C55@sourceware.org> Date: Thu, 13 Oct 2022 16:44:43 +0000 (GMT) List-Id: https://gcc.gnu.org/g:c853d655ab27d288b9dcadb2920f7cd28dc1390d commit r13-3283-gc853d655ab27d288b9dcadb2920f7cd28dc1390d Author: Eric Botcazou Date: Wed Oct 12 09:27:19 2022 +0200 Fix emit_group_store regression on big-endian The recent optimization implemented for complex modes contains an oversight for big-endian platforms: it uses a lowpart SUBREG when the integer modes have different sizes, but this does not match the semantics of the PARALLELs which have a bundled byte offset; this offset is always zero in the code path and the lowpart is not at offset zero on big-endian platforms. gcc/ * expr.cc (emit_group_stote): Fix handling of modes of different sizes for big-endian targets in latest change and add commentary. Diff: --- gcc/expr.cc | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/gcc/expr.cc b/gcc/expr.cc index ba627f176a7..b897b6dc385 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -2813,50 +2813,69 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, else adj_bytelen = bytelen; + /* Deal with destination CONCATs by either storing into one of the parts + or doing a copy after storing into a register or stack temporary. */ if (GET_CODE (dst) == CONCAT) { if (known_le (bytepos + adj_bytelen, GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))) dest = XEXP (dst, 0); + else if (known_ge (bytepos, GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))) { bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))); dest = XEXP (dst, 1); } + else { machine_mode dest_mode = GET_MODE (dest); machine_mode tmp_mode = GET_MODE (tmps[i]); - scalar_int_mode imode; + scalar_int_mode dest_imode; gcc_assert (known_eq (bytepos, 0) && XVECLEN (src, 0)); - if (finish == 1 + /* If the source is a single scalar integer register, and the + destination has a complex mode for which a same-sized integer + mode exists, then we can take the left-justified part of the + source in the complex mode. */ + if (finish == start + 1 && REG_P (tmps[i]) - && COMPLEX_MODE_P (dest_mode) && SCALAR_INT_MODE_P (tmp_mode) - && int_mode_for_mode (dest_mode).exists (&imode)) + && COMPLEX_MODE_P (dest_mode) + && int_mode_for_mode (dest_mode).exists (&dest_imode)) { - if (tmp_mode != imode) + const scalar_int_mode tmp_imode + = as_a (tmp_mode); + + if (GET_MODE_BITSIZE (dest_imode) + < GET_MODE_BITSIZE (tmp_imode)) { - rtx tmp = gen_reg_rtx (imode); - emit_move_insn (tmp, gen_lowpart (imode, tmps[i])); - dst = gen_lowpart (dest_mode, tmp); + dest = gen_reg_rtx (dest_imode); + if (BYTES_BIG_ENDIAN) + tmps[i] = expand_shift (RSHIFT_EXPR, tmp_mode, tmps[i], + GET_MODE_BITSIZE (tmp_imode) + - GET_MODE_BITSIZE (dest_imode), + NULL_RTX, 1); + emit_move_insn (dest, gen_lowpart (dest_imode, tmps[i])); + dst = gen_lowpart (dest_mode, dest); } else dst = gen_lowpart (dest_mode, tmps[i]); } + + /* Otherwise spill the source onto the stack using the more + aligned of the two modes. */ else if (GET_MODE_ALIGNMENT (dest_mode) - >= GET_MODE_ALIGNMENT (tmp_mode)) + >= GET_MODE_ALIGNMENT (tmp_mode)) { dest = assign_stack_temp (dest_mode, GET_MODE_SIZE (dest_mode)); - emit_move_insn (adjust_address (dest, - tmp_mode, - bytepos), + emit_move_insn (adjust_address (dest, tmp_mode, bytepos), tmps[i]); dst = dest; } + else { dest = assign_stack_temp (tmp_mode, @@ -2864,6 +2883,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, emit_move_insn (dest, tmps[i]); dst = adjust_address (dest, dest_mode, bytepos); } + break; } }