aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/arm/aarch-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/arm/aarch-common.c')
-rw-r--r--gcc-4.9/gcc/config/arm/aarch-common.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/config/arm/aarch-common.c b/gcc-4.9/gcc/config/arm/aarch-common.c
index c11f7e954..af8fc9996 100644
--- a/gcc-4.9/gcc/config/arm/aarch-common.c
+++ b/gcc-4.9/gcc/config/arm/aarch-common.c
@@ -31,6 +31,42 @@
#include "c-family/c-common.h"
#include "rtl.h"
+/* In ARMv8-A there's a general expectation that AESE/AESMC
+ and AESD/AESIMC sequences of the form:
+
+ AESE Vn, _
+ AESMC Vn, Vn
+
+ will issue both instructions in a single cycle on super-scalar
+ implementations. This function identifies such pairs. */
+
+int
+aarch_crypto_can_dual_issue (rtx producer, rtx consumer)
+{
+ rtx producer_src, consumer_src;
+
+ producer = single_set (producer);
+ consumer = single_set (consumer);
+
+ producer_src = producer ? SET_SRC (producer) : NULL;
+ consumer_src = consumer ? SET_SRC (consumer) : NULL;
+
+ if (producer_src && consumer_src
+ && GET_CODE (producer_src) == UNSPEC && GET_CODE (consumer_src) == UNSPEC
+ && ((XINT (producer_src, 1) == UNSPEC_AESE
+ && XINT (consumer_src, 1) == UNSPEC_AESMC)
+ || (XINT (producer_src, 1) == UNSPEC_AESD
+ && XINT (consumer_src, 1) == UNSPEC_AESIMC)))
+ {
+ unsigned int regno = REGNO (SET_DEST (producer));
+
+ return REGNO (SET_DEST (consumer)) == regno
+ && REGNO (XVECEXP (consumer_src, 0, 0)) == regno;
+ }
+
+ return 0;
+}
+
typedef struct
{
rtx_code search_code;