[llvm] [AArch64] Add C1-Nano scheduling model (PR #182316)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 7 06:55:04 PDT 2026


================
@@ -0,0 +1,1747 @@
+//==- AArch64Sched1Nano.td - ARM C1-Nano Scheduling Definitions -*- 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 machine model for the ARM C1-Nano processor.
+//
+//===----------------------------------------------------------------------===//
+
+// ===---------------------------------------------------------------------===//
+// The following definitions describe the per-operand machine model.
+// This works with MachineScheduler. See MCSchedModel.h for details.
+
+// C1-Nano machine model for scheduling and other instruction cost heuristics.
+def C1NanoModel : SchedMachineModel {
+  let MicroOpBufferSize = 0;  // The C1-Nano is an in-order processor
+  let IssueWidth = 3;         // It dual-issues under most circumstances
+  let LoadLatency = 3;        // Cycles for loads to access the cache.
+                              // 2 is best case, 4 is normal case.
+                              // 3 seems to be a good tradeoff
+  let PostRAScheduler = 1;    // Enable PostRA scheduler pass.
+  let CompleteModel = 1;      // Covers instructions applicable to C1-Nano.
+
+  list<Predicate> UnsupportedFeatures = !listconcat(SMEUnsupported.F,
+                                                    [HasSVE2p1, HasSVEB16B16,
+                                                     HasCPA, HasCSSC]);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Subtarget-specific SchedWrite types
+
+let SchedModel = C1NanoModel in {
+
+//===----------------------------------------------------------------------===//
+// Define each kind of processor resource and number available.
+
+// Modeling each pipeline as a ProcResource using the BufferSize = 0 since the
+// C1-Nano is in-order.
+let BufferSize = 0 in {
+  def C1NanoUnitALU0   : ProcResource<1>;    // Int ALU0
+  def C1NanoUnitALU1   : ProcResource<1>;    // Int ALU1
+  def C1NanoUnitMAC    : ProcResource<1>;    // Int MAC, 64-bit wide
+  def C1NanoUnitDiv    : ProcResource<1>;    // Int Division, not pipelined
+  // There are 2 LS pipes, 1 for Load/Store; 1 for Load only
+  def C1NanoUnitLdSt   : ProcResource<1>;    // Load/Store shared pipe
+  def C1NanoUnitLd1    : ProcResource<1>;    // Load pipe
+  def C1NanoUnitB      : ProcResource<1>;    // Branch
+  def C1NanoUnitPAC    : ProcResource<1>;    // Pointer Authentication (PAC) pipe
+
+  // The FP DIV/SQRT instructions execute totally differently from the FP ALU
+  // instructions, which can mostly be dual-issued; that's why for now we model
+  // them with 2 resources.
+  def C1NanoUnitVALU0  : ProcResource<1>;    // SIMD/FP/SVE ALU0
+  def C1NanoUnitVALU1  : ProcResource<1>;    // SIMD/FP/SVE ALU1
+  def C1NanoUnitVMAC0  : ProcResource<1>;    // SIMD/FP/SVE MAC0
+  def C1NanoUnitVMAC1  : ProcResource<1>;    // SIMD/FP/SVE MAC1
+  def C1NanoUnitVMC    : ProcResource<1>;    // SIMD/FP/SVE multicycle instrs  (e.g Div, SQRT, cryptography)
+}
+
+def C1NanoUnitLd     : ProcResGroup<[C1NanoUnitLdSt, C1NanoUnitLd1]>;
+def C1NanoUnitVALU   : ProcResGroup<[C1NanoUnitVALU0, C1NanoUnitVALU1]>;
+def C1NanoUnitALU    : ProcResGroup<[C1NanoUnitALU0, C1NanoUnitALU1]>;
+def C1NanoUnitVMAC   : ProcResGroup<[C1NanoUnitVMAC0, C1NanoUnitVMAC1]>;
+
+// It is difficult to correctly model the throughput when the throughput
+// is less than 2 and the pipeline used is one of the paired resources above,
+// because the throughput produced is half the expected value.
+// Currently we work around this by only using one pipeline even when the
+// Optimization Guides suggests we can use 2 pipelines at a time.
+// In order to not overwhelm a pipeline by always using the same one,
+// spread the usage be "randomly" using the _A or _B variants.
+
+def C1NanoUnitALU_A   : ProcResGroup<[C1NanoUnitALU0]>;
+def C1NanoUnitALU_B   : ProcResGroup<[C1NanoUnitALU1]>;
+def C1NanoUnitVALU_A  : ProcResGroup<[C1NanoUnitVALU0]>;
+def C1NanoUnitVALU_B  : ProcResGroup<[C1NanoUnitVALU1]>;
+def C1NanoUnitVMAC_A  : ProcResGroup<[C1NanoUnitVMAC0]>;
+def C1NanoUnitVMAC_B  : ProcResGroup<[C1NanoUnitVMAC1]>;
+def C1NanoUnitLd_A    : ProcResGroup<[C1NanoUnitLdSt]>;
+def C1NanoUnitLd_B    : ProcResGroup<[C1NanoUnitLd1]>;
+
+// These latencies are modeled without taking into account forwarding paths
+// (the software optimisation guide lists latencies taking into account
+// typical forwarding paths).
+def : WriteRes<WriteImm, [C1NanoUnitALU]> { let Latency = 1; }    // MOVN, MOVZ
+def : WriteRes<WriteI, [C1NanoUnitALU]> { let Latency = 1; }      // ALU
+def : WriteRes<WriteISReg, [C1NanoUnitALU]> { let Latency = 1; }  // ALU of Shifted-Reg
+def : WriteRes<WriteIEReg, [C1NanoUnitALU]> { let Latency = 1; }  // ALU of Extended-Reg
+def : WriteRes<WriteExtr, [C1NanoUnitALU]> { let Latency = 2; }   // EXTR from a reg pair
+def : WriteRes<WriteIS, [C1NanoUnitALU]> { let Latency = 2; }     // Shift/Scale
+
+// MAC
+def : WriteRes<WriteIM32, [C1NanoUnitMAC]> { let Latency = 3; }   // 32-bit Multiply
+def : WriteRes<WriteIM64, [C1NanoUnitMAC]> { let Latency = 4; let ReleaseAtCycles = [2];}   // 64-bit Multiply
+
+// Div
+def : WriteRes<WriteID32, [C1NanoUnitDiv]> {
+  let Latency = 12; let ReleaseAtCycles = [12];
+}
+def : WriteRes<WriteID64, [C1NanoUnitDiv]> {
+  let Latency = 20; let ReleaseAtCycles = [20];
+}
+
+//===----------------------------------------------------------------------===//
+// Define customized scheduler read/write types specific to the C1-Nano
+
+//===----------------------------------------------------------------------===//
+class C1NanoWrite<int n, ProcResourceKind res> : SchedWriteRes<[res]> {
+  let Latency = n;
+}
+
+class C1NanoMCWrite<int n, int m, ProcResourceKind res> : SchedWriteRes<[res]> {
+  let Latency = n;
+  let ReleaseAtCycles = [m];
+  let BeginGroup = 1;
+}
+
+class C1NanoMC_RC0Write<int n, ProcResourceKind res> : SchedWriteRes<[res]> {
+  let Latency = n;
+  let BeginGroup = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Define generic 2 micro-op types
+def C1NanoWrite_10cyc_1VMAC_1VALU : SchedWriteRes<[C1NanoUnitVALU, C1NanoUnitVMAC]> {
+  let Latency     = 10;
+  let NumMicroOps = 2;
+}
+
+def C1NanoWrite_10cyc_1VMAC_1VALU_A : SchedWriteRes<[C1NanoUnitVALU_A, C1NanoUnitVMAC_A]> {
+  let Latency     = 10;
+  let NumMicroOps = 2;
+}
+
+def C1NanoWrite_14cyc_1VMAC_1VALU_B : SchedWriteRes<[C1NanoUnitVALU_B, C1NanoUnitVMAC_B]> {
+  let Latency     = 14;
+  let NumMicroOps = 2;
+}
+
+class C1NanoWrite_PAC_B <int lat> : SchedWriteRes<[C1NanoUnitPAC, C1NanoUnitB]> {
+  let Latency = lat;
+  let NumMicroOps = 2;
+}
+
+// FEAT_MOPS instructions use both ALU and Load/Store pipelines.
+class C1NanoWriteMOPS<int lat, int release> : SchedWriteRes<[C1NanoUnitALU, C1NanoUnitLdSt]> {
+  let Latency = lat;
+  let ReleaseAtCycles = [release, release];
+}
+
+// Note: For some "Main" MOPS instructions, the SWOG latency depends on the runtime
+// value in Xn; we model the base latency here.
+class C1NanoWriteMOPSDynamic<int lat, int release> : SchedWriteRes<[C1NanoUnitALU, C1NanoUnitLdSt]> {
+  let Latency = lat;
+  let ReleaseAtCycles = [release, release];
+}
+
+// Load
+def : WriteRes<WriteLD, [C1NanoUnitLd]> { let Latency = 2; }
+def : WriteRes<WriteLDIdx, [C1NanoUnitLd]> { let Latency = 2; }
+def : WriteRes<WriteLDHi, [C1NanoUnitLd]> { let Latency = 2; }
+
+// Pre/Post Indexing - Performed as part of address generation
+def : WriteRes<WriteAdr, []> { let Latency = 0; }
+
+// Store
+let RetireOOO = 1 in {
+def : WriteRes<WriteST, [C1NanoUnitLdSt]> { let Latency = 1; }
+def : WriteRes<WriteSTP, [C1NanoUnitLdSt]> { let Latency = 1; }
+def : WriteRes<WriteSTIdx, [C1NanoUnitLdSt]> { let Latency = 1; }
+}
+def : WriteRes<WriteSTX, [C1NanoUnitLdSt]> { let Latency = 3; }
+
+// Vector Store - Similar to vector loads, can take 1-3 cycles to issue.
+def : WriteRes<WriteVST, [C1NanoUnitLdSt]> { let Latency = 5;
+                                          let ReleaseAtCycles = [2];}
+
+def : WriteRes<WriteAtomic, []> { let Unsupported = 1; }
+
+// Branch
+def : WriteRes<WriteBr, [C1NanoUnitB]>;
+def : WriteRes<WriteBrReg, [C1NanoUnitB]>;
+def : WriteRes<WriteSys, [C1NanoUnitB]>;
+def : WriteRes<WriteBarrier, [C1NanoUnitB]>;
+def : WriteRes<WriteHint, [C1NanoUnitB]>;
+
+// FP ALU
+//   As WriteF result is produced in F5 and it can be mostly forwarded
+//   to consumer at F1, the effectively Latency is set as 4.
+def : WriteRes<WriteF, [C1NanoUnitVALU]> { let Latency = 4; }
+def : WriteRes<WriteFCmp, [C1NanoUnitVALU_A]> { let Latency = 1; }
+def : WriteRes<WriteFCvt, [C1NanoUnitVALU]> { let Latency = 4; }
+def : WriteRes<WriteFCopy, [C1NanoUnitVALU]> { let Latency = 3; }
+def : WriteRes<WriteFImm, [C1NanoUnitVALU]> { let Latency = 3; }
+
+class C1NanoVSt<int n> : SchedWriteRes<[C1NanoUnitLdSt]> {
+  let RetireOOO = 1;
+  let ReleaseAtCycles = [n];
+}
+
+def C1NanoVSt0      : SchedWriteRes<[C1NanoUnitLdSt]> {
+  let RetireOOO = 1;
+}
+
+def : SchedAlias<WriteVd, C1NanoWrite<4, C1NanoUnitVALU>>;
+def : SchedAlias<WriteVq, C1NanoWrite<4, C1NanoUnitVALU>>;
+
+// FP VALU specific new schedwrite definitions
+def C1NanoWriteVALU_F2 : SchedWriteRes<[C1NanoUnitVALU]> { let Latency = 2;}
+def C1NanoWriteVALU_F3 : SchedWriteRes<[C1NanoUnitVALU]> { let Latency = 3;}
+def C1NanoWriteVALU_F4 : SchedWriteRes<[C1NanoUnitVALU]> { let Latency = 4;}
+def C1NanoWriteVALU0_F3 : SchedWriteRes<[C1NanoUnitVALU_A]> { let Latency = 3;}
+def C1NanoWriteVALU1_F4 : SchedWriteRes<[C1NanoUnitVALU_B]> { let Latency = 4;}
+
+// FP Mul, Div, Sqrt. Div/Sqrt are not pipelined
+def : WriteRes<WriteFMul, [C1NanoUnitVMAC]> { let Latency = 4; }
+
+let RetireOOO = 1 in {
+def : WriteRes<WriteFDiv, [C1NanoUnitVMC]> { let Latency = 22;
+                                            let ReleaseAtCycles = [29]; }
+def C1NanoWriteVMAC : SchedWriteRes<[C1NanoUnitVMAC]> { let Latency = 4; }
+def C1NanoWriteFDivHP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 8;
+                                                     let ReleaseAtCycles = [5]; }
+def C1NanoWriteFDivSP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 13;
+                                                     let ReleaseAtCycles = [10]; }
+def C1NanoWriteFDivDP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 22;
+                                                     let ReleaseAtCycles = [19]; }
+def C1NanoWriteFSqrtHP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 8;
+                                                      let ReleaseAtCycles = [5]; }
+def C1NanoWriteFSqrtSP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 12;
+                                                      let ReleaseAtCycles = [9]; }
+def C1NanoWriteFSqrtDP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 22;
+                                                      let ReleaseAtCycles = [19]; }
+def C1NanoWriteFSqrtScalarHP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 11;
+                                                      let ReleaseAtCycles = [5]; }
+def C1NanoWriteFSqrtScalarSP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 14;
+                                                      let ReleaseAtCycles = [9]; }
+def C1NanoWriteFSqrtScalarDP : SchedWriteRes<[C1NanoUnitVMC]> { let Latency = 25;
+                                                      let ReleaseAtCycles = [19]; }
+}
+//===----------------------------------------------------------------------===//
+// Subtarget-specific SchedRead types.
+
+def : ReadAdvance<ReadVLD, 0>;
+def : ReadAdvance<ReadExtrHi, 0>;
+def : ReadAdvance<ReadAdrBase, 0>;
+def : ReadAdvance<ReadST, 1>;
+
+def : ReadAdvance<ReadI, 0>;
+def : ReadAdvance<ReadISReg, 0>;
+def : ReadAdvance<ReadIEReg, 0>;
+
+
+// MUL
+def : ReadAdvance<ReadIM, 0>;
+def : ReadAdvance<ReadIMA, 2>;
+
+// Div
+def : ReadAdvance<ReadID, 0>;
+
+// Forwarded types
+def C1NanoWr_ADRP  : SchedWriteRes<[C1NanoUnitALU]> { let Latency = 1; }
+def C1NanoWr_LDR   : SchedWriteRes<[C1NanoUnitLd]> { let Latency = 2; }
+def C1NanoRd_LDR   : SchedReadAdvance<2, [C1NanoWr_ADRP, C1NanoWr_LDR]>;
+def : SchedAlias<ReadAdrBase, C1NanoRd_LDR>;
+
+//===----------------------------------------------------------------------===//
+// Subtarget-specific InstRWs.
+
+def C1NanoWriteALU0 : SchedWriteRes<[C1NanoUnitALU0]> {
+  let Latency = 1;
+}
+def C1NanoWriteALU1 : SchedWriteRes<[C1NanoUnitALU_A]> {
+  let Latency = 1;
+}
+def C1NanoWriteVALU0 : SchedWriteRes<[C1NanoUnitVALU_A]> {
+  let Latency = 1;
+}
+
+// Address generation
+def : InstRW<[C1NanoWr_ADRP], (instrs ADR, ADRP)>;
+
+// CMP/CMN are implemented via ADDS/SUBS with Rd = ZR.
+def C1NanoWriteISRegCmp : SchedWriteVariant<[
+       SchedVar<IsReg0ZeroPred, [WriteI]>,
+       SchedVar<RegShiftedPred, [WriteISReg]>,
+       SchedVar<NoSchedPred, [WriteI]>]>;
+
+// Arithmetic, basic, flagset
+def : InstRW<[C1NanoWriteALU1], (instregex "^(ADCS|SBCS)(W|X)(r|i)$")>;
+
+// Conditional compare
+def : InstRW<[C1NanoWriteALU0], (instregex "^(CCMN|CCMP)(W|X)(r|i)$")>;
+
+// Variable shift
+def : InstRW<[WriteI], (instregex "(ASR|LSL|LSR|ROR)V[WX]r")>;
+// ROR (immediate) is implemented as an EXTR (EXTR Rd, Rs, Rs, #Imm).
+// Keep EXTR's base latency, but model the ROR (immediate) as 1-cycle.
+def C1NanoWriteExtrRORImm : SchedWriteVariant<[
+       SchedVar<IsRORImmIdiomPred, [WriteI]>,
+       SchedVar<NoSchedPred, [WriteExtr]>]>;
+def : InstRW<[C1NanoWriteExtrRORImm], (instrs EXTRWrri, EXTRXrri)>;
+
+// FP conditional compare
+def : InstRW<[C1NanoMCWrite<5, 5, C1NanoUnitVALU_B>], (instregex "FCCMP")>;
+
+def C1NanoWriteISReg : SchedWriteVariant<[
+       SchedVar<RegShiftedPred, [WriteISReg]>,
+       SchedVar<NoSchedPred, [WriteI]>]>;
+def : InstRW<[C1NanoWriteISReg], (instregex ".*rs$")>;
+
+// Reverse bits
+def : InstRW<[WriteI], (instrs RBITWr, RBITXr)>;
+
+// Multiply accumulate long
+def : InstRW<[C1NanoWrite<2, C1NanoUnitMAC>], (instregex "[SU]M(ADD|SUB)L")>;
+
+// Multiply high
+def : InstRW<[C1NanoMCWrite<6, 4, C1NanoUnitMAC>], (instregex "[SU]MULHr")>;
+
+// ASIMD FP compare
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>],
+             (instregex "^(FACGE|FACGT|FCMEQ|FCMGE|FCMGT|FCMLE|FCMLT)(v|16|32|64)")>;
+
+// ASIMD reverse bits.
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "RBITv")>;
+
+// ASIMD count
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^(CLS|CLZ|CNT)v")>;
+
+// ASIMD scalar DUP (asm mnemonic is "mov", e.g. "mov b0, v0.b[1]").
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "DUPi")>;
+
+// ASIMD transfer, element to gen reg
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]MOVvi")>;
+
+// ASIMD transfer from vector element to GPR with sign-extension.
+// ASIMD move between vector elements (asm mnemonic is "mov", e.g. "mov v2.b[0], v0.b[0]").
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "INSvi(8|16|32|64)lane")>;
+
+// ASIMD transfer, gen reg to element
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "INSvi(8|16|32|64)gpr")>;
+
+// FP scalar load instructions
+// -----------------------------------------------------------------------------
+
+// Load vector reg, literal
+def : InstRW<[C1NanoWrite<3, C1NanoUnitLd>], (instrs LDRSl, LDRDl, LDRQl)>;
+
+// Load vector reg, unscaled immediate
+def : InstRW<[C1NanoWrite<3, C1NanoUnitLd>], (instregex "LDUR[BHSDQ]i")>;
+
+// Load vector register, unsigned immediate
+def : InstRW<[C1NanoWrite<3, C1NanoUnitLd>], (instregex "LDR[BHSDQ]ui")>;
+
+// Load vector register, register offset
+def : InstRW<[C1NanoWrite<3, C1NanoUnitLd>], (instregex "LDR[BHSDQ]ro[WX]")>;
+
+// Pointer Authentication Instructions (v8.3 PAC)
+// -----------------------------------------------------------------------------
+
+// Compute pointer authentication code, using generic key
+def : InstRW<[C1NanoWrite<5, C1NanoUnitPAC>], (instrs PACGA)>;
+// Authenticate data address
+// Authenticate instruction address
+// Compute pointer authentication code for data address
+// Compute pointer authentication code for instruction address
+def : InstRW<[C1NanoWrite<4, C1NanoUnitPAC>], (instregex "^AUT", "^PAC[DI]")>;
+
+// Branch and link, register, with pointer authentication
+// Branch, register, with pointer authentication
+// Branch, return, with pointer authentication
+def : InstRW<[C1NanoWrite_PAC_B<1>], (instrs BLRAA, BLRAAZ, BLRAB, BLRABZ, BRAA,
+                                            BRAAZ, BRAB, BRABZ, RETAA, RETAB,
+                                            ERETAA, ERETAB)>;
+
+// Load register, with pointer authentication
+def : InstRW<[C1NanoWrite<2, C1NanoUnitPAC>], (instregex "^LDRA[AB](indexed|writeback)")>;
+
+// Strip pointer authentication code
+def : InstRW<[C1NanoWrite<4, C1NanoUnitPAC>], (instrs XPACD, XPACI, XPACLRI)>;
+
+// Miscellaneous data-processing instructions
+// -----------------------------------------------------------------------------
+
+// Flag set instructions
+def : InstRW<[C1NanoMCWrite<2, 2, C1NanoUnitALU_A>], (instregex "^SETF(8|16)")>;
+
+// Flag manipulation instructions, rotate and select
+def : InstRW<[C1NanoMCWrite<1, 1, C1NanoUnitALU_B>], (instregex "^RMIF")>;
+
+// Load instructions
+// -----------------------------------------------------------------------------
+def C1NanoWriteVLD1 : SchedWriteRes<[C1NanoUnitLd]> { let Latency = 2; }
+def C1NanoWriteVLD1SI : SchedWriteRes<[C1NanoUnitLd]> { let Latency = 2; let SingleIssue = 1; }
+def C1NanoWriteLDP1 : SchedWriteRes<[C1NanoUnitLd]> { let Latency = 2; }
+def C1NanoWriteLDP2 : SchedWriteRes<[C1NanoUnitLd]> { let Latency = 2; }
+def C1NanoWriteLDPFP : SchedWriteRes<[C1NanoUnitLd]> { let Latency = 3; }
+
+// Integer loads, immediate and register offset.
+def : InstRW<[C1NanoWr_LDR, C1NanoRd_LDR], (instregex "^LDR[WX]ui$")>;
+def : InstRW<[C1NanoWr_LDR, C1NanoRd_LDR], (instregex "^LDR[WX]ro[WX]$")>;
+
+def : InstRW<[WriteAdr, C1NanoWrite<3, C1NanoUnitLd>], (instregex "LDR[BHSDQ](pre|post)")>;
+
+def : InstRW<[C1NanoWriteLDP1, C1NanoWriteLDP1], (instregex "LDPSWi")>;
+def : InstRW<[WriteAdr, C1NanoWriteLDP1, C1NanoWriteLDP1],
+             (instregex "LDPSW(pre|post)")>;
+
+def : InstRW<[C1NanoWriteVLD1SI, C1NanoWriteLDP1], (instregex "LDPWi")>;
+def : InstRW<[C1NanoWriteLDPFP, C1NanoWriteLDP1], (instregex "LDN?P[SDQ]i")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD1SI, C1NanoWriteLDP1], (instregex "LDPW(pre|post)")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD1, C1NanoWriteLDP2], (instregex "LDPX(i|pre|post)")>;
+def : InstRW<[WriteAdr, C1NanoWriteLDPFP, C1NanoWriteLDP1], (instregex "LDP[SDQ](pre|post)")>;
+def : InstRW<[WriteI], (instrs COPY)>;
+
+//---
+// Vector Loads - 128-bit per cycle
+//---
+//   1-element structures
+def C1NanoWriteVLD1Latency3Release1: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 3; let ReleaseAtCycles = [1]; }
+def C1NanoWriteVLD1Latency3: SchedWriteRes<[C1NanoUnitLd]> { let Latency = 3; }
+def C1NanoWriteVLD1Latency4Release2: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4; let ReleaseAtCycles = [2]; }
+def C1NanoWriteVLD1Latency5Release3: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5; let ReleaseAtCycles = [3]; }
+def C1NanoWriteVLD1Latency6Release5: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 6; let ReleaseAtCycles = [5]; }
+
+def : InstRW<[C1NanoWriteVLD1Latency3], (instregex "LD1Onev(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+def : InstRW<[C1NanoWriteVLD1Latency3Release1], (instregex "LD1Twov(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+def : InstRW<[C1NanoWriteVLD1Latency4Release2], (instregex "LD1Threev(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+def : InstRW<[C1NanoWriteVLD1Latency4Release2], (instregex "LD1Fourv(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+def : InstRW<[C1NanoWriteVLD1Latency3], (instregex "LD1i(8|16|32|64)$")>;                // single element
+def : InstRW<[C1NanoWriteVLD1Latency3], (instregex "LD1Rv(8b|4h|2s|1d|16b|8h|4s|2d)$")>; // replicate
+
+def : InstRW<[WriteAdr, C1NanoWriteVLD1Latency3], (instregex "LD1Onev(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD1Latency3Release1], (instregex "LD1Twov(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD1Latency4Release2], (instregex "LD1Threev(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD1Latency4Release2], (instregex "LD1Fourv(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD1Latency3], (instregex "LD1i(8|16|32|64)_POST$")>;                // single element
+def : InstRW<[WriteAdr, C1NanoWriteVLD1Latency3], (instregex "LD1Rv(8b|4h|2s|1d|16b|8h|4s|2d)_POST$")>; // replicate
+
+//    2-element structures
+def C1NanoWriteVLD2Latency3Release1: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 3; let ReleaseAtCycles = [1]; }
+def C1NanoWriteVLD2Latency3Release2: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 3; let ReleaseAtCycles = [2]; }
+def C1NanoWriteVLD2Latency4Release1: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4; let ReleaseAtCycles = [1]; }
+def C1NanoWriteVLD2Latency4Release2: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4; let ReleaseAtCycles = [2]; }
+def C1NanoWriteVLD2Latency4Release4: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4; let ReleaseAtCycles = [4]; }
+
+def : InstRW<[C1NanoWriteVLD2Latency4Release1], (instregex "LD2Twov(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+def : InstRW<[C1NanoWriteVLD2Latency4Release4], (instregex "LD2i(8|16|32|64)$")>;
+def : InstRW<[C1NanoWriteVLD2Latency3Release1], (instregex "LD2Rv(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+
+def : InstRW<[WriteAdr, C1NanoWriteVLD2Latency4Release1], (instregex "LD2Twov(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD2Latency4Release4], (instregex "LD2i(8|16|32|64)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD2Latency3Release1], (instregex "LD2Rv(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+
+//    3-element structures
+def C1NanoWriteVLD3Latency4Release2: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4; let ReleaseAtCycles = [2]; }
+def C1NanoWriteVLD3Latency5Release3: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5; let ReleaseAtCycles = [3]; }
+def C1NanoWriteVLD3Latency5Release5: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5; let ReleaseAtCycles = [5]; }
+
+def : InstRW<[C1NanoWriteVLD3Latency5Release3], (instregex "LD3Threev(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+def : InstRW<[C1NanoWriteVLD3Latency5Release5], (instregex "LD3i(8|16|32|64)$")>;
+def : InstRW<[C1NanoWriteVLD3Latency4Release2], (instregex "LD3Rv(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+
+def : InstRW<[WriteAdr, C1NanoWriteVLD3Latency5Release3], (instregex "LD3Threev(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD3Latency5Release5], (instregex "LD3i(8|16|32|64)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD3Latency4Release2], (instregex "LD3Rv(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+
+//    4-element structures
+def C1NanoWriteVLD4Latency4Release2: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4; let ReleaseAtCycles = [2]; }
+def C1NanoWriteVLD4Latency5Release3: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5; let ReleaseAtCycles = [3]; }
+def C1NanoWriteVLD4Latency6Release5: SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 6; let ReleaseAtCycles = [5]; }
+
+def : InstRW<[C1NanoWriteVLD4Latency5Release3], (instregex "LD4Fourv(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+def : InstRW<[C1NanoWriteVLD4Latency6Release5], (instregex "LD4i(8|16|32|64)$")>;
+def : InstRW<[C1NanoWriteVLD4Latency4Release2], (instregex "LD4Rv(8b|16b|4h|8h|2s|4s|1d|2d)$")>;
+
+def : InstRW<[WriteAdr, C1NanoWriteVLD4Latency5Release3], (instregex "LD4Fourv(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD4Latency6Release5], (instregex "LD4i(8|16|32|64)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVLD4Latency4Release2], (instregex "LD4Rv(8b|16b|4h|8h|2s|4s|1d|2d)_POST$")>;
+
+//---
+// Vector Stores
+//---
+// 1 Element structures
+def C1NanoWriteVST1Release1 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4;
+                                                  let ReleaseAtCycles  = [1]; }
+def C1NanoWriteVST1Release2 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4;
+                                                  let ReleaseAtCycles  = [2]; }
+def C1NanoWriteVST1Release3 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4;
+                                                  let ReleaseAtCycles  = [3]; }
+def C1NanoWriteVST1Release4 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 4;
+                                                  let ReleaseAtCycles  = [4]; }
+def C1NanoWriteVST2Release1 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5;
+                                                  let ReleaseAtCycles = [1]; }
+def C1NanoWriteVST2Release2 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5;
+                                                  let ReleaseAtCycles = [2]; }
+def C1NanoWriteVST3Release4 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5;
+                                                  let ReleaseAtCycles = [4]; }
+def C1NanoWriteVST3Release6 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5;
+                                                  let ReleaseAtCycles = [6]; }
+def C1NanoWriteVST4Release2 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5;
+                                                  let ReleaseAtCycles = [2]; }
+def C1NanoWriteVST4Release4 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5;
+                                                  let ReleaseAtCycles = [4]; }
+def C1NanoWriteVST4Release8 : SchedWriteRes<[C1NanoUnitLdSt]> { let Latency = 5;
+                                                  let ReleaseAtCycles = [8]; }
+
+def : InstRW<[C1NanoWriteVST1Release1], (instregex "ST1i(8|16|32|64)$")>;
+def : InstRW<[C1NanoWriteVST1Release1], (instregex "ST1Onev(8b|4h|2s|1d)$")>;
+def : InstRW<[C1NanoWriteVST1Release1], (instregex "ST1Onev(16b|8h|4s|2d)$")>;
+def : InstRW<[C1NanoWriteVST1Release1], (instregex "ST1Twov(8b|4h|2s|1d)$")>;
+def : InstRW<[C1NanoWriteVST1Release2], (instregex "ST1Twov(16b|8h|4s|2d)$")>;
+def : InstRW<[C1NanoWriteVST1Release2], (instregex "ST1Threev(8b|4h|2s|1d)$")>;
+def : InstRW<[C1NanoWriteVST1Release3], (instregex "ST1Threev(16b|8h|4s|2d)$")>;
+def : InstRW<[C1NanoWriteVST1Release2], (instregex "ST1Fourv(8b|4h|2s|1d)$")>;
+def : InstRW<[C1NanoWriteVST1Release4], (instregex "ST1Fourv(16b|8h|4s|2d)$")>;
+
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release1], (instregex "ST1i(8|16|32|64)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release1], (instregex "ST1Onev(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release1], (instregex "ST1Onev(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release1], (instregex "ST1Twov(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release2], (instregex "ST1Twov(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release2], (instregex "ST1Threev(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release3], (instregex "ST1Threev(16b|8h|4s|2d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release2], (instregex "ST1Fourv(8b|4h|2s|1d)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST1Release4], (instregex "ST1Fourv(16b|8h|4s|2d)_POST$")>;
+
+// 2 Element structures
+def : InstRW<[C1NanoWriteVST2Release2], (instregex "ST2i(8|16|32|64)$")>;
+def : InstRW<[C1NanoWriteVST2Release1], (instregex "ST2Twov(8b|4h|2s)$")>;
+def : InstRW<[C1NanoWriteVST4Release2], (instregex "ST2Twov(16b|8h|4s|2d)$")>;
+
+def : InstRW<[WriteAdr, C1NanoWriteVST2Release2], (instregex "ST2i(8|16|32|64)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST2Release1], (instregex "ST2Twov(8b|4h|2s)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST4Release2], (instregex "ST2Twov(16b|8h|4s|2d)_POST$")>;
+
+// 3 Element structures
+def : InstRW<[C1NanoWriteVST3Release4], (instregex "ST3i(8|16|32|64)$")>;
+def : InstRW<[C1NanoWriteVST3Release4], (instregex "ST3Threev(8b|4h|2s)$")>;
+def : InstRW<[C1NanoWriteVST3Release6], (instregex "ST3Threev(16b|8h|4s|2d)$")>;
+
+def : InstRW<[WriteAdr, C1NanoWriteVST3Release4], (instregex "ST3i(8|16|32|64)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST3Release4], (instregex "ST3Threev(8b|4h|2s)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST3Release6], (instregex "ST3Threev(16b|8h|4s|2d)_POST$")>;
+
+// 4 Element structures
+def : InstRW<[C1NanoWriteVST4Release8], (instregex "ST4i(8|16|32|64)$")>;
+def : InstRW<[C1NanoWriteVST4Release4], (instregex "ST4Fourv(8b|4h|2s)$")>;
+def : InstRW<[C1NanoWriteVST4Release8], (instregex "ST4Fourv(16b|8h|4s|2d)$")>;
+
+def : InstRW<[WriteAdr, C1NanoWriteVST4Release8], (instregex "ST4i(8|16|32|64)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST4Release4], (instregex "ST4Fourv(8b|4h|2s)_POST$")>;
+def : InstRW<[WriteAdr, C1NanoWriteVST4Release8], (instregex "ST4Fourv(16b|8h|4s|2d)_POST$")>;
+
+//---
+// Floating Point Conversions, MAC, DIV, SQRT
+//---
+def : InstRW<[C1NanoWriteVALU_F3], (instregex "^DUP(v2i64|v2i32|v4i32|v4i16|v8i16|v8i8|v16i8)")>;
+def : InstRW<[C1NanoWriteVALU_F4], (instregex "^XTN")>;
+
+// FP convert, from vec to gen reg
+def : InstRW<[C1NanoWriteVALU_F4], (instregex "^FCVT[ALMNPZ][SU](S|U)?(W|X)")>;
+def : InstRW<[C1NanoWriteVALU_F4], (instregex "^FCVT(X)?[ALMNPXZ](S|U|N)?v")>;
+
+// FP convert, Javascript from vec to gen reg
+def : InstRW<[C1NanoWriteVALU1_F4], (instrs FJCVTZS)>;
+
+def : InstRW<[C1NanoWriteVALU_F4], (instregex "^(S|U)CVTF(S|U)(W|X)(H|S|D)")>;
+def : InstRW<[C1NanoWriteVALU_F4], (instregex "^(S|U)CVTF(h|s|d)")>;
+def : InstRW<[C1NanoWriteVALU_F4], (instregex "^(S|U)CVTFv")>;
+
+// MOPS instructions
+// -----------------------------------------------------------------------------
+
+//Memory Copy Forward-only Prologue
+def : InstRW<[C1NanoWriteMOPS<2, 2>], (instregex "^CPYFP")>;
+
+// Memory Copy Forward-only Main
+def : InstRW<[C1NanoWriteMOPSDynamic<1, 1>], (instregex "^CPYFM")>;
+
+// Memory Copy Forward-only Epilogue
+def : InstRW<[C1NanoWriteMOPS<1, 1>], (instregex "^CPYFE")>;
+
+// Memory Copy Prologue
+def : InstRW<[C1NanoWriteMOPS<3, 3>], (instregex "^CPYP")>;
+
+// Memory Copy Main
+def : InstRW<[C1NanoWriteMOPSDynamic<1, 1>], (instregex "^CPYM")>;
+
+// Memory Copy Epilogue
+def : InstRW<[C1NanoWriteMOPS<1, 1>], (instregex "^CPYE")>;
+
+// Memory Set Prologue
+def : InstRW<[C1NanoWriteMOPS<2, 2>], (instregex "^SETP")>;
+
+// Memory Set Main
+def : InstRW<[C1NanoWriteMOPS<1, 1>], (instregex "^SETM")>;
+
+// Memory Set Epilogue
+def : InstRW<[C1NanoWriteMOPS<1, 1>], (instregex "^SETE")>;
+
+// Memory Set with tag setting Prologue
+def : InstRW<[C1NanoWriteMOPS<2, 2>], (instregex "^SETGP")>;
+
+// Memory Set with tag setting Main
+def : InstRW<[C1NanoWriteMOPS<1, 1>], (instregex "^SETGM")>;
+
+// Memory Set with tag setting Epilogue
+def : InstRW<[C1NanoWriteMOPS<1, 1>], (instregex "^MOPSSETGE")>;
+
+// ASIMD FP data processing instructions
+// -----------------------------------------------------------------------------
+
+def : InstRW<[C1NanoWriteVMAC], (instregex "^FN?M(ADD|SUB)")>;
+def : InstRW<[C1NanoWriteVMAC], (instregex "^FCADDv")>;
+def : InstRW<[C1NanoWriteVMAC], (instregex "^FCMLAv")>;
+def : InstRW<[C1NanoWriteVMAC], (instregex "^FML(A|S)v")>;
+def : InstRW<[C1NanoWriteFDivHP], (instrs FDIVHrr)>;
+def : InstRW<[C1NanoWriteFDivSP], (instrs FDIVSrr)>;
+def : InstRW<[C1NanoWriteFDivDP], (instrs FDIVDrr)>;
+def : InstRW<[C1NanoWriteVALU_F2], (instrs FMOVSr, FMOVDr)>;
+def : InstRW<[C1NanoWriteVALU_F3], (instrs FMOVv2f32_ns, FMOVv4f32_ns, FMOVv2f64_ns, FMOVv4f16_ns, FMOVv8f16_ns)>;
+def : InstRW<[C1NanoWriteFSqrtScalarHP], (instrs FSQRTHr)>;
+def : InstRW<[C1NanoWriteFSqrtScalarSP], (instrs FSQRTSr)>;
+def : InstRW<[C1NanoWriteFSqrtScalarDP], (instrs FSQRTDr)>;
+def : InstRW<[C1NanoWriteFDivHP], (instregex "^FDIVv.*16$")>;
+def : InstRW<[C1NanoWriteFDivSP], (instregex "^FDIVv.*32$")>;
+def : InstRW<[C1NanoWriteFDivDP], (instregex "^FDIVv.*64$")>;
+def : InstRW<[C1NanoWriteFSqrtHP], (instregex "^FSQRT.*16$")>;
+def : InstRW<[C1NanoWriteFSqrtSP], (instregex "^FSQRT.*32$")>;
+def : InstRW<[C1NanoWriteFSqrtDP], (instregex "^FSQRT.*64$")>;
+
+def : InstRW<[C1NanoWriteVALU0_F3], (instrs FCSELHrrr, FCSELSrrr, FCSELDrrr)>;
+
+// ASIMD FP multiply
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "FMULX?(16|32|64|v)")>;
+
+// ASIMD FP multiply accumulate long
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "FML[AS]L2?(v|lane)")>;
+
+// ASIMD miscellaneous instructions
+// -----------------------------------------------------------------------------
+
+// ASIMD reciprocal estimate
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "FRECP[EX]v", "URECPEv", "[FU]RSQRTEv")>;
+
+// ASIMD reciprocal step
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "FR(ECPS|SQRTS)(16|32|64|v)")>;
+
+// ASIMD integer instructions
+// -----------------------------------------------------------------------------
+
+// ASIMD absolute diff
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]ABDv(2i32|4i16|8i8)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]ABDv(16i8|4i32|8i16)")>;
+// ASIMD move, integer immediate
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^MOVI(v|D)")>;
+// ASIMD reverse
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^REV(16|32|64)v")>;
+// ASIMD absolute diff accum
+def : InstRW<[C1NanoMCWrite<5, 3, C1NanoUnitVALU_A>], (instregex "[SU]ABAL?v")>;
+// ASIMD absolute diff long
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]ABDLv")>;
+// ASIMD arith, basic
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "(ABS|ADD|SUB|NEG)v",
+  "[SU](HADDv|HSUBv)")>;
+// ASIMD, arith, basic, long, saturate
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex  "SADDLv", "UADDLv", "SADDWv",
+  "UADDWv", "SSUBLv", "USUBLv", "SSUBWv", "USUBWv")>;
+// ASIMD, arith, complex
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instregex  "ADDHNv", "SUBHNv")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instregex "([SU]QADD|[SU]QSUB|SQNEG|SUQADD|USQADD)v(16i8|2i64|4i32|8i16)$")>;
+// ASIMD, arith, complex, rounding, add and subtract
+def : InstRW<[C1NanoMCWrite<6, 3, C1NanoUnitVALU_B>], (instregex "RADDHNv", "RSUBHNv")>;
+// ASIMD, arith, complex, rounding halving addition
+def : InstRW<[C1NanoWrite<2, C1NanoUnitVALU>], (instregex "[SU]RHADDv")>;
+// ASIMD, arith, pair-wise
+//def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]ADDLPv", "ADDPv")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]ADDLPv", "ADDPv")>;
+// ASIMD arith, reduce
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU_A>], (instregex  "ADDVv")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU_B>], (instregex  "SADDLVv", "UADDLVv")>;
+// ASIMD compare
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "CM(EQ|GE|GT|HI|HS|LE|LT)v(1i64|2i32|4i16|8i8)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "CM(EQ|GE|GT|HI|HS|LE|LT)v(2i64|4i32|8i16|16i8)")>;
+// ASIMD compare test
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "CMTSTv(1i64|2i32|4i16|8i8)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "CMTSTv(2i64|4i32|8i16|16i8)")>;
+// ASIMD unzip/zip/transpose
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^(TRN|UZP|ZIP)[12]v")>;
+// ASIMD extract
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^EXTv")>;
+// ASIMD table lookup / table lookup extension
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instrs TBLv8i8One, TBLv16i8One)>;
+def : InstRW<[C1NanoMCWrite<5, 2, C1NanoUnitVALU_A>], (instrs TBLv8i8Two, TBLv16i8Two)>;
+def : InstRW<[C1NanoMCWrite<6, 3, C1NanoUnitVALU_B>], (instrs TBLv8i8Three, TBLv16i8Three)>;
+def : InstRW<[C1NanoMCWrite<7, 4, C1NanoUnitVALU_A>], (instrs TBLv8i8Four, TBLv16i8Four)>;
+def : InstRW<[C1NanoMCWrite<5, 2, C1NanoUnitVALU_B>], (instrs TBXv8i8One, TBXv16i8One)>;
+def : InstRW<[C1NanoMCWrite<6, 3, C1NanoUnitVALU_A>], (instrs TBXv8i8Two, TBXv16i8Two)>;
+def : InstRW<[C1NanoMCWrite<7, 4, C1NanoUnitVALU_B>], (instrs TBXv8i8Three, TBXv16i8Three)>;
+def : InstRW<[C1NanoMCWrite<8, 5, C1NanoUnitVALU_A>], (instrs TBXv8i8Four, TBXv16i8Four)>;
+// ASIMD logical
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "(AND|EOR|NOT|ORN)v8i8",
+  "(ORR|BIC)v(2i32|4i16|8i8)$", "MVNIv(2i|2s|4i16)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "(AND|EOR|NOT|ORN)v16i8",
+  "(ORR|BIC)v(16i8|4i32|8i16)$", "MVNIv(4i32|4s|8i16)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^(BIF|BIT|BSL)v")>;
+// ASIMD max/min, basic
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU](MIN|MAX)P?v(2i32|4i16|8i8)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU](MIN|MAX)P?v(16i8|4i32|8i16)")>;
+// ASIMD max/min, reduce
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU_A>], (instregex "[SU](MAX|MIN)Vv")>;
+// ASIMD FP max/min, reduce.
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU_A>], (instregex "^F(MAX|MIN)(NM)?Vv")>;
+// ASIMD multiply, by element
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "^MULv(2i32|4i16|4i32|8i16)_indexed$",
+  "SQR?DMULHv(1i16|1i32|2i32|4i16|4i32|8i16)(_indexed)?$")>;
+// ASIMD multiply
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "^MULv(2i32|4i16|4i32|8i8|8i16|16i8)$")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^PMULv(8i8|16i8)")>;
+// ASIMD multiply accumulate
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "ML[AS]v(2i32|4i16|8i8)$")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "ML[AS]v(16i8|4i32|8i16)$")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "ML[AS]v(2i32|4i16|4i32|8i16)_indexed$")>;
+// ASIMD multiply accumulate half
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "SQRDML[AS]H[vi]")>;
+// ASIMD multiply accumulate long
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "[SU]ML[AS]Lv")>;
+// ASIMD multiply accumulate long #2
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "SQDML[AS]L[iv]")>;
+// ASIMD dot product
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "(S|U|SU|US)DOTv8i8")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "(S|U|SU|US)DOTv16i8")>;
+// ASIMD dot product, by scalar
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "(S|U|SU|US)DOTlanev")>;
+// ASIMD multiply long
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "[SU]MULLv", "SQDMULL[iv]")>;
+// ASIMD polynomial (8x8) multiply long
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instrs PMULLv8i8, PMULLv16i8)>;
+// ASIMD pairwise add and accumulate
+def : InstRW<[C1NanoMCWrite<5, 3, C1NanoUnitVALU_A>], (instregex "[SU]ADALPv")>;
+// ASIMD shift accumulate
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]SRA(d|v2i32|v4i16|v8i8)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]SRAv(16i8|2i64|4i32|8i16)")>;
+// ASIMD shift accumulate #2
+def : InstRW<[C1NanoMCWrite<5, 3, C1NanoUnitVALU_B>], (instregex "[SU]RSRA[vd]")>;
+// ASIMD shift by immed
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "SHLd$", "SHLv",
+  "SLId$", "SRId$", "[SU]SHR[vd]", "SHRNv(8i8|4i16|2i32)")>;
+// ASIMD shift by immediate and insert, basic
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^SLIv.*_shift", "^SRIv.*_shift")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instregex "SHRNv(16i8|8i16|4i32)")>;
+// ASIMD shift by immed
+// SXTL and UXTL are aliases for SHLL
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[US]?SHLLv")>;
+// ASIMD shift by immed #2
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]RSHR(d|v2i32|v4i16|v8i8)",
+  "[SU]RSHRv(16i8|2i64|4i32|8i16)")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instregex "RSHRNv(2i32|4i16|8i8)",
+  "RSHRNv(16i8|4i32|8i16)")>;
+// ASIMD shift by register
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]SHLv(1i64|2i32|4i16|8i8)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]SHLv(2i64|4i32|8i16|16i8)")>;
+// ASIMD shift by register #2
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]RSHLv(1i64|2i32|4i16|8i8)")>;
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "[SU]RSHLv(2i64|4i32|8i16|16i8)")>;
+
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instregex "[SU]QSHLv(1i64|2i32|4i16|8i8)")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instregex "[SU]QSHLv(2i64|4i32|8i16|16i8)")>;
+
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instregex "[SU]QRSHLv(1i64|2i32|4i16|8i8)")>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instregex "[SU]QRSHLv(2i64|4i32|8i16|16i8)")>;
+
+// ASIMD BFloat16 (BF16) instructions
+// -----------------------------------------------------------------------------
+
+// ASIMD dot product
+def : InstRW<[C1NanoWrite_10cyc_1VMAC_1VALU], (instregex "^BFDOTv", "^BF16DOT")>;
+
+// ASIMD matrix multiply accumulate
+def : InstRW<[C1NanoWrite_14cyc_1VMAC_1VALU_B], (instregex "^BFMMLA$")>;
+
+// ASIMD multiply accumulate long
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVMAC>], (instregex "^BFMLAL[BT]$", "^BFMLAL[BT]Idx$")>;
+
+// Cryptography extensions
+// -----------------------------------------------------------------------------
+
+// Crypto AES ops
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instregex "^AES[DE]rr$", "^AESI?MCrr")>;
+
+// Crypto polynomial (64x64) multiply long
+def : InstRW<[C1NanoMCWrite<3, 2, C1NanoUnitVMC>], (instrs PMULLv1i64, PMULLv2i64)>;
+
+// Crypto SHA1 hash acceleration op
+def : InstRW<[C1NanoMCWrite<3, 1, C1NanoUnitVALU_B>], (instregex "^SHA1H")>;
+
+// Crypto SHA1 schedule acceleration ops
+def : InstRW<[C1NanoMCWrite<3, 2, C1NanoUnitVMC>], (instregex "^SHA1(SU0|SU1)")>;
+
+// Crypto SHA1 hash acceleration ops
+// Crypto SHA256 hash acceleration ops
+def : InstRW<[C1NanoMCWrite<4, 2, C1NanoUnitVMC>], (instregex "^SHA1[CMP]", "^SHA256H2?")>;
+
+// Crypto SHA256 schedule acceleration ops
+def : InstRW<[C1NanoMCWrite<4, 2, C1NanoUnitVMC>], (instregex "^SHA256SU[01]")>;
+
+// Crypto SHA512 hash acceleration ops
+def : InstRW<[C1NanoMCWrite<9, 7, C1NanoUnitVMC>], (instregex "^SHA512(H|H2|SU0|SU1)")>;
+
+// Crypto SHA3 ops
+def : InstRW<[C1NanoWrite<3, C1NanoUnitVALU>], (instrs BCAX, EOR3)>;
+def : InstRW<[C1NanoWrite<4, C1NanoUnitVALU>], (instrs XAR)>;
+def : InstRW<[C1NanoMCWrite<3, 2, C1NanoUnitVALU_A>], (instrs RAX1)>;
+
+
+// Crypto SM3 ops
+def : InstRW<[C1NanoMCWrite<9, 7, C1NanoUnitVMC>], (instregex "^SM3PARTW[12]$", "^SM3SS1$",
+                                                            "^SM3TT[12][AB]$")>;
+
+// Crypto SM4 ops
+def : InstRW<[C1NanoMCWrite<9, 7, C1NanoUnitVMC>], (instrs SM4E, SM4ENCKEY)>;
+
+// CRC
+// -----------------------------------------------------------------------------
+
+def : InstRW<[C1NanoWrite<2, C1NanoUnitMAC>], (instregex "^CRC32")>;
+
+// SVE Predicate instructions
+// -----------------------------------------------------------------------------
+
+// Note Correction to what is stated in the Arm C1-Nano Core Software Optimization
+//      Guide issue 4, section 22.4 SVE Predicate instructions:
+//      - PALU should be ALU0
+//      - VALU should be ALU0
+
+// Loop control, based on predicate
+def : InstRW<[C1NanoWrite<2, C1NanoUnitALU0>], (instrs BRKA_PPmP, BRKA_PPzP,
+                                                  BRKB_PPmP, BRKB_PPzP)>;
+
+// Loop control, based on predicate and flag setting
+def : InstRW<[C1NanoWrite<2, C1NanoUnitALU0>], (instrs BRKAS_PPzP, BRKBS_PPzP)>;
+
+// Loop control, propagating
+def : InstRW<[C1NanoWrite<2, C1NanoUnitALU0>], (instrs BRKN_PPzP, BRKPA_PPzPP, BRKPB_PPzPP)>;
+
+// Loop control, propagating and flag setting
+def : InstRW<[C1NanoWrite<2, C1NanoUnitALU0>], (instrs BRKNS_PPzP, BRKPAS_PPzPP, BRKPBS_PPzPP)>;
+
+// Loop control, based on GPR
+def : InstRW<[C1NanoWrite<2, C1NanoUnitALU0>],
+             (instregex "^WHILE(GE|GT|HI|HS|LE|LO|LS|LT)_P(WW|XX)_[BHSD]")>;
+
+def : InstRW<[C1NanoWrite<2, C1NanoUnitALU0>], (instregex "^WHILE(RW|WR)_PXX_[BHSD]")>;
+
+// Loop terminate
+def : InstRW<[C1NanoWrite<1, C1NanoUnitALU1>], (instregex "^CTERM(EQ|NE)_(WW|XX)")>;
+
+// Predicate counting scalar
+def : InstRW<[C1NanoWrite<1, C1NanoUnitALU>], (instrs ADDPL_XXI, ADDVL_XXI, RDVLI_XI)>;
+
+def : InstRW<[C1NanoWrite<1, C1NanoUnitALU0>],
+             (instregex "^CNT[BHWD]_XPiI")>;
+
+def : InstRW<[C1NanoWrite<1, C1NanoUnitALU1>],
+             (instregex "^(INC|DEC)[BHWD]_XPiI")>;
+
+def : InstRW<[C1NanoWrite<5, C1NanoUnitALU0>],
+             (instregex "^(SQINC|SQDEC|UQINC|UQDEC)[BHWD]_[XW]Pi(Wd)?I")>;
+
+// Predicate counting scalar, active predicate
+def : InstRW<[C1NanoWrite<1, C1NanoUnitALU0>],
+             (instregex "^CNTP_XPP_[BHSD]")>;
+
+def : InstRW<[C1NanoWrite<1, C1NanoUnitALU0>],
+             (instregex "^(DEC|INC)P_XP_[BHSD]")>;
+
+def : InstRW<[C1NanoWrite<2, C1NanoUnitALU0>],
+             (instregex "^(SQDEC|SQINC|UQDEC|UQINC)P_XP_[BHSD]",
+                        "^(UQDEC|UQINC)P_WP_[BHSD]")>;
+
+// Predicate counting scalar, active predicate, saturating, 32-bit.
+def : InstRW<[C1NanoWrite<1, C1NanoUnitALU0>],
+             (instregex "^(SQDEC|SQINC)P_XPWd_[BHSD]")>;
+
+// Predicate counting vector, active predicate
+def : InstRW<[C1NanoWrite<3, C1NanoUnitALU0>],
+             (instregex "^(DEC|INC)P_ZP_[HSD]")>;
----------------
walkerkd wrote:

Rejected.  The instruction is CNT and not CNTP.   CNT is already handled

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


More information about the llvm-commits mailing list