File pr124439.patch of Package gcc16

From 4bcf6c461a9b8fb6e68de3f0b695881b9ac6e934 Mon Sep 17 00:00:00 2001
From: Robin Dapp <rdapp@oss.qualcomm.com>
Date: Wed, 4 Mar 2026 10:02:07 +0100
Subject: [PATCH] lra: Validate regno and mode in equiv substitution.
 [PR124041]

We can perform equivalence substitution in subreg context:

(insn 34 32 36 3 (set (reg:SI 103 [ _7 ])
        (subreg:SI (reg/f:DI 119) 0)) "bla.c":7:41 104 {*movsi_aarch64}

becomes

(insn 34 32 36 3 (set (reg:SI 103 [ _7 ])
        (subreg:SI (reg/f:DI 64 sfp) 0)) "bla.c":7:41 104 {*movsi_aarch64}
     (nil))

but aarch64_hard_regno_mode_ok doesn't like that:

  if (regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM)
    return mode == Pmode;

and ICEs further on.

Therefore, this patch checks hard_regno_mode_ok if we substitute a hard
reg in subreg context.

	PR rtl-optimization/124041

gcc/ChangeLog:

	* lra-constraints.cc (curr_insn_transform): Check if hardreg is
	valid in subreg context.

gcc/testsuite/ChangeLog:

	* gcc.dg/torture/pr124041.c: New test.

Signed-off-by: Robin Dapp <rdapp@oss.qualcomm.com>
---
 gcc/lra-constraints.cc                  | 14 +++++++++++++-
 gcc/testsuite/gcc.dg/torture/pr124041.c | 17 +++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr124041.c

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 84f78b40d6a..fae7b49bdbd 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -4402,11 +4402,23 @@ curr_insn_transform (bool check_only_p)
 	  continue;
 
 	old = op = *curr_id->operand_loc[i];
+	machine_mode outer_mode = GET_MODE (old);
+	bool subreg_p = false;
 	if (GET_CODE (old) == SUBREG)
-	  old = SUBREG_REG (old);
+	  {
+	    old = SUBREG_REG (old);
+	    subreg_p = true;
+	  }
 	subst = get_equiv_with_elimination (old, curr_insn);
 	original_subreg_reg_mode[i] = VOIDmode;
 	equiv_substition_p[i] = false;
+
+	/* If we are about to replace a register inside a subreg, check if
+	   the target can handle that.  */
+	if (subreg_p && REG_P (subst) && HARD_REGISTER_P (subst)
+	    && !targetm.hard_regno_mode_ok (REGNO (subst), outer_mode))
+	  continue;
+
 	if (subst != old)
 	  {
 	    equiv_substition_p[i] = true;
diff --git a/gcc/testsuite/gcc.dg/torture/pr124041.c b/gcc/testsuite/gcc.dg/torture/pr124041.c
new file mode 100644
index 00000000000..f966757e4b5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr124041.c
@@ -0,0 +1,17 @@
+/* { dg-compile } */
+/* { dg-additional-options "-O2  -fno-strict-aliasing -fstack-protector -ftrivial-auto-var-init=zero -fsanitize=thread -Wall" } */
+
+char *trick_compiler(void *);
+int do_usercopy_stack_callee_i;
+char *do_usercopy_stack_callee(long value)
+{
+    char buf[28];
+    for (; do_usercopy_stack_callee_i < sizeof(buf); do_usercopy_stack_callee_i++)
+        buf[do_usercopy_stack_callee_i] = value;
+    return trick_compiler(buf);
+}
+void do_usercopy_stack(void)
+{
+    char *bad_stack;
+    bad_stack = do_usercopy_stack_callee((long)&bad_stack);
+}
-- 
2.53.0

openSUSE Build Service is sponsored by