[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} } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.