Skip to content

Commit 86dce00

Browse files
committed
aarch64: Recognise svundef idiom [PR114577]
GCC 14 adds the header file arm_neon_sve_bridge.h to help interface SVE and Advanced SIMD code. One of the defined idioms is: svset_neonq (svundef_TYPE (), advsimd_vector) which simply reinterprets advsimd_vector as an SVE vector without regard for what's in the upper bits. GCC was failing to recognise this idiom, which was likely to significantly hamper adoption. There is (AFAIK) no good way of representing an extension with undefined bits in gimple. We could add an internal-only builtin to represent it, but the current framework makes that somewhat awkward. It also doesn't seem very forward-looking. This patch instead goes for the simpler approach of recognising undefined arguments at expansion time. gcc/ PR target/114577 * config/aarch64/aarch64-sve-builtins.h (aarch64_sve::lookup_fndecl): Declare. * config/aarch64/aarch64-sve-builtins.cc (aarch64_sve::lookup_fndecl): New function. * config/aarch64/aarch64-sve-builtins-base.cc (is_undef): Likewise. (svset_neonq_impl::expand): Optimise expansions whose first argument is undefined. gcc/testsuite/ PR target/114577 * gcc.target/aarch64/sve/acle/general/pr114577_1.c: New test. * gcc.target/aarch64/sve/acle/general/pr114577_2.c: Likewise.
1 parent 85621f9 commit 86dce00

File tree

5 files changed

+184
-0
lines changed

5 files changed

+184
-0
lines changed

gcc/config/aarch64/aarch64-sve-builtins-base.cc

+27
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,31 @@
4747
#include "aarch64-builtins.h"
4848
#include "ssa.h"
4949
#include "gimple-fold.h"
50+
#include "tree-ssa.h"
5051

5152
using namespace aarch64_sve;
5253

5354
namespace {
5455

56+
/* Return true if VAL is an undefined value. */
57+
static bool
58+
is_undef (tree val)
59+
{
60+
if (TREE_CODE (val) == SSA_NAME)
61+
{
62+
if (ssa_undefined_value_p (val, false))
63+
return true;
64+
65+
gimple *def = SSA_NAME_DEF_STMT (val);
66+
if (gcall *call = dyn_cast<gcall *> (def))
67+
if (tree fndecl = gimple_call_fndecl (call))
68+
if (const function_instance *instance = lookup_fndecl (fndecl))
69+
if (instance->base == functions::svundef)
70+
return true;
71+
}
72+
return false;
73+
}
74+
5575
/* Return the UNSPEC_CMLA* unspec for rotation amount ROT. */
5676
static int
5777
unspec_cmla (int rot)
@@ -1142,6 +1162,13 @@ class svset_neonq_impl : public function_base
11421162
expand (function_expander &e) const override
11431163
{
11441164
machine_mode mode = e.vector_mode (0);
1165+
1166+
/* If the SVE argument is undefined, we just need to reinterpret the
1167+
Advanced SIMD argument as an SVE vector. */
1168+
if (!BYTES_BIG_ENDIAN
1169+
&& is_undef (CALL_EXPR_ARG (e.call_expr, 0)))
1170+
return simplify_gen_subreg (mode, e.args[1], GET_MODE (e.args[1]), 0);
1171+
11451172
rtx_vector_builder builder (VNx16BImode, 16, 2);
11461173
for (unsigned int i = 0; i < 16; i++)
11471174
builder.quick_push (CONST1_RTX (BImode));

gcc/config/aarch64/aarch64-sve-builtins.cc

+16
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,22 @@ get_vector_type (sve_type type)
10551055
return acle_vector_types[type.num_vectors - 1][vector_type];
10561056
}
10571057

1058+
/* If FNDECL is an SVE builtin, return its function instance, otherwise
1059+
return null. */
1060+
const function_instance *
1061+
lookup_fndecl (tree fndecl)
1062+
{
1063+
if (!fndecl_built_in_p (fndecl, BUILT_IN_MD))
1064+
return nullptr;
1065+
1066+
unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
1067+
if ((code & AARCH64_BUILTIN_CLASS) != AARCH64_BUILTIN_SVE)
1068+
return nullptr;
1069+
1070+
unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
1071+
return &(*registered_functions)[subcode]->instance;
1072+
}
1073+
10581074
/* Report an error against LOCATION that the user has tried to use
10591075
function FNDECL when extension EXTENSION is disabled. */
10601076
static void

gcc/config/aarch64/aarch64-sve-builtins.h

+1
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,7 @@ extern tree acle_svprfop;
810810

811811
bool vector_cst_all_same (tree, unsigned int);
812812
bool is_ptrue (tree, unsigned int);
813+
const function_instance *lookup_fndecl (tree);
813814

814815
/* Try to find a mode with the given mode_suffix_info fields. Return the
815816
mode on success or MODE_none on failure. */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* { dg-options "-O" } */
2+
/* { dg-final { check-function-bodies "**" "" } } */
3+
4+
#include <arm_neon_sve_bridge.h>
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
svint32_t svundef_foo ();
11+
12+
/*
13+
** f1: { target aarch64_little_endian }
14+
** ldr q0, \[x0\]
15+
** ret
16+
*/
17+
svint32_t
18+
f1 (int *a)
19+
{
20+
return svset_neonq (svundef_s32 (), vld1q_s32 (a));
21+
}
22+
23+
/*
24+
** f2: { target aarch64_little_endian }
25+
** ldr q0, \[x0\]
26+
** ret
27+
*/
28+
svint32_t
29+
f2 (int *a)
30+
{
31+
svint32_t undef;
32+
return svset_neonq (undef, vld1q_s32 (a));
33+
}
34+
35+
/*
36+
** f3: { target aarch64_little_endian }
37+
** mov [vz]0.[^\n]+, [vz]1.[^\n]+
38+
** ret
39+
*/
40+
svint32_t
41+
f3 (int32x4_t v0, int32x4_t v1)
42+
{
43+
return svset_neonq (svundef_s32 (), v1);
44+
}
45+
46+
/*
47+
** f4: { target aarch64_little_endian }
48+
** uzp1 z([0-9]+)\.s, z0\.s, z1\.s
49+
** ldr q([0-9]+), \[x0\]
50+
** ptrue p([0-7])\.s, vl4
51+
** sel z0\.s, p\3, z\2\.s, z\1\.s
52+
** ret
53+
*/
54+
svint32_t
55+
f4 (int *a, svint32_t x, svint32_t y)
56+
{
57+
x = svuzp1 (x, y);
58+
int32x4_t z = vld1q_s32 (a);
59+
return svset_neonq (x, z);
60+
}
61+
62+
/*
63+
** f5:
64+
** ...
65+
** bl svundef_foo
66+
** ...
67+
** sel z0\.s, [^\n]+
68+
** ...
69+
** ret
70+
*/
71+
svint32_t
72+
f5 (int *a)
73+
{
74+
return svset_neonq (svundef_foo (), vld1q_s32 (a));
75+
}
76+
77+
/*
78+
** f6:
79+
** ...
80+
** blr x[0-9]+
81+
** ...
82+
** sel z0\.s, [^\n]+
83+
** ...
84+
** ret
85+
*/
86+
svint32_t
87+
f6 (int *a, svint32_t (*svundef_s32) ())
88+
{
89+
return svset_neonq (svundef_s32 (), vld1q_s32 (a));
90+
}
91+
92+
#ifdef __cplusplus
93+
}
94+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* { dg-options "-O -msve-vector-bits=256" } */
2+
/* { dg-final { check-function-bodies "**" "" } } */
3+
4+
#include <arm_neon_sve_bridge.h>
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
/*
11+
** f1: { target aarch64_little_endian }
12+
** ldr q0, \[x0\]
13+
** ret
14+
*/
15+
svint32_t
16+
f1 (int *a)
17+
{
18+
return svset_neonq (svundef_s32 (), vld1q_s32 (a));
19+
}
20+
21+
/*
22+
** f2: { target aarch64_little_endian }
23+
** ldr q0, \[x0\]
24+
** ret
25+
*/
26+
svint32_t
27+
f2 (int *a)
28+
{
29+
svint32_t undef;
30+
return svset_neonq (undef, vld1q_s32 (a));
31+
}
32+
33+
/*
34+
** f3: { target aarch64_little_endian }
35+
** mov [vz]0.[^\n]+, [vz]1.[^\n]+
36+
** ret
37+
*/
38+
svint32_t
39+
f3 (int32x4_t v0, int32x4_t v1)
40+
{
41+
return svset_neonq (svundef_s32 (), v1);
42+
}
43+
44+
#ifdef __cplusplus
45+
}
46+
#endif

0 commit comments

Comments
 (0)