Skip to main content

polydat_core/compile/
simd_tier1.rs

1// Copyright 2024-2026 Jonathan Shook
2// SPDX-License-Identifier: Apache-2.0
3
4//! End-to-end Tier-1 scalar-flow SIMD promotion.
5//!
6//! This module deliberately implements only the sealed perfect-ordinal slice:
7//! one selected scalar output, one `u64` ordinal input that varies inside an
8//! owned source lease, pure exact total lane-independent member nodes, and
9//! scope-stable scalar broadcasts. The canonical scalar DAG is retained as the
10//! oracle and fragment/recovery path; the synthesized register DAG is a
11//! parallel execution plan, not a mutation of scalar graph semantics.
12
13use std::collections::{BTreeMap, BTreeSet, HashMap};
14use std::fmt;
15use std::sync::Arc;
16
17use crate::ast::{Bits128, PortType, Purity, Value};
18use crate::compile::assembly::{PolydatAssembler, ResolvedDag, WireRef};
19use crate::compile::jit::JitKernelRaw;
20use crate::compile::jit::host_isa::EffectiveIsa;
21use crate::compile::simd_plan::{SimdTypeShape, validate_simd_variant};
22use crate::iteration::simd_ordinal::{OrdinalLaneClock, OrdinalPacketStamp};
23use crate::iteration::source::OrdinalBatchLease;
24use crate::kernel::{InputKind, PolydatKernel, PolydatProgram, WireSource};
25
26const TIER1_U64_LANES: usize = 2;
27const TIER1_MIN_MEMBERS: usize = 2;
28
29#[derive(Clone, Debug, PartialEq, Eq)]
30/// Why a Tier-1 SIMD plan could not be built, started, or advanced;
31/// `Display` renders each with its names.
32pub enum Tier1SimdError {
33    /// The selected output does not exist.
34    OutputNotFound(String),
35    /// The driving input does not exist.
36    DrivingInputNotFound(String),
37    /// The selected output does not depend on the driving input.
38    DrivingInputNotUsed(String),
39    /// The selected node has more than one output port.
40    OutputPortUnsupported,
41    /// Fewer nodes could be promoted than the plan requires.
42    TooFewMembers {
43        /// Promotable nodes found.
44        found: usize,
45        /// The minimum required.
46        minimum: usize,
47    },
48    /// A node in the cone cannot be promoted.
49    NodeIneligible {
50        /// The node.
51        node: String,
52        /// Why it cannot be promoted.
53        reason: String,
54    },
55    /// A node changes the lane shape.
56    ShapeMismatch {
57        /// The node.
58        node: String,
59    },
60    /// A node cannot serve as a packet boundary.
61    BoundaryUnsupported {
62        /// The node.
63        node: String,
64    },
65    /// A boundary does not carry the scalar type the plan requires.
66    BoundaryTypeMismatch {
67        /// The boundary's name.
68        boundary: String,
69        /// The scalar type required.
70        expected: PortType,
71    },
72    /// An input other than the driving ordinal is externally writable.
73    MutableBroadcast(String),
74    /// A node accepts `None` inputs, for which packets have no validity semantics.
75    NoneAwareNode(String),
76    /// The output has a visibility modifier and cannot be packetized speculatively.
77    OutputModifierUnsupported(String),
78    /// The output is an init binding, not a scalar stream.
79    ConstOutputUnsupported(String),
80    /// The lease driver supports `u64` over two `i64` lanes only, not this type.
81    RuntimeShapeUnsupported(PortType),
82    /// A constant boundary node could not be evaluated safely.
83    ConstantEvaluationFailed(String),
84    /// The register-typed graph could not be built.
85    VectorGraphBuild(String),
86    /// The effective native ISA declined the graph.
87    VectorCompilation(String),
88    /// Native ISA detection failed.
89    CapabilityDetection(String),
90    /// The previous ordinal lease is not fully drained.
91    ActiveLease,
92    /// The lease targets an input other than the plan's driving input.
93    LeaseInputMismatch {
94        /// The plan's driving input index.
95        expected: usize,
96        /// The lease's input index.
97        got: usize,
98    },
99    /// The lease arrived out of reservation order.
100    LeaseSequenceMismatch {
101        /// The sequence expected.
102        expected: u64,
103        /// The sequence received.
104        got: u64,
105    },
106    /// The lease's stream or generation changed within one activation.
107    LeaseStreamMismatch,
108    /// The activation epoch moved backwards.
109    ActivationWentBackwards {
110        /// The epoch before.
111        previous: u64,
112        /// The epoch received.
113        got: u64,
114    },
115    /// The name is not a scope-stable broadcast input of the plan.
116    UnknownBroadcast(String),
117    /// A broadcast value has the wrong type.
118    BroadcastTypeMismatch {
119        /// The broadcast's name.
120        name: String,
121        /// The type expected.
122        expected: PortType,
123        /// The type received.
124        got: PortType,
125    },
126}
127
128impl fmt::Display for Tier1SimdError {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        match self {
131            Self::OutputNotFound(name) => write!(f, "SIMD output '{name}' does not exist"),
132            Self::DrivingInputNotFound(name) => {
133                write!(f, "SIMD driving input '{name}' does not exist")
134            }
135            Self::DrivingInputNotUsed(name) => {
136                write!(
137                    f,
138                    "selected output does not depend on driving input '{name}'"
139                )
140            }
141            Self::OutputPortUnsupported => {
142                f.write_str("Tier-1 SIMD requires the selected node's sole output port")
143            }
144            Self::TooFewMembers { found, minimum } => write!(
145                f,
146                "Tier-1 SIMD requires at least {minimum} promoted nodes, found {found}"
147            ),
148            Self::NodeIneligible { node, reason } => {
149                write!(f, "node '{node}' is not SIMD-promotable: {reason}")
150            }
151            Self::ShapeMismatch { node } => {
152                write!(f, "node '{node}' changes the SIMD lane shape")
153            }
154            Self::BoundaryUnsupported { node } => {
155                write!(
156                    f,
157                    "node '{node}' cannot be used as a Tier-1 packet boundary"
158                )
159            }
160            Self::BoundaryTypeMismatch { boundary, expected } => write!(
161                f,
162                "SIMD boundary '{boundary}' does not carry the required {expected} scalar type"
163            ),
164            Self::MutableBroadcast(name) => write!(
165                f,
166                "input '{name}' is externally writable; only the driving ordinal may change inside a lease"
167            ),
168            Self::NoneAwareNode(node) => write!(
169                f,
170                "node '{node}' accepts None inputs and needs explicit packet validity semantics"
171            ),
172            Self::OutputModifierUnsupported(name) => write!(
173                f,
174                "output '{name}' has a visibility modifier and cannot be speculatively packetized"
175            ),
176            Self::ConstOutputUnsupported(name) => write!(
177                f,
178                "output '{name}' is an init binding and cannot be advanced as a scalar stream"
179            ),
180            Self::RuntimeShapeUnsupported(typ) => write!(
181                f,
182                "the landed Tier-1 lease driver supports u64/RegI64x2, not {typ}"
183            ),
184            Self::ConstantEvaluationFailed(node) => {
185                write!(
186                    f,
187                    "constant boundary node '{node}' could not be evaluated safely"
188                )
189            }
190            Self::VectorGraphBuild(reason) => {
191                write!(f, "failed to build the register-typed SIMD graph: {reason}")
192            }
193            Self::VectorCompilation(reason) => {
194                write!(
195                    f,
196                    "the effective native ISA declined the SIMD graph: {reason}"
197                )
198            }
199            Self::CapabilityDetection(reason) => {
200                write!(f, "native ISA detection failed: {reason}")
201            }
202            Self::ActiveLease => f.write_str("the previous ordinal lease is not fully drained"),
203            Self::LeaseInputMismatch { expected, got } => write!(
204                f,
205                "ordinal lease targets input {got}, but the SIMD plan drives input {expected}"
206            ),
207            Self::LeaseSequenceMismatch { expected, got } => write!(
208                f,
209                "ordinal lease arrived out of reservation order: expected {expected}, got {got}"
210            ),
211            Self::LeaseStreamMismatch => {
212                f.write_str("ordinal lease stream/generation changed within one activation")
213            }
214            Self::ActivationWentBackwards { previous, got } => write!(
215                f,
216                "activation epoch moved backwards from {previous} to {got}"
217            ),
218            Self::UnknownBroadcast(name) => {
219                write!(
220                    f,
221                    "'{name}' is not a scope-stable broadcast input of this SIMD plan"
222                )
223            }
224            Self::BroadcastTypeMismatch {
225                name,
226                expected,
227                got,
228            } => write!(f, "broadcast '{name}' expects {expected}, got {got}"),
229        }
230    }
231}
232
233impl std::error::Error for Tier1SimdError {}
234
235/// Recoverable lease-start failure. Ownership of the reserved ordinal range is
236/// returned to the caller so it can be processed through another scalar path.
237#[derive(Debug)]
238pub struct Tier1LeaseStartError {
239    reason: Tier1SimdError,
240    lease: OrdinalBatchLease,
241}
242
243impl Tier1LeaseStartError {
244    /// Why the lease could not start.
245    pub const fn reason(&self) -> &Tier1SimdError {
246        &self.reason
247    }
248
249    /// The reason and the lease, whose ordinal range is the caller's again.
250    pub fn into_parts(self) -> (Tier1SimdError, OrdinalBatchLease) {
251        (self.reason, self.lease)
252    }
253}
254
255impl fmt::Display for Tier1LeaseStartError {
256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257        self.reason.fmt(f)
258    }
259}
260
261impl std::error::Error for Tier1LeaseStartError {}
262
263#[derive(Clone, Debug, PartialEq, Eq)]
264/// What a Tier-1 SIMD plan promotes: the output, the driving input, the
265/// lane shape, the member nodes, and the broadcast inputs.
266pub struct Tier1SimdDescriptor {
267    /// The output the plan computes.
268    pub output: String,
269    /// The input whose ordinals the packets stride.
270    pub driving_input: String,
271    /// The scalar type of the stream.
272    pub scalar_type: PortType,
273    /// The register type a packet carries.
274    pub register_type: PortType,
275    /// Lanes per packet.
276    pub lanes: u8,
277    /// The nodes promoted into the vector graph.
278    pub member_nodes: Vec<String>,
279    /// Scope-stable inputs broadcast across the lanes.
280    pub broadcast_inputs: Vec<String>,
281    /// The native ISA the plan was compiled for.
282    pub effective_isa_fingerprint: String,
283}
284
285#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
286/// Counters of a plan's execution.
287pub struct Tier1SimdStats {
288    /// Ordinal leases drained to completion.
289    pub leases_completed: u64,
290    /// Packets computed by the vector graph.
291    pub vector_packets: u64,
292    /// Lanes of a partial packet, computed one at a time.
293    pub scalar_fragment_lanes: u64,
294    /// Lanes computed one at a time after a lease fell back to the scalar path.
295    pub scalar_recovery_lanes: u64,
296    /// Values handed out.
297    pub values_drained: u64,
298}
299
300#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
301enum BoundaryKey {
302    Input(usize),
303    Constant(usize),
304}
305
306#[derive(Clone, Debug)]
307enum BoundaryValue {
308    Driving,
309    Broadcast { input_index: usize, name: String },
310    Constant { value: Value },
311}
312
313struct ReadyPacket {
314    stamp: OrdinalPacketStamp,
315    lanes: [Value; TIER1_U64_LANES],
316}
317
318struct ActiveLease {
319    lease: OrdinalBatchLease,
320    activation_epoch: u64,
321    next_ordinal: u64,
322    scalar_only: bool,
323    ready: Option<ReadyPacket>,
324}
325
326/// Per-fiber Tier-1 executor. The scalar and native register kernels share no
327/// mutable state with another fiber.
328pub struct Tier1SimdExecutor {
329    descriptor: Tier1SimdDescriptor,
330    shape: SimdTypeShape,
331    driving_input_index: usize,
332    scalar: PolydatKernel,
333    vector: JitKernelRaw,
334    vector_output_slot: usize,
335    boundaries: Vec<BoundaryValue>,
336    active: Option<ActiveLease>,
337    activation_epoch: Option<u64>,
338    expected_lease_sequence: u64,
339    stream_identity: Option<(u64, u64)>,
340    stats: Tier1SimdStats,
341}
342
343impl Tier1SimdExecutor {
344    /// The plan's description.
345    pub fn descriptor(&self) -> &Tier1SimdDescriptor {
346        &self.descriptor
347    }
348
349    /// The counters so far.
350    pub const fn stats(&self) -> Tier1SimdStats {
351        self.stats
352    }
353
354    /// The scalar program the plan falls back to.
355    pub fn scalar_program(&self) -> &Arc<PolydatProgram> {
356        self.scalar.program()
357    }
358
359    /// Whether a lease is open.
360    pub const fn has_active_lease(&self) -> bool {
361        self.active.is_some()
362    }
363
364    /// Values left in the open lease, or zero.
365    pub fn remaining(&self) -> u64 {
366        self.active
367            .as_ref()
368            .map(|active| active.lease.range().end - active.next_ordinal)
369            .unwrap_or(0)
370    }
371
372    /// Freeze one scope-stable input value for subsequent packet evaluation.
373    /// Rebinding during an owned lease is rejected rather than invalidating
374    /// already-reserved logical inputs.
375    pub fn set_broadcast(&mut self, name: &str, value: Value) -> Result<(), Tier1SimdError> {
376        if self.active.is_some() {
377            return Err(Tier1SimdError::ActiveLease);
378        }
379        let Some(input_index) = self.boundaries.iter().find_map(|boundary| match boundary {
380            BoundaryValue::Broadcast {
381                input_index,
382                name: candidate,
383            } if candidate == name => Some(*input_index),
384            _ => None,
385        }) else {
386            return Err(Tier1SimdError::UnknownBroadcast(name.to_string()));
387        };
388        if !value.satisfies_slot(self.shape.scalar) || value.port_type() != self.shape.scalar {
389            return Err(Tier1SimdError::BroadcastTypeMismatch {
390                name: name.to_string(),
391                expected: self.shape.scalar,
392                got: value.port_type(),
393            });
394        }
395        self.scalar.state().set_input(input_index, value);
396        Ok(())
397    }
398
399    /// Accept an owned source reservation. A rejection returns the lease in
400    /// [`Tier1LeaseStartError`] so the caller can scalar-process it.
401    pub fn begin_lease(
402        &mut self,
403        lease: OrdinalBatchLease,
404        activation_epoch: u64,
405    ) -> Result<(), Tier1LeaseStartError> {
406        let validation = self.validate_lease(&lease, activation_epoch);
407        if let Err(reason) = validation {
408            return Err(Tier1LeaseStartError { reason, lease });
409        }
410
411        if self.activation_epoch != Some(activation_epoch) {
412            self.activation_epoch = Some(activation_epoch);
413            self.expected_lease_sequence = 0;
414            self.stream_identity = None;
415        }
416        self.stream_identity = Some((lease.stream_id(), lease.source_generation()));
417        let next_ordinal = lease.range().start;
418        self.active = Some(ActiveLease {
419            lease,
420            activation_epoch,
421            next_ordinal,
422            scalar_only: false,
423            ready: None,
424        });
425        Ok(())
426    }
427
428    fn validate_lease(
429        &self,
430        lease: &OrdinalBatchLease,
431        activation_epoch: u64,
432    ) -> Result<(), Tier1SimdError> {
433        if self.active.is_some() {
434            return Err(Tier1SimdError::ActiveLease);
435        }
436        if lease.input_index() != self.driving_input_index {
437            return Err(Tier1SimdError::LeaseInputMismatch {
438                expected: self.driving_input_index,
439                got: lease.input_index(),
440            });
441        }
442        if let Some(previous) = self.activation_epoch {
443            if activation_epoch < previous {
444                return Err(Tier1SimdError::ActivationWentBackwards {
445                    previous,
446                    got: activation_epoch,
447                });
448            }
449            if activation_epoch == previous {
450                if lease.sequence() != self.expected_lease_sequence {
451                    return Err(Tier1SimdError::LeaseSequenceMismatch {
452                        expected: self.expected_lease_sequence,
453                        got: lease.sequence(),
454                    });
455                }
456                if let Some(identity) = self.stream_identity
457                    && identity != (lease.stream_id(), lease.source_generation())
458                {
459                    return Err(Tier1SimdError::LeaseStreamMismatch);
460                }
461            } else if lease.sequence() != 0 {
462                return Err(Tier1SimdError::LeaseSequenceMismatch {
463                    expected: 0,
464                    got: lease.sequence(),
465                });
466            }
467        } else if lease.sequence() != 0 {
468            return Err(Tier1SimdError::LeaseSequenceMismatch {
469                expected: 0,
470                got: lease.sequence(),
471            });
472        }
473        Ok(())
474    }
475
476    /// Discard an uncommitted register packet and process the remainder of the
477    /// active lease through the retained scalar graph. The consumer frontier
478    /// does not move and the shared source cursor is not touched.
479    pub fn force_scalar_recovery(&mut self) {
480        if let Some(active) = self.active.as_mut() {
481            active.ready = None;
482            active.scalar_only = true;
483        }
484    }
485
486    /// Drain committed scalar values in ordinal order. Calls may use arbitrary
487    /// burst sizes; a partly consumed register packet remains in `BatchState`.
488    pub fn drain_into(&mut self, output: &mut [Value]) -> usize {
489        if output.is_empty() || self.active.is_none() {
490            return 0;
491        }
492
493        let mut written = 0;
494        while written < output.len() && self.active.is_some() {
495            let needs_packet = {
496                let active = self.active.as_ref().expect("checked above");
497                active
498                    .ready
499                    .as_ref()
500                    .is_none_or(|ready| !ready.stamp.contains(active.next_ordinal))
501            };
502            if needs_packet {
503                self.materialize_packet();
504            }
505
506            let mut completed = false;
507            {
508                let active = self.active.as_mut().expect("packet materialized");
509                let ready = active.ready.as_ref().expect("packet materialized");
510                let lane = (active.next_ordinal - ready.stamp.base_ordinal) as usize;
511                output[written] = ready.lanes[lane].clone();
512                written += 1;
513                self.stats.values_drained += 1;
514                active.next_ordinal += 1;
515
516                if active.next_ordinal >= ready.stamp.base_ordinal + self.shape.lanes as u64 {
517                    active.ready = None;
518                }
519                if active.next_ordinal >= active.lease.range().end {
520                    completed = true;
521                }
522            }
523
524            if completed {
525                self.active = None;
526                self.expected_lease_sequence = self.expected_lease_sequence.wrapping_add(1);
527                self.stats.leases_completed += 1;
528            }
529        }
530        written
531    }
532
533    fn materialize_packet(&mut self) {
534        let (
535            base_ordinal,
536            range,
537            consumer_frontier,
538            scalar_only,
539            activation_epoch,
540            stream_id,
541            generation,
542        ) = {
543            let active = self.active.as_ref().expect("active lease");
544            (
545                OrdinalLaneClock::<TIER1_U64_LANES>::packet_base(active.next_ordinal),
546                active.lease.range(),
547                active.next_ordinal,
548                active.scalar_only,
549                active.activation_epoch,
550                active.lease.stream_id(),
551                active.lease.source_generation(),
552            )
553        };
554        let mut valid_mask = 0u16;
555        for lane in 0..TIER1_U64_LANES {
556            let ordinal = base_ordinal + lane as u64;
557            if ordinal >= range.start && ordinal >= consumer_frontier && ordinal < range.end {
558                valid_mask |= 1 << lane;
559            }
560        }
561
562        let full_mask = (1u16 << TIER1_U64_LANES) - 1;
563        let lanes = if valid_mask == full_mask && !scalar_only {
564            self.stats.vector_packets += 1;
565            self.eval_vector_packet(base_ordinal)
566        } else {
567            let mut lanes = [Value::U64(0), Value::U64(0)];
568            for (lane, slot) in lanes.iter_mut().enumerate() {
569                if valid_mask & (1 << lane) != 0 {
570                    *slot = self.eval_scalar_ordinal(base_ordinal + lane as u64);
571                    if scalar_only {
572                        self.stats.scalar_recovery_lanes += 1;
573                    } else {
574                        self.stats.scalar_fragment_lanes += 1;
575                    }
576                }
577            }
578            lanes
579        };
580
581        self.active.as_mut().expect("active lease").ready = Some(ReadyPacket {
582            stamp: OrdinalPacketStamp {
583                stream_id,
584                source_generation: generation,
585                activation_epoch,
586                dependency_epoch: 0,
587                base_ordinal,
588                lane_count: TIER1_U64_LANES as u8,
589                valid_mask,
590            },
591            lanes,
592        });
593    }
594
595    fn eval_vector_packet(&mut self, base_ordinal: u64) -> [Value; TIER1_U64_LANES] {
596        let mut coords = Vec::with_capacity(self.boundaries.len() * 2);
597        for boundary in &self.boundaries {
598            let bits = match boundary {
599                BoundaryValue::Driving => {
600                    Bits128::from_lanes_i64([base_ordinal as i64, (base_ordinal + 1) as i64])
601                }
602                BoundaryValue::Broadcast { input_index, .. } => {
603                    let value = self.scalar.state_ref().get_input(*input_index).as_u64();
604                    Bits128::from_lanes_i64([value as i64; TIER1_U64_LANES])
605                }
606                BoundaryValue::Constant { value } => {
607                    let value = value.as_u64();
608                    Bits128::from_lanes_i64([value as i64; TIER1_U64_LANES])
609                }
610            };
611            coords.extend_from_slice(&bits.0);
612        }
613        self.vector.eval(&coords);
614        let bits = Bits128([
615            self.vector.get_slot(self.vector_output_slot),
616            self.vector.get_slot(self.vector_output_slot + 1),
617        ]);
618        bits.lanes_i64().map(|lane| Value::U64(lane as u64))
619    }
620
621    fn eval_scalar_ordinal(&mut self, ordinal: u64) -> Value {
622        self.scalar
623            .state()
624            .set_input(self.driving_input_index, Value::U64(ordinal));
625        self.scalar.pull(&self.descriptor.output).clone()
626    }
627}
628
629fn is_input_alias(resolved: &ResolvedDag, node_idx: usize) -> Option<usize> {
630    let node = &resolved.nodes[node_idx];
631    let meta = node.meta();
632    if !meta.name.starts_with("__port_") || meta.wire_inputs().len() != 1 || meta.outs.len() != 1 {
633        return None;
634    }
635    match resolved.wiring[node_idx].as_slice() {
636        [WireSource::Input(input_idx)] => Some(*input_idx),
637        _ => None,
638    }
639}
640
641fn is_constant_boundary(resolved: &ResolvedDag, node_idx: usize) -> bool {
642    resolved.wiring[node_idx].is_empty()
643        && resolved.nodes[node_idx].meta().wire_inputs().is_empty()
644        && resolved.nodes[node_idx].meta().outs.len() == 1
645        && resolved.nodes[node_idx].purity() == Purity::Pure
646}
647
648fn evaluate_constant_boundary(
649    resolved: &ResolvedDag,
650    node_idx: usize,
651) -> Result<Value, Tier1SimdError> {
652    let node = &resolved.nodes[node_idx];
653    let mut output = [Value::None];
654    std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
655        node.eval(&[], &mut output);
656    }))
657    .map_err(|_| Tier1SimdError::ConstantEvaluationFailed(node.meta().name.clone()))?;
658    Ok(output[0].clone())
659}
660
661fn boundary_key_for_source(resolved: &ResolvedDag, source: &WireSource) -> Option<BoundaryKey> {
662    match source {
663        WireSource::Input(input_idx) => Some(BoundaryKey::Input(*input_idx)),
664        WireSource::NodeOutput(node_idx, port) if *port == 0 => {
665            if let Some(input_idx) = is_input_alias(resolved, *node_idx) {
666                Some(BoundaryKey::Input(input_idx))
667            } else if is_constant_boundary(resolved, *node_idx) {
668                Some(BoundaryKey::Constant(*node_idx))
669            } else {
670                None
671            }
672        }
673        _ => None,
674    }
675}
676
677/// Discover, synthesize, and compile the first production SIMD slice.
678pub(crate) fn compile_tier1_ordinal(
679    resolved: ResolvedDag,
680    driving_input: &str,
681    output: &str,
682) -> Result<Tier1SimdExecutor, Tier1SimdError> {
683    let effective_isa = EffectiveIsa::detect().map_err(Tier1SimdError::CapabilityDetection)?;
684    let driving_input_index = resolved
685        .input_defs
686        .iter()
687        .position(|input| input.name == driving_input)
688        .ok_or_else(|| Tier1SimdError::DrivingInputNotFound(driving_input.to_string()))?;
689    let (output_node, output_port) = resolved
690        .output_map
691        .get(output)
692        .copied()
693        .ok_or_else(|| Tier1SimdError::OutputNotFound(output.to_string()))?;
694    if output_port != 0 || resolved.nodes[output_node].meta().outs.len() != 1 {
695        return Err(Tier1SimdError::OutputPortUnsupported);
696    }
697    if resolved.output_modifiers.contains_key(output) {
698        return Err(Tier1SimdError::OutputModifierUnsupported(
699            output.to_string(),
700        ));
701    }
702    if resolved.const_outputs.contains(output) {
703        return Err(Tier1SimdError::ConstOutputUnsupported(output.to_string()));
704    }
705
706    let mut members = BTreeSet::new();
707    let mut boundary_keys = BTreeSet::new();
708    let mut stack = vec![output_node];
709    while let Some(node_idx) = stack.pop() {
710        if is_input_alias(&resolved, node_idx).is_some()
711            || is_constant_boundary(&resolved, node_idx)
712        {
713            continue;
714        }
715        if !members.insert(node_idx) {
716            continue;
717        }
718        for source in &resolved.wiring[node_idx] {
719            if let Some(key) = boundary_key_for_source(&resolved, source) {
720                boundary_keys.insert(key);
721            } else if let WireSource::NodeOutput(upstream, port) = source {
722                if *port != 0 {
723                    return Err(Tier1SimdError::BoundaryUnsupported {
724                        node: resolved.nodes[*upstream].meta().name.clone(),
725                    });
726                }
727                stack.push(*upstream);
728            }
729        }
730    }
731    if members.len() < TIER1_MIN_MEMBERS {
732        return Err(Tier1SimdError::TooFewMembers {
733            found: members.len(),
734            minimum: TIER1_MIN_MEMBERS,
735        });
736    }
737
738    let mut shape = None;
739    let mut variants = BTreeMap::new();
740    let mut member_names = Vec::with_capacity(members.len());
741    for &node_idx in &members {
742        let node = &resolved.nodes[node_idx];
743        if node.accepts_none_inputs() {
744            return Err(Tier1SimdError::NoneAwareNode(node.meta().name.clone()));
745        }
746        let validated = validate_simd_variant(node.as_ref()).map_err(|reason| {
747            Tier1SimdError::NodeIneligible {
748                node: node.meta().name.clone(),
749                reason: reason.to_string(),
750            }
751        })?;
752        if let Some(expected) = shape {
753            if expected != validated.shape {
754                return Err(Tier1SimdError::ShapeMismatch {
755                    node: node.meta().name.clone(),
756                });
757            }
758        } else {
759            shape = Some(validated.shape);
760        }
761        member_names.push(format!("{node_idx}:{}", node.meta().name));
762        variants.insert(node_idx, validated);
763    }
764    let shape = shape.expect("minimum member count establishes a shape");
765    if shape.scalar != PortType::U64 {
766        return Err(Tier1SimdError::RuntimeShapeUnsupported(shape.scalar));
767    }
768
769    if !boundary_keys.contains(&BoundaryKey::Input(driving_input_index)) {
770        return Err(Tier1SimdError::DrivingInputNotUsed(
771            driving_input.to_string(),
772        ));
773    }
774
775    let mut boundary_values = Vec::with_capacity(boundary_keys.len());
776    let mut boundary_names = Vec::with_capacity(boundary_keys.len());
777    let mut boundary_to_name = BTreeMap::new();
778    let mut broadcast_inputs = Vec::new();
779    for (position, key) in boundary_keys.iter().enumerate() {
780        let vector_name = format!("__simd_boundary_{position}");
781        boundary_to_name.insert(key.clone(), vector_name.clone());
782        boundary_names.push(vector_name);
783        match key {
784            BoundaryKey::Input(input_index) => {
785                let input = &resolved.input_defs[*input_index];
786                if input.port_type != shape.scalar {
787                    return Err(Tier1SimdError::BoundaryTypeMismatch {
788                        boundary: input.name.clone(),
789                        expected: shape.scalar,
790                    });
791                }
792                if *input_index == driving_input_index {
793                    boundary_values.push(BoundaryValue::Driving);
794                } else {
795                    if input.kind == InputKind::ExternalWrite {
796                        return Err(Tier1SimdError::MutableBroadcast(input.name.clone()));
797                    }
798                    broadcast_inputs.push(input.name.clone());
799                    boundary_values.push(BoundaryValue::Broadcast {
800                        input_index: *input_index,
801                        name: input.name.clone(),
802                    });
803                }
804            }
805            BoundaryKey::Constant(node_idx) => {
806                let value = evaluate_constant_boundary(&resolved, *node_idx)?;
807                if value.port_type() != shape.scalar {
808                    return Err(Tier1SimdError::BoundaryTypeMismatch {
809                        boundary: resolved.nodes[*node_idx].meta().name.clone(),
810                        expected: shape.scalar,
811                    });
812                }
813                boundary_values.push(BoundaryValue::Constant { value });
814            }
815        }
816    }
817
818    let mut vector_assembler = PolydatAssembler::new(boundary_names.clone());
819    for name in &boundary_names {
820        vector_assembler.set_input_type(name, shape.register);
821    }
822    vector_assembler.set_context(&resolved.source, "(Tier-1 SIMD register plan)");
823
824    let mut vector_node_names = HashMap::new();
825    for &node_idx in &members {
826        let validated = &variants[&node_idx];
827        let mut wires = Vec::with_capacity(resolved.wiring[node_idx].len());
828        for source in &resolved.wiring[node_idx] {
829            if let Some(key) = boundary_key_for_source(&resolved, source) {
830                wires.push(WireRef::input(
831                    boundary_to_name
832                        .get(&key)
833                        .expect("discovered boundary has vector input"),
834                ));
835            } else if let WireSource::NodeOutput(upstream, port) = source {
836                let upstream_name = vector_node_names.get(upstream).ok_or_else(|| {
837                    Tier1SimdError::BoundaryUnsupported {
838                        node: resolved.nodes[*upstream].meta().name.clone(),
839                    }
840                })?;
841                wires.push(WireRef::node_port(upstream_name, *port));
842            } else {
843                return Err(Tier1SimdError::VectorGraphBuild(
844                    "unresolved scalar boundary".to_string(),
845                ));
846            }
847        }
848        let wire_types = vec![shape.register; wires.len()];
849        let vector_node =
850            crate::dsl::factory::build_node(validated.vector_node, &wires, &wire_types, &[])
851                .map_err(|error| Tier1SimdError::VectorGraphBuild(error.to_string()))?;
852        let name = format!("__simd_node_{node_idx}");
853        vector_assembler.add_node(&name, vector_node, wires);
854        vector_node_names.insert(node_idx, name);
855    }
856    let vector_output_node =
857        vector_node_names
858            .get(&output_node)
859            .ok_or_else(|| Tier1SimdError::BoundaryUnsupported {
860                node: resolved.nodes[output_node].meta().name.clone(),
861            })?;
862    vector_assembler.add_output(output, WireRef::node_port(vector_output_node, output_port));
863    let vector = vector_assembler
864        .try_compile_pure_jit_raw()
865        .map_err(Tier1SimdError::VectorCompilation)?;
866    let vector_output_slot = vector.resolve_output(output).ok_or_else(|| {
867        Tier1SimdError::VectorCompilation("compiled output slot is missing".to_string())
868    })?;
869
870    let selected_output_map = HashMap::from([(output.to_string(), (output_node, output_port))]);
871    let scalar_program = Arc::new(PolydatProgram::with_inputs(
872        resolved.nodes,
873        resolved.wiring,
874        resolved.input_defs,
875        resolved.coord_count,
876        selected_output_map,
877        vec![output.to_string()],
878        &resolved.source,
879        &resolved.context,
880    ));
881    let scalar = PolydatKernel::from_program(scalar_program);
882
883    Ok(Tier1SimdExecutor {
884        descriptor: Tier1SimdDescriptor {
885            output: output.to_string(),
886            driving_input: driving_input.to_string(),
887            scalar_type: shape.scalar,
888            register_type: shape.register,
889            lanes: shape.lanes,
890            member_nodes: member_names,
891            broadcast_inputs,
892            effective_isa_fingerprint: effective_isa.fingerprint(),
893        },
894        shape,
895        driving_input_index,
896        scalar,
897        vector,
898        vector_output_slot,
899        boundaries: boundary_values,
900        active: None,
901        activation_epoch: None,
902        expected_lease_sequence: 0,
903        stream_identity: None,
904        stats: Tier1SimdStats::default(),
905    })
906}