arm: gimple fold aes[ed] [PR114522]

Message ID 20250212110152.997315-1-christophe.lyon@linaro.org
State Committed
Commit 926c989131e914e69cd73529d183ebd9d637798a
Headers
Series 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

Christophe Lyon Feb. 12, 2025, 11:01 a.m. UTC
  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

Richard Earnshaw (foss) Feb. 13, 2025, 11:33 a.m. UTC | #1
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);
>      }
  

Patch

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);
     }