[openwrt/openwrt] toolchain: gcc: backport patch to fix ICE with PowerPC targets

LEDE Commits lede-commits at lists.infradead.org
Wed May 14 02:23:37 PDT 2025


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/18de64d87bee66e58fa7c25ddcc4faf1bee4a354

commit 18de64d87bee66e58fa7c25ddcc4faf1bee4a354
Author: Matthias Schiffer <mschiffer at universe-factory.net>
AuthorDate: Tue May 13 21:58:56 2025 +0200

    toolchain: gcc: backport patch to fix ICE with PowerPC targets
    
    During the build of perl, the following ICE was reported in
    https://github.com/openwrt/packages/issues/24565 when targeting PowerPC:
    
        during RTL pass: reload
        blocksort.c: In function 'mainSort.isra':
        blocksort.c:1011:1: internal compiler error: in patch_jump_insn, at cfgrtl.cc:1303
         1011 | }
              | ^
        0x7d49cee29d8f __libc_start_call_main
                ../sysdeps/nptl/libc_start_call_main.h:58
        0x7d49cee29e3f __libc_start_main_impl
                ../csu/libc-start.c:392
        Please submit a full bug report, with preprocessed source (by using -freport-bug).
        Please include the complete backtrace with any bug report.
        See <http://bugs.openwrt.org/> for instructions.
    
    The same issue also caused the CI failures in
    https://github.com/openwrt/packages/pull/26501.
    
    The issue only occurs with GCC 14.2.0, but not with the head of the
    releases/gcc-14 maintenance branch; a bisect found that this patch fixes
    it.
    
    Signed-off-by: Matthias Schiffer <mschiffer at universe-factory.net>
    Link: https://github.com/openwrt/openwrt/pull/18797
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 ...-Reuse-scratch-registers-generated-by-LRA.patch | 107 +++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/toolchain/gcc/patches-14.x/021-Reuse-scratch-registers-generated-by-LRA.patch b/toolchain/gcc/patches-14.x/021-Reuse-scratch-registers-generated-by-LRA.patch
new file mode 100644
index 0000000000..87480716c7
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/021-Reuse-scratch-registers-generated-by-LRA.patch
@@ -0,0 +1,107 @@
+From 840e53f15468b1e808386c6190d7f59227b85495 Mon Sep 17 00:00:00 2001
+Message-ID: <840e53f15468b1e808386c6190d7f59227b85495.1747165068.git.mschiffer at universe-factory.net>
+From: Denis Chertykov <chertykov at gmail.com>
+Date: Thu, 17 Oct 2024 11:12:38 +0400
+Subject: [PATCH] Reuse scratch registers generated by LRA
+
+Test file: udivmoddi.c
+problem insn: 484
+
+Before LRA pass we have:
+(insn 484 483 485 72 (parallel [
+            (set (reg/v:SI 143 [ __q1 ])
+                (plus:SI (reg/v:SI 143 [ __q1 ])
+                    (const_int -2 [0xfffffffffffffffe])))
+            (clobber (scratch:QI))
+        ]) "udivmoddi.c":163:405 discrim 5 186 {addsi3}
+     (nil))
+
+LRA substitute all scratches with new pseudos, so we have:
+(insn 484 483 485 72 (parallel [
+            (set (reg/v:SI 143 [ __q1 ])
+                (plus:SI (reg/v:SI 143 [ __q1 ])
+                    (const_int -2 [0xfffffffffffffffe])))
+            (clobber (reg:QI 619))
+        ]) "/mnt/d/avr-lra/udivmoddi.c":163:405 discrim 5 186 {addsi3}
+     (expr_list:REG_UNUSED (reg:QI 619)
+        (nil)))
+
+Pseudo 619 is a special scratch register generated by LRA which is marked in `scratch_bitmap' and can be tested by call `ira_former_scratch_p(regno)'.
+
+In dump file (udivmoddi.c.317r.reload) we have:
+      Creating newreg=619
+Removing SCRATCH to p619 in insn #484 (nop 3)
+rescanning insn with uid = 484.
+
+After that LRA tries to spill (reg:QI 619)
+It's a bug because (reg:QI 619) is an output scratch register which is already something like spill register.
+
+Fragment from udivmoddi.c.317r.reload:
+      Choosing alt 2 in insn 484:  (0) r  (1) 0  (2) nYnn  (3) &d {addsi3}
+      Creating newreg=728 from oldreg=619, assigning class LD_REGS to r728
+
+IMHO: the bug is in lra-constraints.cc in function `get_reload_reg'
+fragment of `get_reload_reg':
+  if (type == OP_OUT)
+    {
+      /* Output reload registers tend to start out with a conservative
+	 choice of register class.  Usually this is ALL_REGS, although
+	 a target might narrow it (for performance reasons) through
+	 targetm.preferred_reload_class.  It's therefore quite common
+	 for a reload instruction to require a more restrictive class
+	 than the class that was originally assigned to the reload register.
+
+	 In these situations, it's more efficient to refine the choice
+	 of register class rather than create a second reload register.
+	 This also helps to avoid cycling for registers that are only
+	 used by reload instructions.  */
+      if (REG_P (original)
+	  && (int) REGNO (original) >= new_regno_start
+	  && INSN_UID (curr_insn) >= new_insn_uid_start
+__________________________________^^
+	  && in_class_p (original, rclass, &new_class, true))
+	{
+	  unsigned int regno = REGNO (original);
+	  if (lra_dump_file != NULL)
+	    {
+	      fprintf (lra_dump_file, "	 Reuse r%d for output ", regno);
+	      dump_value_slim (lra_dump_file, original, 1);
+	    }
+
+This condition incorrectly limits register reuse to ONLY newly generated instructions.
+i.e. LRA can reuse registers only from insns generated by himself.
+
+IMHO:It's wrong.
+Scratch registers generated by LRA also have to be reused.
+
+The patch is very simple.
+On x86_64, it bootstraps+regtests fine.
+
+gcc/
+	PR target/116550
+	PR target/119340
+	* lra-constraints.cc (get_reload_reg): Reuse scratch registers
+	generated by LRA.
+
+(cherry picked from commit e7393cbb5f2cae50b42713e71984064073aa378a)
+---
+ gcc/lra-constraints.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
+index 10e3d4e4097..d44c73e59c8 100644
+--- a/gcc/lra-constraints.cc
++++ b/gcc/lra-constraints.cc
+@@ -676,7 +676,8 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx original,
+ 	 used by reload instructions.  */
+       if (REG_P (original)
+ 	  && (int) REGNO (original) >= new_regno_start
+-	  && INSN_UID (curr_insn) >= new_insn_uid_start
++	  && (INSN_UID (curr_insn) >= new_insn_uid_start
++	      || ira_former_scratch_p (REGNO (original)))
+ 	  && in_class_p (original, rclass, &new_class, true))
+ 	{
+ 	  unsigned int regno = REGNO (original);
+-- 
+2.49.0
+




More information about the lede-commits mailing list