[PATCH] aarch64: Canonicalize halving-add builtins [PR122715]
Odysseas Georgoudis <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <FRWP195MB28641B44FA34564DF4B25BD1CCD92@FRWP195MB2864.EURP195.PROD.OUTLOOK.COM> |
The first two patches for PR122715 have been committed. This patch handles the remaining AArch64 case. Advanced SIMD halving-add intrinsics remain target builtins in GIMPLE, preventing generic average simplifications from seeing them. Canonicalize SHADD and UHADD to IFN_AVG_FLOOR, and SRHADD and URHADD to IFN_AVG_CEIL. This allows equal operands to be folded by the existing match.pd rule while retaining optab-based instruction selection for other operands. Tested with an aarch64-linux-gnu cross compiler. The targeted tests pass. Thanks, Odysseas
PR122715-aarch64.patch
(application/octet-stream, 6 KB)
From de17c2eac59fb4642f6eacac3884d8018d5dc131 Mon Sep 17 00:00:00 2001 From: Odysseas Georgoudis <[email protected]> Date: Sat, 15 Aug 2026 01:20:17 +0100 Subject: [PATCH] aarch64: Canonicalize halving-add builtins [PR122715] Advanced SIMD halving-add intrinsics remain target builtins in GIMPLE, preventing generic average simplifications from seeing them. Canonicalize SHADD and UHADD to IFN_AVG_FLOOR, and SRHADD and URHADD to IFN_AVG_CEIL. This allows equal operands to be folded by the existing match.pd rule while retaining optab-based instruction selection for other operands. PR target/122715 gcc/ChangeLog: * config/aarch64/aarch64-builtins.cc (aarch64_general_gimple_fold_builtin): Canonicalize halving-add builtins to IFN_AVG_FLOOR and IFN_AVG_CEIL. gcc/testsuite/ChangeLog: * gcc.target/aarch64/avg-pr122715.c: New test. * gcc.target/aarch64/avg-pr122715-2.c: New test. Signed-off-by: Odysseas Georgoudis <[email protected]> --- gcc/config/aarch64/aarch64-builtins.cc | 14 ++ .../gcc.target/aarch64/avg-pr122715-2.c | 33 +++++ .../gcc.target/aarch64/avg-pr122715.c | 129 ++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/avg-pr122715-2.c create mode 100644 gcc/testsuite/gcc.target/aarch64/avg-pr122715.c diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index 8cd1bc4b1a2..bb0a1c978f2 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -5065,6 +5065,20 @@ aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt, 1, args[0]); gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); break; + /* Lower Advanced SIMD halving-add builtins to average internal + functions. */ + BUILTIN_VDQ_BHSI (BINOP, shadd, 0, DEFAULT) + BUILTIN_VDQ_BHSI (BINOPU, uhadd, 0, DEFAULT) + new_stmt = gimple_build_call_internal (IFN_AVG_FLOOR, 2, + args[0], args[1]); + gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); + break; + BUILTIN_VDQ_BHSI (BINOP, srhadd, 0, DEFAULT) + BUILTIN_VDQ_BHSI (BINOPU, urhadd, 0, DEFAULT) + new_stmt = gimple_build_call_internal (IFN_AVG_CEIL, 2, + args[0], args[1]); + gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); + break; BUILTIN_VSDQ_I_DI (BINOP, ashl, 3, DEFAULT) if (TREE_CODE (args[1]) == INTEGER_CST && wi::ltu_p (wi::to_wide (args[1]), element_precision (args[0]))) diff --git a/gcc/testsuite/gcc.target/aarch64/avg-pr122715-2.c b/gcc/testsuite/gcc.target/aarch64/avg-pr122715-2.c new file mode 100644 index 00000000000..c088c1327d0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/avg-pr122715-2.c @@ -0,0 +1,33 @@ +/* PR target/122715 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include <arm_neon.h> + +int32x4_t avg_floor_s32(int32x4_t x, int32x4_t y) +{ + return vhaddq_s32 (x, y); +} + +uint32x4_t avg_floor_u32(uint32x4_t x, uint32x4_t y) +{ + return vhaddq_u32 (x, y); +} + +int32x4_t avg_ceil_s32(int32x4_t x, int32x4_t y) +{ + return vrhaddq_s32 (x, y); +} + +uint32x4_t avg_ceil_u32(uint32x4_t x, uint32x4_t y) +{ + return vrhaddq_u32 (x, y); +} + +/* { dg-final { scan-tree-dump-times {\.AVG_FLOOR} 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times {\.AVG_CEIL} 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-not {__builtin_aarch64_} "optimized" } } */ +/* { dg-final { scan-assembler-times {\tshadd\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tuhadd\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tsrhadd\t} 1 } } */ +/* { dg-final { scan-assembler-times {\turhadd\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/avg-pr122715.c b/gcc/testsuite/gcc.target/aarch64/avg-pr122715.c new file mode 100644 index 00000000000..aa46df3ffd7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/avg-pr122715.c @@ -0,0 +1,129 @@ +/* PR target/122715 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#include <arm_neon.h> + +int8x8_t avg_floor_s8_64(int8x8_t x) +{ + return vhadd_s8 (x, x); +} + +int16x4_t avg_floor_s16_64(int16x4_t x) +{ + return vhadd_s16 (x, x); +} + +int32x2_t avg_floor_s32_64(int32x2_t x) +{ + return vhadd_s32 (x, x); +} + +uint8x8_t avg_floor_u8_64(uint8x8_t x) +{ + return vhadd_u8 (x, x); +} + +uint16x4_t avg_floor_u16_64(uint16x4_t x) +{ + return vhadd_u16 (x, x); +} + +uint32x2_t avg_floor_u32_64(uint32x2_t x) +{ + return vhadd_u32 (x, x); +} + +int8x16_t avg_floor_s8_128(int8x16_t x) +{ + return vhaddq_s8 (x, x); +} + +int16x8_t avg_floor_s16_128(int16x8_t x) +{ + return vhaddq_s16 (x, x); +} + +int32x4_t avg_floor_s32_128(int32x4_t x) +{ + return vhaddq_s32 (x, x); +} + +uint8x16_t avg_floor_u8_128(uint8x16_t x) +{ + return vhaddq_u8 (x, x); +} + +uint16x8_t avg_floor_u16_128(uint16x8_t x) +{ + return vhaddq_u16 (x, x); +} + +uint32x4_t avg_floor_u32_128(uint32x4_t x) +{ + return vhaddq_u32 (x, x); +} + +int8x8_t avg_ceil_s8_64(int8x8_t x) +{ + return vrhadd_s8 (x, x); +} + +int16x4_t avg_ceil_s16_64(int16x4_t x) +{ + return vrhadd_s16 (x, x); +} + +int32x2_t avg_ceil_s32_64(int32x2_t x) +{ + return vrhadd_s32 (x, x); +} + +uint8x8_t avg_ceil_u8_64(uint8x8_t x) +{ + return vrhadd_u8 (x, x); +} + +uint16x4_t avg_ceil_u16_64(uint16x4_t x) +{ + return vrhadd_u16 (x, x); +} + +uint32x2_t avg_ceil_u32_64(uint32x2_t x) +{ + return vrhadd_u32 (x, x); +} + +int8x16_t avg_ceil_s8_128(int8x16_t x) +{ + return vrhaddq_s8 (x, x); +} + +int16x8_t avg_ceil_s16_128(int16x8_t x) +{ + return vrhaddq_s16 (x, x); +} + +int32x4_t avg_ceil_s32_128(int32x4_t x) +{ + return vrhaddq_s32 (x, x); +} + +uint8x16_t avg_ceil_u8_128(uint8x16_t x) +{ + return vrhaddq_u8 (x, x); +} + +uint16x8_t avg_ceil_u16_128(uint16x8_t x) +{ + return vrhaddq_u16 (x, x); +} + +uint32x4_t avg_ceil_u32_128(uint32x4_t x) +{ + return vrhaddq_u32 (x, x); +} + +/* { dg-final { scan-tree-dump-not {__builtin_aarch64_} "optimized" } } */ +/* { dg-final { scan-tree-dump-times {return x_} 24 "optimized" } } */ +/* { dg-final { scan-assembler-not {\t[su]r?hadd\t} } } */ -- 2.43.5