aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorVladimir N. Makarov <vmakarov@redhat.com>2025-01-31 09:39:45 -0500
committerVladimir N. Makarov <vmakarov@redhat.com>2025-01-31 09:40:06 -0500
commitdecc6c0d4d909ce510b6533c48d70d0b353f909a (patch)
tree92def665bbc27785545120a06ca5776451b826f3 /gcc
parent3b49727014f29d46a605ffff228d137e5e582df3 (diff)
downloadgcc-decc6c0d4d909ce510b6533c48d70d0b353f909a.zip
gcc-decc6c0d4d909ce510b6533c48d70d0b353f909a.tar.gz
gcc-decc6c0d4d909ce510b6533c48d70d0b353f909a.tar.bz2
[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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/lra-constraints.cc20
-rw-r--r--gcc/testsuite/gfortran.target/aarch64/aarch64.exp45
-rw-r--r--gcc/testsuite/gfortran.target/aarch64/pr116234.f80
3 files changed, 144 insertions, 1 deletions
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index ee3fd7a..0659aed 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 0000000..79afc69
--- /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 0000000..78b49bc
--- /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