From patchwork Thu Apr 4 13:18:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1919803 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4V9Md75gSFz1yYP for ; Fri, 5 Apr 2024 00:18:33 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 03E653858C98 for ; Thu, 4 Apr 2024 13:18:32 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id B5EE53858C98 for ; Thu, 4 Apr 2024 13:18:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B5EE53858C98 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B5EE53858C98 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1712236690; cv=none; b=jUCKrHP1Fmz4q+ow5asww7lWUHVuC2gudpG55HcFdV5Z1ioQAcSEMTTiYEJ/zATtD+nEehKDcL+YtQ09w7UQjK1OzS3YD1p2sThNf5wrThkMnZYTm+zhFccpSJG58FJEhQOXfzhqLt+/u59AxvfzqX6L2RYc/ImCPBC/saOt1gE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1712236690; c=relaxed/simple; bh=G6nf5jhJ6w8EO+m+rHKBeixaoKiR5FlqnZ384rYLQzI=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=xqwMlj3K7N9x+DL8fVgPrw1oolLF0m9l1vR6MXrk4kmhULs1Akmi68NIqw6Lum4k/UZe99IEvtLWxrlrGL5Ah09kKJ2eI3pcaOqrQQKP1VVgDEVDWZqspAnNLj3HvniK6Fi8YCOsKEgGM2gC2G/KtwQbgl80mSKXMr4IUgMb4/U= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 25848FEC for ; Thu, 4 Apr 2024 06:18:38 -0700 (PDT) Received: from localhost (e121540-lin.manchester.arm.com [10.32.110.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 10D423F64C for ; Thu, 4 Apr 2024 06:18:06 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [pushed] aarch64: Recognise svundef idiom [PR114577] Date: Thu, 04 Apr 2024 14:18:05 +0100 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Spam-Status: No, score=-20.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org 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. Tested on aarch64-linux-gnu & pushed. Richard 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. --- .../aarch64/aarch64-sve-builtins-base.cc | 27 ++++++ gcc/config/aarch64/aarch64-sve-builtins.cc | 16 ++++ gcc/config/aarch64/aarch64-sve-builtins.h | 1 + .../aarch64/sve/acle/general/pr114577_1.c | 94 +++++++++++++++++++ .../aarch64/sve/acle/general/pr114577_2.c | 46 +++++++++ 5 files changed, 184 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr114577_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr114577_2.c diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc index a8c3f84a70b..257ca5bf6ad 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc @@ -47,11 +47,31 @@ #include "aarch64-builtins.h" #include "ssa.h" #include "gimple-fold.h" +#include "tree-ssa.h" using namespace aarch64_sve; namespace { +/* Return true if VAL is an undefined value. */ +static bool +is_undef (tree val) +{ + if (TREE_CODE (val) == SSA_NAME) + { + if (ssa_undefined_value_p (val, false)) + return true; + + gimple *def = SSA_NAME_DEF_STMT (val); + if (gcall *call = dyn_cast (def)) + if (tree fndecl = gimple_call_fndecl (call)) + if (const function_instance *instance = lookup_fndecl (fndecl)) + if (instance->base == functions::svundef) + return true; + } + return false; +} + /* Return the UNSPEC_CMLA* unspec for rotation amount ROT. */ static int unspec_cmla (int rot) @@ -1142,6 +1162,13 @@ public: expand (function_expander &e) const override { machine_mode mode = e.vector_mode (0); + + /* If the SVE argument is undefined, we just need to reinterpret the + Advanced SIMD argument as an SVE vector. */ + if (!BYTES_BIG_ENDIAN + && is_undef (CALL_EXPR_ARG (e.call_expr, 0))) + return simplify_gen_subreg (mode, e.args[1], GET_MODE (e.args[1]), 0); + rtx_vector_builder builder (VNx16BImode, 16, 2); for (unsigned int i = 0; i < 16; i++) builder.quick_push (CONST1_RTX (BImode)); diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index 11f5c5c500c..e124d1f90a5 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -1055,6 +1055,22 @@ get_vector_type (sve_type type) return acle_vector_types[type.num_vectors - 1][vector_type]; } +/* If FNDECL is an SVE builtin, return its function instance, otherwise + return null. */ +const function_instance * +lookup_fndecl (tree fndecl) +{ + if (!fndecl_built_in_p (fndecl, BUILT_IN_MD)) + return nullptr; + + unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); + if ((code & AARCH64_BUILTIN_CLASS) != AARCH64_BUILTIN_SVE) + return nullptr; + + unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; + return &(*registered_functions)[subcode]->instance; +} + /* Report an error against LOCATION that the user has tried to use function FNDECL when extension EXTENSION is disabled. */ static void diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h index e66729ed635..053006776a9 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.h +++ b/gcc/config/aarch64/aarch64-sve-builtins.h @@ -810,6 +810,7 @@ extern tree acle_svprfop; bool vector_cst_all_same (tree, unsigned int); bool is_ptrue (tree, unsigned int); +const function_instance *lookup_fndecl (tree); /* Try to find a mode with the given mode_suffix_info fields. Return the mode on success or MODE_none on failure. */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr114577_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr114577_1.c new file mode 100644 index 00000000000..2566c2d86c4 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr114577_1.c @@ -0,0 +1,94 @@ +/* { dg-options "-O" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +svint32_t svundef_foo (); + +/* +** f1: { target aarch64_little_endian } +** ldr q0, \[x0\] +** ret +*/ +svint32_t +f1 (int *a) +{ + return svset_neonq (svundef_s32 (), vld1q_s32 (a)); +} + +/* +** f2: { target aarch64_little_endian } +** ldr q0, \[x0\] +** ret +*/ +svint32_t +f2 (int *a) +{ + svint32_t undef; + return svset_neonq (undef, vld1q_s32 (a)); +} + +/* +** f3: { target aarch64_little_endian } +** mov [vz]0.[^\n]+, [vz]1.[^\n]+ +** ret +*/ +svint32_t +f3 (int32x4_t v0, int32x4_t v1) +{ + return svset_neonq (svundef_s32 (), v1); +} + +/* +** f4: { target aarch64_little_endian } +** uzp1 z([0-9]+)\.s, z0\.s, z1\.s +** ldr q([0-9]+), \[x0\] +** ptrue p([0-7])\.s, vl4 +** sel z0\.s, p\3, z\2\.s, z\1\.s +** ret +*/ +svint32_t +f4 (int *a, svint32_t x, svint32_t y) +{ + x = svuzp1 (x, y); + int32x4_t z = vld1q_s32 (a); + return svset_neonq (x, z); +} + +/* +** f5: +** ... +** bl svundef_foo +** ... +** sel z0\.s, [^\n]+ +** ... +** ret +*/ +svint32_t +f5 (int *a) +{ + return svset_neonq (svundef_foo (), vld1q_s32 (a)); +} + +/* +** f6: +** ... +** blr x[0-9]+ +** ... +** sel z0\.s, [^\n]+ +** ... +** ret +*/ +svint32_t +f6 (int *a, svint32_t (*svundef_s32) ()) +{ + return svset_neonq (svundef_s32 (), vld1q_s32 (a)); +} + +#ifdef __cplusplus +} +#endif diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr114577_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr114577_2.c new file mode 100644 index 00000000000..0775162e6b5 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr114577_2.c @@ -0,0 +1,46 @@ +/* { dg-options "-O -msve-vector-bits=256" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** f1: { target aarch64_little_endian } +** ldr q0, \[x0\] +** ret +*/ +svint32_t +f1 (int *a) +{ + return svset_neonq (svundef_s32 (), vld1q_s32 (a)); +} + +/* +** f2: { target aarch64_little_endian } +** ldr q0, \[x0\] +** ret +*/ +svint32_t +f2 (int *a) +{ + svint32_t undef; + return svset_neonq (undef, vld1q_s32 (a)); +} + +/* +** f3: { target aarch64_little_endian } +** mov [vz]0.[^\n]+, [vz]1.[^\n]+ +** ret +*/ +svint32_t +f3 (int32x4_t v0, int32x4_t v1) +{ + return svset_neonq (svundef_s32 (), v1); +} + +#ifdef __cplusplus +} +#endif