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