You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Compiler RFC. Proposed only; no implementation is authorized by this issue.
This is the Linx LLVM companion to PTO-ISA/pto-spec#189, which
proposes the common PTO/Linx 0.59 architecture:
one main GPR, predicate, Local Tile, and Shared Tile register level;
no body-local V register file or scalar-import namespace;
ordered B.SEQ and iteration-parallel B.PAR execution markers;
direct top-level Tile B.SUBVIEW / B.ASSEMBLE operands; and
a TileOp virtual assembly layer that folds one physical bundle into one
existing TileOp mnemonic.
Compiler baseline inspected for this RFC: 9fb4f7aa89ee22541bfae288e2085ada266ffd75.
The compiler may prototype target IR and MachineIR, but final ISA instruction
selection, predicate/EXEC effects, encodings, and object identity remain
blocked on accepted PTO/Linx 0.59 contracts.
Goal
Allow element-wise Tile/vector computations to remain ordinary C++ for
loops with ordinary structured control flow (if, else, nested diamonds,
canonical break/continue) while LLVM lowers them to PTO/Linx 0.59 SIMT
execution without exposing V registers or mask-stack operations in source.
The intended source style is CUDA/SYCL-like in one important respect: C++
expresses scalar control flow for one logical element, while the compiler
classifies uniform versus varying values and constructs the execution-mask and
reconvergence protocol.
Illustrative pointer baseline:
voidpiecewise(float *out, constfloat *x, int n) {
#pragma clang loop linx_simt(enable) linx_schedule(auto)
for (int i = 0; i < n; ++i) {
float v = x[i];
if (v > 0.0f) {
if (v > 10.0f)
out[i] = v * 2.0f;
else
out[i] = v + 1.0f;
} else {
out[i] = -v;
}
}
}
The TileOP/API spelling may wrap the operands in a non-addressable Tile view,
but the body must remain the same language-level loop and branches:
template <classDstView, classSrcView>
voidtile_piecewise(DstView dst, SrcView src) {
#pragma clang loop linx_simt(enable) linx_schedule(auto)
for (int i = 0; i < src.size(); ++i) {
auto v = src[i];
if (v > 0)
dst[i] = v + 1;
else
dst[i] = -v;
}
}
The exact public Tile-view class and pragma spelling are review items. The
required semantic contract is ordinary C++ for/if source, not explicit
predicate intrinsics or hand-written bundle assembly.
Current compiler surface and gap
The repository already contains useful 0.58 bring-up pieces:
it can if-convert simple diamonds and reports grouped_layout_requires_exec_mask_save_restore when real grouped
divergence requires missing mask save/restore support;
llvm/include/llvm/IR/IntrinsicsLinx.td defines llvm.linx.vblock.launch with twelve scalar bind slots;
llvm/lib/Target/LinxISA/LinxISAInstrInfo.td defines PSEUDO_VBLOCK_LAUNCH, body-local PSEUDO_V_* instructions, and TileOp
pseudos;
llvm/lib/Target/LinxISA/LinxISABlockify.cpp expands the launch into one of BSTART.{MSEQ,MPAR,VSEQ,VPAR}, B.TEXT, repeated B.IOR imports, body-local
register IDs, dimensions, and BSTOP; and
tests such as autovec_ifconverted_diamond.ll, autovec_nested_mask_branch.ll, and autovec_inner_mask_branch.ll already
exercise multi-block element-wise control flow.
That path is not the 0.59 model. In particular:
it serializes a generated body into the linx-vblock-body-asm function
attribute instead of keeping the body as typed IR/MachineIR;
llvm.linx.vblock.launch models a second twelve-entry ri* scalar import
namespace;
grouped divergence currently falls back or rejects because there is no
explicit mask save/restore and reconvergence representation; and
the four MSEQ/MPAR/VSEQ/VPAR headers combine capability and order rather
than lowering to the proposed B.SEQ / B.PAR order contract.
The 0.59 implementation must remove these architectural assumptions rather
than hide them behind new pseudo names.
Proposed source and frontend contract
Ordinary C++ remains canonical
Clang must preserve the ordinary loop/CFG semantics. The user does not write
EXEC updates, predicate-register allocation, reconvergence labels, control
stack pushes, or B.Z/B.NZ.
The initial frontend should support:
canonical counted for loops;
pointer/span and compiler-recognized non-addressable Tile-view operands;
nested reducible if/else diamonds;
SSA PHIs at merges;
continue and loop-exit tests whose convergence can be proved; and
an explicit opt-in loop hint plus an auto policy.
The frontend emits ordinary LLVM CFG plus loop metadata describing only user
intent and schedule policy. It must not claim that a loop is B.PAR-legal.
That proof belongs to LLVM analyses after optimization.
par is a request, not permission to miscompile: a loop that cannot satisfy
the complete B.PAR contract receives a stable diagnostic. auto falls back
to B.SEQ unless independence is proved.
Source value classification
Uniform numeric values lower to the main GPR state.
Uniform booleans lower to ordinary scalar control and do not modify EXEC.
Varying numeric values remain Tile/region SSA values and must not be
materialized in a body-local V register or ordinary main GPR under B.PAR.
Varying booleans lower to 32-bit control predicates and EXEC masks.
A packed predicate Tile is data, not a control predicate. TCMP/TCMPS
predicate-Tile results must not be implicitly reinterpreted as P1..P7 or
EXEC without an accepted explicit conversion.
LLVM IR and control-stack model
Keep generic SSA/CFG, then annotate divergent control
Do not introduce a source-visible stack. Before target control-flow lowering,
LLVM IR remains normal SSA CFG. A new LinxSIMTControlFlow target pass runs
after loop selection/structurization and uses at least:
UniformityAnalysis to distinguish uniform and divergent branches;
DominatorTree and LoopInfo to find reconvergence and loop joins; and
convergence control to prevent duplication or motion across the SIMT
execution domain.
The design should follow the architecture pattern of AMDGPU SIAnnotateControlFlow.cpp, which maintains a compiler-side stack of {reconvergence block, saved mask SSA value} and inserts target intrinsics for
IF, ELSE, IF_BREAK, LOOP, and END_CF. It must not copy AMD wave64, SGPR, or
instruction semantics.
Provisional Linx target intrinsics, with a 32-bit mask carrier, are:
The exact intrinsic types may become a target extension predicate type, but
the mask width and semantics must stay compatible with the accepted 0.59
predicate/EXEC architecture. These intrinsics are compiler markers; they are
not new portable LLVM semantics or direct promises of one machine opcode.
Abstract control frame
For each divergent structured region LLVM tracks an SSA control frame
equivalent to:
ControlFrame {
saved_exec;
remaining_else_mask;
reconvergence_block;
loop_break_mask; // loops only
loop_continue_mask; // when required
}
The frame may later reside in predicate registers, main GPRs where legal, or
architectural execution-instance control-stack state. It is not addressable
C++ state and must not silently spill to ordinary program memory unless the
ISA/ABI explicitly permits such a spill.
entry_exec = EXEC
then_exec = entry_exec & condition_mask
else_exec = entry_exec & ~condition_mask
execute then under then_exec when nonzero
execute else under else_exec when nonzero
reconverge under the surviving join mask
Early exit, break, and continue update live/broken masks rather than merely
restoring the original mask. The pass must reject irreducible or unsupported
control flow instead of guessing a reconvergence point.
Predicate and EXEC lowering
Introduce an explicit PRED32 MachineIR register class/bank for P0..P7 and
EXEC-related mask values:
P0 is the architectural all-active constant and is never allocated as a
writable destination.
Comparisons in a divergent region produce a PRED32 value masked by the
current EXEC as required by the ISA contract.
Predicate logical operations remain in PRED32; they must not round-trip
through a body-local vector register.
IF/ELSE/END-CF pseudos have explicit and implicit EXEC uses/defs so liveness,
scheduling, sinking, and register allocation cannot move effects across a
mask transition.
A uniform scalar comparison remains a scalar i1/GPR condition and must not
consume P1..P7.
Predicate pressure, nesting depth, call preservation, spill/fill, and trap
preservation must have an explicit policy. If no legal spill exists, the
compiler rejects over-depth control flow with a stable diagnostic.
They deliberately mirror the analyzable shape of RDNA SI_IF, SI_ELSE, SI_LOOP, and SI_END_CF, while lowering to Linx-specific predicate and
execution-instance operations.
B.Z and B.NZ test the current EXEC mask only after PTO/Linx 0.59 assigns
that meaning. They are not general predicate-register branches. A schematic
divergent branch may use:
P.CMP ... ->P1 # exact comparison mnemonic TBD by ISA
EXEC.SAVE.AND P1 ->P2 # exact mask-update carrier TBD by ISA
B.Z .Lelse_or_join
...
EXEC.ELSE P2
B.Z .Ljoin
...
EXEC.RESTORE P2
These spellings are explanatory, not encoding proposals. LLVM must not emit
them until the owning ISA issue defines the exact carriers and effects.
B.SEQ / B.PAR legality and selection
The current vkind = {MSEQ,MPAR,VSEQ,VPAR} launch field must be replaced by an
orthogonal order policy plus body effect classification.
B.SEQ
Main-GPR writes and loop-carried scalar recurrences are legal.
LLVM preserves the architectural iteration and dynamic instruction commit
order.
Scalar lowering is allowed when it preserves direct Tile view semantics and
precise faults.
Divergent predicates still require well-formed EXEC/reconvergence state.
B.PAR
The complete body inventory must prove no ordinary main-GPR write, including
untaken paths and compiler-synthesized temporaries.
GPR reads use the region-entry snapshot.
Varying numeric values must remain Tile/region SSA values.
Destination ranges must be proved disjoint unless an accepted atomic or
reduction contract owns the overlap.
Generic loop-carried recurrences reject or select B.SEQ; only explicitly
supported reductions may use B.PAR.
Unknown calls, volatile/atomic effects without an accepted contract,
irreducible CFG, unknown aliasing, or unresolved predicate spills reject a
forced par request and force seq under auto.
The pass must emit structured optimization remarks explaining the selected
mode or exact rejection reason.
Direct Tile subview/assemble lowering
For a Tile-view loop, src[i] and dst[i] are compiler-recognized region
operations, not C++ addressable references and not body-local scalar loads.
The selected iteration tuple derives a source region and destination range:
reads become TileOp source operands carrying the parent Tile identity plus B.SUBVIEW range;
writes become TileOp destinations contributing a B.ASSEMBLE range to one
parent working generation;
intermediate varying values use temporary top-level Tile generations and
disjoint regions, not vt/vu/vm/vn registers;
simple side-effect-free diamonds may still be if-converted to select/TSEL;
side-effecting or nested divergent CFG uses the predicate/control-stack
path; and
source snapshots, destination coverage, replay, LAST, fault rollback, and
parent publication follow the accepted PTO generation contract.
The target IR work should compose with the indexed region/session model in #74 rather than invent a second range representation.
ISel, MachineIR, Blockify, and virtual TileOp integration
Required compiler restructuring:
Replace linx-vblock-body-asm string serialization with typed IR and
MachineBasicBlocks for the scheduled body.
Replace llvm.linx.vblock.launch's twelve ri* imports with explicit main
GPR, predicate, Tile parent, region, and assembly-session SSA operands.
Remove 0.59 use of body-local PSEUDO_V_* immediate register IDs.
Preserve control-flow and predicate pseudos through ISel and register
allocation with explicit EXEC dependencies.
Make Blockify emit one 0.59 scheduled-region header, B.TEXT, the selected B.SEQ/B.PAR marker, dimensions, direct top-level bindings, and one
boundary.
Lower Tile arithmetic through the existing PSEUDO_TILEOP_* family and a
generated 0.59 TileOp schema shared by compiler expansion, assembler, and
bundle-aware disassembler.
Emit B.SUBVIEW and B.ASSEMBLE immediately adjacent to their owning
binder; never materialize VLOAD/VSTORE copies.
Preserve both explicit-BSTOP and next-BSTART bundle boundaries without
consuming the next header during virtual disassembly.
Emit the exact PTO ISA 0.59 object note and reject mixed 0.58/0.59 inputs.
Diagnostics and conservative fallback
Provide stable diagnostics/remarks for at least:
loop not canonical or trip/range not provable;
irreducible or unsupported divergent CFG;
reconvergence point not unique;
predicate/control-stack depth exhausted;
predicate spill required but no legal carrier exists;
ordinary GPR write in forced B.PAR;
compiler-synthesized GPR temporary makes B.PAR illegal;
loop-carried recurrence not an accepted parallel reduction;
overlapping or unproved destination assembly ranges;
varying value would escape to GPR, ABI, memory, or an unknown call;
packed predicate Tile used as a control predicate without conversion;
unsupported call, exception, setjmp/longjmp, inline assembly, or volatile
effect inside the region; and
target PTO identity does not provide required predicate/EXEC operations.
auto selects the safe B.SEQ or leaves the loop scalar. A forced par
request must reject rather than silently change ordering.
Minimum test matrix
Clang C++
ordinary pointer loop and Tile-view loop with the same for/if body;
simple, nested, and empty-arm diamonds;
uniform versus varying branch conditions;
canonical continue, break, and tail masks;
forced seq, forced legal par, forced illegal par, and auto fallback;
diagnostics for address-taking/escape of non-addressable Tile element views.
LLVM IR and analysis
UniformityAnalysis classification;
insertion and nesting of IF/ELSE/END-CF markers;
loop IF_BREAK/LOOP mask progression;
PHI values at reconvergence;
early-exit live-mask behavior;
convergence/noduplicate protection against clone, speculation, CSE, and
sinking across mask transitions;
irreducible CFG and control-stack-depth negatives; and
no linx-vblock-body-asm string body in the 0.59 lane.
MIR, register allocation, and CodeGen
P0 constant behavior and P1..P7 allocation;
nested predicate liveness, allowed spills or fail-closed pressure handling;
explicit EXEC uses/defs on every control pseudo;
no body-local ri/vt/vu/vm/vn class and no VLOAD/VSTORE bridge;
B.SEQ GPR recurrence and B.PAR GPR-write rejection;
direct Tile parent subview and destination assembly operands;
TSEL if-conversion versus real divergent branch cost-model cases; and
typed TileOp pseudos expanded through the generated 0.59 schema.
MC/object and runtime
integrated Clang assembler plus standalone MC for every new physical form;
object/relocation/.note.pto.isa checks for linx32 and linx64;
explicit-BSTOP and next-BSTART bundle disassembly;
virtual TileOp and physical bundle round trips;
runtime nested-divergence sentinels with inactive-lane no-effect checks;
exact B.SEQ ordered recurrence results;
scheduling-independent B.PAR results and entry snapshots;
precise fault/restart at then, else, loop, and reconvergence boundaries; and
same-ELF comparison across QEMU, functional model, and RTL/cycle model when
available.
Proposed implementation stages
Typed-body cleanup: preserve the existing accepted scalar-replay tests
while replacing string body emission and ri* imports with typed IR/MIR.
B.SEQ control flow: implement uniformity, PRED32, IF/ELSE/END-CF, and
precise ordered lowering for nested diamonds.
B.PAR legality: add whole-body GPR-write/effect preflight and proven
disjoint-region selection.
Loop control: add break/continue/live-mask/reconvergence and predicate
pressure policy.
MC and release closure: switch to accepted 0.59 encodings, virtual
TileOp bundle folding, object identity, cross-model tests, and exact-head
component pins.
Acceptance boundary
This issue is ready for implementation only after PTO-ISA/pto-spec#189 freezes
the 0.59 execution-instance state, predicate/EXEC operations, B.SEQ/B.PAR
legality, B.Z/B.NZ meaning, and object identity.
Completion requires all of the following:
ordinary C++ for/if source reaches typed LLVM and MachineIR;
divergent control has explicit analyzable mask/reconvergence state;
predicates use the accepted main predicate namespace;
no second V/scalar-import register level survives in 0.59 output;
B.SEQ and B.PAR are selected and validated under their exact contracts;
Tile values access the same top-level register state through direct
subview/assemble ranges;
compiler, assembler, disassembler, emulator, and model agree on one 0.59
object; and
source, IR, MIR, assembly, object-disassembly, and runtime tests cover the
same representative nested element-wise kernel.
Status and dependency
Compiler RFC. Proposed only; no implementation is authorized by this issue.
This is the Linx LLVM companion to
PTO-ISA/pto-spec#189, which
proposes the common PTO/Linx 0.59 architecture:
B.SEQand iteration-parallelB.PARexecution markers;B.SUBVIEW/B.ASSEMBLEoperands; andexisting TileOp mnemonic.
Compiler baseline inspected for this RFC:
9fb4f7aa89ee22541bfae288e2085ada266ffd75.The compiler may prototype target IR and MachineIR, but final ISA instruction
selection, predicate/EXEC effects, encodings, and object identity remain
blocked on accepted PTO/Linx 0.59 contracts.
Goal
Allow element-wise Tile/vector computations to remain ordinary C++
forloops with ordinary structured control flow (
if,else, nested diamonds,canonical
break/continue) while LLVM lowers them to PTO/Linx 0.59 SIMTexecution without exposing V registers or mask-stack operations in source.
The intended source style is CUDA/SYCL-like in one important respect: C++
expresses scalar control flow for one logical element, while the compiler
classifies uniform versus varying values and constructs the execution-mask and
reconvergence protocol.
Illustrative pointer baseline:
The TileOP/API spelling may wrap the operands in a non-addressable Tile view,
but the body must remain the same language-level loop and branches:
The exact public Tile-view class and pragma spelling are review items. The
required semantic contract is ordinary C++
for/ifsource, not explicitpredicate intrinsics or hand-written bundle assembly.
Current compiler surface and gap
The repository already contains useful 0.58 bring-up pieces:
llvm/lib/Target/LinxISA/LinxISASIMTAutoVectorize.cpprecognizes countedloops, affine memory, reductions, selects, and structured inner CFG;
grouped_layout_requires_exec_mask_save_restorewhen real groupeddivergence requires missing mask save/restore support;
llvm/include/llvm/IR/IntrinsicsLinx.tddefinesllvm.linx.vblock.launchwith twelve scalar bind slots;llvm/lib/Target/LinxISA/LinxISAInstrInfo.tddefinesPSEUDO_VBLOCK_LAUNCH, body-localPSEUDO_V_*instructions, and TileOppseudos;
llvm/lib/Target/LinxISA/LinxISABlockify.cppexpands the launch into one ofBSTART.{MSEQ,MPAR,VSEQ,VPAR},B.TEXT, repeatedB.IORimports, body-localregister IDs, dimensions, and
BSTOP; andautovec_ifconverted_diamond.ll,autovec_nested_mask_branch.ll, andautovec_inner_mask_branch.llalreadyexercise multi-block element-wise control flow.
That path is not the 0.59 model. In particular:
linx-vblock-body-asmfunctionattribute instead of keeping the body as typed IR/MachineIR;
llvm.linx.vblock.launchmodels a second twelve-entryri*scalar importnamespace;
PSEUDO_V_*carries immediate body-localri/vt/vu/vm/vnIDs;explicit mask save/restore and reconvergence representation; and
than lowering to the proposed
B.SEQ/B.PARorder contract.The 0.59 implementation must remove these architectural assumptions rather
than hide them behind new pseudo names.
Proposed source and frontend contract
Ordinary C++ remains canonical
Clang must preserve the ordinary loop/CFG semantics. The user does not write
EXEC updates, predicate-register allocation, reconvergence labels, control
stack pushes, or
B.Z/B.NZ.The initial frontend should support:
forloops;if/elsediamonds;continueand loop-exit tests whose convergence can be proved; andautopolicy.The frontend emits ordinary LLVM CFG plus loop metadata describing only user
intent and schedule policy. It must not claim that a loop is
B.PAR-legal.That proof belongs to LLVM analyses after optimization.
Provisional policy values:
paris a request, not permission to miscompile: a loop that cannot satisfythe complete
B.PARcontract receives a stable diagnostic.autofalls backto
B.SEQunless independence is proved.Source value classification
materialized in a body-local V register or ordinary main GPR under
B.PAR.TCMP/TCMPSpredicate-Tile results must not be implicitly reinterpreted as P1..P7 or
EXEC without an accepted explicit conversion.
LLVM IR and control-stack model
Keep generic SSA/CFG, then annotate divergent control
Do not introduce a source-visible stack. Before target control-flow lowering,
LLVM IR remains normal SSA CFG. A new
LinxSIMTControlFlowtarget pass runsafter loop selection/structurization and uses at least:
UniformityAnalysisto distinguish uniform and divergent branches;DominatorTreeandLoopInfoto find reconvergence and loop joins; andexecution domain.
The design should follow the architecture pattern of AMDGPU
SIAnnotateControlFlow.cpp, which maintains a compiler-side stack of{reconvergence block, saved mask SSA value}and inserts target intrinsics forIF, ELSE, IF_BREAK, LOOP, and END_CF. It must not copy AMD wave64, SGPR, or
instruction semantics.
Provisional Linx target intrinsics, with a 32-bit mask carrier, are:
The exact intrinsic types may become a target extension predicate type, but
the mask width and semantics must stay compatible with the accepted 0.59
predicate/EXEC architecture. These intrinsics are compiler markers; they are
not new portable LLVM semantics or direct promises of one machine opcode.
Abstract control frame
For each divergent structured region LLVM tracks an SSA control frame
equivalent to:
The frame may later reside in predicate registers, main GPRs where legal, or
architectural execution-instance control-stack state. It is not addressable
C++ state and must not silently spill to ordinary program memory unless the
ISA/ABI explicitly permits such a spill.
Uniform branches remain ordinary branches. Divergent IF/ELSE conceptually
performs:
Early exit,
break, andcontinueupdate live/broken masks rather than merelyrestoring the original mask. The pass must reject irreducible or unsupported
control flow instead of guessing a reconvergence point.
Predicate and EXEC lowering
Introduce an explicit
PRED32MachineIR register class/bank for P0..P7 andEXEC-related mask values:
writable destination.
current EXEC as required by the ISA contract.
through a body-local vector register.
scheduling, sinking, and register allocation cannot move effects across a
mask transition.
i1/GPR condition and must notconsume P1..P7.
preservation must have an explicit policy. If no legal spill exists, the
compiler rejects over-depth control flow with a stable diagnostic.
Provisional MachineIR pseudos:
They deliberately mirror the analyzable shape of RDNA
SI_IF,SI_ELSE,SI_LOOP, andSI_END_CF, while lowering to Linx-specific predicate andexecution-instance operations.
B.ZandB.NZtest the current EXEC mask only after PTO/Linx 0.59 assignsthat meaning. They are not general predicate-register branches. A schematic
divergent branch may use:
These spellings are explanatory, not encoding proposals. LLVM must not emit
them until the owning ISA issue defines the exact carriers and effects.
B.SEQ/B.PARlegality and selectionThe current
vkind = {MSEQ,MPAR,VSEQ,VPAR}launch field must be replaced by anorthogonal order policy plus body effect classification.
B.SEQorder.
precise faults.
B.PARuntaken paths and compiler-synthesized temporaries.
reduction contract owns the overlap.
B.SEQ; only explicitlysupported reductions may use
B.PAR.irreducible CFG, unknown aliasing, or unresolved predicate spills reject a
forced
parrequest and forcesequnderauto.The pass must emit structured optimization remarks explaining the selected
mode or exact rejection reason.
Direct Tile subview/assemble lowering
For a Tile-view loop,
src[i]anddst[i]are compiler-recognized regionoperations, not C++ addressable references and not body-local scalar loads.
The selected iteration tuple derives a source region and destination range:
B.SUBVIEWrange;B.ASSEMBLErange to oneparent working generation;
disjoint regions, not
vt/vu/vm/vnregisters;side-effecting or nested divergent CFG uses the predicate/control-stack
path; and
LAST, fault rollback, andparent publication follow the accepted PTO generation contract.
The target IR work should compose with the indexed region/session model in
#74 rather than invent a second range representation.
ISel, MachineIR, Blockify, and virtual TileOp integration
Required compiler restructuring:
linx-vblock-body-asmstring serialization with typed IR andMachineBasicBlocks for the scheduled body.
llvm.linx.vblock.launch's twelveri*imports with explicit mainGPR, predicate, Tile parent, region, and assembly-session SSA operands.
PSEUDO_V_*immediate register IDs.allocation with explicit EXEC dependencies.
B.TEXT, the selectedB.SEQ/B.PARmarker, dimensions, direct top-level bindings, and oneboundary.
PSEUDO_TILEOP_*family and agenerated 0.59 TileOp schema shared by compiler expansion, assembler, and
bundle-aware disassembler.
B.SUBVIEWandB.ASSEMBLEimmediately adjacent to their owningbinder; never materialize VLOAD/VSTORE copies.
BSTOPand next-BSTARTbundle boundaries withoutconsuming the next header during virtual disassembly.
Diagnostics and conservative fallback
Provide stable diagnostics/remarks for at least:
B.PAR;B.PARillegal;setjmp/longjmp, inline assembly, or volatileeffect inside the region; and
autoselects the safeB.SEQor leaves the loop scalar. A forcedparrequest must reject rather than silently change ordering.
Minimum test matrix
Clang C++
for/ifbody;continue,break, and tail masks;seq, forced legalpar, forced illegalpar, andautofallback;LLVM IR and analysis
sinking across mask transitions;
linx-vblock-body-asmstring body in the 0.59 lane.MIR, register allocation, and CodeGen
ri/vt/vu/vm/vnclass and no VLOAD/VSTORE bridge;B.SEQGPR recurrence andB.PARGPR-write rejection;MC/object and runtime
.note.pto.isachecks for linx32 and linx64;BSTOPand next-BSTARTbundle disassembly;B.SEQordered recurrence results;B.PARresults and entry snapshots;available.
Proposed implementation stages
while replacing string body emission and
ri*imports with typed IR/MIR.B.SEQcontrol flow: implement uniformity, PRED32, IF/ELSE/END-CF, andprecise ordered lowering for nested diamonds.
direct subview/assemble TileOp pseudos.
B.PARlegality: add whole-body GPR-write/effect preflight and provendisjoint-region selection.
pressure policy.
TileOp bundle folding, object identity, cross-model tests, and exact-head
component pins.
Acceptance boundary
This issue is ready for implementation only after PTO-ISA/pto-spec#189 freezes
the 0.59 execution-instance state, predicate/EXEC operations,
B.SEQ/B.PARlegality,
B.Z/B.NZmeaning, and object identity.Completion requires all of the following:
for/ifsource reaches typed LLVM and MachineIR;B.SEQandB.PARare selected and validated under their exact contracts;subview/assemble ranges;
object; and
same representative nested element-wise kernel.