From: H.J. Lu Date: Thu, 23 Apr 2026 22:39:44 +0000 (+0800) Subject: x86_cse: Use integer load for CONST_VECTOR load X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d16bee7da570f8fc1edf004e9289708fe403c584;p=thirdparty%2Fgcc.git x86_cse: Use integer load for CONST_VECTOR load 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 --- diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index 7fa2c1edbe9..63f9dcc9f93 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -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 index 00000000000..4b99e909f6c --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr125009.C @@ -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 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 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 index 00000000000..8a9935a4491 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr125009.c @@ -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; +}