From 535115caaf97f5201fb528f67f15b4c52be5619d Mon Sep 17 00:00:00 2001
From: Richard Biener <rguenther@suse.de>
Date: Fri, 28 Feb 2025 10:36:11 +0100
Subject: [PATCH] tree-optimization/87984 - hard register assignments not
 preserved

The following disables redundant store elimination to hard register
variables which isn't valid.

	PR tree-optimization/87984
	* tree-ssa-dom.cc (dom_opt_dom_walker::optimize_stmt): Do
	not perform redundant store elimination to hard register
	variables.
	* tree-ssa-sccvn.cc (eliminate_dom_walker::eliminate_stmt):
	Likewise.

	* gcc.target/i386/pr87984.c: New testcase.
---
 gcc/testsuite/gcc.target/i386/pr87984.c | 23 +++++++++++++++++++++++
 gcc/tree-ssa-dom.cc                     |  4 +++-
 gcc/tree-ssa-sccvn.cc                   |  2 ++
 3 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr87984.c

diff --git a/gcc/testsuite/gcc.target/i386/pr87984.c b/gcc/testsuite/gcc.target/i386/pr87984.c
new file mode 100644
index 000000000000..39a6a7480f9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr87984.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+__attribute__((noipa))
+int f(void)
+{
+  int o = 0;
+  for (int i = 0; i < 3; i++)
+    {
+      register int a asm("eax");
+      a = 1;
+      asm("add %1, %0" : "+r"(o) : "r"(a));
+      asm("xor %%eax, %%eax" ::: "eax");
+    }
+  return o;
+}
+
+int main()
+{
+  if (f() != 3)
+    __builtin_abort();
+  return 0;
+}
diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index 291c3a4fa6b5..b1ac35e12fd9 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -2454,7 +2454,9 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
 
       /* Perform simple redundant store elimination.  */
       if (gimple_assign_single_p (stmt)
-	  && TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
+	  && TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME
+	  && (TREE_CODE (gimple_assign_lhs (stmt)) != VAR_DECL
+	      || !DECL_HARD_REGISTER (gimple_assign_lhs (stmt))))
 	{
 	  tree lhs = gimple_assign_lhs (stmt);
 	  tree rhs = gimple_assign_rhs1 (stmt);
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 146840664e2e..5a8c7c3aa10b 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -7081,6 +7081,8 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, gimple_stmt_iterator *gsi)
   if (gimple_assign_single_p (stmt)
       && !gimple_has_volatile_ops (stmt)
       && !is_gimple_reg (gimple_assign_lhs (stmt))
+      && (TREE_CODE (gimple_assign_lhs (stmt)) != VAR_DECL
+	  || !DECL_HARD_REGISTER (gimple_assign_lhs (stmt)))
       && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
 	  || is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
     {
-- 
GitLab