From 2b78bc348d9829620efa6a330d85f028e8ff59f6 Mon Sep 17 00:00:00 2001
From: Lulu Cheng <chenglulu@loongson.cn>
Date: Wed, 13 Aug 2025 11:04:35 +0800
Subject: [PATCH 1/3] LoongArch: Define hook
 TARGET_COMPUTE_PRESSURE_CLASSES[PR120476].

The rtx cost value defined by the target backend affects the
calculation of register pressure classes in the IRA, thus affecting
scheduling.  This may cause program performance degradation.
For example, OpenSSL 3.5.1 SHA512 and SPEC CPU 2017 exchange_r.

This problem can be avoided by defining a set of register pressure
classes in the target backend instead of using the default IRA to
automatically calculate them.

gcc/ChangeLog:

	PR target/120476
	* config/loongarch/loongarch.cc
	(loongarch_compute_pressure_classes): New function.
	(TARGET_COMPUTE_PRESSURE_CLASSES): Define.

(cherry picked from commit d94178d9b3fb1cb869b90d6f061990eae75c770e)
(cherry picked from commit c4e96a094636b3c15b5e3bfde8673ec3b8172993)
---
 gcc/config/loongarch/loongarch.cc | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index ac24c6d768f..734a3cccc58 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -11152,6 +11152,18 @@ loongarch_c_mode_for_suffix (char suffix)
   return VOIDmode;
 }
 
+/* Implement TARGET_COMPUTE_PRESSURE_CLASSES.  */
+
+static int
+loongarch_compute_pressure_classes (reg_class *classes)
+{
+  int i = 0;
+  classes[i++] = GENERAL_REGS;
+  classes[i++] = FP_REGS;
+  classes[i++] = FCC_REGS;
+  return i;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -11426,6 +11438,9 @@ loongarch_c_mode_for_suffix (char suffix)
 #undef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix
 
+#undef TARGET_COMPUTE_PRESSURE_CLASSES
+#define TARGET_COMPUTE_PRESSURE_CLASSES loongarch_compute_pressure_classes
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-loongarch.h"
-- 
2.52.0

From afe70567ca5295299da04fd12ae218f074af8fb5 Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@xry111.site>
Date: Fri, 22 Aug 2025 21:00:53 +0800
Subject: [PATCH 2/3] LoongArch: Fix ICE in highway-1.3.0 testsuite [PR121634]

I can't believe I made such a stupid pasto and the regression test
didn't detect anything wrong.

	PR target/121634

gcc/

	* config/loongarch/simd.md (simd_maddw_evod_<mode>_<su>): Use
	WVEC_HALF instead of WVEC for the mode of the sign_extend for
	the rhs of multiplication.

gcc/testsuite/

	* gcc.target/loongarch/pr121634.c: New test.

(cherry picked from commit 64932714a0786c6ba164cff3468f633cc67b23f5)
(cherry picked from commit 1276b391b4b068655b1d4511d51421302c1a7849)
---
 gcc/config/loongarch/simd.md                  |  2 +-
 gcc/testsuite/gcc.target/loongarch/pr121634.c | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/loongarch/pr121634.c

diff --git a/gcc/config/loongarch/simd.md b/gcc/config/loongarch/simd.md
index dd17cd13fc5..4156b269f9a 100644
--- a/gcc/config/loongarch/simd.md
+++ b/gcc/config/loongarch/simd.md
@@ -773,7 +773,7 @@ (define_insn "simd_maddw_evod_<mode>_<su>"
 	      (vec_select:<VEC_HALF>
 		(match_operand:IVEC 2 "register_operand" "f")
 		(match_operand:IVEC 4 "vect_par_cnst_even_or_odd_half")))
-	    (any_extend:<WVEC>
+	    (any_extend:<WVEC_HALF>
 	      (vec_select:<VEC_HALF>
 		(match_operand:IVEC 3 "register_operand" "f")
 		(match_dup 4))))
diff --git a/gcc/testsuite/gcc.target/loongarch/pr121634.c b/gcc/testsuite/gcc.target/loongarch/pr121634.c
new file mode 100644
index 00000000000..325173ad798
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/pr121634.c
@@ -0,0 +1,15 @@
+/* PR target/121634: ICE in highway-1.3.0 testsuite */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=la464 -mabi=lp64d" } */
+
+typedef short v8i16 __attribute__ ((vector_size (16)));
+typedef int v4i32 __attribute__ ((vector_size (16)));
+typedef long __m128i __attribute__ ((__vector_size__ (16)));
+__m128i x, y;
+
+__m128i
+WidenMulPairwiseAdd (__m128i a, __m128i b)
+{
+  y = (__m128i)__builtin_lsx_vmaddwod_w_h ((v4i32)x, (v8i16){}, (v8i16){});
+  return y;
+}
-- 
2.52.0

From 8f6ddcf1b11e815bf4aa680b15013a47fa69bdb2 Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@xry111.site>
Date: Tue, 8 Jul 2025 14:39:11 +0800
Subject: [PATCH 3/3] lra: Reallow reloading user hard registers if the insn is
 not asm [PR 120983]

The PR 87600 fix has disallowed reloading user hard registers to resolve
earlyclobber-induced conflict.

However before reload, recog completely ignores the constraints of
insns, so the RTL passes may produce insns where some user hard
registers violate an earlyclobber.  Then we'll get an ICE without
reloading them, like what we are recently encountering in LoongArch test
suite.

IIUC "recog does not look at constraints until reload" has been a
well-established rule in GCC for years and I don't have enough skill to
challange it.  So reallow reloading user hard registers (but still
disallow doing so for asm) to fix the ICE.

gcc/ChangeLog:

	PR rtl-optimization/120983
	* lra-constraints.cc (process_alt_operands): Allow reloading
	user hard registers unless the insn is an asm.

(cherry picked from commit e6d3c88e7bb07f94308074f9751e4384a191e022)
(cherry picked from commit 21a87ad785fe1e7c6504c3cf7984e74fe5a5067a)
---
 gcc/lra-constraints.cc | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 7dbc7fe1e00..535991dad06 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -2423,14 +2423,15 @@ process_alt_operands (int only_alternative)
 			if (curr_static_id->operand[nop].type == OP_INOUT
 			    || curr_static_id->operand[m].type == OP_INOUT)
 			  break;
-			/* Operands don't match.  If the operands are
-			   different user defined explicit hard
+			/* Operands don't match.  For asm if the operands
+			   are different user defined explicit hard
 			   registers, then we cannot make them match
 			   when one is early clobber operand.  */
 			if ((REG_P (*curr_id->operand_loc[nop])
 			     || SUBREG_P (*curr_id->operand_loc[nop]))
 			    && (REG_P (*curr_id->operand_loc[m])
-				|| SUBREG_P (*curr_id->operand_loc[m])))
+				|| SUBREG_P (*curr_id->operand_loc[m]))
+			    && INSN_CODE (curr_insn) < 0)
 			  {
 			    rtx nop_reg = *curr_id->operand_loc[nop];
 			    if (SUBREG_P (nop_reg))
@@ -3335,19 +3336,15 @@ process_alt_operands (int only_alternative)
 		  first_conflict_j = j;
 		last_conflict_j = j;
 		/* Both the earlyclobber operand and conflicting operand
-		   cannot both be user defined hard registers.  */
+		   cannot both be user defined hard registers for asm.
+		   Let curr_insn_transform diagnose it.  */
 		if (HARD_REGISTER_P (operand_reg[i])
 		    && REG_USERVAR_P (operand_reg[i])
 		    && operand_reg[j] != NULL_RTX
 		    && HARD_REGISTER_P (operand_reg[j])
-		    && REG_USERVAR_P (operand_reg[j]))
-		  {
-		    /* For asm, let curr_insn_transform diagnose it.  */
-		    if (INSN_CODE (curr_insn) < 0)
+		    && REG_USERVAR_P (operand_reg[j])
+		    && INSN_CODE (curr_insn) < 0)
 		      return false;
-		    fatal_insn ("unable to generate reloads for "
-				"impossible constraints:", curr_insn);
-		  }
 	      }
 	  if (last_conflict_j < 0)
 	    continue;
-- 
2.52.0

