Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Instruction Scheduler Overview

All addresses in this page apply to ptxas v13.0.88 (CUDA 13.0). Other versions will differ.

The ptxas instruction scheduler is a priority list scheduler with a 3-phase architecture. A single top-level orchestrator (sub_8D0640, ScheduleInstructions) drives three passes through one unified scheduling engine (sub_688DD0), each configured by a mode parameter that selects a different optimization objective: register pressure reduction, ILP/latency hiding, or dynamic batch optimization for tensor warpgroup operations. The scheduler runs twice in the ptxas pipeline -- once before register allocation on virtual registers (pre-scheduling) and once after physical register assignment (post-scheduling).

The scheduler consumes a dependency DAG built over the instruction list and produces a final instruction ordering together with SASS control words encoding stall counts, yield hints, barrier assignments, and scoreboard dependencies. The entire subsystem spans roughly 436 KB of code (0x893000--0x8FE000) with an additional 250 KB of supporting infrastructure in the 0x67F000--0x6A0000 range.

Orchestratorsub_8D0640 (22 KB) -- ScheduleInstructions
Unified enginesub_688DD0 (20 KB) -- mode-parameterized scheduling loop
Priority functionsub_8C9320 (47 KB) -- multi-criteria heuristic
Ready list buildersub_6820B0 (1.5 KB) -- zero-predecessor scan
Dependency graphsub_8CF880 (28 KB) + sub_8D9930 (19 KB)
Register budgetsub_8CEE80 (8.7 KB) -- occupancy-aware computation
HW latency profilessub_8E7300--sub_8E9DC0 -- per-SM tables
Opcode tablesub_896D50 (90 KB) -- ROT13-encoded SASS mnemonics
Scheduling arenasub_8E3970 / sub_8E3A80 -- bump allocator
Key knobs76 Sched* knobs; see Configuration
Enable gate"ScheduleInstructions" named option at (a1+8)+1664

3-Phase Pipeline

The orchestrator sub_8D0640 executes the following sequence. All three scheduling phases invoke the same unified engine sub_688DD0 -- the only difference is the mode byte passed as the second argument.

function ScheduleInstructions(sched):
    // 1. Build dependency graph
    BuildDependencyGraph(sched, func)         // sub_8CF880
    vtable[29](sched)                         // InitScheduleData
    PreScheduleSetup(sched, opt_level > 2)    // sub_8CBAD0

    // 2. Gate check
    if not KnobGetBool("ScheduleInstructions"):
        return

    // 3. Set mode flags from knobs 419 (LivenessCountRegComp), 420 (LivenessUseHiLo)
    sched.flags |= (knob_419 << 3) | (knob_420 << 4)

    // 4. Optionally create register pressure tracker
    if sched.flags & 0x10:
        sched.scoreboard = alloc(952)         // sub_69A1A0
        sched.tracker    = alloc(208)         // sub_6B8F70
        if sched.flags & 0x100:
            sched.warp_analysis = alloc(856)  // sub_6BB7C0

    // 5. Reset per-instruction SchedNode fields between passes
    //    (iterates func+104 metadata chain, NOT instruction list)
    for sched_node in func.sched_node_list:       // linked via func+104
        sched_node.depChainHead  = 0              // QWORD +56
        sched_node.extendedState = 0              // QWORD +104
        sched_node.schedulingCost  = 0            // DWORD +76
        sched_node.schedulingClass = -1           // DWORD +84, sentinel

    // 6. Phase 1 — ReduceReg
    if KnobGetBool("ScheduleInstructionsReduceReg"):
        ScheduleEngine(sched, mode=0x39, ...)   // sub_688DD0

    // 7. Phase 2 — Reverse scheduling (ILP / latency)
    ReverseSchedule(sched)                      // sub_8CD6E0
    ComputeRegisterBudget(sched)                // sub_8CEE80

    // 8. Phase 3 — DynBatch
    if KnobGetBool("ScheduleInstructionsDynBatch"):
        AllocDynBatchData(sched)                // sub_8BF890
        ScheduleEngine(sched, mode=0x41, ...)   // sub_688DD0

    // 9. Cleanup
    FreeBitvector(sched.bv)                     // sub_BDC050
    ArenaFreeAll(sched.arena)                   // sub_8E3A80

Phase 1 -- ReduceReg (mode 1, callback 0x39)

Goal: minimize register pressure so the register allocator has headroom. This phase reorders instructions to reduce the maximum number of simultaneously-live virtual registers.

  • Enabled by the named option "ScheduleInstructionsReduceReg" (default: on at -O3).
  • Register targets set from knobs 776 (SchedReduceIncLimit) and 778 (SchedReduceIncLimitHigh) (defaults approximately 250 and 300).
  • The mode byte 0x39 selects the register-pressure-minimizing priority weights inside the unified engine.
  • The engine's inner dispatch reads *(DWORD*)(scheduler+60) == 1 to enter the ReduceReg path.

Phase 2 -- ILP / Latency Hiding (mode 0, callback 0x49)

Goal: maximize instruction-level parallelism and hide memory latencies by interleaving independent operations.

  • Always runs (no separate enable gate).
  • Uses reverse post-order BB iteration via sub_8CD6E0: iterates basic blocks from last to first after resetting liveness with sub_781F80(func, 0).
  • Computes a register budget capped at min(archLimit, 0.95 * maxRegs) via sub_8CEE80.
  • The mode byte 0x49 selects latency-oriented priority weights.
  • After this phase, sub_8CF5D0 evaluates dual-issue eligibility and produces a dual-issue benefit score stored at scheduler+328.

Phase 3 -- DynBatch (mode 2, callback 0x41)

Goal: batch-aware scheduling for GMMA/WGMMA warpgroup tensor operations. Groups tensor instructions into batches that can execute as warpgroup-cooperative operations with minimal pipeline stalls.

  • Enabled by the named option "ScheduleInstructionsDynBatch" and only activates when the function has varying instruction counts across BBs.
  • Controlled by knob 742 (SchedCrossBlock, cross-block scheduling mode).
  • Reads stall/batch depth limits from knobs 805 (SchedTexBatchTargetSelectRegisterTarget), 741 (SchedCountLoadsPerTex), 761 (SchedMaxRLiveOKslack), 762 (SchedMaxRLiveOKslackColdBlocks).
  • Allocates a 184-byte DynBatch context (sub_8BF890) with an 8 * numBBs sub-array for per-BB batch tracking.
  • Context initialization (sub_8C1BA0): sets batch window to 0xFFFFFFFF (sentinel), copies register liveness from func+832.
  • The mode byte 0x41 selects batch-aware priority weights.

DynBatch Context Object (184 bytes)

sub_8BF890 allocates a 184-byte DynBatch context from the scheduling arena at sched+840 and stores the pointer at sched+272. The object is a flat structure containing a function context reference, a 20-slot working array, and a pointer to a variable-length per-BB sub-array.

OffsetSizeTypeInitNamePurpose
+08ptrfuncCtxfuncContextPointer to CompilationContext (copied from sched+8)
+8160QWORD[20]0batchWorkArrayFixed-size working array for batch state tracking; likely holds instruction pointers or batch boundary markers during scheduling
+1688ptralloc'dperBBArrayPer-BB batch tracking sub-array; 8 * numBBs bytes, zero-initialized. Each 8-byte entry holds a batch start/end instruction pointer for one basic block
+1764DWORD0flagsStatus/control flags
+1804----(padding)Pad to 184-byte allocation

The per-BB sub-array size is derived from *(sched+392) (maxBBSizeForAlloc), with an overflow check capping the multiplication at 0xFFFFFFFFFFFFFFF (2^60 - 1) entries.

DynBatch Working State (in scheduler context)

The bulk of the DynBatch working state lives directly in the scheduler context, initialized by sub_8C1BA0 (InitDynBatchState). These fields are used by the priority function during Phase 3 scheduling.

OffsetSizeTypeInitNamePurpose
+4644int320batchSlotCountNumber of instructions accumulated in the current batch
+4684int32--prevBatchSizeSize of previously-completed batch
+4764int32adjadjustedBatchTargetAdjusted batch depth target; capped to min(maxStallCycles, batchTargetCount), halved when 2 * maxStall > target
+4804int32--lastBatchEndPosScheduling position of the last instruction in the current batch
+4888QWORD0xFFFFFFFFbatchWindowBatch window start BB offset; sentinel 0xFFFFFFFF means "no batch active"
+4924int320regDeltaRegister pressure delta accumulator across batch boundaries
+4964int320maxRegInBatchMaximum register pressure observed within current batch
+5004int32from +72regBaseCountBase register count; copied from sched+72, reset on batch boundary
+5048QWORD0maxRegSpanMaximum register span (pressure peak minus baseline) across all batches
+5084int320regBaselineRegister count baseline for delta computation
+5124int320minOverflowCostMinimum overflow cost; updated when batch exceeds register budget
+5164int32-1batchDepthLimitPer-batch maximum depth; -1 = unlimited (overwritten from BB analysis)
+5201byte0batchOverflowSet to 1 when batch exceeds register budget + base count
+5211byte0batchAbortSet to 1 when opcode 96 (WGMMA commit) detected with sched+524 flag
+536+varptr[]--batchSlotsArray of instruction pointers in the current batch; sched+536 + 8*i for slot i

The batch target adjustment algorithm in sub_8C1BA0:

adjustedTarget = maxStallCycles           // from sched+404
if maxStallCycles > batchTargetCount:
    adjustedTarget = batchTargetCount     // cap to target
if batchTargetCount > maxStallCycles:
    if batchMode == 0 and maxStallCycles < batchTargetCount:
        if batchTargetCount >= 2 * maxStallCycles:
            adjustedTarget = batchTargetCount / ceil(batchTargetCount / maxStallCycles)
        else:
            adjustedTarget = batchTargetCount / 2

When a batch boundary is detected (instruction's BB start offset exceeds the batch window), sub_8C1BA0 evaluates the batch: it computes the register pressure delta, checks whether the batch overflows the combined register budget (regBaseCount + regDelta + maxRegSpan), and either accepts the batch or trims it by walking backward through the batchSlots array to find a smaller valid batch.

Unified Scheduling Engine

sub_688DD0 (20 KB) is the single engine that all three phases invoke. Its behavior is parameterized by:

  1. Mode byte (argument a2): 0x39 = ReduceReg, 0x49 = ILP/Latency, 0x41 = DynBatch.
  2. Rebuild flag (argument a4): when true, reconstructs the dependency DAG via sub_6833F0.
  3. Vtable dispatch: uses *(a1+40) and *(a1+48) for polymorphic pre/post scheduling hooks.
function ScheduleEngine(sched, mode, arg3, rebuild):
    if rebuild:
        InitScheduleRegion(sched)               // sub_6833F0
        // allocates 72-byte per-BB records, queries knobs 595 (PreserveSchedOrderSame), 743 (SchedCrossBlockInstsToSpeculate), 747 (SchedCrossBlockTexToSpeculate)

    for each bb in sched.basic_blocks:
        // 10 register pressure counters from per-BB record +4..+40 into context +48..+87
        InitResourceTracking(sched, bb)          // sub_A091C0
        ReadyList = BuildReadyList(sched)        // sub_6820B0

        while ReadyList is not empty:
            best = SelectBestInstruction(sched)  // via priority vtable
            ScheduleInstruction(sched, best)     // sub_682200
            UpdateResourceState(sched, best)     // sub_A09530
            UpdateWARTracking(sched, best)       // sub_A09D40
            RelinkInstruction(best)              // sub_925510

            // Update dependency counts, add newly-ready instructions
            for each successor of best:
                successor.dep_count -= 1
                if successor.dep_count == 0:
                    ReadyList.insert(successor)

The engine manages 10 register pressure counters at scheduler context offsets 48--87 (copied from the per-block record offsets +4--+40 at BB entry). These correspond to the GPU register classes: R (general), P (predicate), UR (uniform), UP (uniform predicate), B (barrier), and 5 architecture-specific classes. Counter [0] (R class) uses a separate update path; counters [1]--[9] are decremented from a per-opcode resource cost table during the scheduling loop.

Ready List Construction

sub_6820B0 (1.5 KB) builds the initial ready list by scanning the instruction linked list for nodes with zero unsatisfied dependencies.

function BuildReadyList(sched):
    for instr in sched.instruction_list:
        if instr.opcode == 52:         // NOP/BB boundary
            continue                    // follow through to real instruction
        if instr.dep_count == 0:
            instr.next_ready = sched.ready_head
            sched.ready_head = instr
            vtable_call(sched, 104, instr)  // ready-list insertion callback
            instr.latency_counter = 0

The ready list is maintained as a sorted linked list (via pointer at instruction offset +16). The priority function determines sort order.

Priority Function

sub_8C9320 (47 KB decompiled, ~1300 lines) is the heart of instruction selection. It computes a scheduling priority score as an 8-bit packed encoding combining multiple heuristic factors. The function uses approximately 200 local variables and a 0x330-byte stack frame.

Priority Factors

FactorSourceWeight adjustment
Register pressureCurrent live count vs budget at sched+432Primary factor in ReduceReg mode
Instruction latencysub_693BC0 latency queryPrimary factor in ILP mode
Critical path positionDAG depth from sched+464, sched+380Favors critical-path instructions
FU contention10-element resource vector via sub_8C7290Avoids saturating a single pipe
Hot/cold memorysub_A9CDE0 (hot=global) / sub_A9CF90 (cold=const)Prioritizes latency-sensitive ops
Anti-dependencyWAR hazard costBreaks ties with anti-dep distance
Barrier dependenciesBarrier flag at instr+376Defers barrier-blocked instructions
Priority queue depthKnob 770 (default 4)Limits lookahead window

Priority Encoding

The priority value is packed into an integer with 8-bit fields. Each field is computed from the corresponding factor and shifted into position. The packed encoding allows the ready list to maintain sort order with a single integer comparison, avoiding multi-key sorting overhead.

Key subroutines called during priority computation:

AddressPurpose
sub_8C67A0Compute resource cost for instruction and update BB resource table
sub_8C7120Barrier tracking update
sub_8C7290Copy 10-element resource vector from per-BB slot (SSE-optimized)
sub_8C7720Instruction reordering within BB (red-black tree operations)
sub_693BC0Memory space classification / latency query
sub_6818D0Register count to hardware-aligned unit conversion

Resource Tracking

The scheduler tracks 10 functional unit resource counters per basic block. Each counter corresponds to a hardware execution pipe.

Resource Vector Layout

Each per-BB resource slot occupies 84 bytes (21 DWORDs) stored at *(scheduler+672) + 84 * slot_index:

Offset (within slot)SizeContent
0--3610 x int32Current resource usage per FU
40--7610 x int32Resource pressure delta
80int32BB-entered flag and auxiliary bits

The 10 functional unit pipes (inferred from resource model queries):

IndexPipeTypical instructions
0Integer ALUIADD, IMAD, ISETP, LOP, SHF
1FP32FADD, FFMA, FMUL, FSETP
2FP64DADD, DFMA, DMUL
3Tensor coreHMMA, IMMA, BMMA, BGMMA
4Load/storeLD, ST, LDG, STG, LDS, STS
5TextureTEX, TLD, TXQ
6Branch/controlBRA, JMP, EXIT, RET, BAR
7Shared memoryATOMS, REDS, LDS, STS
8Special functionMUFU (RCP, RSQ, SIN, COS, EX2, LG2)
9Uniform/predicateUPLOP, UISETP, uniform operations

sub_8C67A0 computes per-instruction resource costs by calling the resource model (sub_A08A00) three times:

  • Mode 1: the instruction's own execution cost
  • Mode 2: operand release costs for last-use operands
  • Mode 3: combined instruction + BB-level impact

SSE intrinsics (_mm_add_epi32) are used for vector accumulation.

Register Budget

sub_8CEE80 (8.7 KB) computes the occupancy-aware register budget that the scheduler respects during instruction ordering.

function ComputeRegisterBudget(sched):
    hw = sched.func.sm_backend          // at func+1584 (provides hw latency profiles)
    maxRegs = hw[154]                   // architecture register limit

    coeff = KnobGetDouble(740)          // default 0.045
    if KnobGetBool(763):                // budget disabled
        budget = hw[157]                // use fixed count from profile
    else:
        physRegs = VirtToPhys(sched, maxRegs)   // sub_A99FE0
        budget = physRegs - (physRegs >> 6)     // 98.4% utilization

    // For sm_50: apply special dual-issue budget
    if arch_id == 5:
        budget = DualIssueBudget(budget)

    pressureCurve = ComputePressureCurve(sched, budget - 2)  // sub_8CE520
    // Piecewise linear model with parameters (4, 2, 6)

    sched.regBudget         = budget     // offset +432
    sched.committedTarget   = ...        // offset +324
    sched.minRegs           = ...        // offset +316
    sched.pressureSlack     = ...        // offset +320

The register pressure curve (sub_8CE520) uses a piecewise linear model parameterized by (4, 2, 6) or a custom string-encoded function from knob 750 (SchedEstimatedLoopIterations).

Dependency Graph

The dependency DAG is built in two stages:

Stage 1: Pre-scheduling scan (sub_8CF880, 28 KB)

Iterates basic blocks in reverse order. For each BB:

  • Checks knobs 314 (FenceInterference) / 313 (FenceCode) for per-instruction scheduling fence conditions
  • Walks the instruction linked list, identifying NOP/control instructions
  • Builds dependency edges via sub_8D9930
  • Manages memory arenas with SSE-optimized copies for instruction metadata arrays

Stage 2: Edge construction (sub_8D9930, 19 KB)

For each pair of instructions in a BB, checks for:

  • RAW (true) dependencies: read-after-write on the same register
  • WAR (anti) dependencies: write-after-read
  • WAW (output) dependencies: write-after-write
  • Memory dependencies: through shared/global memory (conservative ordering)
  • Barrier dependencies: through barrier/sync instructions

Uses operand analysis from sub_894290 (27 KB) which processes 16-bit operand descriptors encoding register class, bank, and dependency type.

Supplementary dependency builders

AddressSizePurpose
sub_68A69031 KBBuildDependencies -- def-use chain construction
sub_6A97B026 KBAddDependencyEdges -- register-level edges
sub_6A2D3011 KBChainDependencies -- memory ordering constraints
sub_6A78F023 KBProcessOperands -- operand dependency extraction

Pre-Scheduling Setup

sub_8CBAD0 (2.9 KB) performs BB scanning and resource allocation before the scheduling passes begin.

Key behaviors:

  • Counts instructions per basic block. If any BB exceeds 4095 instructions, it inserts a scheduling barrier (sub_931920) to split the block.
  • Tracks maximum BB size at scheduler+388.
  • Detects opcode 246 (texture operations) and sets scheduler+384 = 1.
  • Allocates per-slot arrays:
    • scheduler+672: 84-byte scheduling slots (resource tracking)
    • scheduler+280: 48-byte analysis slots (if opt_level > 2)
    • scheduler+248, scheduler+256: register pressure bitvectors sized to (numRegs+1) or (2*numRegs+2) if knob 420 (LivenessUseHiLo, dual-register tracking) is active

Pre-Scheduling vs Post-Scheduling

The scheduler runs at two distinct points in the ptxas pipeline:

AspectPre-schedulingPost-scheduling
TimingBefore physical register allocationAfter physical register allocation
Register modelVirtual registersPhysical registers
Primary goalReduce register pressure, order for regallocHide latencies, minimize stalls
Phases activeAll 3 (ReduceReg, ILP, DynBatch)Refinement pass
Budget sourceOccupancy model estimateActual allocation result
Entrysub_8D0640sub_7F5D50 / sub_A97600 (42 KB)

Post-scheduling uses the actual physical register assignments for precise dependency distances and can make final decisions about stall insertion and scoreboard barrier placement.

Scheduling Variants

The region 0x89C550--0x8BE320 contains 17+ specialized scheduling strategies, each implementing a different approach or targeting a different code pattern:

AddressSizeStrategyNotes
sub_8B939023 KBSoftware pipeliningLoop body overlapping
sub_8B77C015 KBDual-issue schedulingPair co-issuable instructions
sub_8BDC407.9 KBDual-issue pairingInstruction pair selection
sub_8B890012 KBTensor schedulingHMMA/BMMA grouping
sub_8BAAE015 KBLoop-aware schedulingTrip count + register awareness
sub_8B6D6012 KBPressure-optimizedMinimize live range overlap
sub_8B540014 KBLatency-optimizedMaximize memory latency hiding
sub_8B119016 KBBacktracking schedulerUndo and retry on conflict
sub_8B2D9018 KBGlobal schedule optimizationCross-BB considerations
sub_8B459013 KBPermutation searchTry schedule permutations
sub_8A9D8021 KBDepth-first schedulingDFS-based instruction ordering
sub_8AB7509.8 KBCritical path computationDAG analysis for priorities
sub_8BB9C08.2 KBPrefetch schedulingMemory prefetch insertion
sub_8BC0B06.1 KBBarrier coalescenceMerge adjacent barriers
sub_8BC9907.6 KBScoreboard optimizationMinimize scoreboard usage
sub_8BCFA06.8 KBWarp schedule optimizationWarp-level yield tuning
sub_8BE32025 KBComplex scheduling passMulti-strategy combined pass

These variants are selected based on code characteristics (loop structure, tensor operations, function size) and optimization level.

Hardware Latency Profiles

Per-architecture latency and throughput tables are constructed by a family of functions at 0x8E7300--0x8E9DC0. Each table specifies pipeline latencies (integer, FP32, FP64, tensor, memory), scoreboard wait counts, barrier stall cycles, and dual-issue pair compatibility for the target GPU.

AddressArchitectureSize
sub_8E7300sm_70 (Volta)3.3 KB
sub_8E7540sm_722.9 KB
sub_8E7720sm_75 (Turing)3.5 KB
sub_8E7940sm_80 base2.9 KB
sub_8E7B40sm_80 (Ampere)3.3 KB
sub_8E7D80sm_864.4 KB
sub_8E8070sm_873.5 KB
sub_8E8280sm_89 (Ada Lovelace)3.1 KB
sub_8E8480sm_90 (Hopper)5.2 KB
sub_8E8780sm_90a4.6 KB
sub_8E8A90sm_100 (Blackwell DC)3.0 KB
sub_8E8DB0sm_103 (Blackwell Ultra)1.7 KB
sub_8E9000sm_120 (RTX 50xx)2.9 KB
sub_8E92E0sm_120 extended5.5 KB
sub_8E97B0Universal fallback8.8 KB

The warp-level hardware profile (sub_8E4400) maps architecture IDs to dispatch parameters:

Architecture rangeWarpsDispatch slotsEra
<= 20479496sm_50 (Maxwell)
<= 245756176sm_60 (Pascal)
<= 286727192sm_70 (Volta)
<= 327677208sm_75 (Turing)
<= 368638224sm_80 (Ampere)
> 3686316240sm_90+ (Hopper, Blackwell)

Sub-architecture variants (stored at profile offset +26) are assigned by specific SM version codes: 8193, 20481, 24576, 28674--28677, 32768, 36864--36869.

See Latency Model for per-opcode latency tables and functional unit mapping.

Scheduling Knobs

The scheduler reads approximately 76 knobs. The most significant ones (names decoded from ROT13 in the binary):

Knob IDNameTypeDefaultPurpose
313FenceCodewhen-list--Skip scheduling for specific opcodes (per-instruction WHEN condition)
314FenceInterferencewhen-list--Mark interference fences for specific opcodes
419LivenessCountRegCompint32--Forward scheduling mode flag (bit 3 in sched+1376)
420LivenessUseHiLoint32--Dual-register hi/lo tracking (bit 4 in sched+1376)
487--booltrueMaster scheduling/peephole enable
510OptimizeUniformAtomicModeint32--BB pre-optimization mode for uniform atomics
595PreserveSchedOrderSamewhen-list--Preserve scheduling order (per-instruction WHEN condition)
740SchedBumpScaleAugmentFactordouble0.045Register pressure bump scale augmentation coefficient
741SchedCountLoadsPerTexint323Load count per texture operation (stall threshold)
742SchedCrossBlockint32--Cross-block scheduling mode
743SchedCrossBlockInstsToSpeculateint32--Cross-block instruction speculation count
747SchedCrossBlockTexToSpeculateint32--Cross-block texture speculation count
750SchedEstimatedLoopIterationsstring--Estimated loop iteration count override
760SchedMaxRLiveCarefulSlackint32--Reserved register headroom (careful slack for live registers)
761SchedMaxRLiveOKslackint32--Acceptable live-register slack (batch depth on non-sm_50)
762SchedMaxRLiveOKslackColdBlocksint32--Extra register slack for cold basic blocks
763SchedMaxRTargetint32--Maximum register target; 0 disables register budget
769SchedPrefFurthestDepwhen-list--Per-BB scheduling query: prefer furthest dependency
770SchedReadAvailTargetint324Priority queue depth (read-availability lookahead window)
776SchedReduceIncLimitint32~250Forward pass primary register increment limit
778SchedReduceIncLimitHighint32~300Forward pass secondary (high) register increment limit
805SchedTexBatchTargetSelectRegisterTargetint32--Texture batch register target stall limit (capped at 16)
806SchedTexBatchTargetSelectSchedulerTargetint32--Texture batch scheduler target stall limit (capped at 16)

Knob names are stored ROT13-encoded in the binary (see Knobs System for the obfuscation scheme). Types when-list indicate knobs that support per-instruction or per-BB conditional overrides via WHEN= syntax.

The full scheduling context configuration is performed by sub_A95DC0 (35 KB), which reads dozens of knob values and populates the scheduling context structure.

Data Flow Analysis

The scheduler includes a dedicated data flow analysis subsystem (0x8DBAF0--0x8DF1C0) that computes register liveness and propagates def-use information across BB boundaries:

AddressSizePurpose
sub_8DB0708.2 KBInitialize liveness data structures
sub_8DB5F08.4 KBCompute per-BB liveness
sub_8DBAF016 KBFull liveness analysis
sub_8DC3F03.0 KBCompute data flow state
sub_8DC6203.3 KBUpdate data flow on schedule
sub_8DC88010 KBPropagate data flow information
sub_8DCF2023 KBBuild data flow graph for scheduling
sub_8DE7A012 KBIterative data flow solver (fixed-point)
sub_8DEF902.0 KBFinalize data flow

The iterative solver runs until convergence, updating per-BB liveness sets. This information feeds into the priority function's register pressure estimates and into the register budget computation.

Scheduling Output

After instruction ordering is determined, the scheduling output pipeline (0x8F1EB0--0x8FDD60, ~57 KB) converts the abstract schedule into SASS control words:

function EmitScheduleForBB(sched, bb):
    for each instruction in scheduled order:
        stall   = ComputeStallCycles(sched, instr)   // distance to consumer
        yield   = ComputeYieldHint(sched, instr)      // warp scheduling hint
        barrier = AssignBarrier(sched, instr)          // 6 barriers available
        sb_deps = ComputeScoreboardDeps(sched, instr)  // read/write dependencies

        control_word = EncodeControlWord(stall, yield, barrier, sb_deps)
        EmitControlWord(instr, control_word)

Key encoding functions:

AddressPurpose
sub_8F1EB0Main schedule encoding entry
sub_8F3130Encode stall count field
sub_8F31F0Encode barrier field
sub_8F3650Encode yield hint field
sub_8F3860Encode scoreboard dependency field
sub_8F4140Encode complete control word
sub_8F6530Output complete schedule for function

Seven verification functions at 0x8F7610--0x8F8CB0 validate the generated schedule: stall counts, barrier assignments, dependency chains, scoreboard correctness, control word format, yield hints, and overall schedule integrity.

See Scoreboards for the scoreboard and dependency barrier encoding format.

Memory Management

The scheduler uses two allocator strategies:

  1. Arena allocator (sub_8E3970): bump allocator with 10 KB block granularity, 8-byte alignment. Allocations within a scheduling pass use the arena for fast allocation. sub_8E3A80 frees all blocks at once at pass completion.

  2. Free-list allocator (sub_8DA6D0): free-list with block coalescing for persistent scheduling data. Maintains multiple free lists for different size classes. Blocks larger than 0x1FF bytes go to a separate large-block list. Adjacent free blocks are merged on deallocation.

Per-Instruction Scheduling Metadata (SchedNode)

Each instruction has a pointer at instr+40 (sched_slot) to a separate heap-allocated scheduling metadata block called a SchedNode. The metadata offsets documented throughout the scheduling pages (e.g., metadata+24, metadata+32, metadata+108) are relative to this SchedNode, not to the 296-byte Ori instruction object itself. The SchedNode block is at least 112 bytes; all nodes are linked into a singly-linked list at func+104 (Code Object offset +104), separate from the instruction linked list at func+272.

SchedNode Layout

OffsetSizeTypeInitNamePurpose
+08ptr--nextInListSingly-linked next pointer for the func+104 metadata chain
+84i320depCountUnsatisfied dependency count; decremented as predecessors are scheduled; instruction is ready when this reaches 0
+124----(pad)Alignment padding
+168ptr--nextReadyReady list singly-linked next pointer; threaded by sub_6820B0 (BuildReadyList)
+244i32seqbbSlot1-based position within the BB (assigned sequentially by sub_8D9930); used for program-order tiebreaking in priority decisions
+284i320latencyCounterRemaining latency cycles until the instruction's result is available; reset to 0 when placed on the ready list; updated by sub_A09530 (UpdateStallCycles)
+324i32--earliestCycleEarliest available cycle -- the latest completion time among all producer instructions; stall-free when earliestCycle >= scheduler+480 (current cycle)
+364----(reserved)Alignment padding or internal use
+404i320latestDeadlineLatest deadline cycle for scheduling; secondary tiebreaker in the candidate comparison cascade
+444i32--barrierGroupIndexBarrier group assignment; identifies which of the 6 hardware barriers this instruction participates in
+484i32--schedulingFenceCodeScheduling fence code from knob 313 (FenceCode) / 314 (FenceInterference) checks; controls per-instruction scheduling boundaries
+568i640depChainHeadDependency chain data; reset to 0 between scheduling passes
+764i320schedulingCostPer-instruction scheduling cost; accumulated during priority evaluation; reset between passes
+844i32-1schedulingClassScheduling class index assigned by the latency model (sub_89FBA0); indexes into per-architecture latency tables; -1 = unclassified (sentinel)
+884i32--maxPredecessorCycleHighest cycle value among predecessor instructions; used in the priority pre-scan to compute max_pred_cycle
+924i32--maxDependencyCycleHighest cycle value along the dependency chain; used to compute max_dep_cycle for critical-path analysis
+1048i640extendedStateExtended scheduling state; reset to 0 between scheduling passes
+1081byte--flagsPrimary flag byte: bit 0 = barrier-target, bit 1 = has-dependency-set, bit 2 = fence-early (knob 314), bit 3 = fence-late (knob 313), bit 4 = has-register-operand
+1111byte--extendedFlagsExtended flags: bit 7 = uses expensive register file (triggers barrier tracking update in sub_8C7120)

Relationship to the Instruction Object

 Ori Instruction (296 bytes)              SchedNode (>= 112 bytes)
 +--------------------------+             +---------------------------+
 | +0:  prev (BB list)      |   instr+40  | +0:  nextInList           |
 | +8:  next (BB list)      |---sched_slot-->                         |
 | +16: id                  |             | +8:  depCount             |
 | +72: opcode              |             | +16: nextReady            |
 | +80: operand_count       |             | +24: bbSlot               |
 | +84: operands[]          |             | +28: latencyCounter       |
 |                          |             | +32: earliestCycle        |
 |                          |             | +40: latestDeadline       |
 |                          |             | +88: maxPredecessorCycle  |
 |                          |             | +92: maxDependencyCycle   |
 |                          |             | +108: flags               |
 +--------------------------+             +---------------------------+

Lifecycle

  1. Allocation: InitScheduleData (vtable[29], called from sub_8D0640) allocates one SchedNode per instruction from the scheduling arena and stores the pointer at instr+40. Nodes are linked into the func+104 chain.

  2. Initialization: sub_8D9930 (EdgeBuilder) initializes depCount, bbSlot, latencyCounter, latestDeadline, and flags while building dependency edges. Between scheduling phases, the orchestrator resets pass-specific fields: +56 = 0, +104 = 0, DWORD+76 = 0, DWORD+84 = -1.

  3. Population: The dependency graph builder populates depCount from edge analysis. Critical-path computation fills earliestCycle, maxPredecessorCycle, and maxDependencyCycle.

  4. Use: sub_6820B0 (BuildReadyList) checks depCount == 0 and threads ready instructions via nextReady. sub_8C9320 (PriorityFunction) reads all fields to compute the 8-bit scheduling priority.

  5. Cleanup: sub_8E3A80 (ArenaFreeAll) reclaims all SchedNode blocks when the scheduling pass completes.

Sentinel Values

  • bbSlot = -1: unscheduled (set during inter-pass reset at DWORD+84)
  • latencyCounter = 99999 (0x1869F): infinity (used as min_barrier_latency initial value in the priority pre-scan)
  • earliestCycle bit 31 set (>= 0x80000000): not-yet-available (tested in sub_8C9320 pre-scan via < 0x80000000 comparison)

Large Function Handling

Functions exceeding 16383 instructions (*(a1+372) > 0x3FFF) trigger chunk-based scheduling via sub_A9DDD0 (11.5 KB). The function is split into chunks that are scheduled independently and then merged. This avoids quadratic blowup in the dependency DAG construction for very large kernels.

Per-Block Scheduling Record (72 bytes)

sub_6833F0 (InitScheduleRegion, 10 KB) allocates an array of (numBBs + 1) records at 72 bytes each, stored at scheduler+184. Each record tracks the register pressure snapshot, region context pointers, and scheduling characteristic flags for a single basic block. The scheduling engine loads a BB's pressure state from this record at region entry and saves it back when moving to the next BB.

Field Map

OffsetSizeTypeInitNamePurpose
+04i320crossBlockIdNon-zero when the BB is active/scheduled; set to the predecessor BB index during cross-block merging. Tested as a boolean gate by 8+ functions before processing a BB.
+44i320pressure[0]Register pressure snapshot -- R (general-purpose 32-bit registers)
+84i320pressure[1]Register pressure snapshot -- P (predicate registers)
+124i320pressure[2]Register pressure snapshot -- UR (uniform registers)
+164i320pressure[3]Register pressure snapshot -- UP (uniform predicate registers)
+204i320pressure[4]Register pressure snapshot -- B (barrier registers)
+244i320pressure[5]Register pressure snapshot -- arch-specific class 0
+284i320pressure[6]Register pressure snapshot -- arch-specific class 1
+324i320pressure[7]Register pressure snapshot -- arch-specific class 2
+364i320pressure[8]Register pressure snapshot -- arch-specific class 3
+404i320pressure[9]Register pressure snapshot -- arch-specific class 4 / control total
+444----(padding)Not initialized, not accessed
+488ptr0regionContextPointer to 136-byte per-region scheduling state allocated by sub_682F10. Contains region boundaries, mode flags, and instruction range metadata.
+568ptr0regionContext2Second region context pointer, written via successor-BB index mapping. Dereferenced by sub_681C00 to check barrier presence (bit 4 of pointed-to byte).
+641byte& 0x80flagsPer-BB characteristic flags (see below). Low 7 bits cleared on init; bit 7 preserved.
+657----(padding)Padding to 72-byte stride

Pressure Counter Transfer

At the start of each BB's scheduling pass, sub_A091C0 (InitResourceTracking) copies the 10 DWORDs at record offsets +4 through +40 into the scheduler context at context offsets +48 through +87. The scheduling engine then updates the context counters as instructions are scheduled. When cross-block scheduling produces a new pressure snapshot, the engine writes it back with SSE bulk stores:

*(OWORD*)(record + 4)  = pressure[0..3]    // 16 bytes via _mm_store_si128
*(OWORD*)(record + 20) = pressure[4..7]    // 16 bytes via _mm_store_si128
*(QWORD*)(record + 36) = pressure[8..9]    // 8 bytes

During the main scheduling loop, the engine decrements pressure[1] through pressure[9] (9 counters) from a 40-byte per-opcode resource cost table. pressure[0] (R class) is handled via a separate path.

Flags Byte (+64)

BitNameSet byMeaning
0crossBlockBoundarysub_688DD0 (ScheduleEngine)BB is a cross-block scheduling boundary
1regionActivesub_688DD0 (ScheduleEngine)BB belongs to an active scheduling region
2hasCallsub_6833F0 for opcode 96BB contains a CALL instruction
3hasBranchsub_6833F0 for opcodes 188, 190BB contains a branch instruction
4hasBarrierInstrsub_6833F0 via sub_7DF3A0 test (bit 6)BB contains a barrier-flagged instruction
5hasLongLatencyOpsub_6833F0 for memory/texture/tensor opcodes; also vtable[183] arch checkBB contains a long-latency operation (memory, texture, or tensor)
6crossBlockTargetsub_6833F0 cross-block mergeBB is the target of a cross-block scheduling region
7(preserved)Not cleared during initCarries data from a prior pipeline stage; purpose unknown

The opcodes that set bit 5 (hasLongLatencyOp): 18 (with knob 62 gate), 23, 26, 32, 57, 81, 101, 124 (with knob 461 gate), 178, 188, 190, 197, 236, 248, 271, 315. Additionally, any instruction where vtable[183] returns true (architecture-specific long-latency classification) sets bit 5.

Cross-Block Scheduling Setup

After per-BB initialization, sub_6833F0 walks the CFG to identify cross-block scheduling opportunities, gated by knob 744 (SchedCrossBlockReorder). For each predecessor-successor pair within the speculative distance threshold (knobs 743 SchedCrossBlockInstsToSpeculate and 747 SchedCrossBlockTexToSpeculate):

  1. Sets record[pred].crossBlockId = succ_bb_index (marks predecessor active).
  2. Clears bit 6 of record[pred].flags (predecessor is not a cross-block target).
  3. Sets bit 6 of record[succ].flags (successor is a cross-block target).
  4. Calls sub_682F10 to allocate the 136-byte region scheduling context and store pointers at record[pred]+48 and record[succ]+56.
+0                  +4                                           +44  +48              +56              +64  +72
| crossBlockId (4B) | pressure[0..9] (40B = 10 x i32)           |pad | regionCtx (8B) | regionCtx2 (8B)| fl | pad  |
+-------------------+----+----+----+----+----+----+----+----+----+----+----------------+----------------+----+------+

Scheduler Context Object Layout

The scheduling context object (sched / a1) is the central state structure passed as the first argument to every function in the scheduling subsystem. It is populated by sub_A95DC0 (SchedulingContext::configure, 35 KB) which reads dozens of knob values and architecture parameters. The object spans approximately 1600 bytes, from a vtable pointer at offset 0 through architecture-specific SSE vectors at offset +1584.

Core Fields (offsets 0--176)

OffsetSizeTypeNamePurpose
+08void*vtablePolymorphic dispatch; pre/post scheduling hooks at *(a1+40), *(a1+48)
+88ptrfuncContextPointer to CompilationContext; all func/arch queries go through this
+168ptrallocatorMemory allocator interface (vtable-dispatched alloc/free)
+408ptrpreHookVtablePre-scheduling callback (mode-specific polymorphic hook)
+4840int32[10]regPressureCountersPer-register-class live counts (copied from per-BB record +4..+40): R, P, UR, UP, B, and 5 arch-specific. The engine decrements counters [1]..[9] in the scheduling loop; counter [0] (R class) uses a separate path.
+604int32modeScheduling mode: 0 = ILP/Latency, 1 = ReduceReg, 2 = DynBatch
+884int32maxBBDepthMaximum dependency depth across all basic blocks
+924int32maxBBDepthNonTensorMaximum depth excluding tensor instructions
+1761bytescheduleActive1 during ReduceReg and DynBatch phases, 0 during ILP/Latency
+1781bytereduceRegModeWhen set, tightens register budget by ~12.5% + 3

Phase Control (offsets 240--312)

OffsetSizeTypeNamePurpose
+2404int32currentPhasePhase ID: 0 = budget computation, 1 = ReduceReg, 2 = ILP
+2488ptrregBitvector1Register pressure bitvector (numRegs + 1 words)
+2568ptrregBitvector2Second bitvector for dual-register tracking (knob 420, LivenessUseHiLo)
+2808ptranalysisSlots48-byte per-BB analysis slots (allocated when opt_level > 2)
+2921byteregTargetValidWhether register targets from knobs 776/778 (SchedReduceIncLimit/SchedReduceIncLimitHigh) are valid
+2964int32regTargetPrimaryForward-pass primary register target (knob 776 SchedReduceIncLimit, in HW register units)
+3004int32regTargetSecondaryForward-pass secondary register target (knob 778 SchedReduceIncLimitHigh, in HW register units)
+3111bytecfgFlag1Priority queue depth configuration flag
+3124int32cfgParam1Configuration parameter (default 10)

Register Budget (offsets 316--432)

OffsetSizeTypeNamePurpose
+3164int32minRegsMinimum register count from architecture register limit
+3204int32pressureSlackRegister pressure headroom (initialized to 0)
+3244int32committedTargetCommitted register target (set to regBudget after budget computation)
+3284int32dualIssueBenefitDual-issue benefit score from sub_8CF5D0 (sm_50 only)
+3804int32latencyCutoffBarrier-target latency cutoff; controls critical-path bit activation
+3841bytehasTextureOpsSet to 1 when opcode 246 (texture operation) found in any BB
+3884int32maxBBSizeMaximum basic block size in instructions (capped at 4095)
+3924int32maxBBSizeForAllocCopy of maxBBSize used for resource slot allocation sizing

Stall / Batch Parameters (offsets 404--420)

OffsetSizeTypeNamePurpose
+4044int32maxStallCyclesMax stall cycles; from knob 805/806 (SchedTexBatchTargetSelect{Register,Scheduler}Target), capped at 16
+4084int32stallThresholdStall threshold; knob 741 (SchedCountLoadsPerTex), default 3
+4124int32batchDepthBatch depth; knob 761 (SchedMaxRLiveOKslack), default 3 (6 or 12 for sm_50 with dual-issue)
+4164int32extraRegReserveExtra register reservation; knob 762 (SchedMaxRLiveOKslackColdBlocks), default -1 (disabled)
+4204int32spillModeCountdownSpill-mode countdown; when > 0, forces aggressive scheduling with critical-path bit always set

Register Budget and Pressure Tracking (offsets 432--485)

OffsetSizeTypeNamePurpose
+4324int32regBudgetTarget register count (occupancy-aware, from sub_8CEE80)
+4408ptrlivenessBV.dataRegister liveness bitvector data (via sub_BDBA60); sized to numRegs+1 or 2*numRegs+2 if dual-reg
+4488ptrlivenessBV.allocBitvector allocator reference
+4564int32livenessBV.sizeBitvector size in 64-bit words
+4644int32depthThresholdNumber of barrier-target instructions required to activate critical-path bit
+4804int32currentCycleCurrent scheduling cycle; used for stall-free evaluation
+4841bytephaseActivePhase activity flag: 1 = ReduceReg active, 0 = ILP/budget
+4851byteschedDirtyReset to 0 at orchestrator start

Hot-Cold and Yield State (offsets 523--532)

OffsetSizeTypeNamePurpose
+5231bytehotColdEnableHot-cold memory tracking enable; result of sub_8CF5D0 (dual-issue check)
+5241byteyieldStateCurrent yield state; propagated to CONTROL instructions via priority bit 6
+5324int32hotColdBudgetHot-cold budget counter; decremented per cold instruction; tracking deactivates at zero

Architecture Parameters (offsets 604--616)

OffsetSizeTypeNamePurpose
+6044int32archParam1Architecture-dependent parameter (6 for sm_60 era)
+6164int32archParam2Architecture-dependent limit (63 for sm_50 era, 255 for sm_60+)

Resource Tracking and Dependency Data (offsets 672--744)

OffsetSizeTypeNamePurpose
+6728ptrresourceSlotsPer-BB resource cost table; 84 bytes per slot (21 DWORDs: 10 FU usage + 10 FU delta + 1 flag)
+6808ptrdepDataDependency tracking data (zeroed at orchestrator start)
+7208ptrarenaAllocRefArena allocator reference for bitvector buffer resizing
+7288ptrbvBufferGrowable bitvector buffer pointer (1.5x growth factor on realloc)
+7364int32bvCapacityBitvector capacity in words (-1 = uninitialized sentinel)
+7404int32bvAllocatedBitvector allocated word count
+7448ptrfuncContextRef2Second reference to function context for bitvector sizing

Liveness Bitvector (offset 832)

The scheduler tracks register liveness via a bitvector at offset +832 (referenced only in the scheduling algorithm). Each bit represents one register; pressure is computed as popcount(live_bv). This field is part of the larger scheduling state managed by the engine and priority function.

Arena Allocator (offset 840+)

OffsetSizeTypeNamePurpose
+840~120ArenaAllocatorarenaEmbedded bump allocator; freed via sub_8E3A80(sched+840) at each pass end; 10 KB block granularity, 8-byte alignment

Configuration Bitfields (offsets 1032--1098)

The region from +1032 through +1098 (~67 bytes) is a dense bitfield array set by sub_A95DC0 (SchedulingContext::configure). Individual bits control fine-grained scheduling features, gated by architecture version, optimization level, and knob queries. Key fields:

OffsetSizeTypeNamePurpose
+10321bytefeatureFlags0Pipeline feature enables (OR'd with 0x4F)
+10524int32cfgMaxDepthKnob 449 value (default 5); scheduling depth limit
+10641bytecfgSmFlagsBit 0: SM-specific flag (knob 931 or arch > 16386)
+10728doublepressureCoeffKnob 366 value (default 0.25); register pressure coefficient
+10801bytecfgBitmaskBits: [7] always set, [6] knob 868, [5] hot-cold, [4] knob 410, [3] knob 868 alt
+10844int32cfgThresholdKnob 876 value (default 50)
+10881bytecfgBitmask2Bit 3: knob 752 related
+10891bytecfgBitmask3Bit 7: arch == 16387 or arch == 0x4000
+10961bytecfgBitmask4Bit 7: external flag from target descriptor +788
+10971bytecfgBitmask5Bits: [7] target+1844, [4] arch <= 16386, [3] sm_50 dual-issue, [1,0] target+788
+10981bytecfgBitmask6Bit 0: knob 462 (scheduling heuristic), Bit 5: arch == 16386

Architecture-Specific Defaults (offsets 1408--1584)

Set early in sub_A95DC0 based on *(a1+372) >> 12 (architecture class). Three code paths populate these fields for sm_50 era (class < 3), sm_60--sm_89 era (class == 4), and sm_90+ era (class >= 5):

OffsetSizeTypeNamePurpose
+14081bytearchMode0Architecture scheduling mode flag
+14111bytearchMode1Scheduling sub-mode
+14121bytearchMode2Scheduling sub-mode
+14131bytearchMode3Scheduling sub-mode
+14141bytearchMode4Architecture mode flag
+14151bytearchMode5Architecture mode flag; bit 2 checked during batch depth selection
+14161bytearchMode6Architecture mode flag
+144016__m128iarchVectorSSE-loaded scheduling parameters (4 x int32)
+14524int32archWarpSizeWarp/thread configuration: 64 or 128
+14564int32archDispatchSizeDispatch slot parameter: 16, 32, or 64
+14604int32archMaxThreadsMax threads per SM: 512 or 1024
+14644int32archParam5Architecture parameter: 4 (sm_60+ only)
+14724int32archBlockSizeBlock size parameter: 32
+14808int64archSpecDataArchitecture-specific encoded scheduling data
+158416__m128iarchProfileSSE-loaded architecture profile vector

Memory Layout Diagram

SchedulerContext (~1600 bytes)
+--------+--------+--------+--------+--------+--------+--------+--------+
|+0  vtable       |+8  funcContext   |+16 allocator    |+24 (padding)    |
+--------+--------+--------+--------+--------+--------+--------+--------+
|+32 (padding)    |+40 preHookVtable |+48  regPressureCounters[0..9]     |
+--------+--------+--------+--------+--------+--------+--------+--------+
|  ...counters... |+60 mode |+64..84 |+88  maxBBDepth  |+92 maxBBDpthNT |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+96..175 (internal state)           |+176 active|+178 rrMode|           |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+240 phase       |+248 regBV1       |+256 regBV2      |                 |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+280 analysisSlots         |+292 valid|+296 tgtPri|+300 tgtSec|         |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+316 minR|+320 slack|+324 commit|+328 dualIss|  ...  |+380 latCut|     |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+384 tex |+388 maxBB|+392 alloc |    |+404 stall|+408 thresh|+412 batch|
+---------+-------+---------+--------+---------+-------+--------+--------+
|+416 xtraReg|+420 spillCnt|    |+432 budget|+440..456 livenessBV       |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+464 depth  |    |+480 cycle|+484 act|+485 dirty|    |+523 hcE|+524 yld|
+---------+-------+---------+--------+---------+-------+--------+--------+
|+532 hcBudget|  |+604 archP1|  |+616 archP2|                           |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+672 resourceSlots         |+680 depData       |    ...bitvector mgr... |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+720 arenaRef    |+728 bvBuf        |+736 cap  |+740 alloc|+744 funcRef|
+---------+-------+---------+--------+---------+-------+--------+--------+
|                      ...gap / internal state...                        |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+832 liveness bitvector ref |                                           |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+840    ArenaAllocator (embedded sub-object, ~120 bytes)                |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+960..1031 (internal/padding)                                           |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+1032..1098  configuration bitfield array (~67 bytes)                   |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+1099..1407 (internal state, ~308 bytes)                                |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+1408..1416  architecture mode flags (9 bytes)                          |
+---------+-------+---------+--------+---------+-------+--------+--------+
|+1440 archVector (16B) |+1452..1484 arch params |+1584 archProfile (16B)|
+---------+-------+---------+--------+---------+-------+--------+--------+

Function Map

AddressSizeIdentity
sub_6820B01.5 KBBuildReadyList -- zero-dep instruction scan
sub_682200--UnlinkFromReadyList -- remove and update deps
sub_68249014 KBRegisterPressureAnalyzer -- per-class deltas
sub_6833F010 KBInitScheduleRegion -- per-BB setup and knob query
sub_685A1011 KBInstructionBarrierCheck -- opcode analysis
sub_687FE012 KBScheduleBlock -- per-BB scheduling entry
sub_688DD020 KBScheduleEngine -- unified 3-mode engine
sub_68A69031 KBBuildDependencies -- def-use chain DAG
sub_68B9C046 KBDependencyGraphBuilder -- full DAG construction
sub_69220018 KBSchedulingHeuristic -- priority with FP scoring
sub_69553015 KBComputeLatencies -- instruction latency computation
sub_69B7D017 KBTopologicalSort -- valid execution ordering
sub_69F17012 KBCriticalPathAnalysis -- DAG critical path
sub_89310017 KBClassifyInstruction -- opcode/operand analysis
sub_89429027 KBBuildOperandDependencies -- operand-level edges
sub_896D5090 KBInitOpcodeTable -- ROT13 SASS mnemonic table
sub_89FBA085 KBSetOpcodeLatencies -- per-opcode latency table
sub_8BF890929 BAllocDynBatchData -- DynBatch context allocation
sub_8C1BA06.3 KBInitDynBatchState -- batch initialization
sub_8C67A03.7 KBComputeResourceCost -- per-instruction FU cost
sub_8C72905.1 KBGetResourceVector -- SSE-optimized copy
sub_8C772020 KBReorderInstructions -- red-black tree reordering
sub_8C932047 KBComputePriority -- multi-criteria heuristic
sub_8CBAD02.9 KBPreScheduleSetup -- BB scan, 4095-instr limit
sub_8CCF802.3 KBIsLongLatencyOp -- latency > 19 check
sub_8CD1609.3 KBScheduleBasicBlock -- per-BB ordering loop
sub_8CD6E01.3 KBReverseSchedule -- reverse post-order BBs
sub_8CE52012 KBRegisterBudgetCurve -- piecewise linear model
sub_8CEE808.7 KBComputeRegisterBudget -- occupancy-aware
sub_8CF5D03.5 KBCheckDualIssueEligibility
sub_8CF88028 KBBuildDependencyGraph -- pre-scheduling DAG
sub_8D064022 KBScheduleInstructions -- top-level orchestrator
sub_8D993019 KBBuildDependencyEdges -- RAW/WAR/WAW edges
sub_8E3970~53 BArenaAlloc -- bump allocator
sub_8E3A80~22 lnArenaFreeAll -- release all blocks
sub_8E44003.3 KBInitHWProfile_Warp -- warp dispatch params
sub_8E5CA020 KBMasterHWProfileBuilder -- latency/throughput
sub_8F1EB015 KBEncodeScheduleWords -- SASS control word output
sub_8F653013 KBOutputCompleteSchedule -- final output assembly
sub_A95DC035 KBSchedulingContext::configure -- knob loading
sub_A9760042 KBPostSchedulePass::runOnFunction
sub_A9DDD011.5 KBHandleLargeFunction -- chunk-based scheduling

Cross-References

  • Scheduling Algorithm -- priority list scheduling internals, ready list management, backtracking
  • Latency Model -- per-opcode latency tables, functional unit mapping, architecture profiles
  • Scoreboards & Barriers -- scoreboard encoding, dependency barrier assignment, stall/yield format
  • Register Allocation -- register allocator that the scheduler interacts with
  • Phase Manager -- how ScheduleInstructions fits in the 159-phase pipeline
  • Knobs -- the 76 scheduling knobs and the knob query infrastructure
  • GMMA Pipeline -- GMMA/WGMMA operations targeted by DynBatch