//=- X86SchedSandyBridge.td - X86 Sandy Bridge Scheduling ----*- 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 Sandy Bridge to support instruction // scheduling and other instruction cost heuristics. // // Note that we define some instructions here that are not supported by SNB, // but we still have to define them because SNB is the default subtarget for // X86. These instructions are tagged with a comment `Unsupported = 1`. // //===----------------------------------------------------------------------===// def SandyBridgeModel : SchedMachineModel { // All x86 instructions are modeled as a single micro-op, and SB can decode 4 // instructions per cycle. // FIXME: Identify instructions that aren't a single fused micro-op. let IssueWidth = 4; let MicroOpBufferSize = 168; // Based on the reorder buffer. let LoadLatency = 5; let MispredictPenalty = 16; // Based on the LSD (loop-stream detector) queue size. let LoopMicroOpBufferSize = 28; // This flag is set to allow the scheduler to assign // a default model to unrecognized opcodes. let CompleteModel = 0; } let SchedModel = SandyBridgeModel in { // Sandy Bridge can issue micro-ops to 6 different ports in one cycle. // Ports 0, 1, and 5 handle all computation. def SBPort0 : ProcResource<1>; def SBPort1 : ProcResource<1>; def SBPort5 : ProcResource<1>; // Ports 2 and 3 are identical. They handle loads and the address half of // stores. def SBPort23 : ProcResource<2>; // Port 4 gets the data half of stores. Store data can be available later than // the store address, but since we don't model the latency of stores, we can // ignore that. def SBPort4 : ProcResource<1>; // Many micro-ops are capable of issuing on multiple ports. def SBPort01 : ProcResGroup<[SBPort0, SBPort1]>; def SBPort05 : ProcResGroup<[SBPort0, SBPort5]>; def SBPort15 : ProcResGroup<[SBPort1, SBPort5]>; def SBPort015 : ProcResGroup<[SBPort0, SBPort1, SBPort5]>; // 54 Entry Unified Scheduler def SBPortAny : ProcResGroup<[SBPort0, SBPort1, SBPort23, SBPort4, SBPort5]> { let BufferSize=54; } // Integer division issued on port 0. def SBDivider : ProcResource<1>; // FP division and sqrt on port 0. def SBFPDivider : ProcResource<1>; // Integer loads are 5 cycles, so ReadAfterLd registers needn't be available until 5 // cycles after the memory operand. def : ReadAdvance; // Vector loads are 5/6/7 cycles, so ReadAfterVec*Ld registers needn't be available // until 5/6/7 cycles after the memory operand. def : ReadAdvance; def : ReadAdvance; def : ReadAdvance; def : ReadAdvance; // Many SchedWrites are defined in pairs with and without a folded load. // Instructions with folded loads are usually micro-fused, so they only appear // as two micro-ops when queued in the reservation station. // This multiclass defines the resource usage for variants with and without // folded loads. multiclass SBWriteResPair ExePorts, int Lat, list Res = [1], int UOps = 1, int LoadLat = 5> { // Register variant is using a single cycle on ExePort. def : WriteRes { let Latency = Lat; let ResourceCycles = Res; let NumMicroOps = UOps; } // Memory variant also uses a cycle on port 2/3 and adds LoadLat cycles to // the latency (default = 5). def : WriteRes { let Latency = !add(Lat, LoadLat); let ResourceCycles = !listconcat([1], Res); let NumMicroOps = !add(UOps, 1); } } // A folded store needs a cycle on port 4 for the store data, and an extra port // 2/3 cycle to recompute the address. def : WriteRes; def : WriteRes; def : WriteRes; def : WriteRes { let Latency = 5; } def : WriteRes; def : WriteRes; def : WriteRes { let Latency = 5; let NumMicroOps = 0; } // Arithmetic. defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : X86WriteRes; defm : X86WriteRes; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; def : WriteRes { let Latency = 3; } defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // SHLD/SHRD. defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Conditional move. defm : X86WriteRes; // x87 conditional move. def : WriteRes; // Setcc. def : WriteRes { let Latency = 2; let NumMicroOps = 3; } defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; //defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; // This is for simple LEAs with one or two input operands. // The complex ones can only execute on port 1, and they require two cycles on // the port to read all inputs. We don't model that. def : WriteRes; // Bit counts. defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // BMI1 BEXTR/BLS, BMI2 BZHI // NOTE: These don't exist on Sandy Bridge. Ports are guesses. defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Scalar and vector floating point. defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 // Conversion between integer and float. defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : X86WriteRes; defm : X86WriteRes; // Unsupported = 1 defm : X86WriteRes; defm : X86WriteRes; // Unsupported = 1 defm : X86WriteRes; defm : X86WriteRes; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; // Unsupported = 1 defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; // Unsupported = 1 defm : SBWriteResPair; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; // Unsupported = 1 defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; // Unsupported = 1 defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; // Unsupported = 1 // Vector integer operations. defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : X86WriteRes; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; // TODO this is probably wrong for 256/512-bit for the "generic" model defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; // Vector integer shifts. defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 // Vector insert/extract operations. def : WriteRes { let Latency = 2; let NumMicroOps = 2; } def : WriteRes { let Latency = 7; let NumMicroOps = 2; } def : WriteRes { let Latency = 3; let NumMicroOps = 2; } def : WriteRes { let Latency = 5; let NumMicroOps = 3; } //////////////////////////////////////////////////////////////////////////////// // Horizontal add/sub instructions. //////////////////////////////////////////////////////////////////////////////// defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 //////////////////////////////////////////////////////////////////////////////// // String instructions. //////////////////////////////////////////////////////////////////////////////// // Packed Compare Implicit Length Strings, Return Mask def : WriteRes { let Latency = 11; let NumMicroOps = 3; let ResourceCycles = [3]; } def : WriteRes { let Latency = 17; let NumMicroOps = 4; let ResourceCycles = [3,1]; } // Packed Compare Explicit Length Strings, Return Mask def : WriteRes { let Latency = 11; let ResourceCycles = [8]; } def : WriteRes { let Latency = 17; let ResourceCycles = [7, 1]; } // Packed Compare Implicit Length Strings, Return Index def : WriteRes { let Latency = 11; let NumMicroOps = 3; let ResourceCycles = [3]; } def : WriteRes { let Latency = 17; let NumMicroOps = 4; let ResourceCycles = [3,1]; } // Packed Compare Explicit Length Strings, Return Index def : WriteRes { let Latency = 4; let ResourceCycles = [8]; } def : WriteRes { let Latency = 10; let ResourceCycles = [7, 1]; } // MOVMSK Instructions. def : WriteRes { let Latency = 2; } def : WriteRes { let Latency = 2; } def : WriteRes { let Latency = 2; } def : WriteRes { let Latency = 1; } // AES Instructions. def : WriteRes { let Latency = 7; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def : WriteRes { let Latency = 13; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def : WriteRes { let Latency = 12; let NumMicroOps = 2; let ResourceCycles = [2]; } def : WriteRes { let Latency = 18; let NumMicroOps = 3; let ResourceCycles = [2,1]; } def : WriteRes { let Latency = 8; let ResourceCycles = [11]; } def : WriteRes { let Latency = 14; let ResourceCycles = [10, 1]; } // Carry-less multiplication instructions. def : WriteRes { let Latency = 14; let ResourceCycles = [18]; } def : WriteRes { let Latency = 20; let ResourceCycles = [17, 1]; } // Load/store MXCSR. // FIXME: This is probably wrong. Only STMXCSR should require Port4. def : WriteRes { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,1,1,1]; } def : WriteRes { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,1,1,1]; } def : WriteRes { let Latency = 100; } def : WriteRes { let Latency = 100; } def : WriteRes; def : WriteRes; // AVX2/FMA is not supported on that architecture, but we should define the basic // scheduling resources anyway. defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; defm : SBWriteResPair; // Unsupported = 1 // Remaining SNB instrs. def SBWriteResGroup1 : SchedWriteRes<[SBPort1]> { let Latency = 1; let NumMicroOps = 1; let ResourceCycles = [1]; } def: InstRW<[SBWriteResGroup1], (instrs COMP_FST0r, COM_FST0r, UCOM_FPr, UCOM_Fr)>; def SBWriteResGroup2 : SchedWriteRes<[SBPort5]> { let Latency = 1; let NumMicroOps = 1; let ResourceCycles = [1]; } def: InstRW<[SBWriteResGroup2], (instrs FDECSTP, FINCSTP, FFREE, FFREEP, FNOP, LD_Frr, ST_Frr, ST_FPrr)>; def: InstRW<[SBWriteResGroup2], (instrs LOOP, LOOPE, LOOPNE)>; // FIXME: This seems wrong compared to other Intel CPUs. def: InstRW<[SBWriteResGroup2], (instrs RETQ)>; def SBWriteResGroup4 : SchedWriteRes<[SBPort05]> { let Latency = 1; let NumMicroOps = 1; let ResourceCycles = [1]; } def: InstRW<[SBWriteResGroup4], (instrs CDQ, CQO)>; def SBWriteResGroup5 : SchedWriteRes<[SBPort15]> { let Latency = 1; let NumMicroOps = 1; let ResourceCycles = [1]; } def: InstRW<[SBWriteResGroup5], (instrs MMX_PABSBrr, MMX_PABSDrr, MMX_PABSWrr, MMX_PADDQirr, MMX_PALIGNRrri, MMX_PSIGNBrr, MMX_PSIGNDrr, MMX_PSIGNWrr)>; def SBWriteResGroup11 : SchedWriteRes<[SBPort015]> { let Latency = 2; let NumMicroOps = 2; let ResourceCycles = [2]; } def: InstRW<[SBWriteResGroup11], (instrs SCASB, SCASL, SCASQ, SCASW)>; def SBWriteResGroup12 : SchedWriteRes<[SBPort0,SBPort1]> { let Latency = 2; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup12], (instregex "(V?)(U?)COMI(SD|SS)rr")>; def SBWriteResGroup15 : SchedWriteRes<[SBPort0,SBPort015]> { let Latency = 2; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup15], (instrs CWD, FNSTSW16r)>; def SBWriteResGroup18 : SchedWriteRes<[SBPort5,SBPort015]> { let Latency = 2; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup18], (instrs JCXZ, JECXZ, JRCXZ, MMX_MOVDQ2Qrr)>; def SBWriteResGroup21 : SchedWriteRes<[SBPort1]> { let Latency = 3; let NumMicroOps = 1; let ResourceCycles = [1]; } def: InstRW<[SBWriteResGroup21], (instrs PUSHFS64)>; def SBWriteResGroup22 : SchedWriteRes<[SBPort0,SBPort5]> { let Latency = 3; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup22], (instregex "(V?)EXTRACTPSrr")>; def SBWriteResGroup23 : SchedWriteRes<[SBPort05]> { let Latency = 2; let NumMicroOps = 3; let ResourceCycles = [3]; } def: InstRW<[SBWriteResGroup23], (instregex "RCL(8|16|32|64)r1", "RCR(8|16|32|64)r1")>; def SBWriteResGroup25_1 : SchedWriteRes<[SBPort23,SBPort015]> { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,2]; } def: InstRW<[SBWriteResGroup25_1], (instrs LEAVE, LEAVE64)>; def SBWriteResGroup26_2 : SchedWriteRes<[SBPort0,SBPort1,SBPort5]> { let Latency = 3; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup26_2], (instrs COM_FIPr, COM_FIr, UCOM_FIPr, UCOM_FIr)>; def SBWriteResGroup29 : SchedWriteRes<[SBPort1,SBPort015]> { let Latency = 4; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup29], (instrs MOV64sr)>; def SBWriteResGroup29_2 : SchedWriteRes<[SBPort5,SBPort015]> { let Latency = 4; let NumMicroOps = 4; let ResourceCycles = [1,3]; } def: InstRW<[SBWriteResGroup29_2], (instrs PAUSE)>; def SBWriteResGroup31 : SchedWriteRes<[SBPort23]> { let Latency = 5; let NumMicroOps = 1; let ResourceCycles = [1]; } def: InstRW<[SBWriteResGroup31], (instregex "MOVSX(16|32|64)rm(8|16|32)", "MOVZX(16|32|64)rm(8|16)")>; def SBWriteResGroup76 : SchedWriteRes<[SBPort05]> { let Latency = 5; let NumMicroOps = 8; let ResourceCycles = [8]; } def: InstRW<[SBWriteResGroup76], (instregex "RCL(8|16|32|64)r(i|CL)", "RCR(8|16|32|64)r(i|CL)")>; def SBWriteResGroup33 : SchedWriteRes<[SBPort4,SBPort23]> { let Latency = 5; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup33], (instregex "PUSH(16r|32r|64r|64i8)")>; def SBWriteResGroup35 : SchedWriteRes<[SBPort1,SBPort5]> { let Latency = 5; let NumMicroOps = 3; let ResourceCycles = [1,2]; } def: InstRW<[SBWriteResGroup35], (instrs CLI)>; def SBWriteResGroup35_2 : SchedWriteRes<[SBPort1,SBPort4,SBPort23]> { let Latency = 5; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup35_2], (instrs PUSHGS64)>; def: InstRW<[SBWriteResGroup35_2], (instregex "ISTT_FP(16|32|64)m")>; def SBWriteResGroup36 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { let Latency = 5; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup36], (instrs CALL64pcrel32)>; def: InstRW<[SBWriteResGroup36], (instregex "CALL(16|32|64)r", "(V?)EXTRACTPSmr")>; def SBWriteResGroup40 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { let Latency = 5; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup40], (instrs STOSB, STOSL, STOSQ, STOSW)>; def SBWriteResGroup41 : SchedWriteRes<[SBPort5,SBPort015]> { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,3]; } def: InstRW<[SBWriteResGroup41], (instrs FNINIT)>; def SBWriteResGroup45 : SchedWriteRes<[SBPort0,SBPort4,SBPort23,SBPort15]> { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,1,1,1]; } def: InstRW<[SBWriteResGroup45], (instregex "(V?)PEXTR(D|Q)mr", "PUSHF(16|64)")>; def SBWriteResGroup46 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { let Latency = 5; let NumMicroOps = 4; let ResourceCycles = [1,1,1,1]; } def: InstRW<[SBWriteResGroup46], (instregex "CLFLUSH")>; def SBWriteResGroup47 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { let Latency = 5; let NumMicroOps = 5; let ResourceCycles = [1,2,1,1]; } def: InstRW<[SBWriteResGroup47], (instregex "FXRSTOR")>; def SBWriteResGroup48 : SchedWriteRes<[SBPort23]> { let Latency = 6; let NumMicroOps = 1; let ResourceCycles = [1]; } def: InstRW<[SBWriteResGroup48], (instrs MMX_MOVD64from64rm, VBROADCASTSSrm)>; def: InstRW<[SBWriteResGroup48], (instregex "POP(16|32|64)r", "(V?)MOV64toPQIrm", "(V?)MOVDDUPrm", "(V?)MOVDI2PDIrm", "(V?)MOVQI2PQIrm", "(V?)MOVSDrm", "(V?)MOVSHDUPrm", "(V?)MOVSLDUPrm", "(V?)MOVSSrm")>; def SBWriteResGroup49 : SchedWriteRes<[SBPort5,SBPort23]> { let Latency = 6; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup49], (instrs MOV16sm)>; def SBWriteResGroup51 : SchedWriteRes<[SBPort23,SBPort15]> { let Latency = 6; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup51], (instrs MMX_PABSBrm, MMX_PABSDrm, MMX_PABSWrm, MMX_PALIGNRrmi, MMX_PSIGNBrm, MMX_PSIGNDrm, MMX_PSIGNWrm)>; def SBWriteResGroup52 : SchedWriteRes<[SBPort23,SBPort015]> { let Latency = 6; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup52], (instrs LODSL, LODSQ)>; def SBWriteResGroup53 : SchedWriteRes<[SBPort4,SBPort23]> { let Latency = 6; let NumMicroOps = 3; let ResourceCycles = [1,2]; } def: InstRW<[SBWriteResGroup53], (instregex "ST_F(32|64)m", "ST_FP(32|64|80)m")>; def SBWriteResGroup54 : SchedWriteRes<[SBPort23]> { let Latency = 7; let NumMicroOps = 1; let ResourceCycles = [1]; } def: InstRW<[SBWriteResGroup54], (instrs VBROADCASTSDYrm, VBROADCASTSSYrm, VMOVDDUPYrm, VMOVSHDUPYrm, VMOVSLDUPYrm)>; def SBWriteResGroup58 : SchedWriteRes<[SBPort23,SBPort05]> { let Latency = 7; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup58], (instrs VINSERTF128rm)>; def SBWriteResGroup59 : SchedWriteRes<[SBPort23,SBPort15]> { let Latency = 7; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup59], (instrs MMX_PADDQirm)>; def SBWriteResGroup62 : SchedWriteRes<[SBPort5,SBPort23]> { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [2,1]; } def: InstRW<[SBWriteResGroup62], (instrs VERRm, VERWm)>; def SBWriteResGroup63 : SchedWriteRes<[SBPort23,SBPort015]> { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,2]; } def: InstRW<[SBWriteResGroup63], (instrs LODSB, LODSW)>; def SBWriteResGroup64 : SchedWriteRes<[SBPort5,SBPort01,SBPort23]> { let Latency = 7; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup64], (instrs FARJMP64m)>; def SBWriteResGroup66 : SchedWriteRes<[SBPort0,SBPort4,SBPort23]> { let Latency = 7; let NumMicroOps = 4; let ResourceCycles = [1,1,2]; } def: InstRW<[SBWriteResGroup66], (instrs FNSTSWm)>; def SBWriteResGroup67 : SchedWriteRes<[SBPort1,SBPort5,SBPort015]> { let Latency = 7; let NumMicroOps = 4; let ResourceCycles = [1,2,1]; } def: InstRW<[SBWriteResGroup67], (instregex "SLDT(16|32|64)r", "STR(16|32|64)r")>; def SBWriteResGroup68 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { let Latency = 7; let NumMicroOps = 4; let ResourceCycles = [1,1,2]; } def: InstRW<[SBWriteResGroup68], (instrs FNSTCW16m)>; def: InstRW<[SBWriteResGroup68], (instregex "CALL(16|32|64)m")>; def SBWriteResGroup69 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { let Latency = 7; let NumMicroOps = 4; let ResourceCycles = [1,2,1]; } def: InstRW<[SBWriteResGroup69], (instregex "SAR(8|16|32|64)m(1|i)", "SHL(8|16|32|64)m(1|i)", "SHR(8|16|32|64)m(1|i)")>; def SBWriteResGroup77 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { let Latency = 8; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup77], (instregex "(V?)(U?)COMI(SD|SS)rm")>; def SBWriteResGroup81 : SchedWriteRes<[SBPort4, SBPort23, SBPort015]> { let Latency = 6; let NumMicroOps = 3; let ResourceCycles = [1, 2, 1]; } def: InstRW<[SBWriteResGroup81], (instregex "CMPXCHG(8|16)B")>; def SBWriteResGroup83 : SchedWriteRes<[SBPort23,SBPort015]> { let Latency = 8; let NumMicroOps = 5; let ResourceCycles = [2,3]; } def: InstRW<[SBWriteResGroup83], (instrs CMPSB, CMPSL, CMPSQ, CMPSW)>; def SBWriteResGroup84 : SchedWriteRes<[SBPort4,SBPort5,SBPort23]> { let Latency = 8; let NumMicroOps = 5; let ResourceCycles = [1,2,2]; } def: InstRW<[SBWriteResGroup84], (instrs FLDCW16m)>; def SBWriteResGroup85 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { let Latency = 8; let NumMicroOps = 5; let ResourceCycles = [1,2,2]; } def: InstRW<[SBWriteResGroup85], (instregex "ROL(8|16|32|64)m(1|i)", "ROR(8|16|32|64)m(1|i)")>; def SBWriteResGroup86 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { let Latency = 8; let NumMicroOps = 5; let ResourceCycles = [1,2,2]; } def: InstRW<[SBWriteResGroup86], (instrs MOVSB, MOVSL, MOVSQ, MOVSW)>; def: InstRW<[SBWriteResGroup86], (instregex "XADD(8|16|32|64)rm")>; def SBWriteResGroup87 : SchedWriteRes<[SBPort4,SBPort5,SBPort01,SBPort23]> { let Latency = 8; let NumMicroOps = 5; let ResourceCycles = [1,1,1,2]; } def: InstRW<[SBWriteResGroup87], (instrs FARCALL64m)>; def SBWriteResGroup93 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { let Latency = 9; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup93], (instregex "CVT(T?)(SD|SS)2SI(64)?rm")>; def SBWriteResGroup95 : SchedWriteRes<[SBPort5,SBPort01,SBPort23]> { let Latency = 9; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup95], (instregex "LD_F(32|64|80)m")>; def SBWriteResGroup97 : SchedWriteRes<[SBPort1,SBPort4,SBPort23]> { let Latency = 9; let NumMicroOps = 4; let ResourceCycles = [1,1,2]; } def: InstRW<[SBWriteResGroup97], (instregex "IST_F(16|32)m", "IST_FP(16|32|64)m")>; def SBWriteResGroup97_2 : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { let Latency = 9; let NumMicroOps = 6; let ResourceCycles = [1,2,3]; } def: InstRW<[SBWriteResGroup97_2], (instregex "ROL(8|16|32|64)mCL", "ROR(8|16|32|64)mCL", "SAR(8|16|32|64)mCL", "SHL(8|16|32|64)mCL", "SHR(8|16|32|64)mCL")>; def SBWriteResGroup98 : SchedWriteRes<[SBPort4,SBPort23,SBPort015]> { let Latency = 9; let NumMicroOps = 6; let ResourceCycles = [1,2,3]; } def: SchedAlias; def SBWriteResGroup99 : SchedWriteRes<[SBPort4,SBPort23,SBPort05,SBPort015]> { let Latency = 9; let NumMicroOps = 6; let ResourceCycles = [1,2,2,1]; } def: InstRW<[SBWriteResGroup99, ReadAfterLd], (instrs ADC8mr, ADC16mr, ADC32mr, ADC64mr, SBB8mr, SBB16mr, SBB32mr, SBB64mr)>; def SBWriteResGroup100 : SchedWriteRes<[SBPort4,SBPort5,SBPort23,SBPort05,SBPort015]> { let Latency = 9; let NumMicroOps = 6; let ResourceCycles = [1,1,2,1,1]; } def : SchedAlias; // TODO - this is incorrect - no RMW def SBWriteResGroup101 : SchedWriteRes<[SBPort1,SBPort23]> { let Latency = 10; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup101], (instregex "(ADD|SUB|SUBR)_F(32|64)m", "ILD_F(16|32|64)m")>; def SBWriteResGroup104 : SchedWriteRes<[SBPort0,SBPort23]> { let Latency = 11; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup104], (instregex "(V?)PCMPGTQrm")>; def SBWriteResGroup106 : SchedWriteRes<[SBPort1,SBPort23]> { let Latency = 11; let NumMicroOps = 3; let ResourceCycles = [2,1]; } def: InstRW<[SBWriteResGroup106], (instregex "FICOM(P?)(16|32)m")>; def SBWriteResGroup108 : SchedWriteRes<[SBPort05,SBPort23]> { let Latency = 11; let NumMicroOps = 11; let ResourceCycles = [7,4]; } def: InstRW<[SBWriteResGroup108], (instregex "RCL(8|16|32|64)m", "RCR(8|16|32|64)m")>; def SBWriteResGroup111 : SchedWriteRes<[SBPort0,SBPort23]> { let Latency = 12; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup111], (instregex "MUL_F(32|64)m")>; def SBWriteResGroup114 : SchedWriteRes<[SBPort1,SBPort23]> { let Latency = 13; let NumMicroOps = 3; let ResourceCycles = [2,1]; } def: InstRW<[SBWriteResGroup114], (instregex "(ADD|SUB|SUBR)_FI(16|32)m")>; def SBWriteResGroup119 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { let Latency = 15; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup119], (instregex "MUL_FI(16|32)m")>; def SBWriteResGroup130 : SchedWriteRes<[SBPort0,SBPort23]> { let Latency = 31; let NumMicroOps = 2; let ResourceCycles = [1,1]; } def: InstRW<[SBWriteResGroup130], (instregex "DIV(R?)_F(32|64)m")>; def SBWriteResGroup131 : SchedWriteRes<[SBPort0,SBPort1,SBPort23]> { let Latency = 34; let NumMicroOps = 3; let ResourceCycles = [1,1,1]; } def: InstRW<[SBWriteResGroup131], (instregex "DIV(R?)_FI(16|32)m")>; def SBWriteResGroupVzeroall : SchedWriteRes<[SBPort5]> { let Latency = 9; let NumMicroOps = 20; let ResourceCycles = [2]; } def: InstRW<[SBWriteResGroupVzeroall], (instrs VZEROALL)>; def SBWriteResGroupVzeroupper : SchedWriteRes<[]> { let Latency = 1; let NumMicroOps = 4; let ResourceCycles = []; } def: InstRW<[SBWriteResGroupVzeroupper], (instrs VZEROUPPER)>; def: InstRW<[WriteZero], (instrs CLC)>; // Instruction variants handled by the renamer. These might not need execution // ports in certain conditions. // See Agner's Fog "The microarchitecture of Intel, AMD and VIA CPUs", // section "Sandy Bridge and Ivy Bridge Pipeline" > "Register allocation and // renaming". // These can be investigated with llvm-exegesis, e.g. // echo 'pxor %mm0, %mm0' | /tmp/llvm-exegesis -mode=uops -snippets-file=- // echo 'vxorpd %xmm0, %xmm0, %xmm1' | /tmp/llvm-exegesis -mode=uops -snippets-file=- def SBWriteZeroLatency : SchedWriteRes<[]> { let Latency = 0; } def SBWriteZeroIdiom : SchedWriteVariant<[ SchedVar, [SBWriteZeroLatency]>, SchedVar ]>; def : InstRW<[SBWriteZeroIdiom], (instrs SUB32rr, SUB64rr, XOR32rr, XOR64rr)>; def SBWriteFZeroIdiom : SchedWriteVariant<[ SchedVar, [SBWriteZeroLatency]>, SchedVar ]>; def : InstRW<[SBWriteFZeroIdiom], (instrs XORPSrr, VXORPSrr, XORPDrr, VXORPDrr)>; def SBWriteFZeroIdiomY : SchedWriteVariant<[ SchedVar, [SBWriteZeroLatency]>, SchedVar ]>; def : InstRW<[SBWriteFZeroIdiomY], (instrs VXORPSYrr, VXORPDYrr)>; def SBWriteVZeroIdiomLogicX : SchedWriteVariant<[ SchedVar, [SBWriteZeroLatency]>, SchedVar ]>; def : InstRW<[SBWriteVZeroIdiomLogicX], (instrs PXORrr, VPXORrr)>; def SBWriteVZeroIdiomALUX : SchedWriteVariant<[ SchedVar, [SBWriteZeroLatency]>, SchedVar ]>; def : InstRW<[SBWriteVZeroIdiomALUX], (instrs PSUBBrr, VPSUBBrr, PSUBDrr, VPSUBDrr, PSUBQrr, VPSUBQrr, PSUBWrr, VPSUBWrr, PCMPGTBrr, VPCMPGTBrr, PCMPGTDrr, VPCMPGTDrr, PCMPGTWrr, VPCMPGTWrr)>; def SBWritePCMPGTQ : SchedWriteRes<[SBPort0]> { let Latency = 5; let NumMicroOps = 1; let ResourceCycles = [1]; } def SBWriteVZeroIdiomPCMPGTQ : SchedWriteVariant<[ SchedVar, [SBWriteZeroLatency]>, SchedVar ]>; def : InstRW<[SBWriteVZeroIdiomPCMPGTQ], (instrs PCMPGTQrr, VPCMPGTQrr)>; // CMOVs that use both Z and C flag require an extra uop. def SBWriteCMOVA_CMOVBErr : SchedWriteRes<[SBPort05,SBPort015]> { let Latency = 3; let ResourceCycles = [2,1]; let NumMicroOps = 3; } def SBWriteCMOVA_CMOVBErm : SchedWriteRes<[SBPort23,SBPort05,SBPort015]> { let Latency = 8; let ResourceCycles = [1,2,1]; let NumMicroOps = 4; } def SBCMOVA_CMOVBErr : SchedWriteVariant<[ SchedVar, [SBWriteCMOVA_CMOVBErr]>, SchedVar ]>; def SBCMOVA_CMOVBErm : SchedWriteVariant<[ SchedVar, [SBWriteCMOVA_CMOVBErm]>, SchedVar ]>; def : InstRW<[SBCMOVA_CMOVBErr], (instrs CMOV16rr, CMOV32rr, CMOV64rr)>; def : InstRW<[SBCMOVA_CMOVBErm], (instrs CMOV16rm, CMOV32rm, CMOV64rm)>; // SETCCs that use both Z and C flag require an extra uop. def SBWriteSETA_SETBEr : SchedWriteRes<[SBPort05]> { let Latency = 2; let ResourceCycles = [2]; let NumMicroOps = 2; } def SBWriteSETA_SETBEm : SchedWriteRes<[SBPort4,SBPort23,SBPort05]> { let Latency = 3; let ResourceCycles = [1,1,2]; let NumMicroOps = 4; } def SBSETA_SETBErr : SchedWriteVariant<[ SchedVar, [SBWriteSETA_SETBEr]>, SchedVar ]>; def SBSETA_SETBErm : SchedWriteVariant<[ SchedVar, [SBWriteSETA_SETBEm]>, SchedVar ]>; def : InstRW<[SBSETA_SETBErr], (instrs SETCCr)>; def : InstRW<[SBSETA_SETBErm], (instrs SETCCm)>; } // SchedModel