diff options
| author | Theresa Foley <10618364+tangent-vector@users.noreply.github.com> | 2023-01-14 15:31:31 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-14 15:31:31 -0800 |
| commit | 14fab67c5edd8eb697ffb10dbcc0467678521eef (patch) | |
| tree | 88c82d8fd29d496a5a44ff51bc9a0f4f2ab2905f /tests/experimental/liveness/liveness.slang.expected | |
| parent | 4adc64f2a033ec141df6a16e65131612b30fb23b (diff) | |
Fixes for crash when inlining at global scope (#2593)
* Fixes for crash when inlining at global scope
Recent changes to the way inlining is implemented in the Slang compiler
have broken certain scenarios involving `static const` declarations.
The basic problem is that the initial-value expression for a `static const`
gets lowered into IR code at the global scope of a module, and if
that code includes `call`s to stdlib operations marked `forceInlineEarly`,
then we end up trying to apply inlining to code at module scope.
The current inlining operation assumes that all `call`s are in basic
blocks, and that the correct way to do inlining involves splitting
those blocks.
This change adds logic to detect when the callee at a call site to
be inlined consists of a single basic block ending in a `return`,
and in that case it invokes specialized inlining logic that doesn't
split basic blocks and doesn't need to care if the original `call`
is in a basic block.
Thus we are able to inline calls to single-basic-block `forceInlineEarly`
functions called as part of the initialization for global-scope
`static const` variables.
This logic does *not* solve the problem of calls to multi-block
`forceInlineEarly` functions from the global scope. Such calls cannot
really be inlined.
A secondary problem that arises when inlining such calls is that the
callee might include local temporaries (`var` instructions) that are
read and written (`load`s and `store`s), and none of those instructions
should be allowed at the global scope.
In the case of the functions being inlined here, the `load`/`store`
operations are superfluous, and should be cleaned up by our SSA pass.
The only reason that they seem to *not* be getting cleaned up in the
case that was been triggering crashes is that the callee is a generic.
The current logic for the SSA pass was skipping the bodies of generic
functions, so they would not be cleaned up. This change enables the SSA
pass to apply to the bodies of generic functions, and also ensures that
SSA cleanups are applied *before* any `forceInlineEarly` functions get
inlined.
* fixup: liveness test outputs
Diffstat (limited to 'tests/experimental/liveness/liveness.slang.expected')
| -rw-r--r-- | tests/experimental/liveness/liveness.slang.expected | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/tests/experimental/liveness/liveness.slang.expected b/tests/experimental/liveness/liveness.slang.expected index 0a39f0225..e50ecac5a 100644 --- a/tests/experimental/liveness/liveness.slang.expected +++ b/tests/experimental/liveness/liveness.slang.expected @@ -7,10 +7,10 @@ standard output = { layout(row_major) uniform; layout(row_major) buffer; spirv_instruction(id = 256) -void livenessStart_0(spirv_by_reference int _0, spirv_literal int _1); +void livenessStart_0(spirv_by_reference uint _0, spirv_literal int _1); spirv_instruction(id = 256) -void livenessStart_1(spirv_by_reference uint _0, spirv_literal int _1); +void livenessStart_1(spirv_by_reference int _0, spirv_literal int _1); spirv_instruction(id = 257) void livenessEnd_0(spirv_by_reference uint _0, spirv_literal int _1); @@ -21,12 +21,12 @@ void livenessEnd_1(spirv_by_reference int _0, spirv_literal int _1); int someSlowFunc_0(int a_0) { uint _S1 = uint(a_0); - int i_0; uint v_0; - livenessStart_0(i_0, 0); - i_0 = 0; - livenessStart_1(v_0, 0); + int i_0; + livenessStart_0(v_0, 0); v_0 = _S1; + livenessStart_1(i_0, 0); + i_0 = 0; for(;;) { if(i_0 < a_0 * 20) @@ -40,9 +40,10 @@ int someSlowFunc_0(int a_0) uint _S3 = v_0; livenessEnd_0(v_0, 0); uint _S4 = (_S2 | _S3 << 31) * uint(i_0); - i_0 = i_0 + 1; - livenessStart_1(v_0, 0); + int i_1 = i_0 + 1; + livenessStart_0(v_0, 0); v_0 = _S4; + i_0 = i_1; } livenessEnd_1(i_0, 0); return int(v_0); @@ -89,15 +90,15 @@ layout(local_size_x = 4, local_size_y = 1, local_size_z = 1) in; void main() { int index_0 = int(gl_GlobalInvocationID.x); - int i_1; + int i_2; int res_0; - livenessStart_0(i_1, 0); - i_1 = 0; - livenessStart_0(res_0, 0); + livenessStart_1(i_2, 0); + i_2 = 0; + livenessStart_1(res_0, 0); res_0 = index_0; for(;;) { - if(i_1 < index_0) + if(i_2 < index_0) { } else @@ -148,11 +149,11 @@ void main() int _S20 = res_0; livenessEnd_1(res_0, 0); int res_1 = _S20 + _S19; - i_1 = i_1 + 1; - livenessStart_0(res_0, 0); + i_2 = i_2 + 1; + livenessStart_1(res_0, 0); res_0 = res_1; } - livenessEnd_1(i_1, 0); + livenessEnd_1(i_2, 0); int _S21 = res_0; livenessEnd_1(res_0, 0); ((outputBuffer_0)._data[(uint(index_0))]) = _S21; |
