aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2024-01-09 10:14:29 +0100
committerEric Botcazou <ebotcazou@adacore.com>2024-01-09 10:24:57 +0100
commitf34141730266600b615b91d563a85a0b60223b3e (patch)
treecbbfc9a0a6f21b1c6b46e35ed1d7963494584c4e
parentf2e967e0257bc8188840df236595e7218b6bf748 (diff)
downloadgcc-f34141730266600b615b91d563a85a0b60223b3e.zip
gcc-f34141730266600b615b91d563a85a0b60223b3e.tar.gz
gcc-f34141730266600b615b91d563a85a0b60223b3e.tar.bz2
Fix segfault during delay slot scheduling pass
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.
-rw-r--r--gcc/reorg.cc13
-rw-r--r--gcc/testsuite/g++.dg/opt/delay-slot-2.C32
2 files changed, 40 insertions, 5 deletions
diff --git a/gcc/reorg.cc b/gcc/reorg.cc
index e85af71..99228a2 100644
--- a/gcc/reorg.cc
+++ b/gcc/reorg.cc
@@ -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
index 0000000..3810503
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/delay-slot-2.C
@@ -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)
+ ;
+ }();
+}