[gcc r17-3001] [PATCH 2/2] alpha: keep the exception receiver's gpdisp pair together [PR124495]
Jeff Law via Gcc-cvs <[email protected]> Thu, 6 Aug 2026 03:03:01 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:9a72a88b4a5f4c271e78e6ff3ddc76e793dfa69c commit r17-3001-g9a72a88b4a5f4c271e78e6ff3ddc76e793dfa69c Author: Matt Turner <[email protected]> Date: Wed Aug 5 21:02:38 2026 -0600 [PATCH 2/2] alpha: keep the exception receiver's gpdisp pair together [PR124495] exception_receiver and builtin_setjmp_receiver split into an ldah/lda pair that shares a !gpdisp relocation sequence number, so the two insns have to stay in 1-1 correspondence. The first half is an unspec_volatile (*ldgp_er_1), but the second half was a plain unspec (*ldgp_er_2), which makes the halves unequally deletable: once the landing pad turns out not to use $29, the DCE run at the start of the peephole2 pass removes the lda and leaves the ldah behind. The assembler then rejects the result: Error: No lda !gpdisp!1188 was found Compiling C++ with -fassume-sane-operators-new-delete, which is the default, makes this much easier to hit, since it lets more of the cleanup code in a landing pad be optimized away. Add an unspec_volatile variant of *ldgp_er_2 and use it for both receivers. The gpdisp pair emitted after a call needs no such treatment: there the ldah is part of the call insn and both halves are plain unspecs, so they are deleted together. gcc/ChangeLog: PR target/124495 * config/alpha/alpha.md (UNSPECV_LDGP2): New unspec_volatile. (*ldgp_er_2_v): New insn. (*builtin_setjmp_receiver_1): Split the second half of the gpdisp pair to it instead of *ldgp_er_2. (*exception_receiver_1): Ditto. gcc/testsuite/ChangeLog: PR target/124495 * g++.target/alpha/pr124495.C: New test. Diff: --- gcc/config/alpha/alpha.md | 19 +++++++++++++++++-- gcc/testsuite/g++.target/alpha/pr124495.C | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index e567bba066c0..30a9f613e378 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -74,6 +74,7 @@ UNSPECV_MCOUNT UNSPECV_FORCE_MOV UNSPECV_LDGP1 + UNSPECV_LDGP2 UNSPECV_PLDGP2 ; prologue ldgp UNSPECV_SET_TP UNSPECV_RPCC @@ -5081,6 +5082,20 @@ "lda %0,0(%1)\t\t!gpdisp!%2" [(set_attr "cannot_copy" "true")]) +;; Same as *ldgp_er_2, but for the pairs whose first half is the +;; unspec_volatile *ldgp_er_1. Both halves of a gpdisp pair have to be +;; equally deletable: a plain unspec here is removed by DCE as soon as $29 +;; turns out to be unused, and the ldah left behind makes the assembler +;; complain about a missing lda. +(define_insn "*ldgp_er_2_v" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "r") + (match_operand 2 "const_int_operand")] + UNSPECV_LDGP2))] + "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF" + "lda %0,0(%1)\t\t!gpdisp!%2" + [(set_attr "cannot_copy" "true")]) + (define_insn "*prologue_ldgp_er_2" [(set (match_operand:DI 0 "register_operand" "=r") (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "r") @@ -5213,7 +5228,7 @@ [(set (match_dup 1) (unspec_volatile:DI [(match_dup 2) (match_dup 3)] UNSPECV_LDGP1)) (set (match_dup 1) - (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_LDGP2))] + (unspec_volatile:DI [(match_dup 1) (match_dup 3)] UNSPECV_LDGP2))] { if (prev_nonnote_insn (curr_insn) != XEXP (operands[0], 0)) emit_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec (1, operands[0]), @@ -5266,7 +5281,7 @@ [(set (match_dup 0) (unspec_volatile:DI [(match_dup 1) (match_dup 2)] UNSPECV_LDGP1)) (set (match_dup 0) - (unspec:DI [(match_dup 0) (match_dup 2)] UNSPEC_LDGP2))] + (unspec_volatile:DI [(match_dup 0) (match_dup 2)] UNSPECV_LDGP2))] { operands[0] = pic_offset_table_rtx; operands[1] = gen_rtx_REG (Pmode, 26); diff --git a/gcc/testsuite/g++.target/alpha/pr124495.C b/gcc/testsuite/g++.target/alpha/pr124495.C new file mode 100644 index 000000000000..6b1fb397a8b8 --- /dev/null +++ b/gcc/testsuite/g++.target/alpha/pr124495.C @@ -0,0 +1,19 @@ +/* PR target/124495 */ +/* { dg-do assemble } */ +/* { dg-options "-O2 -std=c++17" } */ + +/* The exception receiver expands to an ldah/lda pair sharing a !gpdisp + relocation sequence number. If the landing pad turns out not to use $29, + neither half may be deleted on its own. */ + +#include <memory> +#include <variant> +#include <vector> + +struct S { std::variant<int, std::vector<int>> v; }; + +S * +f (S *first, S *last, S *result) +{ + return std::uninitialized_copy (first, last, result); +}