[llvm] [AArch64] Add ReadAdvance for AESE/AESMC and AESD/AESIMC pairs (PR #213652)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 3 04:57:01 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Andrew Savonichev (asavonic)
<details>
<summary>Changes</summary>
Neoverse N2 (as well as other targets like Cortex-A78) can issue a pair of AESE/AESMC and AESD/AESIMC instructions every cycle (fully pipelined) with an execution latency of two cycles. See the Arm Neoverse N2 Software Optimization Guide s4.7 "AES
encryption/decryption" for more details.
Before the patch, MCA estimated the following sequence to take 400 cycles for 100 iterations (IPC of 1).
aese v0.16b, v1.16b
aesmc v0.16b, v0.16b
aesd v2.16b, v3.16b
aesimc v2.16b, v2.16b
After the patch MCA estimates 200 cycles for 100 iterations (IPC of 2). This matches llvm-exegesis tests perfromed on on Cortex-A78:
---
mode: inverse_throughput
key:
instructions:
- 'AESErr Q0 Q0 Q1'
- 'AESMCrr Q0 Q0'
- 'AESDrr Q2 Q2 Q3'
- 'AESIMCrr Q2 Q2'
config: ''
register_initial_values: []
cpu_name: cortex-a78ae
llvm_triple: aarch64-unknown-linux-gnu
min_instructions: 10000
measurements:
- { key: inverse_throughput, value: 0.5038, per_snippet_value: 2.0152, validation_counters: {} }
---
Full diff: https://github.com/llvm/llvm-project/pull/213652.diff
2 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td (+3-1)
- (added) llvm/test/tools/llvm-mca/AArch64/Neoverse/N2-aes.s (+118)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td b/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td
index 3e2bfc1dd2d0c..086c6d820fd82 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td
@@ -1690,7 +1690,9 @@ def : InstRW<[WriteAdr, N2Write_4c_3L01_3V], (instregex "ST4i(64)_POST$")>;
// -----------------------------------------------------------------------------
// Crypto AES ops
-def : InstRW<[N2Write_2c_1V], (instregex "^AES[DE]rr$", "^AESI?MCrr")>;
+def N2Rd_AES : SchedReadAdvance<2, [N2Write_2c_1V]>;
+def : InstRW<[N2Write_2c_1V], (instregex "^AES[DE]rr$")>;
+def : InstRW<[N2Write_2c_1V, N2Rd_AES], (instregex "^AESI?MCrr")>;
// Crypto polynomial (64x64) multiply long
def : InstRW<[N2Write_2c_1V0], (instrs PMULLv1i64, PMULLv2i64)>;
diff --git a/llvm/test/tools/llvm-mca/AArch64/Neoverse/N2-aes.s b/llvm/test/tools/llvm-mca/AArch64/Neoverse/N2-aes.s
new file mode 100644
index 0000000000000..2d89f34f1ca3d
--- /dev/null
+++ b/llvm/test/tools/llvm-mca/AArch64/Neoverse/N2-aes.s
@@ -0,0 +1,118 @@
+# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py
+# RUN: llvm-mca -mtriple=aarch64 -mcpu=neoverse-n2 -timeline -mattr=aes < %s | FileCheck %s
+
+aese v0.16b, v1.16b
+aesmc v0.16b, v0.16b
+aesd v2.16b, v3.16b
+aesimc v2.16b, v2.16b
+
+# CHECK: Iterations: 100
+# CHECK-NEXT: Instructions: 400
+# CHECK-NEXT: Total Cycles: 204
+# CHECK-NEXT: Total uOps: 400
+
+# CHECK: Dispatch Width: 5
+# CHECK-NEXT: uOps Per Cycle: 1.96
+# CHECK-NEXT: IPC: 1.96
+# CHECK-NEXT: Block RThroughput: 2.0
+
+# CHECK: Instruction Info:
+# CHECK-NEXT: [1]: #uOps
+# CHECK-NEXT: [2]: Latency
+# CHECK-NEXT: [3]: RThroughput
+# CHECK-NEXT: [4]: MayLoad
+# CHECK-NEXT: [5]: MayStore
+# CHECK-NEXT: [6]: HasSideEffects (U)
+
+# CHECK: [1] [2] [3] [4] [5] [6] Instructions:
+# CHECK-NEXT: 1 2 0.50 aese v0.16b, v1.16b
+# CHECK-NEXT: 1 2 0.50 aesmc v0.16b, v0.16b
+# CHECK-NEXT: 1 2 0.50 aesd v2.16b, v3.16b
+# CHECK-NEXT: 1 2 0.50 aesimc v2.16b, v2.16b
+
+# CHECK: Resources:
+# CHECK-NEXT: [0.0] - N2UnitB
+# CHECK-NEXT: [0.1] - N2UnitB
+# CHECK-NEXT: [1.0] - N2UnitD
+# CHECK-NEXT: [1.1] - N2UnitD
+# CHECK-NEXT: [2.0] - N2UnitFlg
+# CHECK-NEXT: [2.1] - N2UnitFlg
+# CHECK-NEXT: [2.2] - N2UnitFlg
+# CHECK-NEXT: [3] - N2UnitL2
+# CHECK-NEXT: [4.0] - N2UnitL01
+# CHECK-NEXT: [4.1] - N2UnitL01
+# CHECK-NEXT: [5] - N2UnitM0
+# CHECK-NEXT: [6] - N2UnitM1
+# CHECK-NEXT: [7.0] - N2UnitS
+# CHECK-NEXT: [7.1] - N2UnitS
+# CHECK-NEXT: [8] - N2UnitV0
+# CHECK-NEXT: [9] - N2UnitV1
+
+# CHECK: Resource pressure per iteration:
+# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2.0] [2.1] [2.2] [3] [4.0] [4.1] [5] [6] [7.0] [7.1] [8] [9]
+# CHECK-NEXT: - - - - - - - - - - - - - - 2.00 2.00
+
+# CHECK: Resource pressure by instruction:
+# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2.0] [2.1] [2.2] [3] [4.0] [4.1] [5] [6] [7.0] [7.1] [8] [9] Instructions:
+# CHECK-NEXT: - - - - - - - - - - - - - - - 1.00 aese v0.16b, v1.16b
+# CHECK-NEXT: - - - - - - - - - - - - - - 1.00 - aesmc v0.16b, v0.16b
+# CHECK-NEXT: - - - - - - - - - - - - - - - 1.00 aesd v2.16b, v3.16b
+# CHECK-NEXT: - - - - - - - - - - - - - - 1.00 - aesimc v2.16b, v2.16b
+
+# CHECK: Timeline view:
+# CHECK-NEXT: 0123456789
+# CHECK-NEXT: Index 0123456789 0123
+
+# CHECK: [0,0] DeeER. . . . . aese v0.16b, v1.16b
+# CHECK-NEXT: [0,1] DeeER. . . . . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [0,2] D=eeER . . . . aesd v2.16b, v3.16b
+# CHECK-NEXT: [0,3] D=eeER . . . . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [1,0] D==eeER . . . . aese v0.16b, v1.16b
+# CHECK-NEXT: [1,1] .D=eeER . . . . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [1,2] .D==eeER . . . . aesd v2.16b, v3.16b
+# CHECK-NEXT: [1,3] .D==eeER . . . . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [2,0] .D===eeER . . . . aese v0.16b, v1.16b
+# CHECK-NEXT: [2,1] .D===eeER . . . . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [2,2] . D===eeER. . . . aesd v2.16b, v3.16b
+# CHECK-NEXT: [2,3] . D===eeER. . . . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [3,0] . D====eeER . . . aese v0.16b, v1.16b
+# CHECK-NEXT: [3,1] . D====eeER . . . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [3,2] . D=====eeER . . . aesd v2.16b, v3.16b
+# CHECK-NEXT: [3,3] . D====eeER . . . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [4,0] . D=====eeER . . . aese v0.16b, v1.16b
+# CHECK-NEXT: [4,1] . D=====eeER . . . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [4,2] . D======eeER . . . aesd v2.16b, v3.16b
+# CHECK-NEXT: [4,3] . D======eeER . . . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [5,0] . D======eeER. . . aese v0.16b, v1.16b
+# CHECK-NEXT: [5,1] . D======eeER. . . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [5,2] . D=======eeER . . aesd v2.16b, v3.16b
+# CHECK-NEXT: [5,3] . D=======eeER . . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [6,0] . D========eeER . . aese v0.16b, v1.16b
+# CHECK-NEXT: [6,1] . D=======eeER . . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [6,2] . D========eeER . . aesd v2.16b, v3.16b
+# CHECK-NEXT: [6,3] . D========eeER . . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [7,0] . D=========eeER . . aese v0.16b, v1.16b
+# CHECK-NEXT: [7,1] . D=========eeER . . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [7,2] . .D=========eeER. . aesd v2.16b, v3.16b
+# CHECK-NEXT: [7,3] . .D=========eeER. . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [8,0] . .D==========eeER . aese v0.16b, v1.16b
+# CHECK-NEXT: [8,1] . .D==========eeER . aesmc v0.16b, v0.16b
+# CHECK-NEXT: [8,2] . .D===========eeER . aesd v2.16b, v3.16b
+# CHECK-NEXT: [8,3] . . D==========eeER . aesimc v2.16b, v2.16b
+# CHECK-NEXT: [9,0] . . D===========eeER. aese v0.16b, v1.16b
+# CHECK-NEXT: [9,1] . . D===========eeER. aesmc v0.16b, v0.16b
+# CHECK-NEXT: [9,2] . . D============eeER aesd v2.16b, v3.16b
+# CHECK-NEXT: [9,3] . . D============eeER aesimc v2.16b, v2.16b
+
+# CHECK: Average Wait times (based on the timeline view):
+# CHECK-NEXT: [0]: Executions
+# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue
+# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready
+# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage
+
+# CHECK: [0] [1] [2] [3]
+# CHECK-NEXT: 0. 10 6.8 0.1 0.0 aese v0.16b, v1.16b
+# CHECK-NEXT: 1. 10 6.6 0.0 0.0 aesmc v0.16b, v0.16b
+# CHECK-NEXT: 2. 10 7.4 0.2 0.0 aesd v2.16b, v3.16b
+# CHECK-NEXT: 3. 10 7.2 0.0 0.0 aesimc v2.16b, v2.16b
+# CHECK-NEXT: 40 7.0 0.1 0.0 <total>
``````````
</details>
https://github.com/llvm/llvm-project/pull/213652
More information about the llvm-commits
mailing list