]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PR117770][LRA]: Check hard regs corresponding insn operands for hard reg clobbers
authorVladimir N. Makarov <vmakarov@redhat.com>
Fri, 29 Nov 2024 19:58:47 +0000 (14:58 -0500)
committerVladimir N. Makarov <vmakarov@redhat.com>
Fri, 29 Nov 2024 19:59:12 +0000 (14:59 -0500)
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.

gcc/lra-lives.cc

index 66c6577e5d601433805c8e2d924d110c2cbf6c34..49134ade713da681992a7dd572a09c040d8a8f26 100644 (file)
@@ -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);
          }