From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22398 invoked by alias); 14 Dec 2007 02:48:49 -0000 Received: (qmail 22374 invoked by uid 48); 14 Dec 2007 02:48:37 -0000 Date: Fri, 14 Dec 2007 02:48:00 -0000 Subject: [Bug rtl-optimization/34456] New: Flaw in branch delay optimization (patch included). X-Bugzilla-Reason: CC Message-ID: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "kkylheku at gmail dot com" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2007-12/txt/msg01238.txt.bz2 This was discovered in GCC 4.1.1 on MIPS, but the problem is in the current SVN head. The mark_set_resources function incorrectly calculates the potentially clobbered registers for a CALL_INSN, using an obsolete approach relying on the call_used_regs array. A potential consequence of this is that a register which should be live is marked dead during the liveness analysis which is done in order to determine whether an instruction move into a delay slot is free of resource conflicts. Thus, it's possible that an instruction which clobbers a register that is live in the fall-through path is moved into a non-annulled delay slot of a branch instruction. This behavior in fact happened when compiling a C++ application for MIPS (n32). The MIPS GP register ($28) is in call_used_regs, but not in call_really_used_regs. The hard reg set regs_invalidated_by_call should be used; it contains the right information compiled from global_regs and call_really_used_regs. The target of the branch instruction in the failed program is an epilogue which restores registers, the first being the GP. This GP-restoring instruction is moved into the branch delay slot, because in the fall-through-code mark_target_live_regs finds a call instruction ahead of anything which uses the GP, and concludes that GP is a dead register. The result is that a GOT-based indirect function call is made using the caller's GP, which is different from the caller's. After this patch, nearly the same code is generated, except that the branch is correctly changed to an annulling one (MIPS ``branch likely''). --- gcc-4.1.1.orig/gcc/resource.c 2007-12-16 11:59:18.000000000 -0800 +++ gcc-4.1.1/gcc/resource.c 2007-12-19 20:59:02.724735120 -0800 @@ -664,9 +664,8 @@ rtx link; res->cc = res->memory = 1; - for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) - if (call_used_regs[r] || global_regs[r]) - SET_HARD_REG_BIT (res->regs, r); + + IOR_HARD_REG_SET (res->regs, regs_invalidated_by_call); for (link = CALL_INSN_FUNCTION_USAGE (x); link; link = XEXP (link, 1)) -- Summary: Flaw in branch delay optimization (patch included). Product: gcc Version: 4.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: kkylheku at gmail dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34456