AArch64: New RTL for ABD

This patch adds new RTL and tests for sabd and uabd

PR tree-optimization/109156

gcc/ChangeLog:

	* config/aarch64/aarch64-simd.md (aarch64_<su>abd<mode>):
	Rename to <su>abd<mode>3.
	* config/aarch64/aarch64-sve.md (<su>abd<mode>_3): Rename
	to <su>abd<mode>3.

gcc/testsuite/ChangeLog:

	* gcc.target/aarch64/abd.h: New file.
	* gcc.target/aarch64/abd_2.c: New test.
	* gcc.target/aarch64/abd_3.c: New test.
	* gcc.target/aarch64/abd_4.c: New test.
	* gcc.target/aarch64/abd_none_2.c: New test.
	* gcc.target/aarch64/abd_none_3.c: New test.
	* gcc.target/aarch64/abd_none_4.c: New test.
	* gcc.target/aarch64/abd_run_1.c: New test.
	* gcc.target/aarch64/sve/abd_1.c: New test.
	* gcc.target/aarch64/sve/abd_none_1.c: New test.
	* gcc.target/aarch64/sve/abd_2.c: New test.
	* gcc.target/aarch64/sve/abd_none_2.c: New test.
This commit is contained in:
Oluwatamilore Adebayo 2023-06-15 07:36:48 +01:00 committed by Richard Sandiford
parent 710b8dec61
commit ea616f687d
14 changed files with 424 additions and 2 deletions

View file

@ -910,6 +910,18 @@
[(set_attr "type" "neon_abd<q>")]
)
(define_expand "<su>abd<mode>3"
[(match_operand:VDQ_BHSI 0 "register_operand")
(USMAX:VDQ_BHSI
(match_operand:VDQ_BHSI 1 "register_operand")
(match_operand:VDQ_BHSI 2 "register_operand"))]
"TARGET_SIMD"
{
emit_insn (gen_aarch64_<su>abd<mode> (operands[0], operands[1], operands[2]));
DONE;
}
)
(define_insn "aarch64_<su>abdl<mode>"
[(set (match_operand:<VWIDE> 0 "register_operand" "=w")
(zero_extend:<VWIDE>

View file

@ -4001,7 +4001,7 @@
;; -------------------------------------------------------------------------
;; Unpredicated integer absolute difference.
(define_expand "<su>abd<mode>_3"
(define_expand "<su>abd<mode>3"
[(use (match_operand:SVE_I 0 "register_operand"))
(USMAX:SVE_I
(match_operand:SVE_I 1 "register_operand")
@ -6973,7 +6973,7 @@
{
rtx ones = force_reg (<VSI2QI>mode, CONST1_RTX (<VSI2QI>mode));
rtx diff = gen_reg_rtx (<VSI2QI>mode);
emit_insn (gen_<su>abd<vsi2qi>_3 (diff, operands[1], operands[2]));
emit_insn (gen_<su>abd<vsi2qi>3 (diff, operands[1], operands[2]));
emit_insn (gen_udot_prod<vsi2qi> (operands[0], diff, ones, operands[3]));
DONE;
}

View file

@ -0,0 +1,68 @@
#ifdef ABD_IDIOM
#define TEST1(S, TYPE) \
__attribute__((noipa)) \
void fn_##S##_##TYPE (S TYPE * restrict a, \
S TYPE * restrict b, \
S TYPE * restrict out) { \
for (int i = 0; i < N; i++) { \
signed TYPE diff = b[i] - a[i]; \
out[i] = diff > 0 ? diff : -diff; \
} }
#define TEST2(S, TYPE1, TYPE2) \
__attribute__((noipa)) \
void fn_##S##_##TYPE1##_##TYPE1##_##TYPE2 \
(S TYPE1 * restrict a, \
S TYPE1 * restrict b, \
S TYPE2 * restrict out) { \
for (int i = 0; i < N; i++) { \
signed TYPE2 diff = b[i] - a[i]; \
out[i] = diff > 0 ? diff : -diff; \
} }
#define TEST3(S, TYPE1, TYPE2, TYPE3) \
__attribute__((noipa)) \
void fn_##S##_##TYPE1##_##TYPE2##_##TYPE3 \
(S TYPE1 * restrict a, \
S TYPE2 * restrict b, \
S TYPE3 * restrict out) { \
for (int i = 0; i < N; i++) { \
signed TYPE3 diff = b[i] - a[i]; \
out[i] = diff > 0 ? diff : -diff; \
} }
#endif
#ifdef ABD_ABS
#define TEST1(S, TYPE) \
__attribute__((noipa)) \
void fn_##S##_##TYPE (S TYPE * restrict a, \
S TYPE * restrict b, \
S TYPE * restrict out) { \
for (int i = 0; i < N; i++) \
out[i] = __builtin_abs(a[i] - b[i]); \
}
#define TEST2(S, TYPE1, TYPE2) \
__attribute__((noipa)) \
void fn_##S##_##TYPE1##_##TYPE1##_##TYPE2 \
(S TYPE1 * restrict a, \
S TYPE1 * restrict b, \
S TYPE2 * restrict out) { \
for (int i = 0; i < N; i++) \
out[i] = __builtin_abs(a[i] - b[i]); \
}
#define TEST3(S, TYPE1, TYPE2, TYPE3) \
__attribute__((noipa)) \
void fn_##S##_##TYPE1##_##TYPE2##_##TYPE3 \
(S TYPE1 * restrict a, \
S TYPE2 * restrict b, \
S TYPE3 * restrict out) { \
for (int i = 0; i < N; i++) \
out[i] = __builtin_abs(a[i] - b[i]); \
}
#endif

View file

@ -0,0 +1,35 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#pragma GCC target "+nosve"
#define N 1024
#define ABD_ABS
#include "abd.h"
TEST1(signed, int)
TEST1(signed, short)
TEST1(signed, char)
TEST2(signed, char, short)
TEST2(signed, char, int)
TEST2(signed, short, int)
TEST3(signed, char, int, short)
TEST3(signed, char, short, int)
TEST1(unsigned, short)
TEST1(unsigned, char)
TEST2(unsigned, char, short)
TEST2(unsigned, char, int)
TEST3(unsigned, char, short, int)
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.4s" 5 } } */
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h, v\[0-9\]+\.8h" 4 } } */
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b, v\[0-9\]+\.16b" 3 } } */
/* { dg-final { scan-assembler-times "uabd\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h, v\[0-9\]+\.8h" 3 } } */
/* { dg-final { scan-assembler-times "uabd\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b, v\[0-9\]+\.16b" 3 } } */
/* { dg-final { scan-assembler-not {\tabs\t} } } */

View file

@ -0,0 +1,36 @@
/* { dg-do compile } */
/* { dg-options "-Ofast" } */
#pragma GCC target "arch=armv8-a"
#define N 1024
#define ABD_ABS
#include "abd.h"
TEST1(signed, int)
TEST1(signed, short)
TEST1(signed, char)
TEST2(signed, char, short)
TEST2(signed, char, int)
TEST2(signed, short, int)
TEST3(signed, char, int, short)
TEST3(signed, char, short, int)
TEST1(unsigned, short)
TEST1(unsigned, char)
TEST2(unsigned, char, short)
TEST2(unsigned, char, int)
TEST2(unsigned, short, int)
TEST3(unsigned, char, short, int)
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.4s" 5 } } */
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h, v\[0-9\]+\.8h" 4 } } */
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b, v\[0-9\]+\.16b" 3 } } */
/* { dg-final { scan-assembler-times "uabd\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h, v\[0-9\]+\.8h" 4 } } */
/* { dg-final { scan-assembler-times "uabd\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b, v\[0-9\]+\.16b" 3 } } */
/* { dg-final { scan-assembler-not {\tabs\t} } } */

View file

@ -0,0 +1,30 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#pragma GCC target "+nosve"
#define N 1024
#define ABD_IDIOM
#include "abd.h"
TEST1(signed, int)
TEST2(signed, char, short)
TEST2(signed, char, int)
TEST2(signed, short, int)
TEST3(signed, char, short, int)
TEST2(unsigned, char, short)
TEST2(unsigned, char, int)
TEST2(unsigned, short, int)
TEST3(unsigned, char, short, int)
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.4s" 1 } } */
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h, v\[0-9\]+\.8h" 3 } } */
/* { dg-final { scan-assembler-times "sabd\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b, v\[0-9\]+\.16b" 2 } } */
/* { dg-final { scan-assembler-times "uabd\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h, v\[0-9\]+\.8h" 3 } } */
/* { dg-final { scan-assembler-times "uabd\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b, v\[0-9\]+\.16b" 2 } } */
/* { dg-final { scan-assembler-not {\tabs\t} } } */

View file

@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#pragma GCC target "+nosve"
#define N 1024
#define ABD_ABS
#include "abd.h"
TEST1(unsigned, int)
TEST3(unsigned, char, int, short)
/* { dg-final { scan-assembler-not {\tsabd\t} } } */
/* { dg-final { scan-assembler-not {\tuabd\t} } } */

View file

@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-Ofast" } */
#pragma GCC target "arch=armv8-a"
#define N 1024
#define ABD_ABS
#include "abd.h"
TEST1(unsigned, int)
TEST3(unsigned, char, int, short)
/* { dg-final { scan-assembler-not {\tsabd\t} } } */
/* { dg-final { scan-assembler-not {\tuabd\t} } } */

View file

@ -0,0 +1,22 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#pragma GCC target "+nosve"
#define N 1024
#define ABD_IDIOM
#include "abd.h"
TEST1(signed, short)
TEST1(signed, char)
TEST3(signed, char, int, short)
TEST1(unsigned, int)
TEST1(unsigned, short)
TEST1(unsigned, char)
TEST3(unsigned, char, int, short)
/* { dg-final { scan-assembler-not {\tsabd\t} } } */
/* { dg-final { scan-assembler-not {\tuabd\t} } } */

View file

@ -0,0 +1,93 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
#pragma GCC target "+nosve"
#define N 16
#define ABD_ABS
#include "abd.h"
TEST1(signed, int)
TEST1(signed, short)
TEST1(signed, char)
TEST1(unsigned, int)
TEST1(unsigned, short)
TEST1(unsigned, char)
#define EMPTY { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
#define sA { -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50 }
#define uA { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 }
#define B { 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 }
#define GOLD { 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75 }
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
s8 sc_out[] = EMPTY;
u8 uc_out[] = EMPTY;
s16 ss_out[] = EMPTY;
u16 us_out[] = EMPTY;
s32 si_out[] = EMPTY;
u32 ui_out[] = EMPTY;
s8 sc_A[] = sA;
s8 sc_B[] = B;
u8 uc_A[] = uA;
u8 uc_B[] = B;
s16 ss_A[] = sA;
s16 ss_B[] = B;
u16 us_A[] = uA;
u16 us_B[] = B;
s32 si_A[] = sA;
s32 si_B[] = B;
u32 ui_A[] = uA;
u32 ui_B[] = B;
s8 sc_gold[] = GOLD;
u8 uc_gold[] = GOLD;
s16 ss_gold[] = GOLD;
u16 us_gold[] = GOLD;
s32 si_gold[] = GOLD;
u32 ui_gold[] = GOLD;
extern void abort (void);
#define CLEAR(arr) \
for (int i = 0; i < N; i++) \
arr[i] = 0;
#define COMPARE(A, B) \
for (int i = 0; i < N; i++) \
if (A[i] != B[i]) \
abort();
int main ()
{
fn_signed_char (sc_A, sc_B, sc_out);
COMPARE (sc_out, sc_gold);
fn_unsigned_char (uc_A, uc_B, uc_out);
COMPARE (uc_out, uc_gold);
fn_signed_short (ss_A, ss_B, ss_out);
COMPARE (ss_out, ss_gold)
fn_unsigned_short (us_A, us_B, us_out);
COMPARE (us_out, us_gold)
fn_signed_int (si_A, si_B, si_out);
COMPARE (si_out, si_gold);
fn_unsigned_int (ui_A, ui_B, ui_out);
COMPARE (ui_out, ui_gold);
return 0;
}

View file

@ -0,0 +1,35 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#define N 1024
#define ABD_ABS
#include "../abd.h"
TEST1(signed, int)
TEST1(signed, short)
TEST1(signed, char)
TEST2(signed, char, int)
TEST2(signed, char, short)
TEST2(signed, short, int)
TEST3(signed, char, int, short)
TEST3(signed, char, short, int)
TEST1(unsigned, short)
TEST1(unsigned, char)
TEST2(unsigned, char, short)
TEST2(unsigned, char, int)
TEST2(unsigned, short, int)
TEST3(unsigned, char, short, int)
/* { dg-final { scan-assembler-times "sabd\\tz\[0-9\]+\.s, p\[0-9\]/m, z\[0-9\]+\.s, z\[0-9\]+\.s" 2 } } */
/* { dg-final { scan-assembler-times "sabd\\tz\[0-9\]+\.h, p\[0-9\]/m, z\[0-9\]+\.h, z\[0-9\]+\.h" 3 } } */
/* { dg-final { scan-assembler-times "sabd\\tz\[0-9\]+\.b, p\[0-9\]/m, z\[0-9\]+\.b, z\[0-9\]+\.b" 3 } } */
/* { dg-final { scan-assembler-times "uabd\\tz\[0-9\]+\.h, p\[0-9\]/m, z\[0-9\]+\.h, z\[0-9\]+\.h" 3 } } */
/* { dg-final { scan-assembler-times "uabd\\tz\[0-9\]+\.b, p\[0-9\]/m, z\[0-9\]+\.b, z\[0-9\]+\.b" 3 } } */
/* { dg-final { scan-assembler-not {\tabs\t} } } */

View file

@ -0,0 +1,29 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#define N 1024
#define ABD_IDIOM
#include "../abd.h"
TEST1(signed, int)
TEST2(signed, char, int)
TEST2(signed, char, short)
TEST2(signed, short, int)
TEST3(signed, char, short, int)
TEST2(unsigned, char, int)
TEST2(unsigned, char, short)
TEST2(unsigned, short, int)
TEST3(unsigned, char, short, int)
/* { dg-final { scan-assembler-times "sabd\\tz\[0-9\]+\.s, p\[0-9\]/m, z\[0-9\]+\.s, z\[0-9\]+\.s" 1 } } */
/* { dg-final { scan-assembler-times "sabd\\tz\[0-9\]+\.h, p\[0-9\]/m, z\[0-9\]+\.h, z\[0-9\]+\.h" 2 } } */
/* { dg-final { scan-assembler-times "sabd\\tz\[0-9\]+\.b, p\[0-9\]/m, z\[0-9\]+\.b, z\[0-9\]+\.b" 2 } } */
/* { dg-final { scan-assembler-times "uabd\\tz\[0-9\]+\.h, p\[0-9\]/m, z\[0-9\]+\.h, z\[0-9\]+\.h" 2 } } */
/* { dg-final { scan-assembler-times "uabd\\tz\[0-9\]+\.b, p\[0-9\]/m, z\[0-9\]+\.b, z\[0-9\]+\.b" 2 } } */
/* { dg-final { scan-assembler-not {\tabs\t} } } */

View file

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#define N 1024
#define ABD_ABS
#include "../abd.h"
TEST1(unsigned, int)
TEST3(unsigned, char, int, short)
/* { dg-final { scan-assembler-not {\tsabd\t} } } */
/* { dg-final { scan-assembler-not {\tuabd\t} } } */

View file

@ -0,0 +1,21 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#define N 1024
#define ABD_IDIOM
#include "../abd.h"
TEST1(signed, short)
TEST1(signed, char)
TEST3(signed, char, int, short)
TEST1(unsigned, int)
TEST1(unsigned, short)
TEST1(unsigned, char)
TEST3(unsigned, char, int, short)
/* { dg-final { scan-assembler-not {\tsabd\t} } } */
/* { dg-final { scan-assembler-not {\tuabd\t} } } */