summaryrefslogtreecommitdiff
path: root/source/slang/slang-emit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-emit.cpp')
-rw-r--r--source/slang/slang-emit.cpp68
1 files changed, 42 insertions, 26 deletions
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 1b94c588b..0539f9d1d 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -10,6 +10,7 @@
#include "slang-ir-collect-global-uniforms.h"
#include "slang-ir-dce.h"
#include "slang-ir-dll-import.h"
+#include "slang-ir-eliminate-phis.h"
#include "slang-ir-entry-point-uniforms.h"
#include "slang-ir-entry-point-raw-ptr-params.h"
#include "slang-ir-explicit-global-context.h"
@@ -731,39 +732,54 @@ Result linkAndOptimizeIR(
lowerBitCast(targetRequest, irModule);
simplifyIR(irModule);
- // TODO(JS): We probably want to add a pass that moves phi-node temporaries to
- // IR.
- //
- // Currently these are added as part of emit in
- // emitPhiVarAssignments and emitPhiVarDecls
- //
- // A possible mechanism might be:
- // 1) Find all of the parameters passed between blocks
- // 2) Make a variable for each one of them
- // This could be at the scope for the function, or more ideally a scope that is 'most appropriate' for how the parameter is passed
- // ie the closest scope such that the variable is in scope across the branch.
- // 3) Replace all uses of the parameters passed into a block (except the entry block), with the temporary
- // 3a) Remove the parameters from the start of a block (other than the entry block)
- // 4) For all of the branches in a function
- // 4a) For each parameter passed in the branch, assign to the temporary
- // 4b) Replace the branch with a branch that has no parameters
//
- // This should lead to an equivalent function, where the parameter passing between blocks is removed, and all the temporaries
- // are explicit in the output.
- //
- // I guess there could be a desire to combine the liveness tracking into this pass, because once a phi-temporary has been moved
- // we have lost(?) information about liveness. That could potentially be recovered, but for the phi-temporaries, their
- // initial liveness is trivial, it's when the assignment takes place, at the branch point.
- //
- // If all the temporaries were marked as such, then this would be fairly trivial to recreate.
-
- // TODO(JS): Without a pass to make all variables (including phi ones), the liveness tracking can't track everything
+ // Downstream targets may benefit from having live-range information for
+ // local variables, and our IR currently encodes a reasonably good version
+ // of that information. At this point we will insert live-range markers
+ // for local variables, on when such markers are requested.
+ //
+ // After this point in optimization, any passes that introduce new
+ // temporary variables into the IR module should take responsibility for
+ // producing their own live-range information.
+ //
if (codeGenContext->shouldTrackLiveness())
{
addLivenessTrackingToModule(irModule);
dumpIRIfEnabled(codeGenContext, irModule, "LIVENESS");
+ }
+
+ // As a late step, we need to take the SSA-form IR and move things *out*
+ // of SSA form, by eliminating all "phi nodes" (block parameters) and
+ // introducing explicit temporaries instead. Doing this at the IR level
+ // means that subsequent emit logic doesn't need to contend with the
+ // complexities of blocks with parameters.
+ //
+ eliminatePhis(codeGenContext, irModule);
+#if 0
+ dumpIRIfEnabled(codeGenContext, irModule, "PHIS ELIMINATED");
+#endif
+ // TODO: We need to insert the logic that fixes variable scoping issues
+ // here (rather than doing it very late in the emit process), because
+ // otherwise the `applyGLSLLiveness()` operation below wouldn't be
+ // able to see the live-range information that pass would need to add.
+ // For now we are avoiding that problem by simply *not* emitting live-range
+ // information when we fix variable scoping later on.
+
+ // Depending on the target, certain things that were represented as
+ // single IR instructions will need to be emitted with the help of
+ // function declaratons in output high-level code.
+ //
+ // One example of this is the live-range information, which needs
+ // to be output to GLSL code that uses a glslang extension for
+ // supporting function declarations that map directly to SPIR-V opcodes.
+ //
+ // We execute a pass here to transform any live-range instructions
+ // in the module into function calls, for the targets that require it.
+ //
+ if (codeGenContext->shouldTrackLiveness())
+ {
if (isKhronosTarget(targetRequest))
{
applyGLSLLiveness(irModule);