Hi Jeff,
I'd like to ping my "vec_merge simplification" patch from January,
https://gcc.gnu.org/pipermail/gcc-patches/2026-January/706337.html
that you're previously agreed to look at/review here:
https://gcc.gnu.org/pipermail/gcc-patches/2026-January/706398.html

Replacing two vec_merges with one should universally be a win, but
if any platform (I'm thinking riscv's vmerge/vgather) can demonstrate a
slow down, this indicates a latent missed optimization (during RTL
expansion), which I'm happy to investigate once there's sufficient
analysis/information in a Bugzilla PR.  Fingers-crossed that's not an
issue; the new test case shows a clear improvement on x86_64.


This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check, both with and without --target_board=unix{-m32}
with no new failures.  Ok for mainline?


2026-06-27  Roger Sayle  <[email protected]>

gcc/ChangeLog
        * simplify-rtx.cc (simplify_context::simplify_ternary_operation)
        <case VEC_MERGE>: Simplify a vec_merge of a vec_merge with a
        repeated operand.

gcc/testsuite/ChangeLog
        * gcc.target/i386/avx2-vpblendd128-3.c: New test case.


Thanks again.
Roger
--

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 872ae032869..23fa4702345 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -7802,6 +7802,21 @@ simplify_context::simplify_ternary_operation (rtx_code 
code, machine_mode mode,
                  if (!(sel & ~sel0 & mask) && !side_effects_p (XEXP (op0, 1)))
                    return simplify_gen_ternary (code, mode, mode,
                                                 XEXP (op0, 0), op1, op2);
+
+                 /* Replace (vec_merge (vec_merge a b m) a n) with
+                    (vec_merge a b (m|~n)).  */
+                 if (rtx_equal_p (XEXP (op0, 0), op1)
+                     && ! side_effects_p (op1))
+                   return simplify_gen_ternary (code, mode, mode,
+                                                op1, XEXP (op0, 1),
+                                                GEN_INT ((sel0 | ~sel) & 
mask));
+                 /* Replace (vec_merge (vec_merge b a m) a n) with
+                    (vec_merge b a (m&n)).  */
+                 if (rtx_equal_p (XEXP (op0, 1), op1)
+                     && ! side_effects_p (op1))
+                   return simplify_gen_ternary (code, mode, mode,
+                                                XEXP (op0, 0), op1,
+                                                GEN_INT (sel & sel0 & mask));
                }
            }
          if (GET_CODE (op1) == VEC_MERGE)
@@ -7816,6 +7831,22 @@ simplify_context::simplify_ternary_operation (rtx_code 
code, machine_mode mode,
                  if (!(~sel & ~sel1 & mask) && !side_effects_p (XEXP (op1, 1)))
                    return simplify_gen_ternary (code, mode, mode,
                                                 op0, XEXP (op1, 0), op2);
+
+                 /* Replace (vec_merge a (vec_merge a b m) n) with
+                    (vec_merge a b (m|n)).  */
+                 if (rtx_equal_p (XEXP (op1, 0), op0)
+                     && ! side_effects_p (op0))
+                   return simplify_gen_ternary (code, mode, mode,
+                                                op0, XEXP (op1, 1),
+                                                GEN_INT ((sel | sel1) & mask));
+
+                 /* Replace (vec_merge a (vec_merge b a m) n) with
+                    (vec_merge a b (~m|n)).  */
+                 if (rtx_equal_p (XEXP (op1, 1), op0)
+                     && ! side_effects_p (op0))
+                   return simplify_gen_ternary (code, mode, mode,
+                                                op0, XEXP (op1, 0),
+                                                GEN_INT ((sel | ~sel1) & 
mask));
                }
            }
 
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpblendd128-3.c 
b/gcc/testsuite/gcc.target/i386/avx2-vpblendd128-3.c
new file mode 100644
index 00000000000..a4bd90b48d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpblendd128-3.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-mavx2 -O2" } */
+
+typedef unsigned int v4si __attribute__((vector_size(16)));
+
+v4si foo(v4si vec, int val) {
+    vec[0] = val;
+    vec[2] = val;
+    return vec;
+}
+
+v4si bar(v4si vec, int val) {
+    vec[0] = val;
+    vec[1] = val;
+    vec[2] = val;
+    vec[3] = val;
+    return vec;
+}
+
+/* { dg-final { scan-assembler-times "vpbroadcastd" 2 } } */
+/* { dg-final { scan-assembler-times "vpblendd\[ \\t\]+" 1 } } */
+/* { dg-final { scan-assembler-not "vpinsrd" } } */

Reply via email to