]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix segfault during delay slot scheduling pass
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 9 Jan 2024 09:14:29 +0000 (10:14 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Tue, 9 Jan 2024 09:24:57 +0000 (10:24 +0100)
This is a small regression present on the mainline and 13 branch, although
the underlying problem has probably been there for ages, in the form of a
segfault during the delay slot scheduling pass, for a function that falls
through to exit without any instruction generated for the end of function.

gcc/
PR rtl-optimization/113140
* reorg.cc (fill_slots_from_thread): If we are to branch after the
last instruction of the function, create an end label.

gcc/testsuite/
* g++.dg/opt/delay-slot-2.C: New test.

gcc/reorg.cc
gcc/testsuite/g++.dg/opt/delay-slot-2.C [new file with mode: 0644]

index e85af7134f4cc32e0f3fafe5bdb1a1727b503cb6..99228a22c69e40b8ca3f1777b40b054ed1cefffb 100644 (file)
@@ -2641,7 +2641,8 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
      arithmetic insn after the jump insn and put the arithmetic insn in the
      delay slot.  If we can't do this, return.  */
   if (delay_list->is_empty () && likely
-      && new_thread && !ANY_RETURN_P (new_thread)
+      && new_thread
+      && !ANY_RETURN_P (new_thread)
       && NONJUMP_INSN_P (new_thread)
       && !RTX_FRAME_RELATED_P (new_thread)
       && GET_CODE (PATTERN (new_thread)) != ASM_INPUT
@@ -2729,14 +2730,16 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
 
       gcc_assert (thread_if_true);
 
-      if (new_thread && simplejump_or_return_p (new_thread)
+      if (new_thread
+         && simplejump_or_return_p (new_thread)
          && redirect_with_delay_list_safe_p (insn,
                                              JUMP_LABEL (new_thread),
                                              *delay_list))
-       new_thread = follow_jumps (JUMP_LABEL (new_thread), insn,
-                                  &crossing);
+       new_thread = follow_jumps (JUMP_LABEL (new_thread), insn, &crossing);
 
-      if (ANY_RETURN_P (new_thread))
+      if (!new_thread)
+       label = find_end_label (simple_return_rtx);
+      else if (ANY_RETURN_P (new_thread))
        label = find_end_label (new_thread);
       else if (LABEL_P (new_thread))
        label = new_thread;
diff --git a/gcc/testsuite/g++.dg/opt/delay-slot-2.C b/gcc/testsuite/g++.dg/opt/delay-slot-2.C
new file mode 100644 (file)
index 0000000..3810503
--- /dev/null
@@ -0,0 +1,32 @@
+// PR rtl-optimization/113140
+// Reduced testcase by Rainer Orth <ro@gcc.gnu.org>
+
+// { dg-options "-O -w" }
+
+int *m();
+struct StaticValue {
+  long _val;
+  void setM(int *) { _val = 0; }
+};
+struct Value : StaticValue {
+  template <typename T> T *as();
+};
+Value *alloc();
+struct Scoped {
+  Scoped() {
+    Value v;
+    ptr = alloc();
+    Value *__trans_tmp_1 = v.as<Value>();
+    ptr->setM(__trans_tmp_1 ? m() : 0);
+  }
+  Value *ptr;
+};
+struct QObjectMethod {
+  unsigned long long callInternal() const;
+};
+unsigned long long QObjectMethod::callInternal() const {
+  [] {
+    if (Scoped(); 0)
+      ;
+  }();
+}