diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2024-01-09 10:14:29 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@adacore.com> | 2024-01-09 10:24:57 +0100 |
commit | f34141730266600b615b91d563a85a0b60223b3e (patch) | |
tree | cbbfc9a0a6f21b1c6b46e35ed1d7963494584c4e | |
parent | f2e967e0257bc8188840df236595e7218b6bf748 (diff) | |
download | gcc-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.cc | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/delay-slot-2.C | 32 |
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) + ; + }(); +} |