Sorry, I forgot to add the patch itself.  Here it is.

On 11/29/24 15:01, Vladimir Makarov wrote:

The following patch solves

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117770

The patch was successfully tested and bootstrapped on x864_64, aarch64, ppc64le.

commit e79583cef924f5fb5de551bd61da7b5fdee5c690
Author: Vladimir N. Makarov <vmaka...@redhat.com>
Date:   Fri Nov 29 14:58:47 2024 -0500

    [PR117770][LRA]: Check hard regs corresponding insn operands for hard reg clobbers
    
    When LRA processes early clobbered hard regs explicitly present in the
    insn description, it checks that the hard reg is also used as input.
    If the hard reg is not an input also, it is marked as dying.  For the
    check LRA processed only input hard reg also explicitly present in the
    insn description.  For given PR, the hard reg is used as input as the
    operand and is not present explicitly in the insn description and
    therefore LRA marked the hard reg as dying.  This results in wrong
    allocation and wrong code.  The patch solves the problem by processing
    hard regs used as the insn operand.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/117770
            * lra-lives.cc: Include ira-int.h.
            (process_bb_lives): Check hard regs corresponding insn operands
            for dying hard wired reg clobbers.

diff --git a/gcc/lra-lives.cc b/gcc/lra-lives.cc
index 66c6577e5d6..49134ade713 100644
--- a/gcc/lra-lives.cc
+++ b/gcc/lra-lives.cc
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.	If not see
 #include "insn-config.h"
 #include "regs.h"
 #include "ira.h"
+#include "ira-int.h"
 #include "recog.h"
 #include "cfganal.h"
 #include "sparseset.h"
@@ -990,6 +991,19 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
 	    for (reg2 = curr_static_id->hard_regs; reg2 != NULL; reg2 = reg2->next)
 	      if (reg2->type != OP_OUT && reg2->regno == reg->regno)
 		break;
+	    if (reg2 != NULL)
+	      continue;
+
+	    HARD_REG_SET clobbered_regset;
+	    CLEAR_HARD_REG_SET (clobbered_regset);
+	    SET_HARD_REG_BIT (clobbered_regset, reg->regno);
+
+	    for (reg2 = curr_id->regs; reg2 != NULL; reg2 = reg2->next)
+	      if (reg2->type != OP_OUT && reg2->regno < FIRST_PSEUDO_REGISTER
+		  && ira_hard_reg_set_intersection_p (reg2->regno,
+						      reg2->biggest_mode,
+						      clobbered_regset))
+		break;
 	    if (reg2 == NULL)
 	      make_hard_regno_dead (reg->regno);
 	  }

Reply via email to