[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