The following patch solves

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

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

commit d9835825b3d71bbbb93b3d6669174f4386be2cb1
Author: Vladimir N. Makarov <vmaka...@redhat.com>
Date:   Thu Jan 16 12:17:31 2025 -0500

    [PR118067][LRA]: Use the right mode to evaluate secondary memory reload
    
      In the PR case, LRA made insn alternative costly.  It happened
    because LRA incorrectly found that the alternative needs 2nd memory
    reload as the wrong mode for targetm.secondary_memory_needed was used.
    This resulted in LRA cycling as an alternative with mask regs was
    chosen.  The patch fixes the PR and add more debug printing which
    could be useful in the future for debugging function
    process_alt_operands.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/1180167
            * lra-constraints.cc (process_alt_operands): Use operand mode not
            subreg reg mode.  Add and improve debugging prints for updating
            losers.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/118067
            * gcc.target/i386/pr118067.c: New.

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 8f32e98f1c4..3d5abcfaeb0 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -2465,6 +2465,11 @@ process_alt_operands (int only_alternative)
 			    && (operand_reg[m] == NULL_RTX
 				|| hard_regno[m] < 0))
 			  {
+			    if (lra_dump_file != NULL)
+			      fprintf
+				(lra_dump_file,
+				 "            %d Matched operand reload: "
+				 "losers++\n", m);
 			    losers++;
 			    reload_nregs
 			      += (ira_reg_class_max_nregs[curr_alt[m]]
@@ -2909,6 +2914,10 @@ process_alt_operands (int only_alternative)
 			   "            Strict low subreg reload -- refuse\n");
 		      goto fail;
 		    }
+		  if (lra_dump_file != NULL)
+		    fprintf
+		      (lra_dump_file,
+		       "            %d Operand reload: losers++\n", nop);
 		  losers++;
 		}
 	      if (operand_reg[nop] != NULL_RTX
@@ -2945,7 +2954,14 @@ process_alt_operands (int only_alternative)
 		{
 		  const_to_mem = 1;
 		  if (! no_regs_p)
-		    losers++;
+		    {
+		      if (lra_dump_file != NULL)
+			fprintf
+			  (lra_dump_file,
+			   "            %d Constant reload through memory: "
+			   "losers++\n", nop);
+		      losers++;
+		    }
 		}
 
 	      /* Alternative loses if it requires a type of reload not
@@ -3127,12 +3143,19 @@ process_alt_operands (int only_alternative)
 	      if (this_alternative != NO_REGS
 		  && REG_P (op) && (cl = get_reg_class (REGNO (op))) != NO_REGS
 		  && ((curr_static_id->operand[nop].type != OP_OUT
-		       && targetm.secondary_memory_needed (GET_MODE (op), cl,
+		       && targetm.secondary_memory_needed (mode, cl,
 							   this_alternative))
 		      || (curr_static_id->operand[nop].type != OP_IN
 			  && (targetm.secondary_memory_needed
-			      (GET_MODE (op), this_alternative, cl)))))
-		losers++;
+			      (mode, this_alternative, cl)))))
+		{
+		  if (lra_dump_file != NULL)
+		    fprintf
+		      (lra_dump_file,
+		       "            %d Secondary memory reload needed: "
+		       "losers++\n", nop);
+		  losers++;
+		}
 
 	      if (MEM_P (op) && offmemok)
 		addr_losers++;
@@ -3346,7 +3369,7 @@ process_alt_operands (int only_alternative)
 	      if (lra_dump_file != NULL)
 		fprintf
 		  (lra_dump_file,
-		   "            %d Conflict early clobber reload: reject--\n",
+		   "            %d Conflict early clobber reload: losers++\n",
 		   i);
 	    }
 	  else
@@ -3358,6 +3381,12 @@ process_alt_operands (int only_alternative)
 		  {
 		    curr_alt_match_win[j] = false;
 		    losers++;
+		    if (lra_dump_file != NULL)
+		      fprintf
+			(lra_dump_file,
+			 "            %d Matching conflict early clobber "
+			 "reloads: losers++\n",
+			 j);
 		    overall += LRA_LOSER_COST_FACTOR;
 		  }
 	      if (! curr_alt_match_win[i])
@@ -3375,7 +3404,7 @@ process_alt_operands (int only_alternative)
 		fprintf
 		  (lra_dump_file,
 		   "            %d Matched conflict early clobber reloads: "
-		   "reject--\n",
+		   "losers++\n",
 		   i);
 	    }
 	  /* Early clobber was already reflected in REJECT. */
diff --git a/gcc/testsuite/gcc.target/i386/pr118067.c b/gcc/testsuite/gcc.target/i386/pr118067.c
new file mode 100644
index 00000000000..7a7f072a5d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr118067.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O -fno-split-wide-types -mavx512f" } */
+
+typedef unsigned short U __attribute__((__vector_size__(64)));
+typedef int V __attribute__((__vector_size__(64)));
+typedef __int128 W __attribute__((__vector_size__(64)));
+
+W
+foo(U u, V v)
+{
+  W w;
+  /* __asm__ volatile ("" : "=v"(w)); prevents the -Wuninitialized warning */
+  u[0] >>= 1;
+  v %= (V)w;
+  return (W)u + (W)v;
+}

Reply via email to