diff mbox series

[committed] amdgcn: Fix register size bug

Message ID 3da64e3a-9067-77dd-374e-664445af3344@codesourcery.com
State New
Headers show
Series [committed] amdgcn: Fix register size bug | expand

Commit Message

Andrew Stubbs March 23, 2023, 11:47 a.m. UTC
This patch fixes a bug in which the function prologue would save more 
registers to the stack than there was space allocated. This would cause 
data corruption when the epilogue restored the registers if a child 
function had overwritten that memory.

The problem was caused by insn constraints that allow vectors to be 
placed in scalar registers. This isn't usually allowed without an 
explicit vec_duplicate in the pattern, but some post-reload splitters do 
it sometimes (hence the size calculation mismatch).

A full fix would add vec_duplicate variants of all the instructions that 
support this, but that's a huge explosion of patterns, and this fix is 
enough for correctness, for now.

This has already been committed to the OG12 branch.

Andrew
amdgcn: Fix register size bug

Fix an issue in which "vectors" of duplicate entries placed in scalar
registers caused the following 63 registers to be marked live, for the
purpose of prologue generation, which resulted in stack corruption.

gcc/ChangeLog:

	* config/gcn/gcn.cc (gcn_class_max_nregs): Handle vectors in SGPRs.
	(move_callee_saved_registers): Detect the bug condition early.
diff mbox series

Patch

diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index 5bf88e98083..a7d278cd2f8 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -492,6 +492,15 @@  gcn_class_max_nregs (reg_class_t rclass, machine_mode mode)
     }
   else if (rclass == VCC_CONDITIONAL_REG && mode == BImode)
     return 2;
+
+  /* Vector modes in SGPRs are not supposed to happen (disallowed by
+     gcn_hard_regno_mode_ok), but there are some patterns that have an "Sv"
+     constraint and are used by splitters, post-reload.
+     This ensures that we don't accidentally mark the following 63 scalar
+     registers as "live".  */
+  if (rclass == SGPR_REGS && VECTOR_MODE_P (mode))
+    return CEIL (GET_MODE_SIZE (GET_MODE_INNER (mode)), 4);
+
   return CEIL (GET_MODE_SIZE (mode), 4);
 }
 
@@ -3239,6 +3248,10 @@  move_callee_saved_registers (rtx sp, machine_function *offsets,
       emit_insn (move_vectors);
       emit_insn (move_scalars);
     }
+
+  /* This happens when a new register becomes "live" after reload.
+     Check your splitters!  */
+  gcc_assert (offset <= offsets->callee_saves);
 }
 
 /* Generate prologue.  Called from gen_prologue during pro_and_epilogue pass.