https://gcc.gnu.org/g:43a7ece873eba47a11c0b21b0068eee53740551a

commit r15-2111-g43a7ece873eba47a11c0b21b0068eee53740551a
Author: Richard Sandiford <richard.sandif...@arm.com>
Date:   Wed Jul 17 19:38:12 2024 +0100

    rtl-ssa: Fix move range canonicalisation [PR115929]
    
    In this PR, canonicalize_move_range walked off the end of a list
    and triggered a null dereference.  There are multiple ways of fixing
    that, but I think the approach taken in the patch should be
    relatively efficient.
    
    gcc/
            PR rtl-optimization/115929
            * rtl-ssa/movement.h (canonicalize_move_range): Check for null prev
            and next insns and create an invalid move range for them.
    
    gcc/testsuite/
            PR rtl-optimization/115929
            * gcc.dg/torture/pr115929-2.c: New test.

Diff:
---
 gcc/rtl-ssa/movement.h                    | 20 ++++++++++++++++++--
 gcc/testsuite/gcc.dg/torture/pr115929-2.c | 22 ++++++++++++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/gcc/rtl-ssa/movement.h b/gcc/rtl-ssa/movement.h
index 17d31e0b5cbe..ea1f788df49e 100644
--- a/gcc/rtl-ssa/movement.h
+++ b/gcc/rtl-ssa/movement.h
@@ -76,9 +76,25 @@ inline bool
 canonicalize_move_range (insn_range_info &move_range, insn_info *insn)
 {
   while (move_range.first != insn && !can_insert_after (move_range.first))
-    move_range.first = move_range.first->next_nondebug_insn ();
+    if (auto *next = move_range.first->next_nondebug_insn ())
+      move_range.first = next;
+    else
+      {
+       // Invalidate the range.  prev_nondebug_insn is always nonnull
+       // if next_nondebug_insn is null.
+       move_range.last = move_range.first->prev_nondebug_insn ();
+       return false;
+      }
   while (move_range.last != insn && !can_insert_after (move_range.last))
-    move_range.last = move_range.last->prev_nondebug_insn ();
+    if (auto *prev = move_range.last->prev_nondebug_insn ())
+      move_range.last = prev;
+    else
+      {
+       // Invalidate the range.  next_nondebug_insn is always nonnull
+       // if prev_nondebug_insn is null.
+       move_range.first = move_range.last->next_nondebug_insn ();
+       return false;
+      }
   return bool (move_range);
 }
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr115929-2.c 
b/gcc/testsuite/gcc.dg/torture/pr115929-2.c
new file mode 100644
index 000000000000..c8473a74da6c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr115929-2.c
@@ -0,0 +1,22 @@
+/* { dg-additional-options "-fschedule-insns" } */
+
+int a, b, c, d, e, f;
+int main() {
+  if (e && f)
+    while (1)
+      while (a)
+        a = 0;
+  if (c) {
+    if (b)
+      goto g;
+    int h = a;
+  i:
+    b = ~((b ^ h) | 1 % b);
+    if (a)
+    g:
+      b = 0;
+  }
+  if (d)
+    goto i;
+  return 0;
+}

Reply via email to