arm: gimple fold aes[ed] [PR114522]
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap |
success
|
Build passed
|
Commit Message
Almost a copy/paste from the recent aarch64 version of this patch,
this one is a bit more intrusive because it also introduces
arm_general_gimple_fold_builtin.
With this patch,
gcc.target/arm/aes_xor_combine.c scan-assembler-not veor
passes again.
gcc/ChangeLog:
PR target/114522
* config/arm/arm-builtins.cc (arm_fold_aes_op): New function.
(arm_general_gimple_fold_builtin): New function.
* config/arm/arm-builtins.h (arm_general_gimple_fold_builtin): New
prototype.
* config/arm/arm.cc (arm_gimple_fold_builtin): Call
arm_general_gimple_fold_builtin as needed.
---
gcc/config/arm/arm-builtins.cc | 55 ++++++++++++++++++++++++++++++++++
gcc/config/arm/arm-builtins.h | 1 +
gcc/config/arm/arm.cc | 3 ++
3 files changed, 59 insertions(+)
Comments
On 12/02/2025 11:01, Christophe Lyon wrote:
> Almost a copy/paste from the recent aarch64 version of this patch,
> this one is a bit more intrusive because it also introduces
> arm_general_gimple_fold_builtin.
>
> With this patch,
> gcc.target/arm/aes_xor_combine.c scan-assembler-not veor
> passes again.
>
> gcc/ChangeLog:
>
> PR target/114522
> * config/arm/arm-builtins.cc (arm_fold_aes_op): New function.
> (arm_general_gimple_fold_builtin): New function.
> * config/arm/arm-builtins.h (arm_general_gimple_fold_builtin): New
> prototype.
> * config/arm/arm.cc (arm_gimple_fold_builtin): Call
> arm_general_gimple_fold_builtin as needed.
Thanks for picking this up.
OK.
R.
> ---
> gcc/config/arm/arm-builtins.cc | 55 ++++++++++++++++++++++++++++++++++
> gcc/config/arm/arm-builtins.h | 1 +
> gcc/config/arm/arm.cc | 3 ++
> 3 files changed, 59 insertions(+)
>
> diff --git a/gcc/config/arm/arm-builtins.cc b/gcc/config/arm/arm-builtins.cc
> index e860607686c..c56ab5db985 100644
> --- a/gcc/config/arm/arm-builtins.cc
> +++ b/gcc/config/arm/arm-builtins.cc
> @@ -45,6 +45,9 @@
> #include "arm-builtins.h"
> #include "stringpool.h"
> #include "attribs.h"
> +#include "basic-block.h"
> +#include "gimple.h"
> +#include "ssa.h"
>
> #define SIMD_MAX_BUILTIN_ARGS 7
>
> @@ -4053,4 +4056,56 @@ arm_cde_end_args (tree fndecl)
> }
> }
>
> +/* Fold a call to vaeseq_u8 and vaesdq_u8.
> + That is `vaeseq_u8 (x ^ y, 0)` gets folded
> + into `vaeseq_u8 (x, y)`.*/
> +static gimple *
> +arm_fold_aes_op (gcall *stmt)
> +{
> + tree arg0 = gimple_call_arg (stmt, 0);
> + tree arg1 = gimple_call_arg (stmt, 1);
> + if (integer_zerop (arg0))
> + arg0 = arg1;
> + else if (!integer_zerop (arg1))
> + return nullptr;
> + if (TREE_CODE (arg0) != SSA_NAME)
> + return nullptr;
> + if (!has_single_use (arg0))
> + return nullptr;
> + auto *s = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (arg0));
> + if (!s || gimple_assign_rhs_code (s) != BIT_XOR_EXPR)
> + return nullptr;
> + gimple_call_set_arg (stmt, 0, gimple_assign_rhs1 (s));
> + gimple_call_set_arg (stmt, 1, gimple_assign_rhs2 (s));
> + return stmt;
> +}
> +
> +/* Try to fold STMT, given that it's a call to the built-in function with
> + subcode FCODE. Return the new statement on success and null on
> + failure. */
> +gimple *
> +arm_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt)
> +{
> + gimple *new_stmt = NULL;
> +
> + switch (fcode)
> + {
> + case ARM_BUILTIN_CRYPTO_AESE:
> + case ARM_BUILTIN_CRYPTO_AESD:
> + new_stmt = arm_fold_aes_op (stmt);
> + break;
> + }
> +
> + /* GIMPLE assign statements (unlike calls) require a non-null lhs. If we
> + created an assign statement with a null lhs, then fix this by assigning
> + to a new (and subsequently unused) variable. */
> + if (new_stmt && is_gimple_assign (new_stmt) && !gimple_assign_lhs (new_stmt))
> + {
> + tree new_lhs = make_ssa_name (gimple_call_return_type (stmt));
> + gimple_assign_set_lhs (new_stmt, new_lhs);
> + }
> +
> + return new_stmt;
> +}
> +
> #include "gt-arm-builtins.h"
> diff --git a/gcc/config/arm/arm-builtins.h b/gcc/config/arm/arm-builtins.h
> index 1fa85b602d9..3a646619f44 100644
> --- a/gcc/config/arm/arm-builtins.h
> +++ b/gcc/config/arm/arm-builtins.h
> @@ -32,6 +32,7 @@ enum resolver_ident {
> };
> enum resolver_ident arm_describe_resolver (tree);
> unsigned arm_cde_end_args (tree);
> +gimple *arm_general_gimple_fold_builtin (unsigned int, gcall *);
>
> #define ENTRY(E, M, Q, S, T, G) E,
> enum arm_simd_type
> diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
> index a95ddf8201f..00499a26bae 100644
> --- a/gcc/config/arm/arm.cc
> +++ b/gcc/config/arm/arm.cc
> @@ -76,6 +76,7 @@
> #include "aarch-common.h"
> #include "aarch-common-protos.h"
> #include "machmode.h"
> +#include "arm-builtins.h"
>
> /* This file should be included last. */
> #include "target-def.h"
> @@ -2859,7 +2860,9 @@ arm_gimple_fold_builtin (gimple_stmt_iterator *gsi)
> switch (code & ARM_BUILTIN_CLASS)
> {
> case ARM_BUILTIN_GENERAL:
> + new_stmt = arm_general_gimple_fold_builtin (subcode, stmt);
> break;
> +
> case ARM_BUILTIN_MVE:
> new_stmt = arm_mve::gimple_fold_builtin (subcode, stmt);
> }
@@ -45,6 +45,9 @@
#include "arm-builtins.h"
#include "stringpool.h"
#include "attribs.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "ssa.h"
#define SIMD_MAX_BUILTIN_ARGS 7
@@ -4053,4 +4056,56 @@ arm_cde_end_args (tree fndecl)
}
}
+/* Fold a call to vaeseq_u8 and vaesdq_u8.
+ That is `vaeseq_u8 (x ^ y, 0)` gets folded
+ into `vaeseq_u8 (x, y)`.*/
+static gimple *
+arm_fold_aes_op (gcall *stmt)
+{
+ tree arg0 = gimple_call_arg (stmt, 0);
+ tree arg1 = gimple_call_arg (stmt, 1);
+ if (integer_zerop (arg0))
+ arg0 = arg1;
+ else if (!integer_zerop (arg1))
+ return nullptr;
+ if (TREE_CODE (arg0) != SSA_NAME)
+ return nullptr;
+ if (!has_single_use (arg0))
+ return nullptr;
+ auto *s = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (arg0));
+ if (!s || gimple_assign_rhs_code (s) != BIT_XOR_EXPR)
+ return nullptr;
+ gimple_call_set_arg (stmt, 0, gimple_assign_rhs1 (s));
+ gimple_call_set_arg (stmt, 1, gimple_assign_rhs2 (s));
+ return stmt;
+}
+
+/* Try to fold STMT, given that it's a call to the built-in function with
+ subcode FCODE. Return the new statement on success and null on
+ failure. */
+gimple *
+arm_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt)
+{
+ gimple *new_stmt = NULL;
+
+ switch (fcode)
+ {
+ case ARM_BUILTIN_CRYPTO_AESE:
+ case ARM_BUILTIN_CRYPTO_AESD:
+ new_stmt = arm_fold_aes_op (stmt);
+ break;
+ }
+
+ /* GIMPLE assign statements (unlike calls) require a non-null lhs. If we
+ created an assign statement with a null lhs, then fix this by assigning
+ to a new (and subsequently unused) variable. */
+ if (new_stmt && is_gimple_assign (new_stmt) && !gimple_assign_lhs (new_stmt))
+ {
+ tree new_lhs = make_ssa_name (gimple_call_return_type (stmt));
+ gimple_assign_set_lhs (new_stmt, new_lhs);
+ }
+
+ return new_stmt;
+}
+
#include "gt-arm-builtins.h"
@@ -32,6 +32,7 @@ enum resolver_ident {
};
enum resolver_ident arm_describe_resolver (tree);
unsigned arm_cde_end_args (tree);
+gimple *arm_general_gimple_fold_builtin (unsigned int, gcall *);
#define ENTRY(E, M, Q, S, T, G) E,
enum arm_simd_type
@@ -76,6 +76,7 @@
#include "aarch-common.h"
#include "aarch-common-protos.h"
#include "machmode.h"
+#include "arm-builtins.h"
/* This file should be included last. */
#include "target-def.h"
@@ -2859,7 +2860,9 @@ arm_gimple_fold_builtin (gimple_stmt_iterator *gsi)
switch (code & ARM_BUILTIN_CLASS)
{
case ARM_BUILTIN_GENERAL:
+ new_stmt = arm_general_gimple_fold_builtin (subcode, stmt);
break;
+
case ARM_BUILTIN_MVE:
new_stmt = arm_mve::gimple_fold_builtin (subcode, stmt);
}