Skip to content

Commit 2edb50a

Browse files
Alexandre OlivaAlexandre Oliva
authored andcommitted
[lra] force reg update after spilling to memory [PR120424]
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.
1 parent 8fc9e03 commit 2edb50a

File tree

5 files changed

+51
-2
lines changed

5 files changed

+51
-2
lines changed

gcc/lra-eliminations.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
11851185
setup_can_eliminate (ep, false);
11861186
continue;
11871187
}
1188-
if (ep->can_eliminate != prev && elimination_map[ep->from] == ep)
1188+
if (!ep->can_eliminate && elimination_map[ep->from] == ep)
11891189
{
11901190
/* We cannot use this elimination anymore -- find another
11911191
one. */

gcc/lra-spills.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ spill_pseudos (void)
556556
fprintf (lra_dump_file,
557557
"Changing spilled pseudos to memory in insn #%u\n",
558558
INSN_UID (insn));
559-
lra_push_insn (insn);
559+
lra_push_insn_and_update_insn_regno_info (insn);
560560
if (lra_reg_spill_p || targetm.different_addr_displacement_p ())
561561
lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
562562
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* { dg-do compile } */
2+
/* { dg-options "-march=armv7 -O2 -fstack-clash-protection -fnon-call-exceptions" } */
3+
/* { dg-final { scan-assembler-not {#-8} } } */
4+
/* LRA register elimination gets confused when register spilling
5+
causes arm_frame_pointer_required to switch from false to true, and
6+
ends up using a stack slot below sp. */
7+
8+
void f() {
9+
int i = 0, j = 0;
10+
asm ("" : : "m" (i), "m" (j));
11+
}
12+
13+
void g(void (*fn[])(), int i)
14+
{
15+
auto fn0 = fn[i+0];
16+
auto fn1 = fn[i+1];
17+
auto fn2 = fn[i+2];
18+
auto fn3 = fn[i+3];
19+
fn0();
20+
fn1();
21+
if (!fn2)
22+
throw i+2;
23+
fn2();
24+
fn3();
25+
fn0();
26+
fn1();
27+
}
28+
29+
int
30+
main()
31+
{
32+
void (*fn[4])() = { f, f, f, f };
33+
g (fn, 0);
34+
}

gcc/testsuite/gnat.dg/controlled9.adb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- { dg-do run }
2+
-- { dg-options "-O1 -fstack-check" }
3+
-- from PR middle-end/118939
4+
5+
with Controlled9_Pkg;
6+
procedure Controlled9 is
7+
S : constant Controlled9_Pkg.T_Access := new Controlled9_Pkg.T;
8+
begin
9+
null;
10+
end Controlled9;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
with Ada.Finalization;
2+
package Controlled9_Pkg is
3+
type T is new Ada.Finalization.Controlled with null record;
4+
type T_Access is access all T;
5+
end Controlled9_Pkg;

0 commit comments

Comments
 (0)