[llvm] [AArch64] Initial sched model for Neoverse N3 (PR #106371)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 12 06:51:47 PDT 2024


================
@@ -0,0 +1,2375 @@
+//=- AArch64SchedNeoverseN3.td - NeoverseN3 Scheduling Defs --*- tablegen -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the scheduling model for the Arm Neoverse N3 processors.
+//
+//===----------------------------------------------------------------------===//
+
+def NeoverseN3Model : SchedMachineModel {
+    let IssueWidth            =  10; // Micro-ops dispatched at a time.
+    let MicroOpBufferSize     = 160; // Entries in micro-op re-order buffer. NOTE: Copied from N2.
+    let LoadLatency           =   4; // Optimistic load latency.
+    let MispredictPenalty     =  10; // Extra cycles for mispredicted branch. NOTE: Copied from N2.
+    let LoopMicroOpBufferSize =  16; // NOTE: Copied from Cortex-A57.
+    let CompleteModel         =   1;
+
+    list<Predicate> UnsupportedFeatures = !listconcat(SMEUnsupported.F,
+        [HasSVE2p1, HasPAuthLR, HasCPA, HasCSSC]);
+}
+
+//===----------------------------------------------------------------------===//
+// Define each kind of processor resource and number available on Neoverse N3.
+// Instructions are first fetched and then decoded into internal Macro-OPerations
+// (MOPs). From there, the MOPs proceed through register renaming and dispatch stages.
+// A MOP can be split into two Micro-OPerations (µOPs) further down the pipeline
+// after the decode stage. Once dispatched, µOPs wait for their operands and issue
+// out-of-order to one of thirteen issue pipelines. Each issue pipeline can accept
+// one µOP per cycle.
+
+let SchedModel = NeoverseN3Model in {
+
+// Define the (13) issue ports.
+def N3UnitB   : ProcResource<2>;  // Branch 0/1
+def N3UnitS   : ProcResource<2>;  // Integer Single-Cycle 0/1
+def N3UnitM0  : ProcResource<1>;  // Integer Single/Multi-Cycle 0
+def N3UnitM1  : ProcResource<1>;  // Integer Single/Multi-Cycle 1
+def N3UnitV0  : ProcResource<1>;  // FP/ASIMD 0
+def N3UnitV1  : ProcResource<1>;  // FP/ASIMD 1
+def N3UnitD   : ProcResource<2>;  // Integer Store data 0/1
+def N3UnitL01 : ProcResource<2>;  // Load/Store 0/1
+def N3UnitL2  : ProcResource<1>;  // Load 2
+
+def N3UnitI : ProcResGroup<[N3UnitS, N3UnitM0, N3UnitM1]>;
+def N3UnitM : ProcResGroup<[N3UnitM0, N3UnitM1]>;
+def N3UnitL : ProcResGroup<[N3UnitL01, N3UnitL2]>;
+def N3UnitV : ProcResGroup<[N3UnitV0, N3UnitV1]>;
+
+//===----------------------------------------------------------------------===//
+
+def : ReadAdvance<ReadI,       0>;
+def : ReadAdvance<ReadISReg,   0>;
+def : ReadAdvance<ReadIEReg,   0>;
+def : ReadAdvance<ReadIM,      0>;
+def : ReadAdvance<ReadIMA,     0>;
+def : ReadAdvance<ReadID,      0>;
+def : ReadAdvance<ReadExtrHi,  0>;
+def : ReadAdvance<ReadAdrBase, 0>;
+def : ReadAdvance<ReadST,      0>;
+def : ReadAdvance<ReadVLD,     0>;
+
+// NOTE: Copied from N2.
+def : WriteRes<WriteAtomic,  []> { let Unsupported = 1; }
+def : WriteRes<WriteBarrier, []> { let Latency = 1; }
+def : WriteRes<WriteHint,    []> { let Latency = 1; }
+
+//===----------------------------------------------------------------------===//
+// Define customized scheduler read/write types specific to the Neoverse N3.
+
+//===----------------------------------------------------------------------===//
+// Define generic 0 micro-op types
+
+def N3Write_0c : SchedWriteRes<[]> {
+    let Latency = 0;
+    let NumMicroOps = 0;
+}
+
+def N3Write_4c : SchedWriteRes<[]> {
+    let Latency = 4;
+    let NumMicroOps = 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 1 micro-op types
+
+def N3Write_1c_1B   : SchedWriteRes<[N3UnitB]>   { let Latency = 1; }
+def N3Write_1c_1I   : SchedWriteRes<[N3UnitI]>   { let Latency = 1; }
+def N3Write_2c_1M   : SchedWriteRes<[N3UnitM]>   { let Latency = 2; }
+def N3Write_2c_1M0  : SchedWriteRes<[N3UnitM0]>  { let Latency = 2; }
+def N3Write_3c_1M   : SchedWriteRes<[N3UnitM]>   { let Latency = 3; }
+def N3Write_1c_1M   : SchedWriteRes<[N3UnitM]>   { let Latency = 1; }
+def N3Write_4c_1M   : SchedWriteRes<[N3UnitM]>   { let Latency = 4; }
+def N3Write_1c_1S   : SchedWriteRes<[N3UnitS]>   { let Latency = 1; }
+def N3Write_4c_1L   : SchedWriteRes<[N3UnitL]>   { let Latency = 4; }
+def N3Write_2c_1V   : SchedWriteRes<[N3UnitV]>   { let Latency = 2; }
+def N3Write_5c_1V0  : SchedWriteRes<[N3UnitV0]>  { let Latency = 5; }
+def N3Write_7c_1V0  : SchedWriteRes<[N3UnitV0]>  { let Latency = 7; }
+def N3Write_12c_1V0 : SchedWriteRes<[N3UnitV0]>  { let Latency = 12; }
+def N3Write_3c_1V   : SchedWriteRes<[N3UnitV]>   { let Latency = 3; }
+def N3Write_4c_1V   : SchedWriteRes<[N3UnitV]>   { let Latency = 4; }
+def N3Write_3c_1V0  : SchedWriteRes<[N3UnitV0]>  { let Latency = 3; }
+def N3Write_3c_1M0  : SchedWriteRes<[N3UnitM0]>  { let Latency = 3; }
+def N3Write_6c_1L   : SchedWriteRes<[N3UnitL]>   { let Latency = 6; }
+def N3Write_4c_1V1  : SchedWriteRes<[N3UnitV1]>  { let Latency = 4; }
+def N3Write_3c_1V1  : SchedWriteRes<[N3UnitV1]>  { let Latency = 3; }
+def N3Write_4c_1V0  : SchedWriteRes<[N3UnitV0]>  { let Latency = 4; }
+def N3Write_2c_1V0  : SchedWriteRes<[N3UnitV0]>  { let Latency = 2; }
+def N3Write_2c_1V1  : SchedWriteRes<[N3UnitV1]>  { let Latency = 2; }
+def N3Write_5c_1V   : SchedWriteRes<[N3UnitV]>   { let Latency = 5; }
+def N3Write_1c_1L01 : SchedWriteRes<[N3UnitL01]> { let Latency = 1; }
+
+def N3Write_12c_1M0 : SchedWriteRes<[N3UnitM0]> {
+    let Latency = 12;
+    let ReleaseAtCycles = [12];
+}
+
+def N3Write_20c_1M0 : SchedWriteRes<[N3UnitM0]> {
+    let Latency = 20;
+    let ReleaseAtCycles = [20];
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 2 micro-op types
+
+def N3Write_1c_1B_1S : SchedWriteRes<[N3UnitB, N3UnitS]> {
+    let Latency = 1;
+    let NumMicroOps = 2;
+}
+
+def N3Write_2c_1M_1B : SchedWriteRes<[N3UnitM, N3UnitB]> {
+    let Latency = 2;
+    let NumMicroOps = 2;
+}
+
+def N3Write_5c_1L_1S : SchedWriteRes<[N3UnitL, N3UnitS]> {
+    let Latency = 5;
+    let NumMicroOps = 2;
+}
+
+def N3Write_4c_2L : SchedWriteRes<[N3UnitL, N3UnitL]> {
+    let Latency = 4;
+    let NumMicroOps = 2;
+}
+
+def N3Write_3c_1L01_1V : SchedWriteRes<[N3UnitL01, N3UnitV]> {
+    let Latency = 3;
+    let NumMicroOps = 2;
+}
+
+def N3Write_1c_1L01_1D : SchedWriteRes<[N3UnitL01, N3UnitD]> {
+    let Latency = 1;
+    let NumMicroOps = 2;
+}
+
+def N3Write_5c_1L_1I : SchedWriteRes<[N3UnitL, N3UnitI]> {
+    let Latency = 5;
+    let NumMicroOps = 2;
+}
+
+def N3Write_6c_2L : SchedWriteRes<[N3UnitL, N3UnitL]> {
+    let Latency = 6;
+    let NumMicroOps = 2;
+}
+
+def N3Write_2c_1L01_1V : SchedWriteRes<[N3UnitL01, N3UnitV]> {
+    let Latency = 2;
+    let NumMicroOps = 2;
+}
+
+def N3Write_6c_2V1 : SchedWriteRes<[N3UnitV1, N3UnitV1]> {
+    let Latency = 6;
+    let NumMicroOps = 2;
+}
+
+def N3Write_4c_2V0 : SchedWriteRes<[N3UnitV0, N3UnitV0]> {
+    let Latency = 4;
+    let NumMicroOps = 2;
+}
+
+def N3Write_8c_2V0 : SchedWriteRes<[N3UnitV0, N3UnitV0]> {
+    let Latency = 8;
+    let NumMicroOps = 2;
+}
+
+def N3Write_13c_2V0 : SchedWriteRes<[N3UnitV0, N3UnitV0]> {
+    let Latency = 13;
+    let NumMicroOps = 2;
+}
+
+def N3Write_4c_2V : SchedWriteRes<[N3UnitV, N3UnitV]> {
+    let Latency = 4;
+    let NumMicroOps = 2;
+}
+
+def N3Write_2c_2V : SchedWriteRes<[N3UnitV, N3UnitV]> {
+    let Latency = 2;
+    let NumMicroOps = 2;
+}
+
+def N3Write_8c_1L_1V : SchedWriteRes<[N3UnitL, N3UnitV]> {
+    let Latency = 8;
+    let NumMicroOps = 2;
+}
+
+def N3Write_2c_1V_1L01 : SchedWriteRes<[N3UnitV, N3UnitL01]> {
+    let Latency = 2;
+    let NumMicroOps = 2;
+}
+
+def N3Write_5c_2V0 : SchedWriteRes<[N3UnitV0, N3UnitV0]> {
+    let Latency = 5;
+    let NumMicroOps = 2;
+}
+
+def N3Write_6c_2V0 : SchedWriteRes<[N3UnitV0, N3UnitV0]> {
+    let Latency = 6;
+    let NumMicroOps = 2;
+}
+
+def N3Write_7c_1L_1M : SchedWriteRes<[N3UnitL, N3UnitM]> {
+    let Latency = 7;
+    let NumMicroOps = 2;
+}
+
+def N3Write_8c_1V_1L : SchedWriteRes<[N3UnitV, N3UnitL]> {
+    let Latency = 8;
+    let NumMicroOps = 2;
+}
+
+def N3Write_5c_1M0_1V : SchedWriteRes<[N3UnitM0, N3UnitV]> {
+    let Latency = 5;
+    let NumMicroOps = 2;
+}
+
+def N3Write_5c_1V1_1V : SchedWriteRes<[N3UnitV1, N3UnitV]> {
+    let Latency = 5;
+    let NumMicroOps = 2;
+}
+
+def N3Write_8c_1M0_1V : SchedWriteRes<[N3UnitM0, N3UnitV]> {
+    let Latency = 8;
+    let NumMicroOps = 2;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 3 micro-op types
+
+
+
+def N3Write_6c_3V : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 6;
+    let NumMicroOps = 3;
+}
+
+def N3Write_4c_3V : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 4;
+    let NumMicroOps = 3;
+}
+
+def N3Write_6c_3L : SchedWriteRes<[N3UnitL, N3UnitL, N3UnitL]> {
+    let Latency = 6;
+    let NumMicroOps = 3;
+}
+
+def N3Write_8c_2L_1V : SchedWriteRes<[N3UnitL, N3UnitL, N3UnitV]> {
+    let Latency = 8;
+    let NumMicroOps = 3;
+}
+
+
+def N3Write_7c_2V_1V1 : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV1]> {
+    let Latency = 7;
+    let NumMicroOps = 3;
+}
+
+def N3Write_5c_2V_1V1 : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV1]> {
+    let Latency = 5;
+    let NumMicroOps = 3;
+}
+
+def N3Write_7c_1M_1M0_1V : SchedWriteRes<[N3UnitM, N3UnitM0, N3UnitV]> {
+    let Latency = 7;
+    let NumMicroOps = 3;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 4 micro-op types
+
+def N3Write_5c_1M_1L_2I : SchedWriteRes<[N3UnitM, N3UnitL, N3UnitI, N3UnitI]> {
+    let Latency = 5;
+    let NumMicroOps = 4;
+}
+
+def N3Write_4c_2I_2L : SchedWriteRes<[N3UnitI, N3UnitI, N3UnitL, N3UnitL]> {
+    let Latency = 4;
+    let NumMicroOps = 4;
+}
+
+def N3Write_1c_1L01_1D_2I : SchedWriteRes<[N3UnitL01, N3UnitD, N3UnitI, N3UnitI]> {
+    let Latency = 1;
+    let NumMicroOps = 4;
+}
+
+def N3Write_2c_2I_1L01_1V : SchedWriteRes<[N3UnitI, N3UnitI, N3UnitL01, N3UnitV]> {
+    let Latency = 2;
+    let NumMicroOps = 4;
+}
+
+def N3Write_6c_4V0 : SchedWriteRes<[N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0]> {
+    let Latency = 6;
+    let NumMicroOps = 4;
+}
+
+def N3Write_8c_4V0 : SchedWriteRes<[N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0]> {
+    let Latency = 8;
+    let NumMicroOps = 4;
+}
+
+def N3Write_10c_4V0 : SchedWriteRes<[N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0]> {
+    let Latency = 10;
+    let NumMicroOps = 4;
+}
+
+def N3Write_6c_4V : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 6;
+    let NumMicroOps = 4;
+}
+
+def N3Write_7c_4L : SchedWriteRes<[N3UnitL, N3UnitL, N3UnitL, N3UnitL]> {
+    let Latency = 7;
+    let NumMicroOps = 4;
+}
+
+def N3Write_2c_2L01_2V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitV, N3UnitV]> {
+    let Latency = 2;
+    let NumMicroOps = 4;
+}
+
+def N3Write_4c_2V_2L01 : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitL01, N3UnitL01]> {
+    let Latency = 4;
+    let NumMicroOps = 4;
+}
+
+def N3Write_2c_2V_2L01 : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitL01, N3UnitL01]> {
+    let Latency = 2;
+    let NumMicroOps = 4;
+}
+
+def N3Write_8c_4V : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 8;
+    let NumMicroOps = 4;
+}
+
+def N3Write_2c_1L01_2I_1V : SchedWriteRes<[N3UnitL01, N3UnitI, N3UnitI, N3UnitV]> {
+    let Latency = 2;
+    let NumMicroOps = 4;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 6 micro-op types
+
+def N3Write_4c_3V_3L01 : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV,
+                                        N3UnitL01, N3UnitL01, N3UnitL01]> {
+    let Latency = 4;
+    let NumMicroOps = 6;
+}
+
+def N3Write_2c_3V_3L01 : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV,
+                                        N3UnitL01, N3UnitL01, N3UnitL01]> {
+    let Latency = 2;
+    let NumMicroOps = 6;
+}
+
+def N3Write_8c_4V_2V1 : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV, N3UnitV,
+                                       N3UnitV1, N3UnitV1]> {
+    let Latency = 8;
+    let NumMicroOps = 6;
+}
+
+def N3Write_4c_3L01_3V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitL01,
+                                        N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 4;
+    let NumMicroOps = 6;
+}
+
+def N3Write_3c_3L01_3V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitL01,
+                                        N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 3;
+    let NumMicroOps = 6;
+}
+
+def N3Write_6c_3L01_3V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitL01,
+                                        N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 6;
+    let NumMicroOps = 6;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 7 micro-op types
+
+def N3Write_8c_4L_3V : SchedWriteRes<[N3UnitL, N3UnitL, N3UnitL, N3UnitL,
+                                      N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 8;
+    let NumMicroOps = 7;
+}
+
+def N3Write_10c_4L_3V : SchedWriteRes<[N3UnitL, N3UnitL, N3UnitL, N3UnitL,
+                                       N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 10;
+    let NumMicroOps = 7;
+}
+
+def N3Write_8c_3V_4L : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV,
+                                      N3UnitL, N3UnitL, N3UnitL, N3UnitL]> {
+    let Latency = 8;
+    let NumMicroOps = 7;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 8 micro-op types
+
+def N3Write_12c_8V0 : SchedWriteRes<[N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0,
+                                     N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0]> {
+    let Latency = 12;
+    let NumMicroOps = 8;
+}
+
+def N3Write_4c_4V_4L01 : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV, N3UnitV,
+                                        N3UnitL01, N3UnitL01, N3UnitL01, N3UnitL01]> {
+    let Latency = 4;
+    let NumMicroOps = 8;
+}
+
+def N3Write_8c_8V0 : SchedWriteRes<[N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0,
+                                    N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0]> {
+    let Latency = 8;
+    let NumMicroOps = 8;
+}
+
+def N3Write_16c_8V : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV, N3UnitV,
+                                    N3UnitV, N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 16;
+    let NumMicroOps = 8;
+}
+
+def N3Write_3c_4L01_4V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitL01, N3UnitL01,
+                                        N3UnitV, N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 3;
+    let NumMicroOps = 8;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 10 micro-op types
+
+def N3Write_8c_6L_4V : SchedWriteRes<[N3UnitL, N3UnitL, N3UnitL,
+                                      N3UnitL, N3UnitL, N3UnitL,
+                                      N3UnitV, N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 8;
+    let NumMicroOps = 10;
+}
+
+def N3Write_8c_4V_6L : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV, N3UnitV,
+                                      N3UnitL, N3UnitL, N3UnitL,
+                                      N3UnitL, N3UnitL, N3UnitL]> {
+    let Latency = 8;
+    let NumMicroOps = 10;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 12 micro-op types
+
+def N3Write_12c_5V_7L : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV, N3UnitV, N3UnitV,
+                                       N3UnitL, N3UnitL, N3UnitL, N3UnitL,
+                                       N3UnitL, N3UnitL, N3UnitL]> {
+    let Latency = 12;
+    let NumMicroOps = 12;
+}
+
+def N3Write_4c_3L01_6I_3V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitL01,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 4;
+    let NumMicroOps = 12;
+}
+
+def N3Write_3c_3L01_6I_3V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitL01,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 3;
+    let NumMicroOps = 12;
+}
+
+def N3Write_6c_3L01_6I_3V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitL01,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 6;
+    let NumMicroOps = 12;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 13 micro-op types
+
+def N3Write_9c_3V_4L_6I : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV,
+                                         N3UnitL, N3UnitL, N3UnitL, N3UnitL,
+                                         N3UnitI, N3UnitI, N3UnitI,
+                                         N3UnitI, N3UnitI, N3UnitI]> {
+    let Latency = 9;
+    let NumMicroOps = 13;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 15 micro-op types
+
+def N3Write_10c_6V_9L : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV,
+                                       N3UnitV, N3UnitV, N3UnitV,
+                                       N3UnitL, N3UnitL, N3UnitL,
+                                       N3UnitL, N3UnitL, N3UnitL,
+                                       N3UnitL, N3UnitL, N3UnitL]> {
+    let Latency = 10;
+    let NumMicroOps = 15;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 16 micro-op types
+
+def N3Write_16c_16V0 : SchedWriteRes<[N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0,
+                                      N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0,
+                                      N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0,
+                                      N3UnitV0, N3UnitV0, N3UnitV0, N3UnitV0]> {
+    let Latency = 16;
+    let NumMicroOps = 16;
+}
+
+def N3Write_3c_4L01_8I_4V : SchedWriteRes<[N3UnitL01, N3UnitL01, N3UnitL01, N3UnitL01,
+                                           N3UnitI, N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitV, N3UnitV, N3UnitV, N3UnitV]> {
+    let Latency = 3;
+    let NumMicroOps = 16;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 18 micro-op types
+
+def N3Write_9c_6L_4V_8I : SchedWriteRes<[N3UnitL, N3UnitL, N3UnitL,
+                                         N3UnitL, N3UnitL, N3UnitL,
+                                         N3UnitV, N3UnitV, N3UnitV, N3UnitV,
+                                         N3UnitI, N3UnitI, N3UnitI, N3UnitI,
+                                         N3UnitI, N3UnitI, N3UnitI, N3UnitI]> {
+    let Latency = 9;
+    let NumMicroOps = 18;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 22 micro-op types
+
+def N3Write_13c_7L_5V_10I : SchedWriteRes<[N3UnitL, N3UnitL, N3UnitL, N3UnitL,
+                                           N3UnitL, N3UnitL, N3UnitL,
+                                           N3UnitV, N3UnitV, N3UnitV,
+                                           N3UnitV, N3UnitV,
+                                           N3UnitI, N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI]> {
+    let Latency = 13;
+    let NumMicroOps = 22;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 27 micro-op types
+
+def N3Write_11c_6V_9L_12I : SchedWriteRes<[N3UnitV, N3UnitV, N3UnitV,
+                                           N3UnitV, N3UnitV, N3UnitV,
+                                           N3UnitL, N3UnitL, N3UnitL,
+                                           N3UnitL, N3UnitL, N3UnitL,
+                                           N3UnitL, N3UnitL, N3UnitL,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI, N3UnitI,
+                                           N3UnitI, N3UnitI, N3UnitI]> {
+    let Latency = 11;
+    let NumMicroOps = 27;
+}
+
+// Miscellaneous
+// -----------------------------------------------------------------------------
+
+def : InstRW<[WriteI], (instrs COPY)>;
+
+// Branch Instructions
+// -----------------------------------------------------------------------------
+
+// Branch, immed
+// Compare and branch
+def : SchedAlias<WriteBr, N3Write_1c_1B>;
+
+// Branch, register
+def : SchedAlias<WriteBrReg, N3Write_1c_1B>;
+
+// Branch and link, immed
+// Branch and link, register
+def : InstRW<[N3Write_1c_1B_1S], (instrs BL, BLR)>;
+
+// Arithmetic and Logical Instructions
+// -----------------------------------------------------------------------------
+
+// ALU, basic
+// ALU, basic, flagset
+// Arithmetic, immediate to logical address tag
+// Conditional compare
+// Conditional select
+def : SchedAlias<WriteI, N3Write_1c_1I>;
+
+// ALU, extend and shift
+def : SchedAlias<WriteIEReg, N3Write_2c_1M>;
+
+def N3WriteISReg : SchedWriteVariant<[
+                     SchedVar<IsCheapLSL,  [N3Write_1c_1I]>,
+                     SchedVar<NoSchedPred, [N3Write_2c_1M]>]>;
+
+// Arithmetic, LSL shift, shift <= 4
+// Arithmetic, flagset, LSL shift, shift <= 4
+// Arithmetic, LSR/ASR/ROR shift or LSL shift > 4
+def : SchedAlias<WriteISReg, N3WriteISReg>;
+
+// Convert floating-point condition flags
+def : SchedAlias<WriteSys, N3Write_1c_1I>;
+
+// Flag manipulation instructions
+def : InstRW<[N3Write_1c_1I], (instrs SETF8, SETF16, RMIF, CFINV)>;
+
+// Insert Random Tags
+def : InstRW<[N3Write_2c_1M0], (instrs IRG, IRGstack)>;
+
+// Insert Tag Mask
+// Subtract Pointer
+// Subtract Pointer, flagset
+def : InstRW<[N3Write_1c_1I], (instrs GMI, SUBP, SUBPS)>;
+
+// Logical, shift, no flagset
+def : InstRW<[N3Write_1c_1I],
+             (instregex "^(AND|BIC|EON|EOR|ORN|ORR)[WX]rs$")>;
+
+// Logical, shift, flagset
+def : InstRW<[N3Write_2c_1M], (instregex "^(AND|BIC)S[WX]rs$")>;
+
+// Divide and Multiply Instructions
+// -----------------------------------------------------------------------------
+
+// Integer divides are performed using an iterative algorithm and block any
+// subsequent divide operations until complete.
+
+// Divide, W-form
+def : SchedAlias<WriteID32, N3Write_12c_1M0>;
+
+// Divide, X-form
+def : SchedAlias<WriteID64, N3Write_20c_1M0>;
+
+def N3Wr_IM   : SchedWriteRes<[N3UnitM]>  { let Latency = 2; }
+def N3Wr_IMA  : SchedWriteRes<[N3UnitM0]> { let Latency = 2; }
+def N3Wr_IMUL : SchedWriteVariant<[
+                  SchedVar<IsReg3ZeroPred, [N3Wr_IM]>,
+                  SchedVar<NoSchedPred,    [N3Wr_IMA]>]>;
+def N3Rd_IMA  : SchedReadAdvance<1, [N3Wr_IMA]>;
+
+def : SchedAlias<WriteIM32, N3Write_2c_1M0>;
+def : SchedAlias<WriteIM64, N3Write_2c_1M0>;
+
+// NOTE: Modified from V2
+
+// Multiply
+// Multiply accumulate, W-form
+// Multiply accumulate, X-form
+// Multiply accumulate long
+// Multiply long
+def : InstRW<[N3Wr_IMUL, ReadIM, ReadIM, N3Rd_IMA],
+             (instregex "^M(ADD|SUB)[WX]rrr$",
+                        "^(S|U)M(ADD|SUB)Lrrr$")>;
+
+// Multiply high
+def : InstRW<[N3Write_3c_1M], (instrs SMULHrr, UMULHrr)>;
+
+// Pointer Authentication Instructions
+// -----------------------------------------------------------------------------
+
+// Authenticate data address
+// Authenticate instruction address
+def : InstRW<[N3Write_1c_1M], (instrs AUTDA, AUTDB, AUTDZA, AUTDZB,
+                                      AUTIA, AUTIB, AUTIA1716, AUTIB1716,
+                                      AUTIASP, AUTIBSP, AUTIAZ, AUTIBZ, AUTIZA,
+                                      AUTIZB)>;
+
+// Branch and link, register, with pointer authentication
+// Branch, register, with pointer authentication
+// Branch, return, with pointer authentication
+def : InstRW<[N3Write_2c_1M_1B], (instrs BLRAA, BLRAAZ, BLRAB, BLRABZ, BRAA,
+                                         BRAAZ, BRAB, BRABZ, RETAA, RETAB,
+                                         ERETAA, ERETAB)>;
+
+// Compute pointer authentication code for data address
+def : InstRW<[N3Write_4c_1M], (instrs PACDA, PACDB, PACDZA, PACDZB)>;
+
+// Compute pointer authentication code, using generic key
+def : InstRW<[N3Write_4c_1M], (instrs PACGA)>;
+
+// Compute pointer authentication code for instruction address
+def : InstRW<[N3Write_4c_1M], (instrs PACIA, PACIB, PACIA1716, PACIB1716,
+                                      PACIASP, PACIBSP, PACIAZ, PACIBZ, PACIZA,
+                                      PACIZB)>;
+
+// Load register, with pointer authentication
+def : InstRW<[N3Write_5c_1M_1L_2I], (instregex "^LDRA[AB](indexed|writeback)")>;
+
+// Strip pointer authentication code
+def : InstRW<[N3Write_1c_1M], (instrs XPACD, XPACI, XPACLRI)>;
+
+// Miscellaneous data-processing instructions
+// -----------------------------------------------------------------------------
+
+// Address generation
+def : InstRW<[N3Write_1c_1S], (instrs ADR, ADRP)>;
+
+// Bitfield extract, one, two regs
+def : SchedAlias<WriteExtr, N3Write_1c_1I>;
+
+// Bitfield move, basic
+// Bitfield move, insert
+// Variable shift
+def : SchedAlias<WriteIS, N3Write_1c_1I>;
+
+// Count leading
+// Reverse bits/bytes
+// Covered by WriteI
+
+// Move immed
+def : SchedAlias<WriteImm, N3Write_1c_1I>;
+
+// Load instructions
+// -----------------------------------------------------------------------------
+
+// Load register, literal
+def : InstRW<[N3Write_5c_1L_1S], (instrs LDRWl, LDRXl, LDRSWl, PRFMl)>;
+
+// Load register, unscaled immed
+// Load register, immed post-index
+// Load register, immed pre-index
+// Load register, unsigned immed
+// Load register, immed unprivileged
+def : SchedAlias<WriteAdr, N3Write_1c_1I>;
+def : SchedAlias<WriteLD, N3Write_4c_1L>;
+
+// Load register, register offset, basic
+// Load register, register offset, scale by 4/8
+// Load register, register offset, scale by 2
+// Load register, register offset, extend
+// Load register, register offset, extend, scale by 4/8
+// Load register, register offset, extend, scale by 2
+def : SchedAlias<WriteLDIdx, N3Write_4c_1L>;
+
+def : SchedAlias<WriteLDHi, N3Write_4c>;
+
+// Load pair, signed immed offset, normal, W-form
+def : InstRW<[WriteLD, WriteLDHi], (instrs LDPWi, LDNPWi)>;
+
+// Load pair, signed immed offset, normal, X-form
+def : InstRW<[N3Write_4c_2L, WriteLDHi], (instrs LDPXi, LDNPXi)>;
+
+// Load pair, signed immed offset, signed words
+def : InstRW<[N3Write_4c_2I_2L, WriteLDHi], (instrs LDPSWi)>;
+
+// Load pair, immed post-index or immed pre-index, normal, W-form
+def : InstRW<[WriteAdr, WriteLD, WriteLDHi], (instrs LDPWpost, LDPWpre)>;
+
+// Load pair, immed post-index or immed pre-index, normal, X-form
+def : InstRW<[WriteAdr, N3Write_4c_2L, WriteLDHi], (instrs LDPXpost, LDPXpre)>;
+
+// Load pair, immed post-index or immed pre-index, signed words
+def : InstRW<[N3Write_0c, N3Write_4c_2I_2L, WriteLDHi], (instrs LDPSWpost, LDPSWpre)>;
+
+// Store instructions
+// -----------------------------------------------------------------------------
+
+// Store register, unscaled immed
+// Store register, immed unprivileged
+// Store register, unsigned immed
+def : SchedAlias<WriteST, N3Write_1c_1L01_1D>;
+
+// Store register, immed post-index
+// Store register, immed pre-index
+def : InstRW<[WriteAdr, WriteST], (instregex "^STR(BB|HH|W|X)(post|pre)$")>;
+
+// Store register, register offset, basic
+// Store register, register offset, scaled by 4/8
+// Store register, register offset, scaled by 2
+// Store register, register offset, extend
+// Store register, register offset, extend, scale by 4/8
+// Store register, register offset, extend, scale by 2
+def : SchedAlias<WriteSTIdx, N3Write_1c_1L01_1D>;
+
+// Store pair, immed offset
+def : SchedAlias<WriteSTP, N3Write_1c_1L01_1D>;
+
+// Store pair, immed post-index
+// Store pair, immed pre-index
+def : InstRW<[WriteAdr, WriteSTP], (instregex "^STP[WX](post|pre)$")>;
+
+// Tag Load instructions
+// -----------------------------------------------------------------------------
+
+// Load allocation tag
+def : InstRW<[N3Write_5c_1L_1I], (instrs LDG)>;
+
+// Load multiple allocation tags
+def : InstRW<[N3Write_4c_1L], (instrs LDGM)>;
+
+// Tag store instructions
+// -----------------------------------------------------------------------------
+
+// Store allocation tags to one or two granules, post-index
+// Store allocation tags to one or two granules, pre-index
+// Store allocation tag to one or two granules, zeroing, post-index
+// Store Allocation Tag to one or two granules, zeroing, pre-index
+def : InstRW<[N3Write_1c_1L01_1D_2I], (instregex "^STZ?2?G(Post|Pre)Index$")>;
+
+// Store allocation tags to one or two granules, signed offset
+// Store allocation tag to two granules, zeroing, signed offset
+def : InstRW<[N3Write_1c_1L01_1D], (instregex "^STZ?2?Gi$")>;
+
+// Store allocation tag and reg pair to memory, post-Index
+// Store allocation tag and reg pair to memory, pre-Index
+def : InstRW<[N3Write_1c_1L01_1D_2I], (instrs STGPpost, STGPpre)>;
+
+// Store allocation tag and reg pair to memory, signed offset
+def : InstRW<[N3Write_1c_1L01_1D], (instrs STGPi)>;
+
+// Store multiple allocation tags
+def : InstRW<[N3Write_1c_1L01_1D], (instrs STGM)>;
+
+// Store multiple allocation tags, zeroing
+def : InstRW<[N3Write_1c_1L01_1D], (instrs STZGM)>;
+
+// FP data processing instructions
+// -----------------------------------------------------------------------------
+
+// FP absolute value
+// FP arithmetic
+// FP min/max
+// FP negate
+// FP select
+def : SchedAlias<WriteF, N3Write_2c_1V>;
+
+// FP compare
+def : SchedAlias<WriteFCmp, N3Write_2c_1V>;
+
+// FP divide and square root operations are now performed using
+// a fully pipelined data path.
+
+// FP divide, H-form
+// FP square root, H-form
+def : InstRW<[N3Write_5c_1V0], (instrs FDIVHrr, FSQRTHr)>;
+
+// FP divide, S-form
+// FP square root, S-form
+def : SchedAlias<WriteFDiv , N3Write_7c_1V0>;
+
+// FP divide, D-form
+// FP square root, D-form
+def : InstRW<[N3Write_12c_1V0], (instrs FDIVDrr, FSQRTDr)>;
+
+// FP multiply
+def : SchedAlias<WriteFMul, N3Write_3c_1V>;
+
+// FP multiply accumulate
+def : InstRW<[N3Write_4c_1V], (instregex "^(FMADD|FMSUB|FNMADD|FNMSUB)[DHS]rrr$")>;
+
+// FP round to integral
+def : InstRW<[N3Write_3c_1V0], (instregex "^FRINT([AIMNPXZ]|32X|64X|32Z|64Z)[DHS]r$")>;
+
+// FP miscellaneous instructions
+// -----------------------------------------------------------------------------
+
+// FP convert, from gen to vec reg
+def : InstRW<[N3Write_3c_1M0], (instregex "^[SU]CVTF[SU][WX][HSD]ri$")>;
+
+// FP convert, from vec to gen reg
+// FP convert, Javascript from vec to gen reg
+// FP convert, from vec to vec reg
+def : SchedAlias<WriteFCvt, N3Write_3c_1V0>;
+
+// FP move, immed
+def : SchedAlias<WriteFImm, N3Write_2c_1V>;
+
+// FP move, register
+def : InstRW<[N3Write_2c_1V], (instrs FMOVHr, FMOVSr, FMOVDr)>;
+
+// FP transfer, from gen to low half of vec reg
+def : InstRW<[N3Write_3c_1M0], (instrs FMOVWHr, FMOVXHr, FMOVWSr, FMOVXDr)>;
+
+// FP transfer, from gen to high half of vec reg
+def : InstRW<[N3Write_5c_1M0_1V], (instrs FMOVXDHighr)>;
+
+// FP transfer, from vec to gen reg
+def : SchedAlias<WriteFCopy, N3Write_3c_1V>;
+
+// FP load instructions
+// -----------------------------------------------------------------------------
+
+// Load vector reg, literal, S/D/Q forms
+// Load vector reg, unscaled immed
+// Load vector reg, unsigned immed
+def : InstRW<[N3Write_6c_1L], (instregex "^LDR[SDQ]l$",
+                                         "^LDUR[BHSDQ]i$",
+                                         "^LDR[BHSDQ]ui$")>;
+// Load vector reg, immed post-index
+def : InstRW<[WriteAdr, N3Write_6c_1L], (instregex "^LDR[BHSDQ](post|pre)$")>;
+
+// Load vector reg, register offset, basic
+// Load vector reg, register offset, scale, S/D-form
+// Load vector reg, register offset, scale, H/Q-form
+// Load vector reg, register offset, extend
+// Load vector reg, register offset, extend, scale, S/D-form
+// Load vector reg, register offset, extend, scale, H/Q-form
+def : InstRW<[N3Write_6c_1L], (instregex "^LDR[BHSDQ]ro[WX]$")>;
+
+// Load vector pair, immed offset, S/D-form
+def : InstRW<[N3Write_6c_1L, WriteLDHi], (instregex "^LDN?P[SD]i$")>;
+
+// Load vector pair, immed offset, Q-form
+def : InstRW<[N3Write_6c_2L, WriteLDHi], (instrs LDPQi, LDNPQi)>;
+
+// Load vector pair, immed post-index, S/D-form
+// Load vector pair, immed post-index, Q-form
+// Load vector pair, immed pre-index, S/D-form
+// Load vector pair, immed pre-index, Q-form
+def : InstRW<[WriteAdr, N3Write_6c_2L, WriteLDHi], (instregex "^LDP[SDQ](post|pre)$")>;
+
+// FP store instructions
+// -----------------------------------------------------------------------------
+
+// Store vector reg, unscaled immed, B/H/S/D-form
+// Store vector reg, unscaled immed, Q-form
+def : InstRW<[N3Write_2c_1L01_1V], (instregex "^STUR[BHSDQ]i$")>;
+
+// Store vector reg, immed post-index, B/H/S/D-form
+// Store vector reg, immed post-index, Q-form
+def : InstRW<[WriteAdr, N3Write_2c_1L01_1V], (instregex "^STR[BHSDQ]post$")>;
+
+// Store vector reg, immed pre-index, B/H/S/D-form
+def : InstRW<[WriteAdr, N3Write_3c_1L01_1V], (instregex "^STR[BHSD]pre$")>;
+
+// Store vector reg, immed pre-index, Q-form
+def : InstRW<[WriteAdr, N3Write_2c_1L01_1V], (instrs STRQpre)>;
+
+// Store vector reg, unsigned immed, B/H/S/D-form
+// Store vector reg, unsigned immed, Q-form
+def : InstRW<[N3Write_2c_1L01_1V], (instregex "^STR[BHSDQ]ui$")>;
+
+// Store vector reg, register offset, basic, B/H/S/D-form
+// Store vector reg, register offset, scale, H-form
+// Store vector reg, register offset, scale, S/D-form
+// Store vector reg, register offset, extend, B/H/S/D-form
+// Store vector reg, register offset, extend, scale, H-form
+// Store vector reg, register offset, extend, scale, S/D-form
+def : InstRW<[N3Write_2c_1L01_1V], (instregex "^STR[BHSD]ro[WX]$")>;
+
+def N3WriteSTRQro : SchedWriteVariant<[
+  SchedVar<ScaledIdxPred, [N3Write_2c_2I_1L01_1V]>,
+  SchedVar<NoSchedPred,   [N3Write_2c_1L01_1V]>]>;
+
+// Store vector reg, register offset, basic, Q-form
+// Store vector reg, register offset, scale, Q-form
+// Store vector reg, register offset, extend, Q-form
+// Store vector reg, register offset, extend, scale, Q-form
+def : InstRW<[N3WriteSTRQro], (instregex "^STRQro[WX]$")>;
+
+// Store vector pair, immed offset, S-form
+// Store vector pair, immed offset, D-form
+// Store vector pair, immed offset, Q-form
+def : InstRW<[N3Write_2c_1L01_1V], (instregex "^STN?P[SDQ]i$")>;
+
+// Store vector pair, immed post-index, S-form
+// Store vector pair, immed post-index, D-form
+// Store vector pair, immed post-index, Q-form
+// Store vector pair, immed pre-index, S-form
+// Store vector pair, immed pre-index, D-form
+// Store vector pair, immed pre-index, Q-form
+def : InstRW<[WriteAdr, N3Write_2c_1L01_1V], (instregex "^STP[SDQ](post|pre)$")>;
+
+// ASIMD integer instructions
+// -----------------------------------------------------------------------------
+
+// ASIMD absolute diff
+// ASIMD absolute diff long
+// ASIMD arith, basic
+// ASIMD arith, complex
+// ASIMD arith, pair-wise
+// ASIMD compare
+// ASIMD logical
+// ASIMD max/min, basic and pair-wise
+def : SchedAlias<WriteVd, N3Write_2c_1V>;
+def : SchedAlias<WriteVq, N3Write_2c_1V>;
+
+// ASIMD absolute diff accum
+// ASIMD absolute diff accum long
+// ASIMD pairwise add and accumulate long
+// ASIMD shift accumulate
+def : InstRW<[N3Write_4c_1V1], (instregex "^[SU]ABAL?v",
+                                          "^[SU]ADALPv",
+                                          "^[SU]R?SRAv")>;
+
+// ASIMD arith, reduce, 4H/4S
+def : InstRW<[N3Write_3c_1V1], (instregex "^[SU]?ADDL?Vv4i(16|32)v$")>;
+
+// ASIMD arith, reduce, 8B/8H
+def : InstRW<[N3Write_5c_1V1_1V], (instregex "^[SU]?ADDL?Vv8i(8|16)v$")>;
+
+// ASIMD arith, reduce, 16B
+def : InstRW<[N3Write_6c_2V1], (instregex "^[SU]?ADDL?Vv16i8v$")>;
+
+// ASIMD dot product
+// ASIMD dot product using signed and unsigned integers
+def : InstRW<[N3Write_3c_1V], (instregex "^([SU]|SU|US)DOT(lane)?(v8|v16)i8$")>;
+
+// ASIMD matrix multiply-accumulate
+def : InstRW<[N3Write_3c_1V], (instrs SMMLA, UMMLA, USMMLA)>;
+
+// ASIMD max/min, reduce, 4H/4S
+def : InstRW<[N3Write_3c_1V1], (instregex "^[SU](MAX|MIN)Vv4i(16|32)v$")>;
+
+// ASIMD max/min, reduce, 8B/8H
+def : InstRW<[N3Write_5c_1V1_1V], (instregex "^[SU](MAX|MIN)Vv8i(8|16)v$")>;
+
+// ASIMD max/min, reduce, 16B
+def : InstRW<[N3Write_6c_2V1], (instregex "[SU](MAX|MIN)Vv16i8v$")>;
+
+// ASIMD multiply
+def : InstRW<[N3Write_4c_1V0], (instregex "^MULv", "^SQ(R)?DMULHv")>;
+
+// ASIMD multiply accumulate
+def : InstRW<[N3Write_4c_1V0], (instregex "^MLAv", "^MLSv")>;
+
+// ASIMD multiply accumulate high
+def : InstRW<[N3Write_4c_1V0], (instregex "^SQRDMLAHv", "^SQRDMLSHv")>;
+
+// ASIMD multiply accumulate long
+def : InstRW<[N3Write_4c_1V0], (instregex "^[SU]MLALv", "^[SU]MLSLv")>;
+
+// ASIMD multiply accumulate saturating long
+def : InstRW<[N3Write_4c_1V0], (instregex "^SQDMLALv", "^SQDMLSLv")>;
+
+// ASIMD multiply/multiply long (8x8) polynomial, D-form
+// ASIMD multiply/multiply long (8x8) polynomial, Q-form
+def : InstRW<[N3Write_2c_1V0], (instregex "^PMULL?(v8i8|v16i8)$")>;
+
+// ASIMD multiply long
+def : InstRW<[N3Write_4c_1V0], (instregex "^[SU]MULLv", "^SQDMULLv")>;
+
+// ASIMD shift by immed, basic
+def : InstRW<[N3Write_2c_1V1], (instregex "^SHLv", "^SHLLv", "^SHRNv",
+                                          "^SSHLLv", "^SSHRv", "^USHLLv",
+                                          "^USHRv")>;
+
+// ASIMD shift by immed and insert, basic
+def : InstRW<[N3Write_2c_1V1], (instregex "^SLIv", "^SRIv")>;
+
+// ASIMD shift by immed, complex
+def : InstRW<[N3Write_4c_1V1],
+             (instregex "^RSHRNv", "^SQRSHRNv", "^SQRSHRUNv",
+                        "^(SQSHLU?|UQSHL)[bhsd]$",
+                        "^(SQSHLU?|UQSHL)(v8i8|v16i8|v4i16|v8i16|v2i32|v4i32|v2i64)_shift$",
+                        "^SQSHRNv", "^SQSHRUNv", "^SRSHRv", "^UQRSHRNv",
+                        "^UQSHRNv", "^URSHRv")>;
+
+// ASIMD shift by register, basic
+def : InstRW<[N3Write_2c_1V1], (instregex "^[SU]SHLv")>;
+
+// ASIMD shift by register, complex
+def : InstRW<[N3Write_4c_1V1],
+             (instregex "^[SU]RSHLv", "^[SU]QRSHLv",
+                        "^[SU]QSHL(v1i8|v1i16|v1i32|v1i64|v8i8|v16i8|v4i16|v8i16|v2i32|v4i32|v2i64)$")>;
+
+// ASIMD floating-point instructions
+// -----------------------------------------------------------------------------
+
+// ASIMD FP absolute value/difference
+// ASIMD FP arith, normal
+// ASIMD FP compare
+// ASIMD FP max/min, normal
+// ASIMD FP negate
+// Covered by WriteV[dq]
+
+// ASIMD FP complex add
+def : InstRW<[N3Write_3c_1V], (instregex "^FCADDv")>;
+
+// ASIMD FP complex multiply add
+def : InstRW<[N3Write_4c_1V], (instregex "^FCMLAv")>;
+
+// ASIMD FP convert, long (F16 to F32)
+def : InstRW<[N3Write_4c_2V0], (instregex "^FCVTL(v4|v8)i16")>;
+
+// ASIMD FP convert, long (F32 to F64)
+def : InstRW<[N3Write_3c_1V0], (instregex "^FCVTL(v2|v4)i32")>;
+
+// ASIMD FP convert, narrow (F32 to F16)
+def : InstRW<[N3Write_4c_2V0], (instregex "^FCVTN(v4|v8)i16")>;
+
+// ASIMD FP convert, narrow (F64 to F32)
+def : InstRW<[N3Write_3c_1V0], (instregex "^FCVTN(v2|v4)i32",
+                                          "^FCVTXN(v2|v4)f32")>;
+
+// ASIMD FP convert, other, D-form F32 and Q-form F64
+def : InstRW<[N3Write_3c_1V0], (instregex "^[FSU]CVT[AMNPZ][SU]v2f(32|64)$",
+                                          "^[SU]CVTFv2f(32|64)$")>;
+
+// ASIMD FP convert, other, D-form F16 and Q-form F32
+def : InstRW<[N3Write_4c_2V0], (instregex "^[FSU]CVT[AMNPZ][SU]v4f(16|32)$",
+                                          "^[SU]CVTFv4f(16|32)$")>;
+
+// ASIMD FP convert, other, Q-form F16
+def : InstRW<[N3Write_6c_4V0], (instregex "^[FSU]CVT[AMNPZ][SU]v8f16$",
+                                          "^[SU]CVTFv8f16$")>;
+
+// ASIMD FP divide and square root operations are now performed using
+// a fully pipelined data path.
+
+// ASIMD FP divide, D-form, F16
+def : InstRW<[N3Write_8c_4V0], (instrs FDIVv4f16)>;
+
+// ASIMD FP divide, D-form, F32
+def : InstRW<[N3Write_8c_2V0], (instrs FDIVv2f32)>;
+
+// ASIMD FP divide, Q-form, F16
+def : InstRW<[N3Write_12c_8V0], (instrs FDIVv8f16)>;
+
+// ASIMD FP divide, Q-form, F32
+def : InstRW<[N3Write_10c_4V0], (instrs FDIVv4f32)>;
+
+// ASIMD FP divide, Q-form, F64
+def : InstRW<[N3Write_13c_2V0], (instrs FDIVv2f64)>;
+
+// ASIMD FP arith, max/min, pairwise
+def : InstRW<[N3Write_3c_1V], (instregex "^FADDPv", "^FMAXPv", "^FMAXNMPv",
+                                         "^FMINPv", "^FMINNMPv")>;
+
+// ASIMD FP max/min, reduce, F32 and D-form F16
+def : InstRW<[N3Write_4c_2V], (instregex "^(FMAX|FMIN)(NM)?Vv4(i16|i32)v$")>;
+
+// ASIMD FP max/min, reduce, Q-form F16
+def : InstRW<[N3Write_6c_3V], (instregex "^(FMAX|FMIN)(NM)?Vv8i16v$")>;
+
+// ASIMD FP multiply
+def : InstRW<[N3Write_3c_1V], (instregex "^FMULv", "^FMULXv")>;
+
+// ASIMD FP multiply accumulate
+def : InstRW<[N3Write_4c_1V], (instregex "^FMLAv", "^FMLSv")>;
+
+// ASIMD FP multiply accumulate long
+def : InstRW<[N3Write_4c_1V], (instregex "^FMLALv", "^FMLSLv")>;
+
+// ASIMD FP round, D-form F32 and Q-form F64
+def : InstRW<[N3Write_3c_1V0],
+             (instregex "^FRINT[AIMNPXZ]v2f(32|64)$",
+                        "^FRINT(32|64)[XZ]v2f(32|64)$")>;
+
+// ASIMD FP round, D-form F16 and Q-form F32
+def : InstRW<[N3Write_4c_2V0],
+             (instregex "^FRINT[AIMNPXZ]v4f(16|32)$",
+                        "^FRINT(32|64)[XZ]v4f32$")>;
+
+// ASIMD FP round, Q-form F16
+def : InstRW<[N3Write_6c_4V0], (instregex "^FRINT[AIMNPXZ]v8f16$")>;
+
+// ASIMD FP square root, D-form, F16
+def : InstRW<[N3Write_8c_4V0], (instrs FSQRTv4f16)>;
+
+// ASIMD FP square root, D-form, F32
+def : InstRW<[N3Write_8c_2V0], (instrs FSQRTv2f32)>;
+
+// ASIMD FP square root, Q-form, F16
+def : InstRW<[N3Write_12c_8V0], (instrs FSQRTv8f16)>;
+
+// ASIMD FP square root, Q-form, F32
+def : InstRW<[N3Write_10c_4V0], (instrs FSQRTv4f32)>;
+
+// ASIMD FP square root, Q-form, F64
+def : InstRW<[N3Write_13c_2V0], (instrs FSQRTv2f64)>;
+
+// ASIMD BFloat16 (BF16) instructions
+// -----------------------------------------------------------------------------
+
+// ASIMD convert, F32 to BF16
+def : InstRW<[N3Write_4c_2V0], (instrs BFCVTN, BFCVTN2)>;
+
+// ASIMD dot product
+def : InstRW<[N3Write_4c_1V], (instrs BFDOTv4bf16, BFDOTv8bf16)>;
+
+// ASIMD matrix multiply accumulate
+def : InstRW<[N3Write_5c_1V], (instrs BFMMLA)>;
+
+// ASIMD multiply accumulate long
+def : InstRW<[N3Write_4c_1V], (instrs BFMLALB, BFMLALBIdx, BFMLALT, BFMLALTIdx)>;
+
+// Scalar convert, F32 to BF16
+def : InstRW<[N3Write_3c_1V0], (instrs BFCVT)>;
+
+// ASIMD miscellaneous instructions
+// -----------------------------------------------------------------------------
+
+// ASIMD bit reverse
+// ASIMD bitwise insert
+// ASIMD count
+// ASIMD duplicate, element
+// ASIMD extract
+// ASIMD extract narrow
+// ASIMD insert, element to element
+// ASIMD move, FP immed
+// ASIMD move, integer immed
+// ASIMD reverse
+// ASIMD table lookup, 1 or 2 table regs
+// ASIMD table lookup extension, 1 table reg
+// ASIMD transpose
+// ASIMD unzip/zip
+// Covered by WriteV[dq]
+
+// ASIMD duplicate, gen reg
+def : InstRW<[N3Write_3c_1M0], (instregex "^DUPv.+gpr")>;
+
+// ASIMD extract narrow, saturating
+def : InstRW<[N3Write_4c_1V1], (instregex "^[SU]QXTNv", "^SQXTUNv")>;
+
+// ASIMD reciprocal and square root estimate, D-form U32
+def : InstRW<[N3Write_3c_1V0], (instrs URECPEv2i32, URSQRTEv2i32)>;
+
+// ASIMD reciprocal and square root estimate, Q-form U32
+def : InstRW<[N3Write_4c_2V0], (instrs URECPEv4i32, URSQRTEv4i32)>;
+
+// ASIMD reciprocal and square root estimate, D-form F32 and scalar forms
+def : InstRW<[N3Write_3c_1V0], (instrs FRECPEv1f16, FRECPEv1i32,
+                                       FRECPEv1i64, FRECPEv2f32,
+                                       FRSQRTEv1f16, FRSQRTEv1i32,
+                                       FRSQRTEv1i64, FRSQRTEv2f32)>;
+
+// ASIMD reciprocal and square root estimate, D-form F16 and Q-form F32
+def : InstRW<[N3Write_4c_2V0], (instrs FRECPEv4f16, FRECPEv4f32,
+                                       FRSQRTEv4f16, FRSQRTEv4f32)>;
+
+// ASIMD reciprocal and square root estimate, Q-form F16
+def : InstRW<[N3Write_6c_4V0], (instrs FRECPEv8f16, FRSQRTEv8f16)>;
+
+// ASIMD reciprocal exponent
+def : InstRW<[N3Write_3c_1V0], (instregex "^FRECPXv")>;
+
+// ASIMD reciprocal step
+def : InstRW<[N3Write_4c_1V], (instregex "^FRECPSv", "^FRSQRTSv")>;
+
+// ASIMD table lookup, 3 table regs
+def : InstRW<[N3Write_4c_2V], (instrs TBLv8i8Three, TBLv16i8Three)>;
+
+// ASIMD table lookup, 4 table regs
+def : InstRW<[N3Write_4c_3V], (instrs TBLv8i8Four, TBLv16i8Four)>;
+
+// ASIMD table lookup extension, 2 table reg
+def : InstRW<[N3Write_4c_2V], (instrs TBXv8i8Two, TBXv16i8Two)>;
+
+// ASIMD table lookup extension, 3 table reg
+def : InstRW<[N3Write_6c_3V], (instrs TBXv8i8Three, TBXv16i8Three)>;
+
+// ASIMD table lookup extension, 4 table reg
+def : InstRW<[N3Write_6c_4V], (instrs TBXv8i8Four, TBXv16i8Four)>;
+
+// ASIMD transfer, element to gen reg
+def : InstRW<[N3Write_2c_2V], (instregex "^SMOVvi(((8|16)to(32|64))|32to64)$",
+                                         "^UMOVvi(8|16|32|64)$")>;
+
+// ASIMD transfer, gen reg to element
+def : InstRW<[N3Write_5c_1M0_1V], (instregex "^INSvi(8|16|32|64)gpr$")>;
+
+// ASIMD load instructions
+// -----------------------------------------------------------------------------
+
+// ASIMD load, 1 element, multiple, 1 reg, D-form
+def : InstRW<[N3Write_6c_1L],
+             (instregex "^LD1Onev(8b|4h|2s|1d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_1L],
+             (instregex "^LD1Onev(8b|4h|2s|1d)_POST$")>;
+
+// ASIMD load, 1 element, multiple, 1 reg, Q-form
+def : InstRW<[N3Write_6c_1L], (instregex "^LD1Onev(16b|8h|4s|2d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_1L],
+             (instregex "^LD1Onev(16b|8h|4s|2d)_POST$")>;
+
+// ASIMD load, 1 element, multiple, 2 reg, D-form
+def : InstRW<[N3Write_6c_2L], (instregex "^LD1Twov(8b|4h|2s|1d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_2L],
+             (instregex "^LD1Twov(8b|4h|2s|1d)_POST$")>;
+
+// ASIMD load, 1 element, multiple, 2 reg, Q-form
+def : InstRW<[N3Write_6c_2L], (instregex "^LD1Twov(16b|8h|4s|2d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_2L],
+             (instregex "^LD1Twov(16b|8h|4s|2d)_POST$")>;
+
+// ASIMD load, 1 element, multiple, 3 reg, D-form
+def : InstRW<[N3Write_6c_3L], (instregex "^LD1Threev(8b|4h|2s|1d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_3L],
+             (instregex "^LD1Threev(8b|4h|2s|1d)_POST$")>;
+
+// ASIMD load, 1 element, multiple, 3 reg, Q-form
+def : InstRW<[N3Write_6c_3L], (instregex "^LD1Threev(16b|8h|4s|2d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_3L],
+             (instregex "^LD1Threev(16b|8h|4s|2d)_POST$")>;
+
+// ASIMD load, 1 element, multiple, 4 reg, D-form
+def : InstRW<[N3Write_7c_4L], (instregex "^LD1Fourv(8b|4h|2s|1d)$")>;
+def : InstRW<[WriteAdr, N3Write_7c_4L],
+             (instregex "^LD1Fourv(8b|4h|2s|1d)_POST$")>;
+
+// ASIMD load, 1 element, multiple, 4 reg, Q-form
+def : InstRW<[N3Write_7c_4L], (instregex "^LD1Fourv(16b|8h|4s|2d)$")>;
+def : InstRW<[WriteAdr, N3Write_7c_4L],
+             (instregex "^LD1Fourv(16b|8h|4s|2d)_POST$")>;
+
+// ASIMD load, 1 element, one lane, B/H/S
+// ASIMD load, 1 element, one lane, D
+def : InstRW<[N3Write_8c_1L_1V], (instregex "LD1i(8|16|32|64)$")>;
+def : InstRW<[WriteAdr, N3Write_8c_1L_1V], (instregex "LD1i(8|16|32|64)_POST$")>;
+
+// ASIMD load, 1 element, all lanes, D-form, B/H/S
+// ASIMD load, 1 element, all lanes, D-form, D
+def : InstRW<[N3Write_6c_1L], (instregex "LD1Rv(8b|4h|2s|1d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_1L], (instregex "LD1Rv(8b|4h|2s|1d)_POST$")>;
+
+// ASIMD load, 1 element, all lanes, Q-form
+def : InstRW<[N3Write_6c_1L], (instregex "LD1Rv(16b|8h|4s|2d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_1L], (instregex "LD1Rv(16b|8h|4s|2d)_POST$")>;
+
+// ASIMD load, 2 element, multiple, D-form, B/H/S
+def : InstRW<[N3Write_8c_1L_1V], (instregex "LD2Twov(8b|4h|2s)$")>;
+def : InstRW<[WriteAdr, N3Write_8c_1L_1V], (instregex "LD2Twov(8b|4h|2s)_POST$")>;
+
+// ASIMD load, 2 element, multiple, Q-form, B/H/S
+// ASIMD load, 2 element, multiple, Q-form, D
+def : InstRW<[N3Write_8c_2L_1V], (instregex "LD2Twov(16b|8h|4s|2d)$")>;
+def : InstRW<[WriteAdr, N3Write_8c_2L_1V], (instregex "LD2Twov(16b|8h|4s|2d)_POST$")>;
+
+// ASIMD load, 2 element, one lane, B/H
+// ASIMD load, 2 element, one lane, S
+// ASIMD load, 2 element, one lane, D
+def : InstRW<[N3Write_8c_1L_1V], (instregex "LD2i(8|16|32|64)$")>;
+def : InstRW<[WriteAdr, N3Write_8c_1L_1V], (instregex "LD2i(8|16|32|64)_POST$")>;
+
+// ASIMD load, 2 element, all lanes, D-form, B/H/S
+// ASIMD load, 2 element, all lanes, D-form, D
+def : InstRW<[N3Write_6c_2L], (instregex "LD2Rv(8b|4h|2s|1d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_2L],  (instregex "LD2Rv(8b|4h|2s|1d)_POST$")>;
+
+// ASIMD load, 2 element, all lanes, Q-form
+def : InstRW<[N3Write_6c_2L], (instregex "LD2Rv(16b|8h|4s|2d)$")>;
+def : InstRW<[WriteAdr, N3Write_6c_2L], (instregex "LD2Rv(16b|8h|4s|2d)_POST$")>;
+
+// ASIMD load, 3 element, multiple, D-form, B/H/S
+def : InstRW<[N3Write_8c_4L_3V], (instregex "LD3Threev(8b|4h|2s)$")>;
----------------
FLZ101 wrote:

done.

N3Write_8c_3L_3V still matches the throughput.

https://github.com/llvm/llvm-project/pull/106371


More information about the llvm-commits mailing list