[pushed,PR111917,RA] : Fixing LRA cycling for multi-reg variable containing a fixed reg

Message ID 27a79c6e-d19f-b6d5-e4ad-b139860cd255@redhat.com
State Accepted
Headers
Series [pushed,PR111917,RA] : Fixing LRA cycling for multi-reg variable containing a fixed reg |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Vladimir Makarov Oct. 31, 2023, 3:47 p.m. UTC
  The following patch fixes

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111971

Successfully bootstrapped and tested on x86-64, aarch64, pp64le.
  

Patch

commit df111406b4ea1fe2890e94d51655e571cf260d29
Author: Vladimir N. Makarov <vmakarov@redhat.com>
Date:   Tue Oct 31 10:54:43 2023 -0400

    [RA]: Fixing LRA cycling for multi-reg variable containing a fixed reg
    
    PR111971 test case uses a multi-reg variable containing a fixed reg.  LRA
    rejects such multi-reg because of this when matching the constraint for
    an asm insn.  The rejection results in LRA cycling.  The patch fixes this issue.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/111971
            * lra-constraints.cc: (process_alt_operands): Don't check start
            hard regs for regs originated from register variables.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/111971
            * gcc.target/powerpc/pr111971.c: New test.

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index d10a2a3dc51..0607c8be7cb 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -2609,12 +2609,15 @@  process_alt_operands (int only_alternative)
 		  winreg = true;
 		  if (REG_P (op))
 		    {
+		      tree decl;
 		      if (hard_regno[nop] >= 0
 			  && in_hard_reg_set_p (this_alternative_set,
 						mode, hard_regno[nop])
-			  && !TEST_HARD_REG_BIT
-			      (this_alternative_exclude_start_hard_regs,
-			       hard_regno[nop]))
+			  && ((REG_ATTRS (op) && (decl = REG_EXPR (op)) != NULL
+			       && VAR_P (decl) && DECL_HARD_REGISTER (decl))
+			      || !(TEST_HARD_REG_BIT
+				   (this_alternative_exclude_start_hard_regs,
+				    hard_regno[nop]))))
 			win = true;
 		      else if (hard_regno[nop] < 0
 			       && in_class_p (op, this_alternative, NULL))
diff --git a/gcc/testsuite/gcc.target/powerpc/pr111971.c b/gcc/testsuite/gcc.target/powerpc/pr111971.c
new file mode 100644
index 00000000000..7f058bd4820
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr111971.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+void
+foo (unsigned long long *a)
+{
+  register long long d asm ("r0") = 0x24;
+  long long n;
+  asm ("mr %0, %1" : "=r"(n) : "r"(d));
+  *a++ = n;
+}