forked from pool/gcc15
160 lines
5.2 KiB
Diff
160 lines
5.2 KiB
Diff
|
|
From 00b667cf08a8a91e7226cffaffe08943c5812cd2 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Richard Biener <rguenther@suse.de>
|
||
|
|
Date: Mon, 2 Jun 2025 20:21:45 -0300
|
||
|
|
Subject: [PATCH] [lra] force reg update after spilling to memory [PR120424]
|
||
|
|
To: gcc-patches@gcc.gnu.org
|
||
|
|
|
||
|
|
From: Alexandre Oliva <oliva@adacore.com>
|
||
|
|
|
||
|
|
In the added C++ testcase, a stack slot at a negative sp offset is
|
||
|
|
used to hold a value across a call.
|
||
|
|
|
||
|
|
There are a couple of causes that directly lead to this outcome:
|
||
|
|
|
||
|
|
- the -fstack-clash-protection and -fnon-call-exception options, that
|
||
|
|
cause arm_frame_pointer_required to flip from false to true when the
|
||
|
|
first pseudo gets spilled to memory;
|
||
|
|
|
||
|
|
- when the affected pseudo is spilled to memory, we fail to update lra
|
||
|
|
regno info, because the insns that reference it are already on the
|
||
|
|
lra_constraint_insn_stack;
|
||
|
|
|
||
|
|
There is another potentially-related issue:
|
||
|
|
|
||
|
|
- when we notice that the frame pointer can no longer be eliminated to
|
||
|
|
the stack pointer, we immediately clear can_eliminate, and also
|
||
|
|
prev_can_eliminate, but update_reg_eliminate relied on the latter to
|
||
|
|
tell that it needs to propagate a previous_offset to the
|
||
|
|
newly-selected elimination, or restore the original offsets.
|
||
|
|
|
||
|
|
This patch ensures that we update insn register info after spilling a
|
||
|
|
pseudo to memory, and enables update_reg_eliminate to recognize the
|
||
|
|
case in which a previously-preferred elimination is disabled
|
||
|
|
regardless of prev_can_eliminate.
|
||
|
|
|
||
|
|
for gcc/ChangeLog
|
||
|
|
|
||
|
|
PR rtl-optimization/120424
|
||
|
|
PR middle-end/118939
|
||
|
|
* lra-spills.cc (spill_pseudos): Update insn regno info.
|
||
|
|
* lra-eliminations.cc (update_reg_eliminate): Recognize
|
||
|
|
disabling of active elimination regardless of
|
||
|
|
prev_can_eliminate.
|
||
|
|
|
||
|
|
for gcc/testsuite/ChangeLog
|
||
|
|
|
||
|
|
PR rtl-optimization/120424
|
||
|
|
PR middle-end/118939
|
||
|
|
* g++.target/arm/pr120424.C: New.
|
||
|
|
* gnat.dg/controlled9.adb: New.
|
||
|
|
* gnat.dg/controlled9_pkg.ads: New.
|
||
|
|
|
||
|
|
(cherry picked from commit 2edb50a310896da72710dba7724a3b4a541a1cbb)
|
||
|
|
---
|
||
|
|
gcc/lra-eliminations.cc | 2 +-
|
||
|
|
gcc/lra-spills.cc | 2 +-
|
||
|
|
gcc/testsuite/g++.target/arm/pr120424.C | 34 +++++++++++++++++++++++
|
||
|
|
gcc/testsuite/gnat.dg/controlled9.adb | 10 +++++++
|
||
|
|
gcc/testsuite/gnat.dg/controlled9_pkg.ads | 5 ++++
|
||
|
|
5 files changed, 51 insertions(+), 2 deletions(-)
|
||
|
|
create mode 100644 gcc/testsuite/g++.target/arm/pr120424.C
|
||
|
|
create mode 100644 gcc/testsuite/gnat.dg/controlled9.adb
|
||
|
|
create mode 100644 gcc/testsuite/gnat.dg/controlled9_pkg.ads
|
||
|
|
|
||
|
|
diff --git a/gcc/lra-eliminations.cc b/gcc/lra-eliminations.cc
|
||
|
|
index d84a7d1ee99..bb708b007a4 100644
|
||
|
|
--- a/gcc/lra-eliminations.cc
|
||
|
|
+++ b/gcc/lra-eliminations.cc
|
||
|
|
@@ -1185,7 +1185,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
|
||
|
|
setup_can_eliminate (ep, false);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
- if (ep->can_eliminate != prev && elimination_map[ep->from] == ep)
|
||
|
|
+ if (!ep->can_eliminate && elimination_map[ep->from] == ep)
|
||
|
|
{
|
||
|
|
/* We cannot use this elimination anymore -- find another
|
||
|
|
one. */
|
||
|
|
diff --git a/gcc/lra-spills.cc b/gcc/lra-spills.cc
|
||
|
|
index fc912c43ce6..4febc693d28 100644
|
||
|
|
--- a/gcc/lra-spills.cc
|
||
|
|
+++ b/gcc/lra-spills.cc
|
||
|
|
@@ -556,7 +556,7 @@ spill_pseudos (void)
|
||
|
|
fprintf (lra_dump_file,
|
||
|
|
"Changing spilled pseudos to memory in insn #%u\n",
|
||
|
|
INSN_UID (insn));
|
||
|
|
- lra_push_insn (insn);
|
||
|
|
+ lra_push_insn_and_update_insn_regno_info (insn);
|
||
|
|
if (lra_reg_spill_p || targetm.different_addr_displacement_p ())
|
||
|
|
lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
|
||
|
|
}
|
||
|
|
diff --git a/gcc/testsuite/g++.target/arm/pr120424.C b/gcc/testsuite/g++.target/arm/pr120424.C
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..4d0e49013c0
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/g++.target/arm/pr120424.C
|
||
|
|
@@ -0,0 +1,34 @@
|
||
|
|
+/* { dg-do compile } */
|
||
|
|
+/* { dg-options "-march=armv7 -O2 -fstack-clash-protection -fnon-call-exceptions" } */
|
||
|
|
+/* { dg-final { scan-assembler-not {#-8} } } */
|
||
|
|
+/* LRA register elimination gets confused when register spilling
|
||
|
|
+ causes arm_frame_pointer_required to switch from false to true, and
|
||
|
|
+ ends up using a stack slot below sp. */
|
||
|
|
+
|
||
|
|
+void f() {
|
||
|
|
+ int i = 0, j = 0;
|
||
|
|
+ asm ("" : : "m" (i), "m" (j));
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void g(void (*fn[])(), int i)
|
||
|
|
+{
|
||
|
|
+ auto fn0 = fn[i+0];
|
||
|
|
+ auto fn1 = fn[i+1];
|
||
|
|
+ auto fn2 = fn[i+2];
|
||
|
|
+ auto fn3 = fn[i+3];
|
||
|
|
+ fn0();
|
||
|
|
+ fn1();
|
||
|
|
+ if (!fn2)
|
||
|
|
+ throw i+2;
|
||
|
|
+ fn2();
|
||
|
|
+ fn3();
|
||
|
|
+ fn0();
|
||
|
|
+ fn1();
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int
|
||
|
|
+main()
|
||
|
|
+{
|
||
|
|
+ void (*fn[4])() = { f, f, f, f };
|
||
|
|
+ g (fn, 0);
|
||
|
|
+}
|
||
|
|
diff --git a/gcc/testsuite/gnat.dg/controlled9.adb b/gcc/testsuite/gnat.dg/controlled9.adb
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..fb7acce854e
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gnat.dg/controlled9.adb
|
||
|
|
@@ -0,0 +1,10 @@
|
||
|
|
+-- { dg-do run }
|
||
|
|
+-- { dg-options "-O1 -fstack-check" }
|
||
|
|
+-- from PR middle-end/118939
|
||
|
|
+
|
||
|
|
+with Controlled9_Pkg;
|
||
|
|
+procedure Controlled9 is
|
||
|
|
+ S : constant Controlled9_Pkg.T_Access := new Controlled9_Pkg.T;
|
||
|
|
+begin
|
||
|
|
+ null;
|
||
|
|
+end Controlled9;
|
||
|
|
diff --git a/gcc/testsuite/gnat.dg/controlled9_pkg.ads b/gcc/testsuite/gnat.dg/controlled9_pkg.ads
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..d0e7c28273e
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gnat.dg/controlled9_pkg.ads
|
||
|
|
@@ -0,0 +1,5 @@
|
||
|
|
+with Ada.Finalization;
|
||
|
|
+package Controlled9_Pkg is
|
||
|
|
+ type T is new Ada.Finalization.Controlled with null record;
|
||
|
|
+ type T_Access is access all T;
|
||
|
|
+end Controlled9_Pkg;
|
||
|
|
--
|
||
|
|
2.51.0
|
||
|
|
|