1. Since

(set (reg:TI 111 [ _11 ])
    (xor:TI (reg:TI 112 [ a ])
        (mem/c:TI (symbol_ref:DI ("b") [flags 0x40] <var_decl
0x7fffe97d6ed8 b>) [1 b+0 S16 A128])))

reduces a memory access, comparing against

(set (reg:TI 110 [ _10 ])
    (xor:TI (reg:TI 114 [ _13 ])
        (reg:TI 107 [ x ])))

it should have an additional gain of COSTS_N_INSNS (1).

2. Don't subtract ix86_cost->sse_to_integer for store since

(set (mem/c:TI (symbol_ref:DI ("m0") [flags 0x2] <var_decl
0x7fffe94e4e40 m0>) [1 m0+0 S16 A128])
    (zero_extend:TI (reg/v:DI 99 [ x ])))

it is a store, not an SSE to integer register move.

gcc/

PR target/127020
* config/i386/i386-features.cc
(timode_scalar_chain::compute_convert_gain): Update memory
operand check.

gcc/testsuite/

PR target/127020
* gcc.target/i386/sse4_1-stv-15.c: New test.
* gcc.target/i386/sse4_1-stv-16.c: Likewise.

-- 
H.J.
From b24f5ab5b1773943a7a4284ba74eedceb648944c Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Tue, 25 Aug 2026 04:13:54 +0800
Subject: [PATCH] x86-64: Update memory operand check in TImode STV

1. Since

(set (reg:TI 111 [ _11 ])
    (xor:TI (reg:TI 112 [ a ])
        (mem/c:TI (symbol_ref:DI ("b") [flags 0x40] <var_decl 0x7fffe97d6ed8 b>) [1 b+0 S16 A128])))

reduces a memory access, comparing against

(set (reg:TI 110 [ _10 ])
    (xor:TI (reg:TI 114 [ _13 ])
        (reg:TI 107 [ x ])))

it should have an additional gain of COSTS_N_INSNS (1).

2. Don't subtract ix86_cost->sse_to_integer for store since

(set (mem/c:TI (symbol_ref:DI ("m0") [flags 0x2] <var_decl 0x7fffe94e4e40 m0>) [1 m0+0 S16 A128])
    (zero_extend:TI (reg/v:DI 99 [ x ])))

it is a store, not an SSE to integer register move.

gcc/

	PR target/127020
	* config/i386/i386-features.cc
	(timode_scalar_chain::compute_convert_gain): Update memory
	operand check.

gcc/testsuite/

	PR target/127020
	* gcc.target/i386/sse4_1-stv-15.c: New test.
	* gcc.target/i386/sse4_1-stv-16.c: Likewise.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/config/i386/i386-features.cc              | 18 ++++++++++++++----
 gcc/testsuite/gcc.target/i386/sse4_1-stv-15.c | 15 +++++++++++++++
 gcc/testsuite/gcc.target/i386/sse4_1-stv-16.c | 14 ++++++++++++++
 3 files changed, 43 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/sse4_1-stv-15.c
 create mode 100644 gcc/testsuite/gcc.target/i386/sse4_1-stv-16.c

diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index eb5f82e42cb..09558c4504d 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -1745,7 +1745,11 @@ timode_scalar_chain::compute_convert_gain ()
 	      break;
 	    }
 	  if (!MEM_P (dst))
-	    igain = COSTS_N_INSNS (1);
+	    {
+	      igain = COSTS_N_INSNS (1);
+	      if (MEM_P (XEXP (src, 1)))
+		igain += COSTS_N_INSNS (1);
+	    }
 	  if (CONST_SCALAR_INT_P (XEXP (src, 1)))
 	    igain += timode_immed_const_gain (XEXP (src, 1), bb);
 	  break;
@@ -1917,9 +1921,15 @@ timode_scalar_chain::compute_convert_gain ()
 
 	case ZERO_EXTEND:
 	  if (GET_MODE (XEXP (src, 0)) == DImode)
-	    /* xor (2 bytes) vs. vmovq (5 bytes).  */
-	    igain = speed_p ? COSTS_N_INSNS (1) - ix86_cost->sse_to_integer
-			    : -COSTS_N_BYTES (3);
+	    {
+	      if (MEM_P (dst))
+		/* 2 x movq vs movdqa.  */
+		igain = speed_p ? COSTS_N_INSNS (1) : -COSTS_N_BYTES (3);
+	      else
+		/* xor (2 bytes) vs. vmovq (5 bytes).  */
+		igain = speed_p ? COSTS_N_INSNS (1) - ix86_cost->sse_to_integer
+				: -COSTS_N_BYTES (3);
+	    }
 	  break;
 
 	default:
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-stv-15.c b/gcc/testsuite/gcc.target/i386/sse4_1-stv-15.c
new file mode 100644
index 00000000000..1f51887780e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-stv-15.c
@@ -0,0 +1,15 @@
+/* PR target/127020.  */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -march=x86-64" } */
+
+extern __int128 a, b, c, z;
+
+__int128
+func (__int128 x)
+{
+  return (x ^ a ^ b ^ c ^ z);
+}
+
+/* { dg-final { scan-assembler-times "pxor" 4 } } */
+/* { dg-final { scan-assembler-times "punpcklqdq" 1 } } */
+/* { dg-final { scan-assembler-times "movhlps" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-stv-16.c b/gcc/testsuite/gcc.target/i386/sse4_1-stv-16.c
new file mode 100644
index 00000000000..a8d864960c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-stv-16.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -march=cascadelake -mstv -mno-stackrealign" } */
+
+extern __int128 m0,m1,m2,m3;
+void foo(unsigned long x)
+{
+    __int128 m = x;
+    m0 = m;
+    m1 = m;
+    m2 = m;
+    m3 = m;
+}
+
+/* { dg-final { scan-assembler-times "vmovdqa" 4 } } */
-- 
2.55.0

Reply via email to