<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slang.git/source/slang/slang-ir-specialize.cpp, branch master</title>
<subtitle>Making it easier to work with shaders</subtitle>
<id>https://git.yummers.dev/slang.git/atom?h=master</id>
<link rel='self' href='https://git.yummers.dev/slang.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/'/>
<updated>2025-10-15T01:00:47+00:00</updated>
<entry>
<title>Clean up Slang IR representation of undefined values (#8708)</title>
<updated>2025-10-15T01:00:47+00:00</updated>
<author>
<name>Theresa Foley</name>
<email>10618364+tangent-vector@users.noreply.github.com</email>
</author>
<published>2025-10-15T01:00:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=907410f6a52cf4e7538870ebf5aeb88858f97973'/>
<id>urn:sha1:907410f6a52cf4e7538870ebf5aeb88858f97973</id>
<content type='text'>
Prior to this change, the Slang IR used a single opcode
(`kIROp_Undefined`) to encode all cases of undefined values. The
particular motivation for this change was a need to distinguish those
undefined values that represent a load from an uninitialized memory
location versus other sorts of undefined values. If transforming a
variable into SSA form results in `undefined` values in cases where the
a `load` was executed without a prior `store`, that represents an error
on the programmer's part, and should be diagnosed. However, other cases
of undefined values can arise during program transformation and
optimization, and should not typically result in diagnostics being
emitted.

While it was not the original motivation for this change, it is also
worth noting that the LLVM project has transitioned from initially using
only a single `undef` instruction to having a more nuanced model, and
the same factors that motivated their shift also apply to the Slang IR.
Counter-intuitively, the semantics of undefined values actually need to
be carefully defined.

Concretely, this change splits the pre-existing `undefined` opcode into
two sub-cases:

- `kIROp_LoadFromUninitializedMemory`, to represent the case of loading
from a memory location (such as a local variable) that has not been
initialized.

- `kIROp_Poison`, corresponding to the LLVM `poison` value.

Our poison instruction is intended to have semantics comparable to
LLVM's equivalent. Conceptually, any operation that is invoked with a
poison value as input will (with a few exceptions) produce a poison
value as output. One can think of the behavior of `poison` as similar to
how not-a-number values propagate in floating-point computations: by
default they "infect" the result of any computation they are involved
in. This semantic choice helps to ensure that many optimizations end up
being correct in the presence of undefined values, even if they did not
specifically account for them.

The `kIROp_LoadFromUninitializedMemory` case is comparable to the
combination of `freeze` and `undef` in LLVM. An LLVM `undef` value has
semantics that allow *each* use of that value to be replaced with a
*different* arbitrary value; these semantics cause many optimizations to
only be correct in the absence of undefined values. An LLVM `freeze`
instruction can take an undefined value as input, and produces a single
value that is still arbitrary, but must be consistent across all uses.
The latter semantics are what we want, since a given `load` from an
uninitialized memory location will yield an arbitrary-but-fixed value.

Note that we intentionally do not have a direct analogue to LLVM's
`undef` instruction, because of the way that `undef` causes so many
complications when trying to write optimizations.

We also do not add a `kIROp_Freeze` instruction in this change, but that
is simply because we currently have no need for it.

Existing code that was creating `IRUndefined` values has been updated to
create either `IRPoison` or `IRLoadFromUninitializedMemory` values, as
appropriate to the use case. Code that was checking for the
`kIROp_Undefined` opcode has been updated to either check for both of
the new opcodes (in the case of `switch` statements), or to use
`as&lt;IRUndefined&gt;` to perform a dynamic cast to the common base type of
the two new instructions.

Note that this change does not alter the way that instructions
representing undefined values are typically emitted as ordinary
instructions in the block that produces an undefined value. While
emitting `IRLoadFromUninitializedMemory` as an ordinary instruction is
exactly what we want, the `IRPoison` case would actually be better
represented in Slang IR as a "hoistable" instruction, so that there
would only be a singular `poison` value of each type. Changing
`IRPoison` to be hoistable would be a good follow-up change, but might
run into more challenges depending on what assumptions (if any) the
codebase is making about where undefined values get emitted.

---------

Co-authored-by: slangbot &lt;186143334+slangbot@users.noreply.github.com&gt;</content>
</entry>
<entry>
<title>Specialize interfaces in DebugFunction (#8617)</title>
<updated>2025-10-10T16:41:13+00:00</updated>
<author>
<name>Julius Ikkala</name>
<email>julius.ikkala@gmail.com</email>
</author>
<published>2025-10-10T16:41:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=48afbf9a1075fcf541b2c196c6313aeda57e9637'/>
<id>urn:sha1:48afbf9a1075fcf541b2c196c6313aeda57e9637</id>
<content type='text'>
E.g. in
[generic-extension-2.slang](https://github.com/shader-slang/slang/blob/master/tests/language-feature/extensions/generic-extension-2.slang),
incorrect DebugFunctions are generated for `getFirstOuter`:

```
let  %33        : Void  = DebugFunction("getFirstOuter", 18 : UInt, 3 : UInt, %26, Func(Int, 0 : Int))
```

This happens because specialization passes are leaving a `%IFoo` in the
function type, instead of replacing with a concrete type:
```
let  %34        : Void  = DebugFunction("getFirstOuter", 18 : UInt, 3 : UInt, %26, Func(Int, %IFoo))
```
and later, `cleanUpInterfaceTypes()` just replaces all interfaces with
the literal zero. So now we have a parameter type which isn't actually a
type at all, but an IntLit instead.

I'm not sure if the approach I picked is good, though. Some other
options that crossed my mind were:
* Make `fixUpFuncType` also update related DebugFunctions
- But is there a reason why DebugFunctions separately carry a function
type in the first place?
* Make `cleanUpInterfaceTypes` less aggressive or at least replace types
with a type instead of a value
    - But this will still make the debug info incorrect :(</content>
</entry>
<entry>
<title>Lookup refactor (#8467)</title>
<updated>2025-09-23T16:06:44+00:00</updated>
<author>
<name>kaizhangNV</name>
<email>149626564+kaizhangNV@users.noreply.github.com</email>
</author>
<published>2025-09-23T16:06:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=21c663605330d629e9022314a4720b86b017f295'/>
<id>urn:sha1:21c663605330d629e9022314a4720b86b017f295</id>
<content type='text'>
Close #8201.

This PR unify the lowering logic for LookupDeclRef of an interface
requirement. We will always lower this AST node to a
LookupWitness IR. The key of this IR is the special witnessTableType
`ThisTypeWitness`, this witness Table is simply a wrapper for an
interface type. Our current specialization pass doesn't handle this kind
of LookupWitness IR at all, so we will also add the specialization of
this_type IR as well.</content>
</entry>
<entry>
<title>extend fiddle to allow custom lua splices in more places (#7559)</title>
<updated>2025-07-01T19:03:41+00:00</updated>
<author>
<name>Ellie Hermaszewska</name>
<email>ellieh@nvidia.com</email>
</author>
<published>2025-07-01T19:03:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=5120c1cd072548654c9ce79fa85426a5e48736c4'/>
<id>urn:sha1:5120c1cd072548654c9ce79fa85426a5e48736c4</id>
<content type='text'>
* Add fkYAML submodule

* Generate slang-ir-inst-defs.h from slang-ir-inst-defs.yaml

* generate ir-inst-defs.h

* neaten things

* neaten inst def parser

* add rapidyaml submodule

* remove fkyaml

* remove fkyaml submodule

* remove use of ir-inst-defs.h

* format and warnings

* fix wasm build

* tidy

* remove rapidyaml

* Extend fiddle to allow custom splices in more places

* Use lua to describe ir insts

* fix

* neaten

* neaten

* neaten

* spelling

* neaten

* comment comment out assert

* merge</content>
</entry>
<entry>
<title>Implement spec const for generic parameter (#7121)</title>
<updated>2025-05-15T16:59:15+00:00</updated>
<author>
<name>kaizhangNV</name>
<email>149626564+kaizhangNV@users.noreply.github.com</email>
</author>
<published>2025-05-15T16:59:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=b325474c4aba52cca7e0bcd4eae02d23ca4ab9a3'/>
<id>urn:sha1:b325474c4aba52cca7e0bcd4eae02d23ca4ab9a3</id>
<content type='text'>
Close #6840.

This PR add supports to use specialize constant in generic parameter, and that parameter can also be used as array size, e.g. following code should work:

```
struct MyStruct&lt;let N: int&gt; { float buffer[N]; }
MyStruct&lt;SpecConstVar&gt; s;
```

- Loose the restriction from Link-Time to SpecializationConstant when extract generic argument
- Tweak the logic of how we decide whether a inst is hoistable. Besides checking existing hoistable flag of each 
  IRInst, when we detect a IRInst's type is SpecConstRateType, we will treat that inst hoistable. Because IRInst in 
  global scope can be deduplicated, and every SpecConstRateType inst should be in the global scope or IRGeneric 
  scope (which will be at global scope after specialization).
- Remove the SpecConstIntVal to IRInst map in IR lowering logic, because we already have way to deduplicate the 
  global scope IR.</content>
</entry>
<entry>
<title>Fix regression in partial specialization of existential arguments (#6818)</title>
<updated>2025-04-18T00:58:11+00:00</updated>
<author>
<name>kaizhangNV</name>
<email>149626564+kaizhangNV@users.noreply.github.com</email>
</author>
<published>2025-04-18T00:58:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=ee8a91e22813cf962be25e2c9f9263c20b70e228'/>
<id>urn:sha1:ee8a91e22813cf962be25e2c9f9263c20b70e228</id>
<content type='text'>
Close #6589.

In PR #6487, we support partial specialization. However there is a corner case we didn't handle correctly.

For the IR like this:

%val: specialize(...) = some inst;
%arg1: specialize(...) = makeExistential(%val, ...);
%arg2: %SomeConcreteType: load(...);
call func(%arg1, %arg2);

when we specialize the call func instruct, we will also specialize the function parameters.

On our existing logic, when we find an argument is a makeExistential, we will always extract the existential value, and use its type as the new parameter.

But in this case, %arg1 is not fully specialized yet, so it's type will still be a specialize. In this case, we will change the function's first parameter from an existential type to a specialize. This will result in that we lose the chance to specialize the first argument in the next iteration, because the first parameter of this function is not an existential type any more.

The reason behind this is that we should always keep specializing the arguments and parameters at the same time.

So this PR just does a check before specializing the parameters that if the argument cannot be fully specialized, we won't specialize the parameter this early. Instead, we will wait for the next iteration until the argument can be specialized.</content>
</entry>
<entry>
<title>Allow partial specialization of existential arguments. (#6487)</title>
<updated>2025-03-01T06:46:56+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2025-03-01T06:46:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=dd9d24d29c4a9e05a4510eb9959fafa0ed36618b'/>
<id>urn:sha1:dd9d24d29c4a9e05a4510eb9959fafa0ed36618b</id>
<content type='text'>
* Allow partial specialization of existential arguments.

* Fix.

* Add test case for improved diagnostics.

* Fix compile error.

* Fix tests.

* Fix.

* Fix test.

* Fix compile issue.

* Fix typo.

* Address comment.</content>
</entry>
<entry>
<title>Fix issue with specialization using arithmetic expressions (#6084)</title>
<updated>2025-01-14T22:48:17+00:00</updated>
<author>
<name>Sai Praveen Bangaru</name>
<email>31557731+saipraveenb25@users.noreply.github.com</email>
</author>
<published>2025-01-14T22:48:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=cb835b9596f78771dfd584aaa72aee7bc360b3d4'/>
<id>urn:sha1:cb835b9596f78771dfd584aaa72aee7bc360b3d4</id>
<content type='text'>
</content>
</entry>
<entry>
<title>[Auto-diff] Overhaul auto-diff type tracking + Overhaul dynamic dispatch for differentiable functions (#5866)</title>
<updated>2025-01-09T21:46:24+00:00</updated>
<author>
<name>Sai Praveen Bangaru</name>
<email>31557731+saipraveenb25@users.noreply.github.com</email>
</author>
<published>2025-01-09T21:46:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=87f00a36a123e36b415eeea82e02a8366cc5b881'/>
<id>urn:sha1:87f00a36a123e36b415eeea82e02a8366cc5b881</id>
<content type='text'>
* Overhauled the auto-diff system for dynamic dispatch

* More fixes

* remove intermediate dumps

* Update slang-ast-type.h

* More fixes + add a workaround for existential no-diff

* Update reverse-control-flow-3.slang

* remove dumps

* remove more dumps

* Delete working-reverse-control-flow-3.hlsl

* Cleanup comments + unused variables

* More comment cleanup

* Add support for lowering `DiffPairType(TypePack)` &amp; `MakePair(MakeValuePack, MakeValuePack)`

* Fix array of issues in Falcor tests.

* Update slang-ir-autodiff-pairs.cpp

* More fixes for Falcor image tests

* Small fixups.

---------

Co-authored-by: Yong He &lt;yonghe@outlook.com&gt;</content>
</entry>
<entry>
<title>  Check whether array element is fully specialized (#6000)</title>
<updated>2025-01-08T06:25:32+00:00</updated>
<author>
<name>kaizhangNV</name>
<email>149626564+kaizhangNV@users.noreply.github.com</email>
</author>
<published>2025-01-08T06:25:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=1a56f58fdd0c704e6dc0fad0f0ec33a25a35e60b'/>
<id>urn:sha1:1a56f58fdd0c704e6dc0fad0f0ec33a25a35e60b</id>
<content type='text'>
* Check whether array element is fully specialized

close #5776

When we start specialize a "specialize" IR, we should
make sure all the elements are fully specialized, but
we miss checking the elements of an array. This change
will check the it.

* add test

* add all wrapper types into the check

* add utility function to check if the type is wrapper type

---------

Co-authored-by: zhangkai &lt;zhangkai@zhangkais-MacBook-Pro.local&gt;
Co-authored-by: Yong He &lt;yonghe@outlook.com&gt;</content>
</entry>
</feed>
