Skip to content

Commit a052bfa

Browse files
Deploying to gh-pages from @ beb7391 🚀
1 parent d427d13 commit a052bfa

8 files changed

Lines changed: 598 additions & 506 deletions

File tree

api/src/rustc_codegen_spirv/linker/dce.rs.html

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,15 @@
282282
<a href=#282 id=282 data-nosnippet>282</a> | PtrEqual
283283
<a href=#283 id=283 data-nosnippet>283</a> | PtrNotEqual
284284
<a href=#284 id=284 data-nosnippet>284</a> | PtrDiff =&gt; <span class="bool-val">true</span>,
285-
<a href=#285 id=285 data-nosnippet>285</a> Variable =&gt; inst.operands.first() == <span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>Operand::StorageClass(StorageClass::Function)),
286-
<a href=#286 id=286 data-nosnippet>286</a> <span class="kw">_ </span>=&gt; <span class="bool-val">false</span>,
287-
<a href=#287 id=287 data-nosnippet>287</a> }
288-
<a href=#288 id=288 data-nosnippet>288</a>}</code></pre></div></section></main></body></html>
285+
<a href=#285 id=285 data-nosnippet>285</a> <span class="comment">// Variables with Function or Private storage class are pure and can be DCE'd if unused.
286+
<a href=#286 id=286 data-nosnippet>286</a> // Other storage classes (Input, Output, Uniform, etc.) are part of the shader interface
287+
<a href=#287 id=287 data-nosnippet>287</a> // and must be kept.
288+
<a href=#288 id=288 data-nosnippet>288</a> </span>Variable =&gt; <span class="macro">matches!</span>(
289+
<a href=#289 id=289 data-nosnippet>289</a> inst.operands.first(),
290+
<a href=#290 id=290 data-nosnippet>290</a> <span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>Operand::StorageClass(
291+
<a href=#291 id=291 data-nosnippet>291</a> StorageClass::Function | StorageClass::Private
292+
<a href=#292 id=292 data-nosnippet>292</a> ))
293+
<a href=#293 id=293 data-nosnippet>293</a> ),
294+
<a href=#294 id=294 data-nosnippet>294</a> <span class="kw">_ </span>=&gt; <span class="bool-val">false</span>,
295+
<a href=#295 id=295 data-nosnippet>295</a> }
296+
<a href=#296 id=296 data-nosnippet>296</a>}</code></pre></div></section></main></body></html>

api/src/rustc_codegen_spirv/linker/mod.rs.html

Lines changed: 485 additions & 475 deletions
Large diffs are not rendered by default.

api/src/rustc_codegen_spirv/linker/peephole_opts.rs.html

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,4 +605,78 @@
605605
<a href=#605 id=605 data-nosnippet>605</a> function.blocks[block].instructions.insert(<span class="number">0</span>, phi);
606606
<a href=#606 id=606 data-nosnippet>606</a> }
607607
<a href=#607 id=607 data-nosnippet>607</a> <span class="kw">super</span>::apply_rewrite_rules(<span class="kw-2">&amp;</span>rewrite_rules, <span class="kw-2">&amp;mut </span>function.blocks);
608-
<a href=#608 id=608 data-nosnippet>608</a>}</code></pre></div></section></main></body></html>
608+
<a href=#608 id=608 data-nosnippet>608</a>}
609+
<a href=#609 id=609 data-nosnippet>609</a>
610+
<a href=#610 id=610 data-nosnippet>610</a><span class="doccomment">/// Fold `OpLoad` from Private/Function storage class variables that have constant initializers.
611+
<a href=#611 id=611 data-nosnippet>611</a>///
612+
<a href=#612 id=612 data-nosnippet>612</a>/// This optimization handles patterns like:
613+
<a href=#613 id=613 data-nosnippet>613</a>/// ```text
614+
<a href=#614 id=614 data-nosnippet>614</a>/// %ptr = OpVariable %_ptr_Private_T Private %initializer
615+
<a href=#615 id=615 data-nosnippet>615</a>/// %val = OpLoad %T %ptr
616+
<a href=#616 id=616 data-nosnippet>616</a>/// ```
617+
<a href=#617 id=617 data-nosnippet>617</a>/// After this optimization, uses of `%val` are replaced with `%initializer`.
618+
<a href=#618 id=618 data-nosnippet>618</a>///
619+
<a href=#619 id=619 data-nosnippet>619</a>/// This is particularly important for pointer-to-pointer constants (e.g., `&amp;&amp;123`)
620+
<a href=#620 id=620 data-nosnippet>620</a>/// where the outer pointer variable has a known initializer (the inner pointer).
621+
<a href=#621 id=621 data-nosnippet>621</a>/// Without this optimization, such patterns generate invalid SPIR-V in Logical
622+
<a href=#622 id=622 data-nosnippet>622</a>/// addressing mode (pointer-to-pointer with Private storage class is not allowed).
623+
<a href=#623 id=623 data-nosnippet>623</a></span><span class="kw">pub fn </span>fold_load_from_constant_variable(module: <span class="kw-2">&amp;mut </span>Module) {
624+
<a href=#624 id=624 data-nosnippet>624</a> <span class="kw">use </span>rspirv::spirv::StorageClass;
625+
<a href=#625 id=625 data-nosnippet>625</a>
626+
<a href=#626 id=626 data-nosnippet>626</a> <span class="comment">// Build a map of variable ID -&gt; initializer ID for Private/Function variables
627+
<a href=#627 id=627 data-nosnippet>627</a> // that have constant initializers.
628+
<a href=#628 id=628 data-nosnippet>628</a> </span><span class="kw">let </span>var_initializers: FxHashMap&lt;Word, Word&gt; = module
629+
<a href=#629 id=629 data-nosnippet>629</a> .types_global_values
630+
<a href=#630 id=630 data-nosnippet>630</a> .iter()
631+
<a href=#631 id=631 data-nosnippet>631</a> .filter_map(|inst| {
632+
<a href=#632 id=632 data-nosnippet>632</a> <span class="kw">if </span>inst.class.opcode != Op::Variable {
633+
<a href=#633 id=633 data-nosnippet>633</a> <span class="kw">return </span><span class="prelude-val">None</span>;
634+
<a href=#634 id=634 data-nosnippet>634</a> }
635+
<a href=#635 id=635 data-nosnippet>635</a> <span class="comment">// Check storage class - only Private and Function can be folded
636+
<a href=#636 id=636 data-nosnippet>636</a> </span><span class="kw">let </span>storage_class = inst.operands.first()<span class="question-mark">?</span>.unwrap_storage_class();
637+
<a href=#637 id=637 data-nosnippet>637</a> <span class="kw">if </span>!<span class="macro">matches!</span>(
638+
<a href=#638 id=638 data-nosnippet>638</a> storage_class,
639+
<a href=#639 id=639 data-nosnippet>639</a> StorageClass::Private | StorageClass::Function
640+
<a href=#640 id=640 data-nosnippet>640</a> ) {
641+
<a href=#641 id=641 data-nosnippet>641</a> <span class="kw">return </span><span class="prelude-val">None</span>;
642+
<a href=#642 id=642 data-nosnippet>642</a> }
643+
<a href=#643 id=643 data-nosnippet>643</a> <span class="comment">// Check for initializer (second operand after storage class)
644+
<a href=#644 id=644 data-nosnippet>644</a> </span><span class="kw">let </span>initializer = inst.operands.get(<span class="number">1</span>)<span class="question-mark">?</span>.id_ref_any()<span class="question-mark">?</span>;
645+
<a href=#645 id=645 data-nosnippet>645</a> <span class="prelude-val">Some</span>((inst.result_id<span class="question-mark">?</span>, initializer))
646+
<a href=#646 id=646 data-nosnippet>646</a> })
647+
<a href=#647 id=647 data-nosnippet>647</a> .collect();
648+
<a href=#648 id=648 data-nosnippet>648</a>
649+
<a href=#649 id=649 data-nosnippet>649</a> <span class="kw">if </span>var_initializers.is_empty() {
650+
<a href=#650 id=650 data-nosnippet>650</a> <span class="kw">return</span>;
651+
<a href=#651 id=651 data-nosnippet>651</a> }
652+
<a href=#652 id=652 data-nosnippet>652</a>
653+
<a href=#653 id=653 data-nosnippet>653</a> <span class="comment">// Rewrite OpLoad instructions that load from variables with known initializers
654+
<a href=#654 id=654 data-nosnippet>654</a> </span><span class="kw">let </span><span class="kw-2">mut </span>rewrite_rules: FxHashMap&lt;Word, Word&gt; = FxHashMap::default();
655+
<a href=#655 id=655 data-nosnippet>655</a>
656+
<a href=#656 id=656 data-nosnippet>656</a> <span class="kw">for </span>func <span class="kw">in </span><span class="kw-2">&amp;mut </span>module.functions {
657+
<a href=#657 id=657 data-nosnippet>657</a> <span class="kw">for </span>block <span class="kw">in </span><span class="kw-2">&amp;mut </span>func.blocks {
658+
<a href=#658 id=658 data-nosnippet>658</a> <span class="kw">for </span>inst <span class="kw">in </span><span class="kw-2">&amp;mut </span>block.instructions {
659+
<a href=#659 id=659 data-nosnippet>659</a> <span class="kw">if </span>inst.class.opcode != Op::Load {
660+
<a href=#660 id=660 data-nosnippet>660</a> <span class="kw">continue</span>;
661+
<a href=#661 id=661 data-nosnippet>661</a> }
662+
<a href=#662 id=662 data-nosnippet>662</a> <span class="comment">// OpLoad has pointer as first operand
663+
<a href=#663 id=663 data-nosnippet>663</a> </span><span class="kw">let </span>ptr_id = inst.operands[<span class="number">0</span>].unwrap_id_ref();
664+
<a href=#664 id=664 data-nosnippet>664</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>initializer) = var_initializers.get(<span class="kw-2">&amp;</span>ptr_id) {
665+
<a href=#665 id=665 data-nosnippet>665</a> <span class="comment">// This load can be replaced with the initializer value
666+
<a href=#666 id=666 data-nosnippet>666</a> </span><span class="kw">if let </span><span class="prelude-val">Some</span>(result_id) = inst.result_id {
667+
<a href=#667 id=667 data-nosnippet>667</a> rewrite_rules.insert(result_id, initializer);
668+
<a href=#668 id=668 data-nosnippet>668</a> <span class="comment">// Turn this instruction into a Nop
669+
<a href=#669 id=669 data-nosnippet>669</a> </span><span class="kw-2">*</span>inst = Instruction::new(Op::Nop, <span class="prelude-val">None</span>, <span class="prelude-val">None</span>, Vec::new());
670+
<a href=#670 id=670 data-nosnippet>670</a> }
671+
<a href=#671 id=671 data-nosnippet>671</a> }
672+
<a href=#672 id=672 data-nosnippet>672</a> }
673+
<a href=#673 id=673 data-nosnippet>673</a> }
674+
<a href=#674 id=674 data-nosnippet>674</a> }
675+
<a href=#675 id=675 data-nosnippet>675</a>
676+
<a href=#676 id=676 data-nosnippet>676</a> <span class="kw">if </span>!rewrite_rules.is_empty() {
677+
<a href=#677 id=677 data-nosnippet>677</a> <span class="comment">// Apply rewrite rules to all functions
678+
<a href=#678 id=678 data-nosnippet>678</a> </span><span class="kw">for </span>func <span class="kw">in </span><span class="kw-2">&amp;mut </span>module.functions {
679+
<a href=#679 id=679 data-nosnippet>679</a> <span class="kw">super</span>::apply_rewrite_rules(<span class="kw-2">&amp;</span>rewrite_rules, <span class="kw-2">&amp;mut </span>func.blocks);
680+
<a href=#680 id=680 data-nosnippet>680</a> }
681+
<a href=#681 id=681 data-nosnippet>681</a> }
682+
<a href=#682 id=682 data-nosnippet>682</a>}</code></pre></div></section></main></body></html>

0 commit comments

Comments
 (0)