[gcc r17-3307] i386: Canonicalize PAVG builtins to IFN_AVG_CEIL [PR122715]
"H.J. Lu via Gcc-cvs" <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:a767a6a5609e0d0850291e2a035a8c71e9b14074 commit r17-3307-ga767a6a5609e0d0850291e2a035a8c71e9b14074 Author: Odysseas Georgoudis <[email protected]> Date: Wed Jul 22 21:47:56 2026 +0100 i386: Canonicalize PAVG builtins to IFN_AVG_CEIL [PR122715] PAVG builtins use signed vector types even though the instruction computes an unsigned average rounded up. View-convert the operands to unsigned vector types and canonicalize unmasked and all-ones masked calls to IFN_AVG_CEIL. This exposes the calls to generic simplifications while preserving masks with inactive lanes. For modes without an IFN_AVG_CEIL optab, canonicalize only when equal operands allow the internal function to simplify immediately. PR middle-end/122715 gcc/ChangeLog: * config/i386/i386.cc: Include "internal-fn.h". (ix86_gimple_fold_builtin): Canonicalize PAVG builtins to IFN_AVG_CEIL. gcc/testsuite/ChangeLog: * gcc.target/i386/pr122715.c: New test. * gcc.target/i386/pr122715-2.c: New test. Diff: --- gcc/config/i386/i386.cc | 53 +++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr122715-2.c | 24 ++++++++++ gcc/testsuite/gcc.target/i386/pr122715.c | 76 ++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 0b19f0ff43c7..dcfe4531f117 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see #include "target-globals.h" #include "gimple-iterator.h" #include "gimple-fold.h" +#include "internal-fn.h" #include "tree-vectorizer.h" #include "shrink-wrap.h" #include "builtins.h" @@ -19832,6 +19833,58 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi) } break; + case IX86_BUILTIN_PAVGUSB: + case IX86_BUILTIN_PAVGB: + case IX86_BUILTIN_PAVGW: + case IX86_BUILTIN_PAVGB128: + case IX86_BUILTIN_PAVGW128: + case IX86_BUILTIN_PAVGB256: + case IX86_BUILTIN_PAVGW256: + case IX86_BUILTIN_PAVGB128_MASK: + case IX86_BUILTIN_PAVGW128_MASK: + case IX86_BUILTIN_PAVGB256_MASK: + case IX86_BUILTIN_PAVGW256_MASK: + case IX86_BUILTIN_PAVGB512: + case IX86_BUILTIN_PAVGW512: + gcc_assert (n_args == 2 || n_args == 4); + if (!gimple_call_lhs (stmt)) + break; + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + /* For masked PAVG, only canonicalize if the mask is all ones. */ + if (n_args == 4) + { + elems = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); + if (!ix86_masked_all_ones (elems, gimple_call_arg (stmt, 3))) + break; + } + { + /* PAVG computes an unsigned average rounded towards positive + infinity. The IFN selects signedness from its operand type. */ + tree utype = unsigned_type_for (TREE_TYPE (arg0)); + bool equal_p = operand_equal_p (arg0, arg1, 0); + if (!equal_p + && !direct_internal_fn_supported_p (IFN_AVG_CEIL, utype, + OPTIMIZE_FOR_BOTH)) + break; + + loc = gimple_location (stmt); + tree uarg0 = gimple_build (&stmts, loc, VIEW_CONVERT_EXPR, + utype, arg0); + tree uarg1 = equal_p + ? uarg0 + : gimple_build (&stmts, loc, VIEW_CONVERT_EXPR, utype, arg1); + tree res = gimple_build (&stmts, loc, IFN_AVG_CEIL, utype, + uarg0, uarg1); + res = gimple_build (&stmts, loc, VIEW_CONVERT_EXPR, + TREE_TYPE (gimple_call_lhs (stmt)), res); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + g = gimple_build_assign (gimple_call_lhs (stmt), res); + gimple_set_location (g, loc); + gsi_replace (gsi, g, false); + return true; + } + case IX86_BUILTIN_PBLENDVB256: case IX86_BUILTIN_BLENDVPS256: case IX86_BUILTIN_BLENDVPD256: diff --git a/gcc/testsuite/gcc.target/i386/pr122715-2.c b/gcc/testsuite/gcc.target/i386/pr122715-2.c new file mode 100644 index 000000000000..d115de287f86 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr122715-2.c @@ -0,0 +1,24 @@ +/* PR middle-end/122715 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx512bw -mavx512vl -fdump-tree-optimized" } */ + +#include <immintrin.h> + +__m128i avg_u8_128(__m128i x, __m128i y) +{ + return _mm_avg_epu8 (x, y); +} + +__m128i avg_u8_128_mask_all(__m128i x, __m128i y) +{ + return _mm_mask_avg_epu8 (_mm_setzero_si128 (), (__mmask16) -1, x, y); +} + +__m128i avg_u8_128_mask(__m128i w, __mmask16 mask, __m128i x) +{ + return _mm_mask_avg_epu8 (w, mask, x, x); +} + +/* { dg-final { scan-tree-dump-times {\.AVG_CEIL} 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times {__builtin_ia32_pavgb} 1 "optimized" } } */ +/* { dg-final { scan-assembler-times {vpavgb} 3 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr122715.c b/gcc/testsuite/gcc.target/i386/pr122715.c new file mode 100644 index 000000000000..cdbb1a671040 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr122715.c @@ -0,0 +1,76 @@ +/* PR middle-end/122715 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -m3dnow -mavx2 -mavx512bw -mavx512vl" } */ +/* { dg-additional-options "-fdump-tree-optimized" } */ + +#include <immintrin.h> + +__m64 avg_u8_3dnow(__m64 x) +{ + return (__m64) __builtin_ia32_pavgusb ((__v8qi) x, (__v8qi) x); +} + +__m64 avg_u8_64(__m64 x) +{ + return _mm_avg_pu8 (x, x); +} + +__m64 avg_u16_64(__m64 x) +{ + return _mm_avg_pu16 (x, x); +} + +__m128i avg_u8_128(__m128i x) +{ + return _mm_avg_epu8 (x, x); +} + +__m128i avg_u16_128(__m128i x) +{ + return _mm_avg_epu16 (x, x); +} + +__m256i avg_u8_256(__m256i x) +{ + return _mm256_avg_epu8 (x, x); +} + +__m256i avg_u16_256(__m256i x) +{ + return _mm256_avg_epu16 (x, x); +} + +__m128i avg_u8_128_mask(__m128i x) +{ + return _mm_mask_avg_epu8 (_mm_setzero_si128 (), (__mmask16) -1, x, x); +} + +__m128i avg_u16_128_mask(__m128i x) +{ + return _mm_mask_avg_epu16 (_mm_setzero_si128 (), (__mmask8) -1, x, x); +} + +__m256i avg_u8_256_mask(__m256i x) +{ + return _mm256_mask_avg_epu8 (_mm256_setzero_si256 (), + (__mmask32) -1, x, x); +} + +__m256i avg_u16_256_mask(__m256i x) +{ + return _mm256_mask_avg_epu16 (_mm256_setzero_si256 (), + (__mmask16) -1, x, x); +} + +__m512i avg_u8_512(__m512i x) +{ + return _mm512_avg_epu8 (x, x); +} + +__m512i avg_u16_512(__m512i x) +{ + return _mm512_avg_epu16 (x, x); +} + +/* { dg-final { scan-tree-dump-not {__builtin_ia32_pavg} "optimized" } } */ +/* { dg-final { scan-assembler-not {pavg} } } */