https://gcc.gnu.org/g:efcc06ac1adc833d0b104df038d128031ca85e89

commit r17-5635-gefcc06ac1adc833d0b104df038d128031ca85e89
Author: Richard Earnshaw <[email protected]>
Date:   Tue Oct 20 18:42:08 2026 +0100

    arm: tweak limits on minipool placement [PR127988]
    
    My previous patch changed a number of the calculations on pool
    placement, but this wasn't fully accounted for when inserting a forced
    barrier.  The result was that it was possible to find a barrier in the
    code that had previously been discarded as being too far away.
    
    There was also a small memory leak in the pool dumping code in that
    we weren't destructing the subpools.
    
    gcc/ChangeLog:
    
            PR target/127988
            * config/arm/minipool.cc (minipool::add_forward_ref): Allow
            for pool alignment when checking if the current fix will fit.
            (minipool::create_fix_barrier): Ensure we always have a suitable
            insertion point and fix off-by-one issue when testing if a insn
            is in range.
            (place_minipools): Correctly account for padding and the pool
            skip instruction before inserting a forced barrier.
            (minipool::dump): Call the destructor on subpools before freeing
            them.

Diff:
---
 gcc/config/arm/minipool.cc | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/gcc/config/arm/minipool.cc b/gcc/config/arm/minipool.cc
index 8780120afd10..36714a6b1e77 100644
--- a/gcc/config/arm/minipool.cc
+++ b/gcc/config/arm/minipool.cc
@@ -938,7 +938,12 @@ minipool::add_forward_ref (Mfix *fix, minipool_address loc)
      alignment.  */
   align = std::min (align, ARM_DOUBLEWORD_ALIGN ? 8u: 4u);
 
-  if (loc > m_max_address)
+  /* Check that inserting this value will still leave the pool reachable
+     for all existing entries.  We need to consider the case where
+     the new insertion will increase the alignment of the overall pool.  */
+  if (loc + std::max (get_alignment_size (),
+                     (HOST_WIDE_INT) align - m_insn_align)
+      > m_max_address)
     return NULL;
   std::list<subpool *>::iterator spi
     = find_subpool (align, fix, loc, get_alignment_size ());
@@ -1043,6 +1048,7 @@ minipool::dump (rtx_insn *scan)
   for (spi = m_subpools.begin (); spi != m_subpools.end (); ++spi)
     {
       scan = (*spi)->dump (scan);
+      (*spi)->~subpool ();
       free (*spi);
     }
 
@@ -1062,7 +1068,7 @@ minipool::create_fix_barrier (Mfix *fix, minipool_address 
max_address)
   rtx_barrier *barrier;
   rtx_insn *from = fix->insn;
   /* The instruction after which we will insert the jump.  */
-  rtx_insn *selected = NULL;
+  rtx_insn *selected = from;
   int selected_cost;
   /* The address at which the jump instruction will be placed.  */
   HOST_WIDE_INT selected_address;
@@ -1071,7 +1077,7 @@ minipool::create_fix_barrier (Mfix *fix, minipool_address 
max_address)
   rtx_code_label *label = gen_label_rtx ();
 
   selected_cost = barrier_cost (from);
-  selected_address = fix->address;
+  selected_address = fix->address + fix->insn_size;
 
   while (from && count < max_count)
     {
@@ -1099,8 +1105,7 @@ minipool::create_fix_barrier (Mfix *fix, minipool_address 
max_address)
             still put the pool after the table.  */
          new_cost = barrier_cost (from);
 
-         if (count < max_count
-             && (!selected || new_cost <= selected_cost))
+         if (count <= max_count && new_cost <= selected_cost)
            {
              selected = tmp;
              selected_cost = new_cost;
@@ -1114,8 +1119,7 @@ minipool::create_fix_barrier (Mfix *fix, minipool_address 
max_address)
 
       new_cost = barrier_cost (from);
 
-      if (count < max_count
-         && (!selected || new_cost <= selected_cost))
+      if (count <= max_count && new_cost <= selected_cost)
        {
          selected = from;
          selected_cost = new_cost;
@@ -1125,9 +1129,6 @@ minipool::create_fix_barrier (Mfix *fix, minipool_address 
max_address)
       from = next_nonnote_nondebug_insn (from);
     }
 
-  /* Make sure that we found a place to insert the jump.  */
-  gcc_assert (selected);
-
   /* Create a new JUMP_INSN that branches around a barrier.  */
   from = emit_jump_insn_after (gen_jump (label), selected);
   JUMP_LABEL (from) = label;
@@ -1435,15 +1436,14 @@ place_minipools (void)
             last_barrier being set.  */
          gcc_assert (ftmp);
 
-         max_address = mpool.forwards ();
-         /* Check that there isn't another fix that is in range that
-            we couldn't fit into this pool because the pool was
-            already too large: we need to put the pool before such an
-            instruction.  The pool itself may come just after the
-            fix because create_fix_barrier also allows space for a
-            jump instruction.  */
+         max_address = (mpool.forwards ()
+                        - (mpool.get_alignment_size () + pool_skip));
+         gcc_assert (max_address
+                     >= last_added_fix->address + last_added_fix->insn_size);
+
+         /* Ensure the pool comes before ftmp.  */
          if (ftmp->address < max_address)
-           max_address = ftmp->address + 1;
+           max_address = ftmp->address;
 
          last_barrier = mpool.create_fix_barrier (last_added_fix,
                                                   max_address);

Reply via email to