]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
x86_cse: Use integer load for CONST_VECTOR load
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 23 Apr 2026 22:39:44 +0000 (06:39 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 24 Apr 2026 09:31:06 +0000 (17:31 +0800)
CONST_VECTOR load no larger than integer register

(set (reg:V2QI 294)
     (const_vector:V2QI [(const_int 0 [0]) repeated x2]))

can use integer load.  Use inner mode as the scalar mode for CONST_VECTOR
load source.

gcc/

PR target/125009
* config/i386/i386-features.cc (ix86_place_single_vector_set):
Support CONST_VECTOR load no larger than integer register.
(ix86_broadcast_inner): Use inner mode as the scalar mode for
CONST_VECTOR load source.
(pass_x86_cse::x86_cse): Generate CONST_VECTOR broadcast source
for CONST_VECTOR load no larger than integer register.

gcc/testsuite/

PR target/125009
* g++.target/i386/pr125009.C: New test.
* gcc.target/i386/pr125009.c: Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
gcc/config/i386/i386-features.cc
gcc/testsuite/g++.target/i386/pr125009.C [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr125009.c [new file with mode: 0644]

index 7fa2c1edbe92c4731fe8712b5b74d332fab41188..63f9dcc9f93f3e1a77a41910e5f81329630c9809 100644 (file)
@@ -3321,7 +3321,16 @@ ix86_place_single_vector_set (rtx dest, rtx src, bitmap bbs,
        }
     }
 
-  if (load && load->kind == X86_CSE_VEC_DUP)
+  /* CONST_VECTOR load no larger than integer register
+
+     (set (reg:V2QI 294)
+         (const_vector:V2QI [(const_int 0 [0]) repeated x2]))
+
+     can use integer load.  */
+  if (load
+      && load->kind == X86_CSE_VEC_DUP
+      && (!CONST_VECTOR_P (src)
+         || GET_MODE_SIZE (GET_MODE (dest)) > UNITS_PER_WORD))
     {
       /* Get the source from LOAD as (reg:SI 99) in
 
@@ -3758,7 +3767,10 @@ ix86_broadcast_inner (rtx op, machine_mode mode,
          if (!rtx_equal_p (tmp, first))
            return nullptr;
        }
-      *scalar_mode_p = GET_MODE (first);
+      /* Use the inner mode to handle
+          (const_vector:V2QI [(const_int 0 [0]) repeated x2])
+       */
+      *scalar_mode_p = GET_MODE_INNER (mode);
       *insn_p = nullptr;
       return first;
     }
@@ -4731,8 +4743,23 @@ pass_x86_cse::x86_cse (void)
                  broadcast_source = CONSTM1_RTX (mode);
                  break;
                case X86_CSE_VEC_DUP:
-                 reg = gen_reg_rtx (load->mode);
-                 broadcast_source = gen_rtx_VEC_DUPLICATE (mode, reg);
+                 if (CONST_INT_P (load->val)
+                     && GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
+                   {
+                     /* CONST_VECTOR load no larger than integer
+                        register size can use integer load.  */
+                     int nunits = GET_MODE_NUNITS (mode);
+                     rtvec v = rtvec_alloc (nunits);
+                     for (int j = 0; j < nunits ; j++)
+                       RTVEC_ELT (v, j) = load->val;
+                     broadcast_source = gen_rtx_CONST_VECTOR (mode, v);
+                   }
+                 else
+                   {
+                     reg = gen_reg_rtx (load->mode);
+                     broadcast_source = gen_rtx_VEC_DUPLICATE (mode,
+                                                               reg);
+                   }
                  break;
                default:
                  gcc_unreachable ();
diff --git a/gcc/testsuite/g++.target/i386/pr125009.C b/gcc/testsuite/g++.target/i386/pr125009.C
new file mode 100644 (file)
index 0000000..4b99e90
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-mtune=generic -O2 -std=c++11" } */
+/* { dg-additional-options "-march=pentiumpro" { target ia32 } } */
+
+void *operator new(__SIZE_TYPE__, void *);
+template <typename Value> struct hash_map {
+  void put(Value v) {
+    int e;
+    new (&e) Value(v);
+  }
+};
+struct tree_string {
+  char str[];
+} string;
+long long minsize;
+struct attr_access {
+  bool internal_p;
+  bool static_p;
+} __trans_tmp_1;
+hash_map<attr_access> init_attr_rdwr_indices_rwm;
+void init_attr_rdwr_indices() {
+  for (;;) {
+    attr_access acc{};
+    if (*string.str) {
+      acc.internal_p = true;
+      acc.static_p = minsize;
+    }
+    __trans_tmp_1 = acc;
+    init_attr_rdwr_indices_rwm.put(acc);
+  }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr125009.c b/gcc/testsuite/gcc.target/i386/pr125009.c
new file mode 100644 (file)
index 0000000..8a9935a
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-mtune=generic -O2 -fPIC" } */
+/* { dg-additional-options "-march=pentiumpro" { target ia32 } } */
+
+struct target_var_desc {
+  bool always_copy_from;
+  bool is_attach;
+};
+struct target_mem_desc {
+  struct target_var_desc list[];
+};
+void
+gomp_map_vars_internal (int n, int l)
+{
+  struct target_mem_desc *tgt;
+  int j;
+  for (j = 0; j < l; j++)
+    tgt->list[j].always_copy_from = tgt->list[j].is_attach = false;
+  for (;j < n; j++)
+    tgt->list[j].always_copy_from = tgt->list[j].is_attach = false;
+}