The following patch solves

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

The patch was successfully bootstrapped and tested on x86_64, aarch64, ppc64le.

commit decc6c0d4d909ce510b6533c48d70d0b353f909a
Author: Vladimir N. Makarov <vmaka...@redhat.com>
Date:   Fri Jan 31 09:39:45 2025 -0500

    [PR116234][LRA]: Check debug insn when looking at one insn pseudo occurrence
    
      LRA can change reg class to NO_REGS when pseudo referred in one
    insn.  Checking the references did not take into account that referring
    insn can be a debug insn.  This resulted in different code generation
    with and without debug info generation.  The patch fixes this pitfall.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/116234
            * lra-constraints.cc (multiple_insn_refs_p): New function.
            (curr_insn_transform): Use it.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/116234
            * gfortran.target/aarch64/aarch64.exp: New.
            * gfortran.target/aarch64/pr116234.f: New.

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index ee3fd7a503a..0659aed94c7 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -4144,6 +4144,24 @@ static bool invalid_mode_reg_p (enum machine_mode mode, rtx x)
 	      ira_prohibited_class_mode_regs[rclass][mode]));
 }
 
+/* Return TRUE if regno is referenced in more than one non-debug insn.  */
+static bool
+multiple_insn_refs_p (int regno)
+{
+  unsigned int uid;
+  bitmap_iterator bi;
+  int nrefs = 0;
+  EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi)
+    {
+      if (!NONDEBUG_INSN_P (lra_insn_recog_data[uid]->insn))
+	continue;
+      if (nrefs == 1)
+	return true;
+      nrefs++;
+    }
+  return false;
+}
+
 /* Main entry point of the constraint code: search the body of the
    current insn to choose the best alternative.  It is mimicking insn
    alternative cost calculation model of former reload pass.  That is
@@ -4602,7 +4620,7 @@ curr_insn_transform (bool check_only_p)
 		 registers for other pseudos referenced in the insn.  The most
 		 common case of this is a scratch register which will be
 		 transformed to scratch back at the end of LRA.  */
-	      && bitmap_single_bit_set_p (&lra_reg_info[regno].insn_bitmap))
+	      && !multiple_insn_refs_p (regno))
 	    {
 	      if (lra_get_allocno_class (regno) != NO_REGS)
 		lra_change_class (regno, NO_REGS, "      Change to", true);
diff --git a/gcc/testsuite/gfortran.target/aarch64/aarch64.exp b/gcc/testsuite/gfortran.target/aarch64/aarch64.exp
new file mode 100644
index 00000000000..79afc699318
--- /dev/null
+++ b/gcc/testsuite/gfortran.target/aarch64/aarch64.exp
@@ -0,0 +1,45 @@
+#   Copyright (C) 2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a aarch64 target.
+if { ![istarget aarch64*-*-*] } then {
+  return
+}
+
+# Make sure there is a fortran compiler to test.
+if { ![check_no_compiler_messages fortran_available assembly {
+! Fortran
+program P
+  stop
+end program P
+} ""] } {
+    return
+}
+
+# Load support procs.
+load_lib gfortran-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+gfortran-dg-runtest [lsort \
+   [glob -nocomplain $srcdir/$subdir/*.\[fF\]{,90,95,03,08} ] ] "" ""
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gfortran.target/aarch64/pr116234.f b/gcc/testsuite/gfortran.target/aarch64/pr116234.f
new file mode 100644
index 00000000000..78b49bc86f1
--- /dev/null
+++ b/gcc/testsuite/gfortran.target/aarch64/pr116234.f
@@ -0,0 +1,80 @@
+! { dg-do compile }
+! { dg-options "-fcompare-debug -mcpu=phecda -O2 -funroll-all-loops -c -fno-rename-registers -fno-ivopts" }
+
+      SUBROUTINE FOO(UPLO, N, A, IA, JA, DESCA, SR, SC, SCOND, AMAX,
+     $     EQUED)
+
+      CHARACTER          EQUED, UPLO
+      INTEGER            IA, JA
+      DOUBLE PRECISION   AMAX, SCOND
+
+      INTEGER            DESCA(*)
+      DOUBLE PRECISION   A(*), SR(*)
+
+      INTEGER            IACOL, IAROW, IC, IIA, IOFFA, J, JB, JJ, KK,
+     $     LL, MYCOL, MYROW
+      DOUBLE PRECISION   CJ, SMALL
+      DOUBLE PRECISION   SC(*)
+
+      EXTERNAL           INFOG2L
+
+      LOGICAL            BAR
+      DOUBLE PRECISION   PDLAMCH
+      EXTERNAL           BAR, PDLAMCH
+
+      INTRINSIC          MOD
+
+      CALL INFOG2L(IA, JA, DESCA, MYROW, MYCOL, IIA, IAROW, IACOL)
+
+      CJ = 1
+      SMALL = PDLAMCH(IC, 'Safe minimum') / PDLAMCH(IC, 'Precision')
+
+      IF (SCOND .LT. 0.1D+0 .OR. AMAX .LT. SMALL) THEN
+         JJ = LL
+         JB = LL + 1
+
+         IF (BAR(UPLO, '0')) THEN
+            IF (MYCOL .EQ. IACOL) THEN
+               DO 10 LL = 1, JB
+                  IOFFA = IOFFA + LL
+ 10            CONTINUE
+            END IF
+
+            DO 60 J = 1, JA + 1
+               IF (MYCOL .EQ. IACOL) THEN
+                  IF (MYROW .EQ. IAROW) THEN
+                     DO 30 LL = JJ, JJ + JB - 1
+                        CJ = SC(LL)
+                        DO 20 KK = IIA, MYROW + LL - JJ + 1
+                           A(IOFFA + KK) = A(IOFFA + KK) * CJ * SR(KK)
+ 20                     CONTINUE
+ 30                  CONTINUE
+                  ELSE
+                     DO 50 LL = JJ, JJ + JB
+                        DO 40 KK = IIA, J
+                           A(IOFFA + KK) = A(IOFFA + KK) * CJ * SR(KK)
+ 40                     CONTINUE
+                        IOFFA = IOFFA + KK
+ 50                  CONTINUE
+                  END IF
+               END IF
+
+               IACOL = MOD(IACOL + 1, JA)
+ 60         CONTINUE
+         ELSE
+            IF (MYROW .NE. IAROW) THEN
+               DO 70 LL = 1, JB
+                  A(IOFFA + KK) = A(IOFFA + KK) * CJ
+ 70            CONTINUE
+            END IF
+
+            DO 90 J = 1, JA
+               DO 80 LL = 1, JJ
+                  A(IOFFA + KK) = A(IOFFA + KK) * CJ
+ 80            CONTINUE
+ 90         CONTINUE
+         END IF
+      END IF
+
+      RETURN
+      END

Reply via email to