From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 5389D3861849; Thu, 14 Dec 2023 07:45:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5389D3861849 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1702539948; bh=eScmBXDCASSZDSZISDD4QNAXI/gqy59i7tMN4L5FlBw=; h=From:To:Subject:Date:In-Reply-To:References:From; b=SIzoL3C5MKhOx25ihxTsyFx8iK+NvqekNMlFrf7GggkJ8P4tg6dj2xBTzG2jwR8/O VTo5syR+xf/iyb/rxl2pgxy26r4VrbGvajSMQreo7rS0+o2MsnWGsigcJBHpGAr5d0 Nk6AM4XeM6d3YM9dVAO7UvQHbtFkqN/OdiO7u3zI= From: "jeevitha at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug target/110606] ICE output_operand: '%&' used without any local dynamic TLS references on powerpc64le-linux-gnu Date: Thu, 14 Dec 2023 07:45:47 +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: 13.1.1 X-Bugzilla-Keywords: ice-on-valid-code X-Bugzilla-Severity: normal X-Bugzilla-Who: jeevitha at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: jeevitha at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- 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 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D110606 --- Comment #11 from Jeevitha --- Regarding the test case provided by Matthias Klose: Within the AllocMemory() routine, the compiler aimed to eliminate the entir= e if block but faced difficulties in removing references to the variable 'sMemPo= ol'. The corresponding source code is as follows: if (sMemPool) { __trans_tmp_2 =3D operator new(AllocMemory_size); return __trans_tmp_2; } void *ptr =3D operator new(AllocMemory_size); return ptr; The subsequent details are pertaining to the body of if statement [BB5], wh= ich includes a 'mov' [insn 35] for "AllocMemory_size" and a 'call' [insn 36] for "operator new." Furthermore, regarding the code after the if body [BB6], th= ere was another 'mov' [insn 43] and 'call' [insn 44], similar to those in BB5. Before SCHED1: -------------- BB5: insn 35 set r3, r124 insn 36 call [`operator new`] -> Uses r3,r2 ... insn 78 jump L47 L41: BB6: insn 43 set r3, r124 insn 44 call [`operator new`] -> Uses r3,r2 ... L47: BB7: insn 49 set r5, 0 insn 50 set r4, 1 During the 'sched1' pass, a reordering occurred that moved insn 35 before i= nsn 31 from BB5 to BB4. BB4 contains the check for the 'sMempool' variable [insn 33]: if it's zero, there's a branch to label 41, leading to BB6; otherwise,= it continues with BB5. After SCHED1: ------------- BB3: insn 80 set r145, high(unspec[r2])=20 insn 81 set r139, r145+low(unspec[r2])' BB4: insn 72 set r3, r139 insn 23 set r124, [r138] insn 26 call [`__tls_get_addr`] -> Uses r3,r2 insn 75 set r142, r3 insn 28 set r132, unspec[r142, symbol_ref: `_ZL8sMemPool`] insn 29 set r130, unspec[r132, symbol_ref: `_ZL8sMemPool`] insn 35 set r3, r124 insn 31 set r133, [r130] insn 32 set r134, cmp(r133, 0) insn 33 set pc, { (r134 =3D=3D 0) ? L41 : pc }=20 BB5: insn 36 call [`operator new`] -> Uses r3,r2 ... insn 78 jump L47 L41: BB6=20 insn 43 set r3, r124 insn 44 call [`operator new`] -> Uses r3,r2 ... L47: BB7: insn 49 set r5, 0 insn 50 set r4, 1 In the 'Jump2' pass, the compiler successfully removed the if body (bb5) consisting of insn 36 and insn 78. However, it couldn't remove insn 35, whi= ch was moved to bb4. Additionally, it changed insn 43 to be in bb6 and moved t= he remaining instructions from insn 44 to bb10. As insn 43 and insn 35 are sim= ilar instructions, insn 43 was chosen for deletion in the later pass. After JUMP2: ----------- BB3: .... insn 80 set r28[orig:r145], high(unspec[r2])=20 insn 81 set r28[orig:r139], r28[orig:r145]+low(unspec[r2])' .... BB4: .... .... insn 32 set cr0[orig:r134], cmp(r9[orig:r133], 0) insn 33 set pc, { (cr0[orig:r134] =3D=3D 0) ? L41 : pc } BB5: insn 134 set pc, L133 L41: BB6: insn 43 set r3, r30[orig:r124] L133: BB10: insn 44 call [`operator new`] -> Uses r3,r2 insn 49 set r5,0 insn 50 set r4, 1 .... In cprop_hardreg pass, insn 43 in BB6 is removed After cprop_hardreg: -------------------- BB3: .... insn 80 set r28, high(unspec[r2])=20 insn 81 set r139, r28+low(unspec[r2])' .... BB4: insn 72 set r3, r28[orig:r139] insn 23 set r30[orig:r124], r27[orig:r138] insn 26 call [`__tls_get_addr`] -> Uses r3,r2 insn 28 set r9[orig:r132], unspec[r3[orig:r142],symbol_ref: `_ZL8sMemPool'] insn 29 set r9[orig:r130], unspec[r9[orig:r132],symbol_ref: `_ZL8sMemPool'] insn 35 set r3, r30[orig:r124] insn 31 set r9[orig:r133], [r9][orig:r130] insn 32 set cr0[orig:r134], cmp(r9[orig:r133], 0) insn 33 set pc, { (cr0[orig:r134] =3D=3D 0) ? L41 : pc } BB5: insn 134 set pc, L133 L41: BB6: L133: BB10: insn 44 call [`operator new`] -> Uses r3,r2 insn 49 set r5,0 insn 50 set r4, 1 .... Following the removal of insn 43 in the 'cprop_hardreg' pass, both insn 134= and 33 became unnecessary due to jumping to the same location, which was remove= d in the basic block reordering pass. After BBRO: ----------- BB3: ... insn 80 set r28, high(unspec[r2])=20 insn 81 set r28, r28+low(unspec[r2])' ... BB4: insn 72 set r3, r28 insn 23 set r30, r27 insn 26 call [`__tls_get_addr`] -> Uses r3,r2 insn 28 set r9, unspec[r3,`_ZL8sMemPool'] insn 29 set r9, unspec[r9,`_ZL8sMemPool'] insn 35 set r3, r30 insn 31 set r9, [r9] insn 32 set cr0, cmp(r9, 0) insn 44 call [`operator new`] -> Uses r3,r2 insn 49 set r5,0 insn 50 set r4, 1 ... Upon the removal of these jumps, instructions 32, 31, 29, and 28 in bb4 bec= ame dead, since r9, r3 were used for those jumps. During 'sched2 DCE,' those instructions in BB4 were removed, rendering r3 unused (which was populated = in insn 26). However, its not deleted in this pass: After SCHED2: ------------ BB3: ... insn 80 set r28, high(unspec[r2])=20 insn 81 set r28, r28+low(unspec[r2])' ... BB4: insn 23 set r30, r27 insn 72 set r3, r28 insn 26 call [`__tls_get_addr`] -> Uses r3,r2 insn 35 set r3, r30 insn 44 call [`operator new`] -> Uses r3,r2 insn 49 set r5,0 insn 50 set r4, 1 ... ... The flag 'df_in_progress' is avoiding the call deletion in 'sched2 DCE'. If= the insn 26 is removed, insn 72 can be removed. Consequently, below instruction= s in BB3 could be removed if insn 72 were removed, BB3: insn 80 set r28, high(unspec[r2])=20 insn 81 set r28, r28+low(unspec[r2]) Currently, we have an ICE in insn 80 and 81. Despite of being dead instructions, they remain unremoved until the final pass. The final pass attempts to retrieve a dynamic symbol for insn 80 by iterating over all instruction below, it was present in insn 28. However, insn 28 has already = been removed in 'sched2.' Enabling 'sched2' to handle call deletion successfully removed call_insn 26= and insn 72 in BB4. However, insns 80 and 81 were not removed because live registers (specifically, r28, which is unused) weren't updated for BB3 in t= he same pass. Another 'DCE' pass is required, but our GCC does not have 'DCE' after the 'sched2' pass.=