From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 8631D388E81E; Mon, 1 Mar 2021 06:59:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8631D388E81E From: "cvs-commit at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug target/99234] [10/11 regression] wrong result for 1.0/3.0 with -O2 -fno-omit-frame-pointer -frounding-math Date: Mon, 01 Mar 2021 06:59:11 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: target X-Bugzilla-Version: 10.2.1 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: cvs-commit at gcc dot gnu.org X-Bugzilla-Status: ASSIGNED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: ebotcazou at gcc dot gnu.org X-Bugzilla-Target-Milestone: 10.2 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Mar 2021 06:59:11 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D99234 --- Comment #19 from CVS Commits --- The master branch has been updated by Eric Botcazou : https://gcc.gnu.org/g:074226d5aa86cd3de517014acfe34c7f69a2ccc7 commit r11-7439-g074226d5aa86cd3de517014acfe34c7f69a2ccc7 Author: Eric Botcazou Date: Mon Mar 1 07:53:05 2021 +0100 Fix wrong result for 1.0/3.0 at -O2 -fno-omit-frame-pointer -frounding-= math This wrong-code PR for the C++ compiler on x86-64/Windows is a regressi= on in GCC 9 and later, but the underlying issue has probably been there si= nce SEH was implemented and is exposed by this comment in config/i386/winnt= .c: /* SEH records saves relative to the "current" stack pointer, whether or not there's a frame pointer in place. This tracks the current stack pointer offset from the CFA. */ HOST_WIDE_INT sp_offset; That's not what the (current) Microsoft documentation says; instead it says: /* SEH records offsets relative to the lowest address of the fixed st= ack allocation. If there is no frame pointer, these offsets are from = the stack pointer; if there is a frame pointer, these offsets are from= the value of the stack pointer when the frame pointer was established, i.e. the frame pointer minus the offset in the .seh_setframe directive.= */ That's why the implementation is correct only under the condition that = the frame pointer be established *after* the fixed stack allocation; as a matter of fact, that's clearly the model underpinning SEH, but is the opposite= of what is done e.g. on Linux. However the issue is mostly papered over in practice because: 1. SEH forces use_fast_prologue_epilogue to false, which in turns for= ces save_regs_using_mov to false, so the general regs are always pushed when they need to be saved, which eliminates the offset computation for them. 2. As soon as a frame is larger than 240 bytes, the frame pointer is fixed arbitrarily to 128 bytes above the stack pointer, which of course requi= res that it be established after the fixed stack allocation. So you need a small frame clobbering one of the call-saved XMM register= s in order to generate wrong SEH unwind info. The attached fix makes sure that the frame pointer is always established after the fixed stack allocation by pointing it at or below the lowest = used register save area, i.e. the SSE save area, and removing the special ea= rly saves in the prologue; the end result is a uniform prologue sequence for SEH whatever the frame size. And it avoids a discrepancy between cases where the number of saved general regs is even and cases where it is od= d. gcc/ PR target/99234 * config/i386/i386.c (ix86_compute_frame_layout): For a SEH tar= get, point the hard frame pointer to the SSE register save area inst= ead of the general register save area. Perform only minimal adjust= ment for small frames if it is initially not correctly aligned. (ix86_expand_prologue): Remove early saves for a SEH target. * config/i386/winnt.c (struct seh_frame_state): Document constraint. gcc/testsuite/ * g++.dg/eh/seh-xmm-unwind.C: New test.=