From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.ispras.ru (mail.ispras.ru [83.149.199.84]) by sourceware.org (Postfix) with ESMTPS id 893F93858409 for ; Mon, 13 Dec 2021 14:25:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 893F93858409 Received: from [10.10.3.121] (unknown [10.10.3.121]) by mail.ispras.ru (Postfix) with ESMTPS id 5D001407625E; Mon, 13 Dec 2021 14:25:47 +0000 (UTC) Date: Mon, 13 Dec 2021 17:25:47 +0300 (MSK) From: Alexander Monakov To: gcc-patches@gcc.gnu.org cc: Richard Biener , Alexey Nurmukhametov Subject: [RFC PATCH] tree-ssa-sink: do not sink to in front of setjmp Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-8.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 8BIT X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Dec 2021 14:25:57 -0000 Greetings! While testing our patch that reimplements -Wclobbered on GIMPLE we found a case where tree-ssa-sink moves a statement to a basic block in front of a setjmp call. I am confident that this is unintended and should be considered invalid GIMPLE. One of the edges incoming to a setjmp BB will be an edge from the ABNORMAL_DISPATCHER block, corresponding to transfer of control flow from a longjmp-like function and resulting in a "second return" from setjmp. When that happens, it is not possible for GIMPLE statements in front of setjmp to be somehow re-executed after longjmp. I am unsure how this could be prevented "once and for all" so the following patch just attacks one place (out of three) in tree-ssa-sink by checking 'bb_has_abnormal_pred (sinkbb)'. Alexey (Cc'ed) bootstrapped and regtested the patch on trunk. The testcase is just struct __jmp_buf_tag { }; typedef struct __jmp_buf_tag jmp_buf[1]; struct globals { jmp_buf listingbuf; }; extern struct globals *const ptr_to_globals; void foo() {  if ( _setjmp ( ((*ptr_to_globals).listingbuf )))    ; } Before tree-ssa-sink we have void foo () {   struct globals * ptr_to_globals.0_1;   struct __jmp_buf_tag[1] * _2;   :   ptr_to_globals.0_1 = ptr_to_globals;   _2 = &ptr_to_globals.0_1->listingbuf;   :   _setjmp (_2);   goto ; [INV]   :   .ABNORMAL_DISPATCHER (0);   :   return; } And tree-ssa-sink yields (see BB 3) Sinking _2 = &ptr_to_globals.0_1->listingbuf;  from bb 2 to bb 3 void foo () {   struct globals * ptr_to_globals.0_1;   struct __jmp_buf_tag[1] * _2;   :   ptr_to_globals.0_1 = ptr_to_globals;   :   _2 = &ptr_to_globals.0_1->listingbuf;   _setjmp (_2);   goto ; [INV]   :   .ABNORMAL_DISPATCHER (0);   :   return; } The patch: diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c index c5d67840be3..317e2563114 100644 --- a/gcc/tree-ssa-sink.c +++ b/gcc/tree-ssa-sink.c @@ -461,6 +461,9 @@ statement_sink_location (gimple *stmt, basic_block frombb, else *togsi = gsi_after_labels (sinkbb); + if (bb_has_abnormal_pred (sinkbb)) + return false; + return true; } }