lra: Stop registers being incorrectly marked live [PR92989]
authorRichard Sandiford <richard.sandiford@arm.com>
Sat, 18 Jan 2020 12:41:48 +0000 (12:41 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Mon, 27 Jan 2020 10:53:35 +0000 (10:53 +0000)
lra_assign has an assert to make sure that no pseudo is allocated
to a conflicting hard register.  It used to be restricted to
!flag_ipa_ra, but in g:a1e6ee38e708ef2bdef4 I'd enabled it for
flag_ipa_ra too.  It then tripped while building libstdc++
for mips-mti-linux.

The failure was due to code at the end of process_bb_lives.  For an
abnormal/EH edge, we need to make sure that all pseudos that are live
on entry to the destination conflict with all hard registers that are
clobbered by an abnormal call return.  The usual way to do this would
be to simulate a clobber of the hard registers, by making them live and
them making them dead again.  Making the registers live creates the
conflict; making them dead again restores the correct live set for
whatever follows.

However, process_bb_lives skips the second step (making the registers
dead again) at the start of a BB, presumably on the basis that there's
no further code that needs a correct live set.  The problem for the PR
is that that wasn't quite true in practice.  There was code further
down process_bb_lives that updated the live-in set of the BB for some
registers, and this live set was "contaminated" by registers that
weren't live but that created conflicts.  This information then got
propagated to other blocks, so that registers that were made live
purely to create a conflict at the start of the EH receiver then became
needlessly live throughout preceding blocks.  This in turn created a
fake conflict with pseudos in those blocks, invalidating the choices
made by IRA.

The easiest fix seems to be to update the live-in set *before* adding
the fake live registers.  An alternative would be to simulate the full
clobber, but that seems a bit wasteful.

2020-01-27  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
PR rtl-optimization/92989
* lra-lives.c (process_bb_lives): Update the live-in set before
processing additional clobbers.

gcc/ChangeLog
gcc/lra-lives.c

index db2421d1c947e3f48f9cac6b1a6026d00b8fdab7..91dfcd71a4b213de59d5153ec53e664eac3c900c 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-27  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR rtl-optimization/92989
+       * lra-lives.c (process_bb_lives): Update the live-in set before
+       processing additional clobbers.
+
 2020-01-27  Richard Sandiford  <richard.sandiford@arm.com>
 
        PR rtl-optimization/93170
index 0adac6b5a42434a791dcf0a35e749b7a0b5810e8..f439e8993957c45384abe73b7c47e9ec8e8ed219 100644 (file)
@@ -1023,6 +1023,57 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
        make_hard_regno_live (regno);
       }
 
+  bool live_change_p = false;
+  /* Check if bb border live info was changed.  */
+  unsigned int live_pseudos_num = 0;
+  EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb),
+                           FIRST_PSEUDO_REGISTER, j, bi)
+    {
+      live_pseudos_num++;
+      if (! sparseset_bit_p (pseudos_live, j))
+       {
+         live_change_p = true;
+         if (lra_dump_file != NULL)
+           fprintf (lra_dump_file,
+                    "  r%d is removed as live at bb%d start\n", j, bb->index);
+         break;
+       }
+    }
+  if (! live_change_p
+      && sparseset_cardinality (pseudos_live) != live_pseudos_num)
+    {
+      live_change_p = true;
+      if (lra_dump_file != NULL)
+       EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j)
+         if (! bitmap_bit_p (df_get_live_in (bb), j))
+           fprintf (lra_dump_file,
+                    "  r%d is added to live at bb%d start\n", j, bb->index);
+    }
+
+  /* The order of this code and the code below is important.  At this
+     point hard_regs_live does genuinely contain only live registers.
+     Below we pretend other hard registers are live in order to create
+     conflicts with pseudos, but this fake live set shouldn't leak out
+     into the df info.  */
+  for (i = 0; HARD_REGISTER_NUM_P (i); ++i)
+    {
+      if (!TEST_HARD_REG_BIT (hard_regs_live, i))
+       continue;
+
+      if (!TEST_HARD_REG_BIT (hard_regs_spilled_into, i))
+       continue;
+
+      if (bitmap_bit_p (df_get_live_in (bb), i))
+       continue;
+
+      live_change_p = true;
+      if (lra_dump_file)
+       fprintf (lra_dump_file,
+                "  hard reg r%d is added to live at bb%d start\n", i,
+                bb->index);
+      bitmap_set_bit (df_get_live_in (bb), i);
+    }
+
   /* Pseudos can't go in stack regs at the start of a basic block that
      is reached by an abnormal edge.  Likewise for registers that are at
      least partly call clobbered, because caller-save, fixup_abnormal_edges
@@ -1057,32 +1108,6 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
            make_hard_regno_live (px);
     }
 
-  bool live_change_p = false;
-  /* Check if bb border live info was changed.  */
-  unsigned int live_pseudos_num = 0;
-  EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb),
-                           FIRST_PSEUDO_REGISTER, j, bi)
-    {
-      live_pseudos_num++;
-      if (! sparseset_bit_p (pseudos_live, j))
-       {
-         live_change_p = true;
-         if (lra_dump_file != NULL)
-           fprintf (lra_dump_file,
-                    "  r%d is removed as live at bb%d start\n", j, bb->index);
-         break;
-       }
-    }
-  if (! live_change_p
-      && sparseset_cardinality (pseudos_live) != live_pseudos_num)
-    {
-      live_change_p = true;
-      if (lra_dump_file != NULL)
-       EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j)
-         if (! bitmap_bit_p (df_get_live_in (bb), j))
-           fprintf (lra_dump_file,
-                    "  r%d is added to live at bb%d start\n", j, bb->index);
-    }
   /* See if we'll need an increment at the end of this basic block.
      An increment is needed if the PSEUDOS_LIVE set is not empty,
      to make sure the finish points are set up correctly.  */
@@ -1102,25 +1127,6 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
        check_pseudos_live_through_calls (j, last_call_abi);
     }
 
-  for (i = 0; HARD_REGISTER_NUM_P (i); ++i)
-    {
-      if (!TEST_HARD_REG_BIT (hard_regs_live, i))
-       continue;
-
-      if (!TEST_HARD_REG_BIT (hard_regs_spilled_into, i))
-       continue;
-
-      if (bitmap_bit_p (df_get_live_in (bb), i))
-       continue;
-
-      live_change_p = true;
-      if (lra_dump_file)
-       fprintf (lra_dump_file,
-                "  hard reg r%d is added to live at bb%d start\n", i,
-                bb->index);
-      bitmap_set_bit (df_get_live_in (bb), i);
-    }
-
   if (need_curr_point_incr)
     next_program_point (curr_point, freq);