Hi Uros,
Hopefully Hongtao will approve my patch to support SUBREG conversions in STV https://gcc.gnu.org/pipermail/gcc-patches/2023-June/622706.html but for some of the examples described in the above post (and its test case), I've also come up with an alternate/complementary/supplementary fix of generating the PTEST during RTL expansion, rather than rely on this being caught/optimized later during STV. You may notice in this patch, the tests for TARGET_SSE4_1 and TImode appear last. When I was writing this, I initially also added support for AVX VPTEST and OImode, before realizing that x86 doesn't (yet) support 256-bit OImode (which also explains why we don't have an OImode to V1OImode scalar-to-vector pass). Retaining this clause ordering should minimize the lines changed if things change in future. 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? 2023-06-27 Roger Sayle <ro...@nextmovesoftware.com> gcc/ChangeLog * config/i386/i386-expand.cc (ix86_expand_int_compare): If testing a TImode SUBREG of a 128-bit vector register against zero, use a PTEST instruction instead of first moving it to to scalar registers. Please let me know what you think. Roger --
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index 4a3b07a..53bec08 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -631,7 +631,31 @@ general_scalar_chain::compute_convert_gain () break; case COMPARE: - /* Assume comparison cost is the same. */ + if (XEXP (src, 1) != const0_rtx) + { + /* cmp vs. pxor;pshufd;ptest. */ + igain += COSTS_N_INSNS (m - 3); + } + else if (GET_CODE (XEXP (src, 0)) != AND) + { + /* test vs. pshufd;ptest. */ + igain += COSTS_N_INSNS (m - 2); + } + else if (GET_CODE (XEXP (XEXP (src, 0), 0)) != NOT) + { + /* and;test vs. pshufd;ptest. */ + igain += COSTS_N_INSNS (2 * m - 2); + } + else if (TARGET_BMI) + { + /* andn;test vs. pandn;pshufd;ptest. */ + igain += COSTS_N_INSNS (2 * m - 3); + } + else + { + /* not;and;test vs. pandn;pshufd;ptest. */ + igain += COSTS_N_INSNS (3 * m - 3); + } break; case CONST_INT: